ด้วยความที่สนใจด้าน Virtualization อยู่แล้วก็เลยได้ไปลอง Thinstall โปรแกรมทำ Portable binary
ทำไปทำมาเกิด สงสัยในเรื่องความสามารถการทำ Packing ของมันเลยให้คุณ Tummy ลอง
ก็เลยได้ทราบว่าเจ้าโปรแกรมนี้นอกจากทำ Portable แล้วมันยังมีความสามารถป้องกันการ Debug ได้ระดับนึงด้วย
มาดูกันว่ามันใช้หลักการอะไรและมีวิธีแก้อย่างไร บทความนี่ไม่ได้เขียนเองนำมาจากเว็บต่างประเทศ น่าสนใจเลยนำมาฝากกัน




Contributed by: haggar
Views: 3585

TutorialsLevel : intermediate

=======================
Thinstall 2.521 - manually unpacking
=======================




1. Introduction

Hi folks and welcome to new unpacking tutorial! Today we will see how can Thinstall with double process protection be easily unpacked. I was losing my nerves with this one, but after some time I realised that protection can be tricked with cheap trick. There is one tutorial for single process Thinstall on ARTEAM site http://cracking.accessroot.com/ written by MaDMAn_H3rCul3s which was helpfull to me, so you can also check that tutorial too.




Tools and target:

- OllyDbg 1.10
- ImpREC
- LordPE
- Target is here http://www.reversing.be/binaries/articles/...01004052979.rar

Target for this tutorial was taken from Teddy Rogers site who has nice collection of unpackmes for practice and fun http://tuts4you.com. Also, since I'm using his unpackme archive, this tutorial can be published on his site too.





2. Killing Debug Blocker and finding OEP

As I sad, thinstall has double process protection which is acting like debug blocker feature and it doesn't alowes us to debug process of unpacking. Thinstall own debugger (first process) is creating second process, a debugee, and that second proces is performing unpacking. We need to debug that process instead first one. I was busting my ass trying to figure out how to god damn detach processes, but thanks to my pathetic knowledge about debugging I couldn't find the way. But I was thinking a little; since thinstall can be single protection too, maybe there is way to force double process protection to single one? I was examning this thinstall target and notice that debugger process doesn't use ReadProcessMemory and WriteProcessMemory api's, so debugger proces is just for preventing debugging and it doesn't do anything else. Second process is one that is doing all job. And I found easy way to force thinstal to think that it is single process protection. Lets go

First, use some plugin to hide Olly from IsDebuggerPresent API because thinstall checks this one million times. Open target in Olly and place breakpoint on CreateProcessA. Run target and when you break in kernel return to user code. You will find your self in double process protection loop. Bellow snippet is that whole block of code. You can see that we are in some allocated memory block. Since we are in CreateProcessA part, double process protection has already started. What we need is to break before that API is called. Place hardware bp on execution on this first line below and reastart Olly. Run and you should break at start:
[hide=30]
Code:
7FF8600A PUSH EBP <-------------------- START!!! Place hw bp on execution here and resart to break!!!
7FF8600B MOV EBP,ESP
7FF8600D SUB ESP,0E0
...
cut
...

7FF86100 TEST EAX,EAX
7FF86102 JNZ SHORT 7FF8610C
7FF86104 PUSH 0
7FF86106 CALL DWORD PTR DS:[7FF972D4]; kernel32.ExitProcess
7FF8610C CMP DWORD PTR DS:[7FFA6FE8],0
7FF86113 JE SHORT 7FF86124
7FF86115 CALL DWORD PTR DS:[7FFA6FE8]; kernel32.IsDebuggerPresent
7FF8611B TEST EAX,EAX
7FF8611D JE SHORT 7FF86124
7FF8611F CALL 7FF6ED69
7FF86124 PUSH DWORD PTR SS:[EBP-B4]
7FF8612A PUSH 7FF9CEFC; ASCII "%d.df"
7FF8612F LEA EAX,DWORD PTR SS:[EBP-CC]
7FF86135 PUSH EAX
...
cut
...
7FF86220 PUSH 0
7FF86222 PUSH 0
7FF86224 PUSH 0
7FF86226 PUSH 7FF85D12
7FF8622B PUSH 0
7FF8622D PUSH 0
7FF8622F CALL DWORD PTR DS:[7FF97218]; kernel32.CreateThread
7FF86235 LEAVE
7FF86236 RETN

When you stop at hw bp, remove it and we can go to fooling thinstall. Check this part imidiatley below our bp:

Code:
7FF86047 CALL DWORD PTR DS:[7FF9709C]; kernel32.GetVersionExA
7FF8604D MOV EAX,DWORD PTR DS:[7FFA69AC]
7FF86052 AND EAX,2000000
7FF86057 TEST EAX,EAX
7FF86059 JE 7FF86212
Here protector calls GetVersionExA to check does our system sopports something. It seams that it checks does system support IsDebuggerPresent API. That API is supported only by NT windows family. It seams that thinstall can have double process only on NT computers !?! Anyway, to trick thinstall, change JE to JMP or change Z flag to 1. This way jump will be executed and it will jump across whole double protection procedure, here:

Code:
7FF86212 MOV EAX,DWORD PTR DS:[7FFA69AC]
7FF86217 AND EAX,4000008
7FF8621C TEST EAX,EAX
7FF8621E JE SHORT 7FF86235
7FF86220 PUSH 0
7FF86222 PUSH 0
7FF86224 PUSH 0
7FF86226 PUSH 7FF85D12
7FF8622B PUSH 0
7FF8622D PUSH 0
7FF8622F CALL DWORD PTR DS:[7FF97218]; kernel32.CreateThread
7FF86235 LEAVE
7FF86236 RETN
Ok, debug blocker is killed and we have to find OEP now. I sow this part in MaDMAn_H3rCul3s tutorial. Just search all string references and find this string

ASCII "APISPY: Calling EXE Entry Point %x
"

Double click on it and you will land:
Code:
7FF52C50 PUSH 7FF97660; ASCII "APISPY: Calling EXE Entry Point %x
"
7FF52C55 CALL 7FF54550
7FF52C5A POP ECX
7FF52C5B POP ECX
7FF52C5C CALL DWORD PTR SS:[EBP-3B8] <------------ Place bp here and run!!!

Place bp on that CALL below because that is OEp of packed program. Run and enter call:

004010E3 PUSH 0
004010E5 CALL Thinstal.00401786
004010EA MOV DWORD PTR DS:[406D30],EAX
004010EF PUSH 0
004010F1 PUSH Thinstal.0040110B
004010F6 PUSH 0
004010F8 PUSH 1
004010FA PUSH DWORD PTR DS:[406D30]
00401100 CALL Thinstal.004016FC
00401105 PUSH EAX
00401106 CALL Thinstal.0040177A
0040110B PUSH EBP
0040110C MOV EBP,ESP
0040110E PUSHAD
0040110F MOV EAX,DWORD PTR SS:[EBP+8]
00401112 MOV DWORD PTR DS:[406D44],EAX
00401117 CMP DWORD PTR SS:[EBP+C],110
0040111E JNZ Thinstal.004011FD
00401124 PUSH Thinstal.00406BA1; ASCII "MoleBox Pro"
00401129 PUSH DWORD PTR DS:[406D44]
0040112F CALL Thinstal.00401762; JMP to USER32.SetWindowTextA
00401134 PUSH Thinstal.0040604C; ASCII "-= Del MoleBox Pro Sign =-"
00401139 PUSH 69
0040113B PUSH DWORD PTR DS:[406D44]
00401141 CALL Thinstal.00401756; JMP to USER32.SetDlgItemTextA
00401146 PUSH Thinstal.004060B0; ASCII "http://www.kanxue.cn";
0040114B PUSH 68
...
...
And there it is





3. Problem with imports

If you follow this line:

Code:
0040112F CALL Thinstal.00401762; JMP to USER32.SetWindowTextA
you will find import jumps:

Code:
004016F6 JMP DWORD PTR DS:[4050AC]; USER32.CallWindowProcA
004016FC JMP DWORD PTR DS:[4050B0]
00401702 JMP DWORD PTR DS:[4050B4]; USER32.EndDialog
00401708 JMP DWORD PTR DS:[4050B8]; USER32.GetActiveWindow
0040170E JMP DWORD PTR DS:[4050BC]; USER32.GetCapture
00401714 JMP DWORD PTR DS:[4050C0]; USER32.GetCursorPos
0040171A JMP DWORD PTR DS:[4050C4]; USER32.GetDlgCtrlID
00401720 JMP DWORD PTR DS:[4050C8]; USER32.GetDlgItem
00401726 JMP DWORD PTR DS:[4050A8]; USER32.GetParent
0040172C JMP DWORD PTR DS:[4050A4]; USER32.GetWindowRect
00401732 JMP DWORD PTR DS:[4050A0]; USER32.InvalidateRect
00401738 JMP DWORD PTR DS:[40509C]; USER32.MessageBoxA
0040173E JMP DWORD PTR DS:[405098]; USER32.PtInRect
00401744 JMP DWORD PTR DS:[405094]; USER32.ReleaseCapture
0040174A JMP DWORD PTR DS:[405090]
00401750 JMP DWORD PTR DS:[40508C]; USER32.SetCapture
00401756 JMP DWORD PTR DS:[405088]; USER32.SetDlgItemTextA
0040175C JMP DWORD PTR DS:[405080]; USER32.SetWindowLongA
00401762 JMP DWORD PTR DS:[405084]; USER32.SetWindowTextA
00401768 JMP DWORD PTR DS:[405044]
0040176E JMP DWORD PTR DS:[405048]
00401774 JMP DWORD PTR DS:[40504C]
0040177A JMP DWORD PTR DS:[405050]
00401780 JMP DWORD PTR DS:[405054]
00401786 JMP DWORD PTR DS:[405058]
0040178C JMP DWORD PTR DS:[40505C]; kernel32.GlobalAlloc
00401792 JMP DWORD PTR DS:[405060]; kernel32.GlobalFree
00401798 JMP DWORD PTR DS:[405064]; kernel32.GlobalLock
0040179E JMP DWORD PTR DS:[405068]; kernel32.GlobalUnlock
004017A4 JMP DWORD PTR DS:[40506C]
004017AA JMP DWORD PTR DS:[405070]
004017B0 JMP DWORD PTR DS:[405038]; kernel32.lstrcpyA
004017B6 JMP DWORD PTR DS:[40503C]; kernel32.lstrlenA
004017BC JMP DWORD PTR DS:[405078]
004017C2 JMP DWORD PTR DS:[40501C]; GDI32.CreateFontIndirectA
004017C8 JMP DWORD PTR DS:[405018]; GDI32.GetObjectA
004017CE JMP DWORD PTR DS:[405014]; GDI32.GetStockObject
004017D4 JMP DWORD PTR DS:[405008]; GDI32.SelectObject
004017DA JMP DWORD PTR DS:[40500C]; GDI32.SetBkMode
004017E0 JMP DWORD PTR DS:[405010]; GDI32.SetTextColor
004017E6 JMP DWORD PTR DS:[405000]; comdlg32.GetOpenFileNameA

As you can see, some of them do not lead to API&#39;s. Thinstall has some kind of redirection/emulation. Altough in MaDMAn_H3rCul3s tutorial imports was easy to fix, here is that problem harder. Open ImpREC and find imports. You will see that there is some invalid ones (13 in this case). First, DO NOT USE "Trace level 1" option in ImpREC, or any other! You will get incorrect imports! I have traced like lunatic through protector code in hope that I will found where imports are written, but my memory and hardware breakpoints was ignored and I just couldn&#39;t find redirection algo. That means we will have to manually fix imports. Not really manually, ImpREC and Olly will help us, but this approach will take some time.

This part reminds me to armadillo&#39;s redirection. Let&#39;s take a look. Check this jump in Olly:

Code:
004016FC JMP DWORD PTR DS:[4050B0]
Select it with left click and press ENTER to follow it in disassembler:
Code:
7FF5FE17 PUSH EBP
7FF5FE18 MOV EBP,ESP
7FF5FE1A PUSH ECX
7FF5FE1B PUSH DWORD PTR SS:[EBP+18]
7FF5FE1E PUSH DWORD PTR SS:[EBP+14]
7FF5FE21 PUSH DWORD PTR SS:[EBP+10]
7FF5FE24 PUSH DWORD PTR SS:[EBP+C]
7FF5FE27 PUSH DWORD PTR SS:[EBP+8]
7FF5FE2A CALL 7FF5E28D
7FF5FE2F POP ECX
7FF5FE30 PUSH EAX
7FF5FE31 CALL DWORD PTR DS:[7FF97358]; USER32.DialogBoxParamA
7FF5FE37 MOV DWORD PTR SS:[EBP-4],EAX
7FF5FE3A MOV EAX,DWORD PTR SS:[EBP-4]
7FF5FE3D LEAVE
7FF5FE3E RETN 14
There, dou you see? There is some protectors code and then you can see call to DialogBoxParamA. DialogBoxParamA is API that is stolen.


Let&#39;s see another example. This one is more complex, but you must get feeling. check this jump:

Code:
00401768 JMP DWORD PTR DS:[405044]
Press ENTER to follow it:

Code:
7FF63A61 MOV EAX,7FF94A55
7FF63A66 CALL 7FF89F08
7FF63A6B SUB ESP,54
7FF63A6E MOV EAX,DWORD PTR SS:[EBP+8]
7FF63A71 CMP EAX,DWORD PTR DS:[7FFA3480]
7FF63A77 JNZ SHORT 7FF63A91
7FF63A79 PUSH DWORD PTR SS:[EBP+8]
7FF63A7C CALL DWORD PTR DS:[7FF970B0]; kernel32.CloseHandle
7FF63A82 OR DWORD PTR DS:[7FFA3480],FFFFFFFF
7FF63A89 PUSH 1
7FF63A8B POP EAX; 7FF52C62
7FF63A8C JMP 7FF63C57
7FF63A91 PUSH 1
7FF63A93 PUSH 0
7FF63A95 PUSH DWORD PTR SS:[EBP+8]
7FF63A98 CALL 7FF60AC2
7FF63A9D ADD ESP,0C
7FF63AA0 MOV DWORD PTR SS:[EBP-10],EAX
7FF63AA3 CMP DWORD PTR SS:[EBP-10],0
7FF63AA7 JE 7FF63BD4
7FF63AAD MOV EAX,DWORD PTR DS:[7FFA3154]
7FF63AB2 MOV EAX,DWORD PTR DS:[EAX]
7FF63AB4 AND EAX,100000
7FF63AB9 NEG EAX
7FF63ABB SBB EAX,EAX
7FF63ABD NEG EAX
7FF63ABF MOVZX EAX,AL
7FF63AC2 TEST EAX,EAX
7FF63AC4 JE SHORT 7FF63AD5
7FF63AC6 PUSH DWORD PTR SS:[EBP+8]
7FF63AC9 PUSH 7FF9A114; ASCII "CloseHandle (internal) : h=%x
"
7FF63ACE CALL 7FF54550
7FF63AD3 POP ECX; 7FF52C62
7FF63AD4 POP ECX; 7FF52C62
7FF63AD5 MOV EAX,DWORD PTR SS:[EBP-10]
7FF63AD8 CMP DWORD PTR DS:[EAX],-1
7FF63ADB JE SHORT 7FF63AEE
7FF63ADD MOV EAX,DWORD PTR SS:[EBP-10]
7FF63AE0 PUSH DWORD PTR DS:[EAX]
7FF63AE2 CALL DWORD PTR DS:[7FF970B0]; kernel32.CloseHandle
7FF63AE8 MOV EAX,DWORD PTR SS:[EBP-10]
7FF63AEB OR DWORD PTR DS:[EAX],FFFFFFFF
7FF63AEE CALL DWORD PTR DS:[7FF970A8]; ntdll.RtlGetLastWin32Error
7FF63AF4 MOV DWORD PTR SS:[EBP-14],EAX
7FF63AF7 MOV EAX,DWORD PTR SS:[EBP-10]
7FF63AFA MOV EAX,DWORD PTR DS:[EAX+4]
7FF63AFD MOV EAX,DWORD PTR DS:[EAX+28]
7FF63B00 SHR EAX,13
7FF63B03 AND EAX,3
7FF63B06 CMP EAX,2
7FF63B09 JNZ SHORT 7FF63B60
7FF63B0B MOV EAX,DWORD PTR SS:[EBP-10]
7FF63B0E MOV EAX,DWORD PTR DS:[EAX+4]
7FF63B11 CMP DWORD PTR DS:[EAX+44],2
7FF63B15 JNZ SHORT 7FF63B60
7FF63B17 AND DWORD PTR SS:[EBP-1C],0
7FF63B1B LEA EAX,DWORD PTR SS:[EBP-1C]
7FF63B1E MOV DWORD PTR SS:[EBP-5C],EAX
7FF63B21 AND DWORD PTR SS:[EBP-4],0
7FF63B25 PUSH DWORD PTR SS:[EBP-5C]
7FF63B28 MOV EAX,DWORD PTR SS:[EBP-10]
7FF63B2B MOV ECX,DWORD PTR DS:[EAX+4]
7FF63B2E CALL 7FF609E1
7FF63B33 MOV DWORD PTR SS:[EBP-28],EAX
7FF63B36 MOV EAX,DWORD PTR SS:[EBP-28]; ntdll.77F6D6B0
7FF63B39 MOV EAX,DWORD PTR DS:[EAX]
7FF63B3B MOV DWORD PTR SS:[EBP-2C],EAX
7FF63B3E PUSH DWORD PTR SS:[EBP-2C]
7FF63B41 CALL DWORD PTR DS:[7FF971A8]; kernel32.DeleteFileA
7FF63B47 OR DWORD PTR SS:[EBP-4],FFFFFFFF
7FF63B4B LEA ECX,DWORD PTR SS:[EBP-1C]
7FF63B4E CALL 7FF86F15
7FF63B53 MOV EAX,DWORD PTR SS:[EBP-10]
7FF63B56 MOV EAX,DWORD PTR DS:[EAX+4]
7FF63B59 MOV DWORD PTR DS:[EAX+44],3
7FF63B60 PUSH 7FFA6BB8
7FF63B65 CALL DWORD PTR DS:[7FF97160]; ntdll.RtlEnterCriticalSection
7FF63B6B MOV EAX,DWORD PTR DS:[7FFA6BF8]
7FF63B70 MOV DWORD PTR SS:[EBP-50],EAX
7FF63B73 LEA EAX,DWORD PTR SS:[EBP+8]
7FF63B76 PUSH EAX
7FF63B77 LEA EAX,DWORD PTR SS:[EBP-20]
7FF63B7A PUSH EAX
7FF63B7B MOV ECX,DWORD PTR SS:[EBP-50]
7FF63B7E CALL 7FF6718D
7FF63B83 MOV EAX,DWORD PTR SS:[EBP-20]; ntdll.77F79005
7FF63B86 MOV DWORD PTR SS:[EBP-58],EAX
7FF63B89 MOV EAX,DWORD PTR DS:[7FFA6BF8]
7FF63B8E MOV DWORD PTR SS:[EBP-54],EAX
7FF63B91 PUSH DWORD PTR SS:[EBP-58]; ntdll.77FA34DE
7FF63B94 LEA EAX,DWORD PTR SS:[EBP-24]
7FF63B97 PUSH EAX
7FF63B98 MOV ECX,DWORD PTR SS:[EBP-54]; <&KERNEL32.GetModuleFileNameA>
7FF63B9B CALL 7FF66C85
7FF63BA0 MOV EAX,DWORD PTR SS:[EBP+8]
7FF63BA3 CMP EAX,DWORD PTR DS:[7FFA3484]
7FF63BA9 JNZ SHORT 7FF63BB9
7FF63BAB AND DWORD PTR DS:[7FFA6C1C],0
7FF63BB2 OR DWORD PTR DS:[7FFA3484],FFFFFFFF
7FF63BB9 PUSH 7FFA6BB8
7FF63BBE CALL DWORD PTR DS:[7FF9715C]; ntdll.RtlLeaveCriticalSection
7FF63BC4 PUSH 0
7FF63BC6 CALL DWORD PTR DS:[7FF97044]; ntdll.RtlSetLastWin32Error
7FF63BCC PUSH 1
7FF63BCE POP EAX; 7FF52C62
7FF63BCF JMP 7FF63C57
7FF63BD4 PUSH DWORD PTR SS:[EBP+8]
7FF63BD7 CALL 7FF682DF
7FF63BDC POP ECX; 7FF52C62
7FF63BDD MOV DWORD PTR SS:[EBP-18],EAX
7FF63BE0 CMP DWORD PTR SS:[EBP-18],0
7FF63BE4 JNZ SHORT 7FF63C54
7FF63BE6 PUSH DWORD PTR SS:[EBP+8]
7FF63BE9 CALL DWORD PTR DS:[7FF970B0]; kernel32.CloseHandle
7FF63BEF MOV DWORD PTR SS:[EBP-18],EAX
7FF63BF2 MOV EAX,DWORD PTR DS:[7FFA3154]
7FF63BF7 MOV EAX,DWORD PTR DS:[EAX]
7FF63BF9 AND EAX,100000
7FF63BFE NEG EAX
7FF63C00 SBB EAX,EAX
7FF63C02 NEG EAX
7FF63C04 MOVZX EAX,AL
7FF63C07 TEST EAX,EAX
7FF63C09 JNZ SHORT 7FF63C28
7FF63C0B CMP DWORD PTR SS:[EBP-18],0
7FF63C0F JNZ SHORT 7FF63C54
7FF63C11 MOV EAX,DWORD PTR DS:[7FFA3154]
7FF63C16 MOV EAX,DWORD PTR DS:[EAX]
7FF63C18 AND EAX,8
7FF63C1B NEG EAX
7FF63C1D SBB EAX,EAX
7FF63C1F NEG EAX
7FF63C21 MOVZX EAX,AL
7FF63C24 TEST EAX,EAX
7FF63C26 JE SHORT 7FF63C54
7FF63C28 CMP DWORD PTR SS:[EBP-18],0
7FF63C2C JNZ SHORT 7FF63C37
7FF63C2E MOV DWORD PTR SS:[EBP-60],7FF99900; ASCII "*** failed"
7FF63C35 JMP SHORT 7FF63C3E
7FF63C37 MOV DWORD PTR SS:[EBP-60],7FF9A10C; ASCII "success"
7FF63C3E PUSH DWORD PTR SS:[EBP-60]
7FF63C41 PUSH DWORD PTR SS:[EBP-18]
7FF63C44 PUSH DWORD PTR SS:[EBP+8]
7FF63C47 PUSH 7FF9A0E0; ASCII "CloseHandle (extern) hObject=%x -> %d %s
"
7FF63C4C CALL 7FF54550
7FF63C51 ADD ESP,10
7FF63C54 MOV EAX,DWORD PTR SS:[EBP-18]
7FF63C57 MOV ECX,DWORD PTR SS:[EBP-C]
7FF63C5A MOV DWORD PTR FS:[0],ECX
7FF63C61 LEAVE
7FF63C62 RETN 4
This is not simple, isn&#39;t it Ha, there is lot of API calls here, but which one is right one !?! Check this:

Code:
ntdll.RtlGetLastWin32Error <-------- Forget these ones ntdll.dll. Their purpose is for some internal usage.
ntdll.RtlEnterCriticalSection
ntdll.RtlLeaveCriticalSection
ntdll.RtlSetLastWin32Error
kernel32.DeleteFileA <-------------- It could be this one.
kernel32.CloseHandle <-------------- Or it could be this one.
So it could be DeleteFileA or CloseHandle. But again, thinstall will help us. Check these strings:

"CloseHandle (internal) : h=%x
"
"CloseHandle (extern) hObject=%x -> %d %s
"

These strings are telling you that CloseHandle is API that is stolen. As you can see, it is not easy and you will spend some time. But notice that right API is always close to RETN than others, ntdll.dll ones are for internal usage of protector and text strings will give you help. And finally, you can always run file after fixing and check in stack do they have right parameters.

In Olly you will check that you didn&#39;t make something wrong, but for repairing these imports use ImpREC. When you find IAT, click to show invalid one, than on one-by-one right click on each and select Disassemble/Hex view. There you will see same disassmebler view as in olly (only without strings) and when you see API that you think it is right one, right click on name and in popup menu click "Get Import". API&#39;s that I found from the beggining to the end are:
Code:
CreateThread
ExitThread
CloseHandle
CopyFileA
CreateFileA
ExitProcess
GetFileSize
GetModuleHandleA
ReadFile
WriteFile
ShellExecuteA
SendMessageA
DialogBoxParamA
That&#39;s it, lucky that unpackme is small. For larger number of imports we could try to make some script or more generic approach.

I was going to dump file with LordPE but I get error message "Couldn&#39;t grab process memory ", then I swiched to Intelli&#39;s engine but after fixing imports dump would just exit and also it lost icon. So I dumped it with OllyDump, fixed imports with ImpREC and dump worked fine.





4. Finall words

That&#39;s it ! We have unpacked double process Thinstall and it even wasn&#39;t so hard.

If somedy figure out how to fix imports with elegant patching, it would be nice thing to write small update for this tutorial. Btw, it is interesting how protected file has only one section.

In archive you will find target, dump, tutorial, and tree for ImpREC so you can check your dump.


Greets goes to detten, knight, thorpe, TDC, boro... all biw users, arteam and crackmes.de members. Thanks to MaDMAn_H3rCul3s for his tutorial and Teddy Rogers for his great site with unpackmes.





[haggar]



What&#39;s Related

* http://cracking.accessr...
* http://www.reversing.be...
* http://tuts4you.com
* http://www.kanxue.cn&qu...
* More by haggar
* More from Tutorials



Story Options

* Mail Story to a Friend
* Printable Story Format


Thinstall 2.5 - manually unpacking | 3 comments | Create New Account
The following comments are owned by whomever posted them. This site is not responsible for what they say.
Thinstall 2.5 - manually unpacking
Authored by: lena151 on Thursday, November 03 2005 @ 11:39 AM CET
Great work, as allways.
BTW, see my PM to you on ARTeam.
Regards
[ Reply to This ]
Thinstall 2.5 - manually unpacking
Authored by: haggar on Sunday, January 15 2006 @ 09:58 PM CET
Hi and greetings!


This small tutorial is just update for my Thinstall unpacking tutorial , but this text can be usefull for lot of other packers/protectors (ASPack, UPX, NsPack, Neolite...) that doesn&#39;t destroy IAT information. It&#39;s very simple, there is way how to repair IAT without using ImpREC. It takes little more time , but you get smaller and cleaner dump.


Actually, in Thinstall it takes much less time for fixing since we doesn&#39;t have to trace and find imports. Thinstall uses WriteProcessMemory API to write values in thunks and I didn&#39;t found that when I was unpacking it for the first time.

But, this is not subject of this small tutorial. Let&#39;s see that on example. Check that mine tutorial to see how to kill Debug Blocker and how to find OEP. When you read that (or if you already know that) continue with this text. Are you ready? Yes, OK: Whole point is that Thinstall desn&#39;t destroy import information (thunks, ordinals and image descriptors) and if we prevent filling thunks with imports, we can get perfect dump. Let&#39;s see:


In our example, we kill debug blocker. Before that we sow that one import jump is pointing to his thunk:

Code:
004016F6 JMP DWORD PTR DS:[4050AC]; USER32.CallWindowProcA
Place memory bp on access on 4050AC and run untill you stop at code that is filling that block with bytes:

Code:
7FF89FF3 F3:A5 REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS> <------ This one is filling!!!
7FF89FF5 FF2495 08A1F87F JMP DWORD PTR DS:[EDX*4+7FF8A108]
7FF89FFC 8BC7 MOV EAX,EDI; Thinstal.004050AC
7FF89FFE BA 03000000 MOV EDX,3
7FF8A003 83E9 04 SUB ECX,4
7FF8A006 72 0C JB SHORT 7FF8A014
7FF8A008 83E0 03 AND EAX,3
7FF8A00B 03C8 ADD ECX,EAX
7FF8A00D FF2485 20A0F87F JMP DWORD PTR DS:[EAX*4+7FF8A020]
7FF8A014 FF248D 18A1F87F JMP DWORD PTR DS:[ECX*4+7FF8A118]
7FF8A01B 90 NOP
7FF8A01C -FF248D 9CA0F87F JMP DWORD PTR DS:[ECX*4+7FF8A09C]
7FF8A023 90 NOP
7FF8A024 30A0 F87F5CA0 XOR BYTE PTR DS:[EAX+A05C7FF8],AH
7FF8A02A F8 CLC

Place bp below and run then check dump. You will see whole virgin IAT block that is waiting for filling thunks with API&#39;s:

Code:
00404FFC 14 55 00 00 00 00 00 00 DE 54 00 00 .U.......T..
0040500C EE 54 00 00 FA 54 00 00 CC 54 00 00 BE 54 00 00 .T...T...T...T..
0040501C A8 54 00 00 00 00 00 00 E8 55 00 00 F8 55 00 00 .T.......U...U..
0040502C 06 56 00 00 16 56 00 00 2A 56 00 00 66 54 00 00 .V...V..*V..fT..
0040503C 72 54 00 00 32 56 00 00 BC 53 00 00 CA 53 00 00 rT..2V...S...S..
0040504C D6 53 00 00 E4 53 00 00 F2 53 00 00 00 54 00 00 .S...S...S...T..
0040505C 14 54 00 00 22 54 00 00 30 54 00 00 3E 54 00 00 .T.."T..0T..>T..
0040506C 4E 54 00 00 5A 54 00 00 00 00 00 00 8C 54 00 00 NT..ZT.......T..
0040507C 00 00 00 00 8C 53 00 00 9E 53 00 00 7A 53 00 00 .....S...S..zS..
0040508C 6C 53 00 00 5C 53 00 00 4A 53 00 00 3E 53 00 00 lS..S..JS..>S..
0040509C 30 53 00 00 1E 53 00 00 0E 53 00 00 02 53 00 00 0S...S...S...S..
004050AC 84 52 00 00 96 52 00 00 A8 52 00 00 B4 52 00 00 .R...R...R...R..
004050BC C6 52 00 00 D4 52 00 00 E4 52 00 00 F4 52 00 00 .R...R...R...R..
004050CC 00 00 00 00 CE 55 00 00 B4 55 00 00 A2 55 00 00 .....U...U...U..
004050DC 92 55 00 00 7A 55 00 00 6A 55 00 00 46 55 00 00 .U..zU..jU..FU..
004050EC 36 55 00 00 5C 55 00 00 00 00 00 00 00 00 00 00 6U..U..........
004050FC 00 00 00 00 0C 52 00 00 00 00 00 00 00 00 00 00 .....R..........
0040510C B0 53 00 00 80 50 00 00 B0 51 00 00 00 00 00 00 .S...P...Q......
0040511C 00 00 00 00 7E 54 00 00 24 50 00 00 04 52 00 00 ....~T..$P...R..
0040512C 00 00 00 00 00 00 00 00 9C 54 00 00 78 50 00 00 .........T..xP..
0040513C 94 51 00 00 00 00 00 00 00 00 00 00 0A 55 00 00 .Q...........U..
0040514C 08 50 00 00 8C 51 00 00 00 00 00 00 00 00 00 00 .P...Q..........
0040515C 28 55 00 00 00 50 00 00 5C 52 00 00 00 00 00 00 (U...P..R......
0040516C 00 00 00 00 DE 55 00 00 D0 50 00 00 00 00 00 00 .....U...P......
0040517C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0040518C 14 55 00 00 00 00 00 00 DE 54 00 00 EE 54 00 00 .U.......T...T..
0040519C FA 54 00 00 CC 54 00 00 BE 54 00 00 A8 54 00 00 .T...T...T...T..
004051AC 00 00 00 00 E8 55 00 00 F8 55 00 00 06 56 00 00 .....U...U...V..
004051BC 16 56 00 00 2A 56 00 00 66 54 00 00 72 54 00 00 .V..*V..fT..rT..
004051CC 32 56 00 00 BC 53 00 00 CA 53 00 00 D6 53 00 00 2V...S...S...S..
004051DC E4 53 00 00 F2 53 00 00 00 54 00 00 14 54 00 00 .S...S...T...T..
004051EC 22 54 00 00 30 54 00 00 3E 54 00 00 4E 54 00 00 "T..0T..>T..NT..
004051FC 5A 54 00 00 00 00 00 00 8C 54 00 00 00 00 00 00 ZT.......T......
0040520C 8C 53 00 00 9E 53 00 00 7A 53 00 00 6C 53 00 00 .S...S..zS..lS..
0040521C 5C 53 00 00 4A 53 00 00 3E 53 00 00 30 53 00 00 S..JS..>S..0S..
0040522C 1E 53 00 00 0E 53 00 00 02 53 00 00 84 52 00 00 .S...S...S...R..
0040523C 96 52 00 00 A8 52 00 00 B4 52 00 00 C6 52 00 00 .R...R...R...R..
0040524C D4 52 00 00 E4 52 00 00 F4 52 00 00 00 00 00 00 .R...R...R......
0040525C CE 55 00 00 B4 55 00 00 A2 55 00 00 92 55 00 00 .U...U...U...U..
0040526C 7A 55 00 00 6A 55 00 00 46 55 00 00 36 55 00 00 zU..jU..FU..6U..
0040527C 5C 55 00 00 00 00 00 00 13 00 43 61 6C 6C 57 69 U........CallWi
0040528C 6E 64 6F 77 50 72 6F 63 41 00 8A 00 44 69 61 6C ndowProcA...Dial
0040529C 6F 67 42 6F 78 50 61 72 61 6D 41 00 AD 00 45 6E ogBoxParamA...En
004052AC 64 44 69 61 6C 6F 67 00 D0 00 47 65 74 41 63 74 dDialog...GetAct
004052BC 69 76 65 57 69 6E 64 6F 77 00 D5 00 47 65 74 43 iveWindow...GetC
004052CC 61 70 74 75 72 65 00 00 EC 00 47 65 74 43 75 72 apture....GetCur
004052DC 73 6F 72 50 6F 73 00 00 F1 00 47 65 74 44 6C 67 sorPos....GetDlg
004052EC 43 74 72 6C 49 44 00 00 F2 00 47 65 74 44 6C 67 CtrlID....GetDlg
004052FC 49 74 65 6D 00 00 24 01 47 65 74 50 61 72 65 6E Item..$.GetParen
0040530C 74 00 48 01 47 65 74 57 69 6E 64 6F 77 52 65 63 t.H.GetWindowRec
0040531C 74 00 63 01 49 6E 76 61 6C 69 64 61 74 65 52 65 t.c.InvalidateRe
0040532C 63 74 00 00 9D 01 4D 65 73 73 61 67 65 42 6F 78 ct....MessageBox
0040533C 41 00 C2 01 50 74 49 6E 52 65 63 74 00 00 D2 01 A...PtInRect....
0040534C 52 65 6C 65 61 73 65 43 61 70 74 75 72 65 00 00 ReleaseCapture..
0040535C E2 01 53 65 6E 64 4D 65 73 73 61 67 65 41 00 00 ..SendMessageA..
0040536C EB 01 53 65 74 43 61 70 74 75 72 65 00 00 F8 01 ..SetCapture....
0040537C 53 65 74 44 6C 67 49 74 65 6D 54 65 78 74 41 00 SetDlgItemTextA.
0040538C 1D 02 53 65 74 57 69 6E 64 6F 77 4C 6F 6E 67 41 ..SetWindowLongA
0040539C 00 00 22 02 53 65 74 57 69 6E 64 6F 77 54 65 78 ..".SetWindowTex
004053AC 74 41 00 00 75 73 65 72 33 32 2E 64 6C 6C 00 00 tA..user32.dll..
004053BC >1A 00 43 6C 6F 73 65 48 61 6E 64 6C 65 00 24 00 ..CloseHandle.$.
004053CC >43 6F 70 79 46 69 6C 65 41 00 30 00 43 72 65 61 CopyFileA.0.Crea
004053DC >74 65 46 69 6C 65 41 00 80 00 45 78 69 74 50 72 teFileA...ExitPr
004053EC >6F 63 65 73 73 00 F5 00 47 65 74 46 69 6C 65 53 ocess...GetFileS
004053FC 69 7A 65 00 09 01 47 65 74 4D 6F 64 75 6C 65 48 ize...GetModuleH
0040540C 61 6E 64 6C 65 41 00 00 67 01 47 6C 6F 62 61 6C andleA..g.Global
0040541C 41 6C 6C 6F 63 00 6E 01 47 6C 6F 62 61 6C 46 72 Alloc.n.GlobalFr
0040542C 65 65 00 00 72 01 47 6C 6F 62 61 6C 4C 6F 63 6B ee..r.GlobalLock
0040543C 00 00 79 01 47 6C 6F 62 61 6C 55 6E 6C 6F 63 6B ..y.GlobalUnlock
0040544C 00 00 F7 01 52 65 61 64 46 69 6C 65 00 00 9E 02 ....ReadFile....
0040545C 57 72 69 74 65 46 69 6C 65 00 BB 02 6C 73 74 72 WriteFile...lstr
0040546C 63 70 79 41 00 00 BF 02 6C 73 74 72 6C 65 6E 41 cpyA....lstrlenA
0040547C 00 00 6B 65 72 6E 65 6C 33 32 2E 64 6C 6C 00 00 ..kernel32.dll..
0040548C 67 00 53 68 65 6C 6C 45 78 65 63 75 74 65 41 00 g.ShellExecuteA.
0040549C 73 68 65 6C 6C 33 32 2E 64 6C 6C 00 2F 00 43 72 shell32.dll./.Cr
004054AC 65 61 74 65 46 6F 6E 74 49 6E 64 69 72 65 63 74 eateFontIndirect
004054BC 41 00 CD 00 47 65 74 4F 62 6A 65 63 74 41 00 00 A...GetObjectA..
004054CC DD 00 47 65 74 53 74 6F 63 6B 4F 62 6A 65 63 74 ..GetStockObject
004054DC 00 00 2E 01 53 65 6C 65 63 74 4F 62 6A 65 63 74 ....SelectObject
004054EC 00 00 35 01 53 65 74 42 6B 4D 6F 64 65 00 59 01 ..5.SetBkMode.Y.
004054FC 53 65 74 54 65 78 74 43 6F 6C 6F 72 00 00 67 64 SetTextColor..gd
0040550C 69 33 32 2E 64 6C 6C 00 0A 00 47 65 74 4F 70 65 i32.dll...GetOpe
0040551C 6E 46 69 6C 65 4E 61 6D 65 41 00 00 63 6F 6D 64 nFileNameA..comd
0040552C 6C 67 33 32 2E 64 6C 6C 00 00 AC 00 77 61 76 65 lg32.dll....wave
0040553C 4F 75 74 43 6C 6F 73 65 00 00 B5 00 77 61 76 65 OutClose....wave
0040554C 4F 75 74 47 65 74 50 6F 73 69 74 69 6F 6E 00 00 OutGetPosition..
0040555C B8 00 77 61 76 65 4F 75 74 4F 70 65 6E 00 B9 00 ..waveOutOpen...
0040556C 77 61 76 65 4F 75 74 50 61 75 73 65 00 00 BA 00 waveOutPause....
0040557C 77 61 76 65 4F 75 74 50 72 65 70 61 72 65 48 65 waveOutPrepareHe
0040558C 61 64 65 72 00 00 BB 00 77 61 76 65 4F 75 74 52 ader....waveOutR
0040559C 65 73 65 74 00 00 BC 00 77 61 76 65 4F 75 74 52 eset....waveOutR
004055AC 65 73 74 61 72 74 00 00 C0 00 77 61 76 65 4F 75 estart....waveOu
004055BC 74 55 6E 70 72 65 70 61 72 65 48 65 61 64 65 72 tUnprepareHeader
004055CC 00 00 C1 00 77 61 76 65 4F 75 74 57 72 69 74 65 ....waveOutWrite
004055DC 00 00 77 69 6E 6D 6D 2E 64 6C 6C 00 46 00 43 72 ..winmm.dll.F.Cr
004055EC 65 61 74 65 54 68 72 65 61 64 00 00 81 00 45 78 eateThread....Ex
004055FC 69 74 54 68 72 65 61 64 00 00 07 02 52 65 73 75 itThread....Resu
0040560C 6D 65 54 68 72 65 61 64 00 00 53 02 53 65 74 54 meThread..S.SetT
0040561C 68 72 65 61 64 50 72 69 6F 72 69 74 79 00 60 02 hreadPriority.`.
0040562C 53 6C 65 65 70 00 62 02 53 75 73 70 65 6E 64 54 Sleep.b.SuspendT
0040563C 68 72 65 61 64 hread
Now, binary copy all that block and find OEP. Check then that IAT block and you will see changes - API&#39;s are placed in thunks, also some pointers to protectors code (API&#39;s that we need to fix). In my tutorial I traced every single invalid import but I didn&#39;t thinking. There is easier way. Binary paste that block that you have copied before into same place, ei. IAT block must look again like virgin one, untached above. Then dump. Dump will crush. Reason of crushing is just that IAT information is incorrect in PE header because that is old info for Thinstall IAT. We just need to enter correct value with LordPE. Open LordPE and load dump in PE editor. Click directories button, check ImportTable, it has:

Code:
RVA: 0
Size: 0
We just need to enter correct values. Now you need to read some PE format tutorial (goppit wrote very good one) and you&#39;ll know what to do. RVA must point to image_import_descriptors and Size is size of all image_import_descriptors (plus zero terminating one). IAT is this:

Code:
004050FC 0C 52 00 00 00 00 00 00 00 00 00 00 .R..........
0040510C B0 53 00 00 80 50 00 00 B0 51 00 00 00 00 00 00 .S...P...Q......
0040511C 00 00 00 00 7E 54 00 00 24 50 00 00 04 52 00 00 ....~T..$P...R..
0040512C 00 00 00 00 00 00 00 00 9C 54 00 00 78 50 00 00 .........T..xP..
0040513C 94 51 00 00 00 00 00 00 00 00 00 00 0A 55 00 00 .Q...........U..
0040514C 08 50 00 00 8C 51 00 00 00 00 00 00 00 00 00 00 .P...Q..........
0040515C 28 55 00 00 00 50 00 00 5C 52 00 00 00 00 00 00 (U...P..R......
0040516C 00 00 00 00 DE 55 00 00 D0 50 00 00 00 00 00 00 .....U...P......
0040517C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
So enter in LordPE:

Code:
RVA: 00005100
Size: 0000008B
Save changes.


Run dump, it should work perfect


Ofcourse, average crackers know this, but I think that begginers could find this text usefull. Also, this will only work if Thinstall protected app doesn&#39;t have dependencies. In such case, we should extract them from package.


See you!

Ref: http://www.reversing.be/article.php?...05110100440274[/hide]