Hmily 发表于 2015-7-11 22:31

UPX手动脱壳后的半完美修复

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载入,开始脱壳

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


06590D90   60                  pushad
//UPX加壳的EP         ★
06590D91   BE 00A05006         mov   esi,650A000
06590D96   8DBE 0070EFF9       lea   edi,dword ptr ds:
06590D9C   57                  push    edi
06590D9D   89E5                mov   ebp,esp
06590D9F   8D9C24 80C1FFFF   lea   ebx,dword ptr ss:
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 <10000000
设置条件断点是为了Shift+F9 中断后取消断点返回


065918D5   FF96 144E1906       call    dword ptr ds: ; kernel32.GetProcAddress
065918DB   09C0                or      eax,eax
065918DD   74 07               je      short 065918E6
065918DF   8903                mov   dword ptr ds:,eax
065918E1   83C3 04             add   ebx,4
065918E4   EB E1               jmp   short 065918C7
//循环处理输入表


0013FF94   065918DB/CALL 到 GetProcAddress 来自 exeinfop.065918D5
0013FF98   7C800000|hModule = 7C800000 (kernel32)
0013FF9C   0658E009\ProcNameOrOrdinal = "Sleep"         ★

请注意,0658E009这里可以看到函数名列表。


0658E00953 6C 65 65 70 00 00 5C 01 00 00 10 3E 13 06 01Sleep..\....>...
0658E0196C 73 74 72 63 70 79 41 00 01 6C 73 74 72 63 6DlstrcpyA..lstrcm
0658E02970 41 00 01 57 72 69 74 65 46 69 6C 65 00 01 57pA..WriteFile..W
0658E03961 69 74 46 6F 72 53 69 6E 67 6C 65 4F 62 6A 65aitForSingleObje
0658E04963 74 00 01 56 69 72 74 75 61 6C 51 75 65 72 79ct..VirtualQuery
……

如果使用ImportREC发现某些函数是输出转向,可以在表里用原始的函数名来核实修复
可惜这些函数不在原来的位置,想完美修复输入表要手动挪移处理太麻烦,还是用ImportREC吧


0658EF0E4E 74 51 75 65 72 79 49 6E 66 6F 72 6D 61 74 69NtQueryInformati
0658EF1E6F 6E 50 72 6F 63 65 73 73 00 01 4E 74 53 65 74onProcess..NtSet
0658EF2E49 6E 66 6F 72 6D 61 74 69 6F 6E 54 68 72 65 61InformationThrea
0658EF3E64 00 00 A4 01 00 00 60 3F 13 06 01 43 6F 54 61d......`?...CoTa

发现此版使用了几个NTDLL函数,这个不是输出转向,就是用了NTDLL

_____________________________________________
三.原始PE信息

在数据窗口向下拉动滚动条,输入表函数名列表的最后我们发现了一些熟悉的信息:PE


0658FC3950 45 00 00 4C 01 09 00 19 5E 42 2A 00 00 00 00PE..L....^B*....
0658FC4900 00 00 00 E0 00 8F 81 0B 01 02 19 00 60 11 00.............`..
0658FC5900 AA 05 00 00 00 00 00 84 7A 11 00 00 10 00 00.........z......
0658FC6900 80 11 00 00 00 40 00 00 10 00 00 00 02 00 00......@.........
0658FC7904 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00................
0658FC8900 E0 18 06 00 04 00 00 00 00 00 00 02 00 00 00................
0658FC9900 00 10 00 00 40 00 00 00 00 10 00 00 10 00 00.....@..........
0658FCA900 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00................
0658FCB900 40 13 06 78 2F 00 00 00 B0 14 06 00 26 04 00.@..x/.......&..
0658FCC900 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00................
0658FCD900 90 13 06 38 1D 01 00 00 00 00 00 00 00 00 00....8...........
0658FCE900 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00................
0658FCF900 80 13 06 18 00 00 00 00 00 00 00 00 00 00 00................
0658FD0900 00 00 00 00 00 00 00 E8 48 13 06 58 07 00 00.........H..X...
0658FD1900 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00................
0658FD2900 00 00 00 00 00 00 00 2E 74 65 78 74 00 00 00.........text...
0658FD39EC 51 11 00 00 10 00 00 00 52 11 00 00 04 00 00.Q.......R......
0658FD4900 00 00 00 00 00 00 00 00 00 00 00 20 00 00 60............ ..`
0658FD592E 69 74 65 78 74 00 00 0C 0D 00 00 00 70 11 00.itext.......p..
0658FD6900 0E 00 00 00 56 11 00 00 00 00 00 00 00 00 00.....V..........
0658FD7900 00 00 00 20 00 00 60 2E 64 61 74 61 00 00 00.... ..`.data...
0658FD8904 32 00 00 00 80 11 00 00 34 00 00 00 64 11 00.2.......4...d..
0658FD9900 00 00 00 00 00 00 00 00 00 00 00 40 00 00 C0............@...
0658FDA92E 62 73 73 00 00 00 00 DC 70 01 06 00 C0 11 00.bss.....p......
0658FDB900 00 00 00 00 98 11 00 00 00 00 00 00 00 00 00................
0658FDC900 00 00 00 00 00 00 C0 2E 69 64 61 74 61 00 00.........idata..
0658FDD978 2F 00 00 00 40 13 06 00 30 00 00 00 98 11 00x/...@...0......
0658FDE900 00 00 00 00 00 00 00 00 00 00 00 40 00 00 C0............@...
0658FDF92E 74 6C 73 00 00 00 00 34 00 00 00 00 70 13 06.tls....4....p..
0658FE0900 00 00 00 00 C8 11 00 00 00 00 00 00 00 00 00................
0658FE1900 00 00 00 00 00 00 C0 2E 72 64 61 74 61 00 00.........rdata..
0658FE2918 00 00 00 00 80 13 06 00 02 00 00 00 C8 11 00................
0658FE3900 00 00 00 00 00 00 00 00 00 00 00 40 00 00 40............@..@
0658FE492E 72 65 6C 6F 63 00 00 38 1D 01 00 00 90 13 06.reloc..8.......
0658FE5900 1E 01 00 00 CA 11 00 00 00 00 00 00 00 00 00................
0658FE6900 00 00 00 40 00 00 42 2E 72 73 72 63 00 00 00....@..B.rsrc...
0658FE7900 26 04 00 00 B0 14 06 00 26 04 00 00 E8 12 00.&.......&......
0658FE8900 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


065918EC   8BAE 184E1906       mov   ebp,dword ptr ds:
065918F2   8DBE 00F0FFFF       lea   edi,dword ptr ds:
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:
0659190B   8020 7F             and   byte ptr ds:,7F
0659190E   8060 28 7F          and   byte ptr ds:,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:
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 飞向光明之巅         ★


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没有获得有效输入表,那就手动定位输入表范围吧。
在程序中随便找个输入表调用:


00517A9B   E8 C4FAEEFF         call    00407564
//F7进入
00407570   E8 2BFFFFFF         call    004074A0 ; jmp 到 kernel32.GetModuleHandleA
//F7进入
004074A0   FF25 D8495306       jmp   dword ptr ds:; kernel32.GetModuleHandleA


在数据窗口中跟随65349D8,点右键选择“长型”->“地址”的查看模式

向上拉滚动条找到开始处:
065348D800000000
065348DC00000000
065348E000000000
065348E400000000
//上面很多00000000,IAT RVA=065348E8-00400000=061348E8         ★
065348E8770F4880oleaut32.SysFreeString
065348EC771244ADoleaut32.SysReAllocStringLen
065348F0770F4BA7oleaut32.SysAllocStringLen

向下拉滚动条,找到IAT结束处:
0653502C77D1EDDAUSER32.SetLayeredWindowAttributes
0653503000000000
065350347C92D7FEntdll.ZwQueryInformationProcess
065350387C92DCAEntdll.ZwSetInformationThread
0653503C00000000
//下面很多00000000,IAT Size=0653503C-065348E8=754         ★
0653504000000000
0653504400000000

在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.观察现在的区段,根据这些信息来修理。




①.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,崩溃了


00517ABD   C605 BE7A5100 E9    mov   byte ptr ds:,0E9
//写代码段
00517AC4   C605 877A5100 E8    mov   byte ptr ds:,0E8
00517ACB   8B03                mov   eax,dword ptr ds:

修改.itext代码段属性为E0000020,增加可写属性

02.区段数经验
BP CreateFileA <10000000Shift+F9 中断后取消断点


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 <10000000Shift+F9 中断后取消断点


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处


005021D2    803D DCF65206 00       cmp   byte ptr ds:,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:
005021FF    A1 B0F35200            mov   eax,dword ptr ds:
00502204    8B80 60030000          mov   eax,dword ptr ds:
0050220A    33D2                   xor   edx,edx
0050220C    E8 E302F5FF            call    004524F4
00502211    803D BE2D5306 03       cmp   byte ptr ds:,3
//检验区段数是否为3
00502218    75 12                  jnz   short 0050222C
//NOP掉
0050221A    A1 B0F35200            mov   eax,dword ptr ds:
0050221F    8B80 60030000          mov   eax,dword ptr ds:
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
             http://www.unpack.cn
               2009.06.13 24:00

吾爱T阿杰 发表于 2015-7-11 22:33

本帖最后由 吾爱T阿杰 于 2015-7-11 22:35 编辑

我相信我能看懂,,,然而并不是,,,
                                                                  沙发
出售瓜子花生,茶水饮料

pnccm 发表于 2015-7-14 09:51

老大你发这个对于菜鸟的我们。看图文教程我们完全无法理解。这样的教程虽然在你眼里是小菜一碟,但对于我们来说完全是天书啊。最好自己弄个视频讲解下。但还是觉得对于新手来说。你会不会觉得这样的内容会不会太深奥了。

曾经流过的泪 发表于 2015-7-11 22:39

好长啊,,有点压力。。

LzG 发表于 2015-7-11 22:42

火钳留名!

ollydebug 发表于 2015-7-11 22:48

感谢分享

junmx 发表于 2015-7-11 23:01

谢谢lz的无私奉献

topcookie 发表于 2015-7-11 23:10

曾经感觉最简单的UPX成长以后又一次深深打击了偶这个菜鸟,有点看天书的感觉

wanmei 发表于 2015-7-11 23:16

楼上08年的大神   

smile1110 发表于 2015-7-11 23:29

能不能截图呢,看文字不太习惯

sai沈 发表于 2015-7-12 00:26

大神发帖,一定要学习!
页: [1] 2 3 4
查看完整版本: UPX手动脱壳后的半完美修复