UPX手动脱壳后的半完美修复 fly
http://www.unpack.cn/thread-37017-1-1.html
调试环境: WinXP、OnlyDBG、PEiD、LordPE、ImportREC
作者声明: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教
_____________________________________________________________
UPX这么多年来一直是最好的压缩壳之一。
UPX怎么脱壳最完美?用UPX自脱最完美。但是某些修改的UPX无法自脱,用upxfix处理了也无法自脱,那只能使用通用脱壳机或者手动来动态脱壳了。希望DiKen继续维护UPXFIX,让UPX都能完美自脱。
手动脱壳难以完美还原,我来简单说说UPX手动脱壳后的半完美修复吧,仅供参考
试炼品 ExeInfoPE.V0.0.2.3 :http://www.unpack.cn/thread-34191-1-1.html
真不明白A.S.L搞什么,一个PE侦测软件搞这么怪异干啥?exeinfope.exe的区段学PEP,运行一下物理内存和虚拟内存各用了100多M,还卡住了跑不起来。
_____________________________________________
一.EP
用OllyDbg载入,开始脱壳
[Asm] 纯文本查看 复制代码 0659195B E8 00000000 call 06591960
//ExeInfoPE.V0.0.2.3EP伪装MoleBox
06591960 60 pushad
06591961 E8 4F000000 call 065919B5
06591966 61 popad
06591967 90 nop
06591968 90 nop
06591969 90 nop
……
065919B3 EB 01 jmp short 065919B6
065919B5 C3 retn
065919B6 E9 D5F3FFFF jmp 06590D90
//跳回原来UPX的EP
[Asm] 纯文本查看 复制代码
06590D90 60 pushad
//UPX加壳的EP ★
06590D91 BE 00A05006 mov esi,650A000
06590D96 8DBE 0070EFF9 lea edi,dword ptr ds:[esi+F9EF7000]
06590D9C 57 push edi
06590D9D 89E5 mov ebp,esp
06590D9F 8D9C24 80C1FFFF lea ebx,dword ptr ss:[esp-3E80]
06590DA6 31C0 xor eax,eax
06590DA8 50 push eax
06590DA9 39DC cmp esp,ebx
06590DAB 75 FB jnz short 06590DA8
UPX脱壳大家都会,没啥说的
要细看的话可以参阅laype的闲庭信步之UPX:http://www.unpack.cn/thread-27488-1-1.html
_____________________________________________
二.输入表函数名列表
BP GetProcAddress [ESP]<10000000
设置条件断点是为了Shift+F9 中断后取消断点返回
[Asm] 纯文本查看 复制代码
065918D5 FF96 144E1906 call dword ptr ds:[esi+6194E14] ; kernel32.GetProcAddress
065918DB 09C0 or eax,eax
065918DD 74 07 je short 065918E6
065918DF 8903 mov dword ptr ds:[ebx],eax
065918E1 83C3 04 add ebx,4
065918E4 EB E1 jmp short 065918C7
//循环处理输入表
[Asm] 纯文本查看 复制代码
0013FF94 065918DB /CALL 到 GetProcAddress 来自 exeinfop.065918D5
0013FF98 7C800000 |hModule = 7C800000 (kernel32)
0013FF9C 0658E009 \ProcNameOrOrdinal = "Sleep" ★
请注意,0658E009这里可以看到函数名列表。
[Asm] 纯文本查看 复制代码
0658E009 53 6C 65 65 70 00 00 5C 01 00 00 10 3E 13 06 01 Sleep..\....>...
0658E019 6C 73 74 72 63 70 79 41 00 01 6C 73 74 72 63 6D lstrcpyA..lstrcm
0658E029 70 41 00 01 57 72 69 74 65 46 69 6C 65 00 01 57 pA..WriteFile..W
0658E039 61 69 74 46 6F 72 53 69 6E 67 6C 65 4F 62 6A 65 aitForSingleObje
0658E049 63 74 00 01 56 69 72 74 75 61 6C 51 75 65 72 79 ct..VirtualQuery
……
如果使用ImportREC发现某些函数是输出转向,可以在表里用原始的函数名来核实修复
可惜这些函数不在原来的位置,想完美修复输入表要手动挪移处理太麻烦,还是用ImportREC吧
[Asm] 纯文本查看 复制代码
0658EF0E 4E 74 51 75 65 72 79 49 6E 66 6F 72 6D 61 74 69 NtQueryInformati
0658EF1E 6F 6E 50 72 6F 63 65 73 73 00 01 4E 74 53 65 74 onProcess..NtSet
0658EF2E 49 6E 66 6F 72 6D 61 74 69 6F 6E 54 68 72 65 61 InformationThrea
0658EF3E 64 00 00 A4 01 00 00 60 3F 13 06 01 43 6F 54 61 d......`?...CoTa
发现此版使用了几个NTDLL函数,这个不是输出转向,就是用了NTDLL
_____________________________________________
三.原始PE信息
在数据窗口向下拉动滚动条,输入表函数名列表的最后我们发现了一些熟悉的信息:PE
[Asm] 纯文本查看 复制代码
0658FC39 50 45 00 00 4C 01 09 00 19 5E 42 2A 00 00 00 00 PE..L....^B*....
0658FC49 00 00 00 00 E0 00 8F 81 0B 01 02 19 00 60 11 00 .............`..
0658FC59 00 AA 05 00 00 00 00 00 84 7A 11 00 00 10 00 00 .........z......
0658FC69 00 80 11 00 00 00 40 00 00 10 00 00 00 02 00 00 ......@.........
0658FC79 04 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 ................
0658FC89 00 E0 18 06 00 04 00 00 00 00 00 00 02 00 00 00 ................
0658FC99 00 00 10 00 00 40 00 00 00 00 10 00 00 10 00 00 .....@..........
0658FCA9 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 ................
0658FCB9 00 40 13 06 78 2F 00 00 00 B0 14 06 00 26 04 00 .@..x/.......&..
0658FCC9 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0658FCD9 00 90 13 06 38 1D 01 00 00 00 00 00 00 00 00 00 ....8...........
0658FCE9 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0658FCF9 00 80 13 06 18 00 00 00 00 00 00 00 00 00 00 00 ................
0658FD09 00 00 00 00 00 00 00 00 E8 48 13 06 58 07 00 00 .........H..X...
0658FD19 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0658FD29 00 00 00 00 00 00 00 00 2E 74 65 78 74 00 00 00 .........text...
0658FD39 EC 51 11 00 00 10 00 00 00 52 11 00 00 04 00 00 .Q.......R......
0658FD49 00 00 00 00 00 00 00 00 00 00 00 00 20 00 00 60 ............ ..`
0658FD59 2E 69 74 65 78 74 00 00 0C 0D 00 00 00 70 11 00 .itext.......p..
0658FD69 00 0E 00 00 00 56 11 00 00 00 00 00 00 00 00 00 .....V..........
0658FD79 00 00 00 00 20 00 00 60 2E 64 61 74 61 00 00 00 .... ..`.data...
0658FD89 04 32 00 00 00 80 11 00 00 34 00 00 00 64 11 00 .2.......4...d..
0658FD99 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 C0 ............@...
0658FDA9 2E 62 73 73 00 00 00 00 DC 70 01 06 00 C0 11 00 .bss.....p......
0658FDB9 00 00 00 00 00 98 11 00 00 00 00 00 00 00 00 00 ................
0658FDC9 00 00 00 00 00 00 00 C0 2E 69 64 61 74 61 00 00 .........idata..
0658FDD9 78 2F 00 00 00 40 13 06 00 30 00 00 00 98 11 00 x/...@...0......
0658FDE9 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 C0 ............@...
0658FDF9 2E 74 6C 73 00 00 00 00 34 00 00 00 00 70 13 06 .tls....4....p..
0658FE09 00 00 00 00 00 C8 11 00 00 00 00 00 00 00 00 00 ................
0658FE19 00 00 00 00 00 00 00 C0 2E 72 64 61 74 61 00 00 .........rdata..
0658FE29 18 00 00 00 00 80 13 06 00 02 00 00 00 C8 11 00 ................
0658FE39 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 40 ............@..@
0658FE49 2E 72 65 6C 6F 63 00 00 38 1D 01 00 00 90 13 06 .reloc..8.......
0658FE59 00 1E 01 00 00 CA 11 00 00 00 00 00 00 00 00 00 ................
0658FE69 00 00 00 00 40 00 00 42 2E 72 73 72 63 00 00 00 ....@..B.rsrc...
0658FE79 00 26 04 00 00 B0 14 06 00 26 04 00 00 E8 12 00 .&.......&......
0658FE89 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 40 ............@..@
原来UPX还保留了这些原始的PE信息,半完美修复就依靠这些了。记得几年前是heXer发现的,感谢。
_____________________________________________
四.OEP
UPX以前版本跳OEP的特定码是POPD JMP,自V1.94开始改了一些
UPX V1.94-V3.X跳OEP特定码:618D??????6A0039C475FA83????E9
[Asm] 纯文本查看 复制代码
065918EC 8BAE 184E1906 mov ebp,dword ptr ds:[esi+6194E18]
065918F2 8DBE 00F0FFFF lea edi,dword ptr ds:[esi-1000]
065918F8 BB 00100000 mov ebx,1000
065918FD 50 push eax
065918FE 54 push esp
065918FF 6A 04 push 4
06591901 53 push ebx
06591902 57 push edi
06591903 FFD5 call ebp ; kernel32.VirtualProtect
06591905 8D87 1F020000 lea eax,dword ptr ds:[edi+21F]
0659190B 8020 7F and byte ptr ds:[eax],7F
0659190E 8060 28 7F and byte ptr ds:[eax+28],7F
06591912 58 pop eax
06591913 50 push eax
06591914 54 push esp
06591915 50 push eax
06591916 53 push ebx
06591917 57 push edi
06591918 FFD5 call ebp ; kernel32.VirtualProtect
0659191A 58 pop eax
0659191A 58 pop eax
0659191B 61 popad
//UPX V1.94-V3.X跳OEP特定码 ★
0659191C 8D4424 80 lea eax,dword ptr ss:[esp-80]
06591920 6A 00 push 0
06591922 39C4 cmp esp,eax
06591924 75 FA jnz short 06591920
06591926 83EC 80 sub esp,-80
06591929 E9 5661F8F9 jmp 00517A84
//跳OEP 飞向光明之巅 ★
[Asm] 纯文本查看 复制代码
00517A84 55 push ebp
//OEP
00517A85 8BEC mov ebp,esp
00517A87 B9 07000000 mov ecx,7
00517A8C 6A 00 push 0
00517A8E 6A 00 push 0
00517A90 49 dec ecx
00517A91 75 F9 jnz short 00517A8C
00517A93 53 push ebx
00517A94 56 push esi
00517A95 57 push edi
00517A96 B8 4C5F5100 mov eax,515F4C
00517A9B E8 C4FAEEFF call 00407564
运行PETools来dump进程,ImportREC填入OEP RVA=00117A84没有获得有效输入表,那就手动定位输入表范围吧。
在程序中随便找个输入表调用:
[Asm] 纯文本查看 复制代码
00517A9B E8 C4FAEEFF call 00407564
//F7进入
00407570 E8 2BFFFFFF call 004074A0 ; jmp 到 kernel32.GetModuleHandleA
//F7进入
004074A0 FF25 D8495306 jmp dword ptr ds:[65349D8]; kernel32.GetModuleHandleA
在数据窗口中跟随65349D8,点右键选择“长型”->“地址”的查看模式
[Asm] 纯文本查看 复制代码 向上拉滚动条找到开始处:
065348D8 00000000
065348DC 00000000
065348E0 00000000
065348E4 00000000
//上面很多00000000,IAT RVA=065348E8-00400000=061348E8 ★
065348E8 770F4880 oleaut32.SysFreeString
065348EC 771244AD oleaut32.SysReAllocStringLen
065348F0 770F4BA7 oleaut32.SysAllocStringLen
向下拉滚动条,找到IAT结束处:
0653502C 77D1EDDA USER32.SetLayeredWindowAttributes
06535030 00000000
06535034 7C92D7FE ntdll.ZwQueryInformationProcess
06535038 7C92DCAE ntdll.ZwSetInformationThread
0653503C 00000000
//下面很多00000000,IAT Size=0653503C-065348E8=754 ★
06535040 00000000
06535044 00000000
在ImportREC填入:OEP RVA=00117A84,IAT RVA=061348E8,IAT Size=754,获取到全部有效的函数
_____________________________________________
五.半完美修复
正常脱壳直接fixdump后就可以了,这样的话就不必写这篇教程了。
01.复制dump.exe为BakDumped.exe备份。在OllyDBG中复制出0658FC39-0658FE98的数据,这是第三部分所说的UPX保留的原始PE信息。用WinHex打开dump.exe,在0X100的PEsignature处写入复制的原始PE信息数据。
现在dump.exe的图标没有了,没关系,开始手动修复PE吧。
02.观察现在的区段,根据这些信息来修理。
[Asm] 纯文本查看 复制代码
①.text VituralOffset=00001000 VituralSize=001151EC RawOffset=00000400 RawSize=00115200
用WinHex删除00000400->00000FFF(00001000-00000400=0C00)的数据,顺手把0X3DB-0X3FFF的UPX遗留数据全部置00
②.itext VituralOffset=00117000 VituralSize=00000D0C RawOffset=00115600 RawSize=00000E00
用WinHex删除00115600->001163FF(00117000-00115600-0C00=0E00)的数据,
③.data VituralOffset=00118000 VituralSize=00003204 RawOffset=00116400 RawSize=00003400
用WinHex删除00116400->001165FF(00118000-00116400-0C00-0E00=0200)的数据
④.bss VituralOffset=0011C000 VituralSize=060170DC RawOffset=00119800 RawSize=00000000
用WinHex删除00119800->0011A3FF(0011C000-00119800-0C00-0E00-0200=0C00)的数据
⑤.idata VituralOffset=06134000 VituralSize=00002F78 RawOffset=00119800 RawSize=00003000
用WinHex删除00119800->061317FF(06134000-00119800-0C00-0E00-0200-0C00=06018000)的数据
⑥.tls VituralOffset=06137000 VituralSize=00000034 RawOffset=0011C800 RawSize=00000000
RawSize=00000000 且.tls和下面的.rdata区段RawOffset都=0011C800,因此这里就不必删除了
⑦.rdata VituralOffset=06138000 VituralSize=00000018 RawOffset=0011C800 RawSize=00000200
用WinHex删除0011C800->0011D7FF(06138000-0011C800-0C00-0E00-0200-0C00-06018000=1000)的数据
⑧.reloc VituralOffset=06139000 VituralSize=00011D38 RawOffset=0011CA00 RawSize=00011E00
因为加壳时去除了exeinfope.exe的重定位表,就把RawSize改为0吧,下面一起删除空数据
⑨.rsrc VituralOffset=0614B000 VituralSize=00042600 RawOffset=0012E800 RawSize=00042600
资源段还是用DT_FixRes处理一下,这个段可以删除了,用WinHex删除0011CA00->文件末尾的全部数据
dump.exe基本瘦身完毕。
03.修复资源
①.用PETools打开dump.exe,点击Sections,右键->KillSection(From Header),删除最后的.rsrc区段
②.用DT_FixRes打开之前备份的BakDumped.exe,资源段可以放在原0614B000处。Dump的NewRVA=0614B000,FileAlignment=200,获得修复的资源数据rsrc.bin
③.在PETools打开dump.exe的Sections Editor界面,点右键->Load Secton From Disk->选择rsrc.bin,新的区段RVA=0614B000,修改新区段名.NewSH为.rsrc,Characteristics=40000040
④.在PETools打开dump.exe的Directories界面里修正Resource Directory RVA=0614B000,Size=00042600
04.修正重定位信息
在PETools打开dump.exe的Directories界面里修正Base Relocation Table的RVA和Size都为0,因为没有重定位表了
05.修复输入表
①.在PETools打开dump.exe的Directories界面里看到
Import Directory RVA=06134000,Size=00002F78
Import Address Table RVA=061348E8,Size=00000758
②.如果ImportREC把输入表直接放在原来的06134000处,会覆盖掉061348E8处的IAT,如果放在061348E8+00000758后则.idata的Size不够
③.可以设置ImportREC修复输入表增加区段,可以设置ImportREC为CreatNewIAT,甚至可以对.idata扩容并改造其下的其他段。最终选择CreatNewIAT,一般还是建议找足够的空余空间存放输入表,而不要CreatNewIAT
④.ImportREC获取好输入表后还在一边等候召唤,Options->NewImport里面仅仅选择->CreatNewIAT,设置取消"Add New Section"选项,New Import Info填入RVA=06134000,FixDump
06.美中不足
就是因为输入表没有完美还原,所以只能说是:手动脱壳后的半完美修复。
_____________________________________________
六.去除检验
01.运行dumped_.exe,崩溃了
[Asm] 纯文本查看 复制代码
00517ABD C605 BE7A5100 E9 mov byte ptr ds:[517ABE],0E9
//写代码段
00517AC4 C605 877A5100 E8 mov byte ptr ds:[517A87],0E8
00517ACB 8B03 mov eax,dword ptr ds:[ebx]
修改.itext代码段属性为E0000020,增加可写属性
02.区段数经验
BP CreateFileA [ESP]<10000000 Shift+F9 中断后取消断点
[Asm] 纯文本查看 复制代码
0013FF14 00403D48 /CALL 到 CreateFileA 来自 dumped_.00403D43
0013FF18 0052F400 |FileName = "*\ExeInfoPE.V0.0.2.3\dumped_.exe"
0013FF1C 80000000 |Access = GENERIC_READ
0013FF20 00000003 |ShareMode = FILE_SHARE_READ|FILE_SHARE_WRITE
0013FF24 00000000 |pSecurity = NULL
0013FF28 00000003 |Mode = OPEN_EXISTING
0013FF2C 00000080 |Attributes = NORMAL
0013FF30 00000000 \hTemplateFile = NULL
BP ReadFile [ESP]<10000000 Shift+F9 中断后取消断点
[Asm] 纯文本查看 复制代码
0013FEF8 004036DD /CALL 到 ReadFile 来自 dumped_.004036DA
0013FEFC 000000AC |hFile = 000000AC (window)
0013FF00 06532CB8 |Buffer = dumped_.06532CB8
0013FF04 00000400 |BytesToRead = 400 (1024.)
0013FF08 0013FF1C |pBytesRead = 0013FF1C
0013FF0C 00000000 \pOverlapped = NULL
把dumped_.exe的PE头数据读取到06532CB8处
[Asm] 纯文本查看 复制代码
005021D2 803D DCF65206 00 cmp byte ptr ds:[652F6DC],0
005021D9 6A 00 push 0
005021DB BA B82C5306 mov edx,6532CB8
005021E0 B9 00040000 mov ecx,400
005021E5 B8 B8F35200 mov eax,52F3B8
005021EA E8 5115F0FF call 00403740
005021EF B8 B8F35200 mov eax,52F3B8
005021F4 E8 8715F0FF call 00403780
005021F9 FE05 50AB5100 inc byte ptr ds:[51AB50]
005021FF A1 B0F35200 mov eax,dword ptr ds:[52F3B0]
00502204 8B80 60030000 mov eax,dword ptr ds:[eax+360]
0050220A 33D2 xor edx,edx
0050220C E8 E302F5FF call 004524F4
00502211 803D BE2D5306 03 cmp byte ptr ds:[6532DBE],3
//检验区段数是否为3
00502218 75 12 jnz short 0050222C
//NOP掉
0050221A A1 B0F35200 mov eax,dword ptr ds:[52F3B0]
0050221F 8B80 60030000 mov eax,dword ptr ds:[eax+360]
00502225 B2 01 mov dl,1
00502227 E8 C802F5FF call 004524F4
0050222C B2 02 mov dl,2
0050222E 8BC3 mov eax,ebx
00502230 E8 83FDFFFF call 00501FB8
00502235 EB 07 jmp short 0050223E
A.S.L喜欢设置检验,以前的版本还有EP和区段名等检验,这个版本没有发现其他校验,脱壳版和原版一样可以在Win2000和WinXP上运行。
Game Over
_____________________________________________________________
, _/
/| _.-~/ \_ , 青春都一晌
( /~ / \~-._ |\
`\\ _/ \ ~\ ) 忍把浮名
_-~~~-.) )__/;;,. \_ //'
/'_,\ --~ \ ~~~- ,;;\___( (.-~~~-. 换了脱壳轻狂
`~ _( ,_..--\ ( ,;'' / ~-- /._`\
/~~//' /' `~\ ) /--.._, )_ `~
" `~" " `" /~'`\ `\\~~\
" " "~' ""
fly [CUG]
http://www.unpack.cn
2009.06.13 24:00 |