《Windows PE》17.3 FSG壳
回顾第十六章PE病毒的16.2.2病毒分析案例一中,我们分析的病毒样本Lab01-03.exe使用了FSG壳。本节我们就来详细分析FSG壳。
本节必须掌握的知识点:
静态分析
手工脱壳
17.3.1 静态分析
■FSG壳的特点
FSG壳是一种经典的加壳工具,主要用于对可执行文件进行压缩和加密处理。下面是FSG壳的一些特点和工作原理:
●压缩功能:FSG壳使用定制的高效压缩算法对可执行文件进行压缩,从而减小文件大小。压缩后的文件会包含解压缩代码和数据,以便在运行时还原原始的可执行文件。
●加密保护:除了压缩,FSG壳还会对可执行文件进行加密处理,以增强文件的安全性。加密可以防止未经授权的访问和修改,保护程序的知识产权和机密性。
●运行时解压缩:在程序运行时,FSG壳会先解密和解压缩原始的可执行文件,然后将其加载到内存中执行。这种运行时解压缩的方式有助于保护程序的代码和数据不被恶意篡改或窥探。
●反调试和反分析:FSG壳通常包含反调试和反分析技术,用于防止调试器和逆向工程工具的使用。这些技术可以增加对程序的保护,使其更难以被破解和篡改。
●资源优化:通过压缩和加密处理,FSG壳可以帮助优化程序的资源占用和加载速度,提高程序的运行效率和用户体验。
实验一百一十五:FSG壳静态分析
让我们使用WinHex工具对FSG壳做静态分析,对比加壳前后的变化。
■静态分析
分析环境:VMWare16.2.1,Windows XP系统。
分析样本:
原程序HelloWorld.exe;
加壳程序HelloWorld_fsg.exe;
脱壳程序HelloWorld_unfsg.exe;
【注】样本程序不支持Windows 64位系统。
●加壳前
将原程序HelloWorld.exe拖入WinHex,PE头信息如下:
000000B0 50 45 00 00 4C 01 03 00 8C 10 A7 60 00 00 00 00 PE..L...?....
000000C0 00 00 00 00 E0 00 0F 01 0B 01 05 0C 00 02 00 00 ....?..........
000000D0 00 04 00 00 00 00 00 00 00 10 00 00 00 10 00 00 ................
000000E0 00 20 00 00 00 00 40 00 00 10 00 00 00 02 00 00 . ....@.........
000000F0 04 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 ................
00000100 00 40 00 00 00 04 00 00 00 00 00 00 02 00 00 00 .@..............
00000110 00 00 10 00 00 10 00 00 00 00 10 00 00 10 00 00 ................
00000120 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 ................
00000130 10 20 00 00 3C 00 00 00 00 00 00 00 00 00 00 00 . ..<...........
00000140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000150 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000170 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000180 00 00 00 00 00 00 00 00 00 20 00 00 10 00 00 00 ......... ......
00000190 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000001A0 00 00 00 00 00 00 00 00 2E 74 65 78 74 00 00 00 .........text...
000001B0 24 00 00 00 00 10 00 00 00 02 00 00 00 04 00 00 $...............
000001C0 00 00 00 00 00 00 00 00 00 00 00 00 20 00 00 60 ............ ..`
000001D0 2E 72 64 61 74 61 00 00 92 00 00 00 00 20 00 00 .rdata..?... ..
000001E0 00 02 00 00 00 06 00 00 00 00 00 00 00 00 00 00 ................
000001F0 00 00 00 00 40 00 00 40 2E 64 61 74 61 00 00 00 ....@..@.data...
00000200 0D 00 00 00 00 30 00 00 00 02 00 00 00 08 00 00 .....0..........
00000210 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 C0 ............@..
1.NumberOfSections:节区数3;
2.AddressOfEntryPoint:程序入口地址0x1000;
3.BaseOfCode:代码节起始地址0x1000;
4.BaseOfData:数据节起始地址0x2000;
5.ImageBase:程序建议装载基址0x4000;
6.SectionAlignment:内存对齐颗粒度0x1000;
7.FileAlignment:文件对齐颗粒度0x200;
8.SizeOflmage:映像文件大小0x4000;
9.导入表RAV地址:0x2010;
10.函数地址表RVA地址:0x2000;
11.3个节区:
.text
00000400 6A 00 6A 00 68 00 30 40 00 6A 00 E8 08 00 00 00 j.j.h.0@.j.?...
00000410 6A 00 E8 07 00 00 00 CC FF 25 08 20 40 00 FF 25 j.?...?%. @.%
00000420 00 20 40 00 00 00 00 00 00 00 00 00 00 00 00 00 . @.............
.rdata
00000600 76 20 00 00 00 00 00 00 5C 20 00 00 00 00 00 00 v ......\ ......
00000610 54 20 00 00 00 00 00 00 00 00 00 00 6A 20 00 00 T ..........j ..
00000620 08 20 00 00 4C 20 00 00 00 00 00 00 00 00 00 00 . ..L ..........
00000630 84 20 00 00 00 20 00 00 00 00 00 00 00 00 00 00 ?... ..........
00000640 00 00 00 00 00 00 00 00 00 00 00 00 76 20 00 00 ............v ..
00000650 00 00 00 00 5C 20 00 00 00 00 00 00 B1 01 4D 65 ....\ ......?Me
00000660 73 73 61 67 65 42 6F 78 41 00 75 73 65 72 33 32 ssageBoxA.user32
00000670 2E 64 6C 6C 00 00 9B 00 45 78 69 74 50 72 6F 63 .dll..?ExitProc
00000680 65 73 73 00 6B 65 72 6E 65 6C 33 32 2E 64 6C 6C ess.kernel32.dll
.data;
00000800 48 65 6C 6C 6F 57 6F 72 6C 64 50 45 00 00 00 00 HelloWorldPE....
●加壳后
将加壳程序HelloWorld_fsg.exe拖入WinHex,PE头信息如下:
00000000 4D 5A 00 00 00 00 00 00 00 00 00 00 50 45 00 00 MZ..........PE..
00000010 4C 01 02 00 46 53 47 21 00 00 00 00 00 00 00 00 L...FSG!........
00000020 E0 00 0F 01 0B 01 00 00 00 02 00 00 00 04 00 00 ?..............
00000030 00 00 00 00 54 01 00 00 00 10 00 00 0C 00 00 00 ....T...........
00000040 00 00 40 00 00 10 00 00 00 02 00 00 04 00 00 00 ..@.............
00000050 00 00 00 00 04 00 00 00 00 00 00 00 00 60 00 00 .............`..
00000060 00 02 00 00 00 00 00 00 02 00 00 00 00 00 10 00 ................
00000070 00 10 00 00 00 00 10 00 00 10 00 00 00 00 00 00 ................
00000080 10 00 00 00 00 00 00 00 00 00 00 00 7C 50 00 00 ............|P..
00000090 84 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ?..............
000000A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000100 00 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 .............@..
00000110 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000120 00 00 00 00 00 00 00 00 E0 00 00 C0 00 00 00 00 ........?.?...
00000130 00 00 00 00 00 10 00 00 00 50 00 00 FD 00 00 00 .........P..?..
00000140 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000150 E0 00 00 C0 ?.
1.NumberOfSections:节区数2;
2.AddressOfEntryPoint:程序入口地址0x154;
3.BaseOfCode:代码节起始地址0x1000;
4.BaseOfData:数据节起始地址0x0C;
5.ImageBase:程序建议装载基址0x40000;
6.SectionAlignment:内存对齐颗粒度0x1000;
7.FileAlignment:文件对齐颗粒度0x200;
8.SizeOflmage:映像文件大小0x6000;
9.导入表RAV地址:0x507C;
10.函数地址表RVA地址:无;
11.2个节区
第一个节区:节区名(无),节区大小0x4000,内存RVA地址0x1000,文件对齐后大小0,文件起始地址0,节区属性0xC00000E0;
程序的入口地址0x154位于第一个节区,因此可以判断此节区为代码段。如下所示:
00000150 87 25 C0 50 40 00 61 94 55 A4 B6 80 ?繮@.a擴ざ€
00000160 FF 13 73 F9 33 C9 FF 13 73 16 33 C0 FF 13 73 1F .s??.s.3?.s.
00000170 B6 80 41 B0 10 FF 13 12 C0 73 FA 75 3A AA EB E0 秬A?..纒鷘:?
00000180 FF 53 08 02 F6 83 D9 01 75 0E FF 53 04 EB 24 AC S..鰞?u.S.??
00000190 D1 E8 74 2D 13 C9 EB 18 91 48 C1 E0 08 AC FF 53 谚t-.呻.慔拎.?S
000001A0 04 3B 43 F8 73 0A 80 FC 05 73 06 83 F8 7F 77 02 .;C鴖.€?s.凐w.
000001B0 41 41 95 8B C5 B6 00 56 8B F7 2B F0 F3 A4 5E EB AA晪哦.V嬿+痼?
000001C0 9F 5E AD 97 AD 50 FF 53 10 95 8B 07 40 78 F3 75 焇瓧璓S.晪.@x髐
000001D0 03 FF 63 0C 50 55 FF 53 14 AB EB EE 33 C9 41 FF .c.PUS.?葾
000001E0 13 13 C9 FF 13 72 F8 C3 02 D2 75 05 8A 16 46 12 ..?.r.襲.?F.
000001F0 D2 C3 4B 45 52 4E 45 4C 33 32 2E 64 6C 6C 00 00 颐KERNEL32.dll..
第二个节区:节区名(无),节区大小0x1000,内存RVA地址0x5000,文件对齐后大小0xFD,文件起始地址0x200,节区属性0xC00000E0;
导入表RVA地址0x507C,位于第二个节区,偏移0x7C,因此导入表在文件内的地址0x27C:
00000270 D4 50 00 00 訮..
00000280 00 00 00 00 00 00 00 00 F2 01 00 00 D4 50 00 00 ........?..訮..
00000290 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000002A0 00 00 00 00 00 10 40 00 00 50 40 00 10 20 40 00 ......@..P@.. @.
000002B0 00 00 00 00 C4 50 40 00 80 00 00 00 00 7D 00 00 ....腜@.€....}..
000002C0 A4 50 40 00 E8 01 40 00 DC 01 40 00 DE 01 40 00 @.?@.?@.?@.
000002D0 00 10 40 00 DE 50 00 00 EC 50 00 00 00 00 00 00 ..@.轕..霵......
000002E0 4C 6F 61 64 4C 69 62 72 61 72 79 41 00 00 47 65 LoadLibraryA..Ge
000002F0 74 50 72 6F 63 41 64 64 72 65 73 73 00 tProcAddress.
第二个节区0x200~0x27B之间的数据,暂时不太清楚是什么?
00000200 6A E1 9C 04 68 0C 30 40 0F E8 70 08 E1 08 07 88 j釡.h.0@.鑠.?.?
00000210 CC FF 7E 25 6D 20 2A 0C C2 28 01 FF DF 71 77 2E ?~%m *.?.遯w.
00000220 59 E6 03 5D 48 08 7F 44 08 6A DC 09 22 4B 84 98 Y?]H.D.j?"K剺
00000230 FC 4C F9 5B 5E E0 4D 65 73 E2 61 75 67 0E 42 6F 麹鵞^郙es鈇ug.Bo
00000240 78 41 0F 75 7F 40 72 33 32 2E 64 6C E3 40 1A 45 xA.u@r32.dl鉆.E
00000250 78 69 06 74 50 72 6F 63 43 E0 6B CF 32 6E 0A 6C xi.tProcC鄈?n.l
00000260 1C 52 3F 01 7D DC 1C 48 65 6C 4E 6F 57 4E 72 C3 .R?.}?HelNoWNr?
00000270 64 50 45 84 7F FE BD 80 00 00 00 00 dPE?€....
【注意】在加壳程序的0x14地址处有FSG壳标志字符串“FSG!”。
●脱壳后
使用FSG脱壳工具Unpacker对加壳程序HelloWorld_fsg.exe进行脱壳处理。
图17-2 FSG脱壳
然后将脱壳后的程序HelloWorld_unfsg.exe拖入WinHex,PE头信息如下:
00000000 4D 5A 00 00 00 00 00 00 00 00 00 00 50 45 00 00 MZ..........PE..
00000010 4C 01 03 00 46 53 47 21 00 00 00 00 00 00 00 00 L...FSG!........
00000020 E0 00 0F 01 0B 01 00 00 00 02 00 00 00 04 00 00 ?..............
00000030 00 00 00 00 00 10 00 00 00 10 00 00 0C 00 00 00 ................
00000040 00 00 40 00 00 10 00 00 00 10 00 00 04 00 00 00 ..@.............
00000050 00 00 00 00 04 00 00 00 00 00 00 00 00 70 00 00 .............p..
00000060 00 02 00 00 00 00 00 00 02 00 00 00 00 00 10 00 ................
00000070 00 10 00 00 00 00 10 00 00 10 00 00 00 00 00 00 ................
00000080 10 00 00 00 00 00 00 00 00 00 00 00 00 60 00 00 .............`..
00000090 84 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ?..............
000000A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000100 00 00 00 00 2E 52 49 46 31 00 00 00 00 40 00 00 .....RIF1....@..
00000110 00 10 00 00 00 40 00 00 00 10 00 00 00 00 00 00 .....@..........
00000120 00 00 00 00 00 00 00 00 E0 00 00 C0 2E 52 49 46 ........?.?RIF
00000130 32 00 00 00 00 10 00 00 00 50 00 00 00 10 00 00 2........P......
00000140 00 50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 .P..............
00000150 E0 00 00 C0 2E 52 49 46 00 00 61 94 00 10 00 00 ?.?RIF..a?...
00000160 00 60 00 00 00 10 00 00 00 60 00 00 FF 13 73 1F .`.......`...s.
00000170 B6 80 41 B0 10 FF 13 12 20 00 00 E0 秬A?.. ..?
对比脱壳前的变化:
- 节区数量变为3个;
- 程序入口地址变为0x1000;
- 映像文件大小变为:0x7000;
- 导入表RVA地址变为:0x6000;
5.3个节区分别为:
RIF1:节区大小0x4000,内存RVA地址0x1000,文件对齐大小0x4000,文件起始地址0x1000,节区属性0xC00000E0。
00001000 6A 00 6A 00 68 00 30 40 00 6A 00 E8 08 00 00 00 j.j.h.0@.j.?...
00001010 6A 00 E8 07 00 00 00 CC FF 25 08 20 40 00 FF 25 j.?...?%. @.%
00001020 00 20 40 00 00 00 00 00 00 00 00 00 00 00 00 00 . @.............
【注】对应原程序HelloWorld.exe的.text节区。
00002000 76 20 00 00 00 00 00 00 5C 20 00 00 00 00 00 00 v ......\ ......
00002010 08 20 40 00 6A 20 40 00 00 20 40 00 84 20 40 00 . @.j @.. @.?@.
00002020 00 00 00 00 4C 20 00 00 00 00 00 00 00 00 00 00 ....L ..........
00002030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00002040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00002050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 4D 65 ..............Me
00002060 73 73 61 67 65 42 6F 78 41 00 75 73 65 72 33 32 ssageBoxA.user32
00002070 2E 64 6C 6C 00 00 00 00 45 78 69 74 50 72 6F 63 .dll....ExitProc
00002080 65 73 73 00 6B 65 72 6E 65 6C 33 32 2E 64 6C 6C ess.kernel32.dll
【注】对应原程序HelloWorld.exe的.rdata节区。
00003000 48 65 6C 6C 6F 57 6F 72 6C 64 50 45 00 00 00 00 HelloWorldPE....
【注】对应原程序HelloWorld.exe的.data节区。
RIF2:节区大小0x1000,内存RVA地址0x5000,文件对齐大小0x1000,文件起始地址0x5000,节区属性0xC00000E0。
00005000 6A E1 9C 04 68 0C 30 40 0F E8 70 08 E1 08 07 88 j釡.h.0@.鑠.?.?
00005010 CC FF 7E 25 6D 20 2A 0C C2 28 01 FF DF 71 77 2E ?~%m *.?.遯w.
00005020 59 E6 03 5D 48 08 7F 44 08 6A DC 09 22 4B 84 98 Y?]H..D.j?"K剺
00005030 FC 4C F9 5B 5E E0 4D 65 73 E2 61 75 67 0E 42 6F 麹鵞^郙es鈇ug.Bo
00005040 78 41 0F 75 7F 40 72 33 32 2E 64 6C E3 40 1A 45 xA.u.@r32.dl鉆.E
00005050 78 69 06 74 50 72 6F 63 43 E0 6B CF 32 6E 0A 6C xi.tProcC鄈?n.l
00005060 1C 52 3F 01 7D DC 1C 48 65 6C 4E 6F 57 4E 72 C3 .R?.}?HelNoWNr?
00005070 64 50 45 84 7F FE BD 80 00 00 00 00 D4 50 00 00 dPE?€....訮..
00005080 00 00 00 00 00 00 00 00 F2 01 00 00 D4 50 00 00 ........?..訮..
00005090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000050A0 00 00 00 00 00 10 40 00 00 50 40 00 10 20 40 00 ......@..P@.. @.
000050B0 00 00 00 00 C4 50 40 00 80 00 00 00 00 7D 00 00 ....腜@.€....}..
000050C0 C4 FF 13 00 E8 01 40 00 DC 01 40 00 DE 01 40 00 ?..?@.?@.?@.
000050D0 00 10 40 00 7B 1D 80 7C 40 AE 80 7C 00 00 00 00 ..@.{.€|@畝|....
000050E0 4C 6F 61 64 4C 69 62 72 61 72 79 41 00 00 47 65 LoadLibraryA..Ge
000050F0 74 50 72 6F 63 41 64 64 72 65 73 73 00 00 00 00 tProcAddress....
【注】对应加壳程序HelloWorld_fsg.exe的第二个节区,包含导入表。
RIF:节区大小0x1000,内存RVA地址0x6000,文件对齐大小0x1000,文件起始地址0x6000,节区属性0xC0000020。
00006000 08 20 00 00 00 00 00 00 00 00 00 00 6A 20 00 00 . ..........j ..
00006010 08 20 00 00 00 20 00 00 00 00 00 00 00 00 00 00 . ... ..........
00006020 84 20 00 00 00 20 00 00 00 00 00 00 00 00 00 00 ?... ..........
【注】对应原程序HelloWorld.exe的函数地址表。
总结
通过对原程序、加壳程序和脱壳程序的静态分析,我们可以得出以下结论:
●加壳过程:
1.NumberOfSections:节区数2;——修改了节区数量。
2.AddressOfEntryPoint:程序入口地址0x154;——修改了程序入口地址,从壳代码开始执行。
3.BaseOfCode:代码节起始地址0x1000;——未改变。
4.BaseOfData:数据节起始地址0x0C;——修改了数据节起始地址,对PE头进行了压缩,这也造成了Windows 64位系统下无法执行。
5.ImageBase:程序建议装载基址0x40000;——未改变。
6.SectionAlignment:内存对齐颗粒度0x1000;——未改变。
7.FileAlignment:文件对齐颗粒度0x200;——未改变。
8.SizeOflmage:映像文件大小0x6000;——由0x4000改为0x6000。
9.导入表RAV地址:0x507C;——导入表RVA地址由0x2010改为0x507C。
10.函数地址表RVA地址:无;——函数地址表RAV地址有0x2000改为0。
11.2个节区
第一个节区:节区名(无),节区大小0x4000,内存RVA地址0x1000,文件对齐后大小0,文件起始地址0,节区属性0xC00000E0;
程序的入口地址0x154位于第一个节区,因此可以判断此节区为代码段。
第二个节区:节区名(无),节区大小0x1000,内存RVA地址0x5000,文件对齐后大小0xFD,文件起始地址0x200,节区属性0xC00000E0;
导入表RVA地址0x507C,位于第二个节区,偏移0x7C,因此导入表在文件内的地址0x27C。
第二个节区0x200~0x27B之间的数据,暂时不太清楚是什么?
详见下面的手工脱壳讲解。
●脱壳过程:
对比脱壳前的变化:
- 节区数量变为3个;——用户还原原程序的3个节区。
- 程序入口地址变为0x1000;——修改为原程序的入口地址。
- 映像文件大小变为:0x7000;——增加两个节区,分别保存导入表和函数地址表。
- 导入表RVA地址变为:0x6000;——导入表单独解析,存入RIF2节区。
5.3个节区分别为:
RIF1:节区大小0x4000,内存RVA地址0x1000,文件对齐大小0x4000,文件起始地址0x1000,节区属性0xC00000E0。
【注】存储原程序HelloWorld.exe的.text节区。
【注】存储原程序HelloWorld.exe的.rdata节区。
【注】存储原程序HelloWorld.exe的.data节区。
RIF2:节区大小0x1000,内存RVA地址0x5000,文件对齐大小0x1000,文件起始地址0x5000,节区属性0xC00000E0。
【注】存储加壳程序HelloWorld_fsg.exe的第二个节区,包含导入表。
RIF:节区大小0x1000,内存RVA地址0x6000,文件对齐大小0x1000,文件起始地址0x6000,节区属性0xC0000020。
【注】存储原程序HelloWorld.exe的函数地址表。
17.3.2 手工脱壳
不同的壳程序通常都会有一个对应的脱壳工具。但是多数情况下,必须进行手动脱壳。手动脱壳有时候很快,且不费精力。有时候却是一件费事且艰巨的过程。
■手动脱壳方法
手动脱壳程序的方法有两种:
●找到加壳的算法,然后编写一个程序逆向运行它。通过逆向运行这个算法,这个程序可以解开加壳程序的每一步操作。虽然有一些自动化的工具可以完成这些工作,但是这种方法效率很低,因为编写的脱壳程序仅针对单个的加壳程序。所以,即使辅以自动化,这个过程依然需要大量的时间来完成。
●运行脱壳程序,让脱壳存根帮你工作,让它从内存中转储出进程,然后你再手动修正PE头部,保持程序的完整。这是一种非常有效的方法。
接下来我们使用第二种方法解析下面的两个加壳程序。
实验一百一十六:FSG壳动态分析
让我们借助OllyDbg调试器调试跟踪加壳程序HelloWorld_fsg.exe,找到程序的OEP原程序入口地址。
■调试跟踪加壳程序HelloWorld_fsg.exe
将加壳程序HelloWorld_fsg.exe拖入OllyDbg调试器。从入口地址0x00400154开始按F8单步执行(期间可以使用F4跟随断点跳过循环,加快调试进程),直到跟踪到0x004001D1地址处,如下图所示:
图17-3 单步跟踪加壳程序到关键跳转语句
在0x004001D1地址处,按F8单步执行,跳转到原程序入口地址0x00401000。如图17-4所示。点击鼠标右键“分析”->“分析代码”就可以正确显示反汇编代码了。
此时,打开内存映像窗口,可以看到,加壳程序除了PE头之外,包含两个节区。第一个节区为代码段,第二个节区为输入表。双击代码段节区,数据窗口显示原程序的代码段。
此时,再双击第二个节区,打开数据窗口,如图17-5所示。和之前我们静态分析PE文件中第二个节区数据没有任何变化。说明这里的数据是只读数据,应该是在加壳时需要用到的额外数据。
图17-4 跳转到原程序入口地址
图17-5 查看加壳程序第二个节区数据
总结
如果需要动态调试加壳程序,关键是找到跳转原程序入口地址的JMP指令,剩下的事情和调试未加壳程序是一样的。动态调试的过程和静态分析是相互印证的过程。
此外,FSG加壳程序的PE头都会带有FSG壳的标识字符串“FSG!”,可以作为判断依据。
■手工脱壳
实验一百一十七:HelloWorld_fsg.exe手工脱壳
让我们借助OllyDbg调试器、LordPE、ImpotREC工具实现加壳程序HelloWorld_fsg.exe手工脱壳。
●HelloWorld_fsg.exe
第一步:使用OllyDbg调试器单步跟踪,跳转到原程序的入口地址(OEP)。
图17-6 跳转程序入口地址
第二步:使用OllyDbg插件OllyDump进行程序的脱壳操作。点击鼠标右键“用OllyDump脱壳调试进程”,弹出如下对话框窗口。
图17-7 dump脱壳程序
注意检查“起始地址”、“入口点地址”是否正确,不要勾选“重建输入表”选项,等待稍后修复输入表。点击“脱壳”选项,保存为OllyDump_HelloWorld.exe。
还可以使用LordPE工具dump脱壳文件。打开LordPE,选择当前正在调试的进程HelloWorld_fsg.exe,如下图所示:
图17-8 使用LordPE dump脱壳文件
点击鼠标右键“完全脱壳”,保存脱壳文件为dumped_HelloWorld.exe。使用LordPE工具dump下来的脱壳文件和使用OllyDump插件几乎完全一样。
第三步:修复输入表。如果使用纯手工修复是可以的。但是如果导入函数很多,可以借助于ImportREC工具修复导入表和IAT表。
打开ImportREC工具,附加当前调试的加壳程序HelloWorld_fsg.exe,如图17-9所示。
输入程序的OEP入口RVA地址00001000,然后点击自动查找,发现提示“在此OEP没有找到任何有用的信息!”。如果没有找到IAT信息,则要手动填入IAT的RVA和大小。
图17-9 自动查找IAT
使用WinHex打开dump文件OllyDump_HelloWorld.exe,我们会发现在文件偏移00002000H地址处有导入表和IAT表信息,如下所示:
00002000 A2 BF 81 7C FF FF FF FF EA 07 D5 77 FF FF FF 7F ⒖亅?誻
00002010 08 20 40 00 6A 20 40 00 00 20 40 00 84 20 40 00 . @.j @.. @.?@.
00002020 00 00 00 00 4C 20 00 00 00 00 00 00 00 00 00 00 ....L ..........
00002030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00002040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00002050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 4D 65 ..............Me
00002060 73 73 61 67 65 42 6F 78 41 00 75 73 65 72 33 32 ssageBoxA.user32
00002070 2E 64 6C 6C 00 00 00 00 45 78 69 74 50 72 6F 63 .dll....ExitProc
00002080 65 73 73 00 6B 65 72 6E 65 6C 33 32 2E 64 6C 6C ess.kernel32.dll
00002090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
此时,查看调试器中的内存窗口地址0x00402000,如下图所示:
图17-10 查看OllyDbg调试器IAT表
内存地址0x00402000处存储的就是内存中的IAT表。我们据此修复PE文件内的IAT表就可以了。
因此,我们将OEP下方的“RVA”栏填写为:00002000,“大小”栏填写00001000。然后点击获取输入表。
图17-11 获取输入表
查看左侧窗口显示的导入函数,其中有些是无效的,点击“显示无效的”按钮,筛选出无效的导入函数,如图所示:
图17-12 筛选无效导入函数
然后在输入表函数栏点击鼠标右键“剪切指针”,删除无效导入函数。如下图所示:
图17-13 删除无效函数
最后点击左侧按钮“修复转储文件”,选择需要转存的dump文件,保存修复后的文件unpack_HelloWorld.exe。
第四步:运行修复后的文件,成功!对比修复后的变化。
将修复之后保存的文件unpack_HelloWorld.exe拖入WinHex:
节区二:
00002000 4A 60 00 00 00 00 00 00 64 60 00 00 00 00 00 00 J`......d`......
00002010 08 20 40 00 6A 20 40 00 00 20 40 00 84 20 40 00 . @.j @.. @.?@.
00002020 00 00 00 00 4C 20 00 00 00 00 00 00 00 00 00 00 ....L ..........
00002030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00002040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00002050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 4D 65 ..............Me
00002060 73 73 61 67 65 42 6F 78 41 00 75 73 65 72 33 32 ssageBoxA.user32
00002070 2E 64 6C 6C 00 00 00 00 45 78 69 74 50 72 6F 63 .dll....ExitProc
00002080 65 73 73 00 6B 65 72 6E 65 6C 33 32 2E 64 6C 6C ess.kernel32.dll
4A 60 00 00 00 00 00 00 64 60 00 00 00 00 00 00为修复后的IAT表,对应节区三种中的函数导入表。
节区三:
00006000 00 00 00 00 00 00 00 00 00 00 00 00 3C 60 00 00 ............<`..
00006010 00 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . ..............
00006020 58 60 00 00 08 20 00 00 00 00 00 00 00 00 00 00 X`... ..........
00006030 00 00 00 00 00 00 00 00 00 00 00 00 6B 65 72 6E ............kern
00006040 65 6C 33 32 2E 64 6C 6C 00 00 B7 00 45 78 69 74 el32.dll..?Exit
00006050 50 72 6F 63 65 73 73 00 75 73 65 72 33 32 2E 64 Process.user32.d
00006060 6C 6C 00 00 DD 01 4D 65 73 73 61 67 65 42 6F 78 ll..?MessageBox
00006070 41 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 A...............
将unpack_HelloWorld.exe拖入OllyDbg,查看内存窗口:
00402000 >E0 3B 60 77 00 00 00 00 B0 FD 7B 77 00 00 00 00 ?`w....褒{w....
00402010 08 20 40 00 6A 20 40 00 00 20 40 00 84 20 40 00 @.j @.. @.?@.
00402020 00 00 00 00 4C 20 00 00 00 00 00 00 00 00 00 00 ....L ..........
00402030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00402040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00402050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 4D 65 ..............Me
00402060 73 73 61 67 65 42 6F 78 41 00 75 73 65 72 33 32 ssageBoxA.user32
00402070 2E 64 6C 6C 00 00 00 00 45 78 69 74 50 72 6F 63 .dll....ExitProc
00402080 65 73 73 00 6B 65 72 6E 65 6C 33 32 2E 64 6C 6C ess.kernel32.dll
IAT表已修复完成,可以正常运行。
实验一百一十八:Lab1-03.exe手工脱壳
让我们借助OllyDbg调试器、ImpotREC工具实现加壳程序Lab1-03.exe手工脱壳。
●Lab1-03.exe
我们再以第十六章的病毒分析案例一Lab1-03.exe为例,完成手工脱壳。
第一步:将加壳程序Lab1-03.exe拖入OllyDbg调试器,快速定位OEP原程序入口地址。如下图所示:
图17-14 快速定位OEP
如上图所示,为何在0x004050E1地址处下F2断点?打开内存映射窗口,第一个节区的地址区间从0x00401000开始,大小为3000H。将Lab1-03.exe拖入WinHex,观察3个节区的属性都是可读可写可执行。加壳程序的入口地址为0x00405000,0x004050E1地址处的反汇编指令是一个JE指令,跳转地址为0x00401090。因此,这个地址很可疑。接着按F8单步执行,然后按F9执行,多次重复这一动作,直到完成跳转为止。再不济,一步步单步跟踪,最终也是可以找到OEP的。如下图所示:
图17-15 跳转OEP地址
第二步:使用OllyDbg插件OllyDump进行程序的脱壳操作。点击鼠标右键“用OllyDump脱壳调试进程”,弹出如下对话框窗口。
图17-16 dump脱壳程序
注意检查“起始地址”、“入口点地址”是否正确,不要勾选“重建输入表”选项,等待稍后修复输入表。点击“脱壳”选项,保存为dumped_Lab01-03.exe。
还可以使用LordPE工具dump脱壳文件。打开LordPE,选择当前正在调试的进程Lab01-03.exe,如下图所示:
图17-17 使用LordPE dump脱壳文件
点击鼠标右键“完全脱壳”,保存脱壳文件为dumped_Lab01-03.exe。使用LordPE工具dump下来的脱壳文件和使用OllyDump插件几乎完全一样。
第三步:修复输入表。如果使用纯手工修复是可以的。但是如果导入函数很多,可以借助于ImportREC工具修复导入表和IAT表。
打开ImportREC工具,附加当前调试的加壳程序Lab01-03.exe,如图17-18所示。
输入程序的OEP入口RVA地址00001090,然后点击自动查找,发现提示“在此OEP没有找到任何有用的信息!”。如果没有找到IAT信息,则要手动填入IAT的RVA和大小。
图17-18 自动查找IAT
点击“确定”之后,点击右侧“获取输入表”按钮,如图17-19所示。
图17-19 获取输入表
图17-20 修复IAT后转存储文件
由左侧的窗口可知,输入函数的DLL RVA地址为0x00002000。因此,我们将OEP下方的“RVA”栏填改写为:00002000,“大小”栏不变(20个输入函数*4)。然后重新点击获取输入表。再点击“显示无效的”按钮,然后在输入表函数栏点击鼠标右键“剪切指针”,删除无效导入函数。如图17-20所示。
最后点击左侧按钮“修复转储文件”,选择需要转存的dump文件,保存修复后的文件unpack_Lab01-03_.exe。
第四步:运行修复后的文件,成功!对比修复后的变化。
将修复之后保存的文件unpack_HelloWorld.exe拖入WinHex:
.rdata节区:
00002000 5C 60 00 00 6C 60 00 00 7A 60 00 00 8E 60 00 00 \`..l`..z`..巂..
00002010 A0 60 00 00 AE 60 00 00 BE 60 00 00 C6 60 00 00 燻..甡..綻..芵..
00002020 D4 60 00 00 DC 60 00 00 EC 60 00 00 F8 60 00 00 訿..躟..靈..鴃..
00002030 0C 61 00 00 00 00 00 00 2A 61 00 00 38 61 00 00 .a......*a..8a..
00002040 4A 61 00 00 00 00 00 00 64 61 00 00 74 61 00 00 Ja......da..ta..
00002050 88 61 00 00 00 00 00 00 01 DF 02 00 00 00 00 00 坅.......?.....
00002060 C0 00 00 00 00 00 00 46 61 16 0C D3 AF CD D0 11 ?.....Fa..盈托.
00002070 8A 3E 00 C0 4F C9 E2 6E FF FF FF FF 80 11 40 00 ?.繭赦n€.@.
00002080 94 11 40 00 00 00 00 00 00 00 00 00 00 00 00 00 ?@.............
.mackt节区:
00006050 6D 73 76 63 72 74 2E 64 6C 6C 00 00 6F 00 5F 5F msvcrt.dll..o.__
00006060 67 65 74 6D 61 69 6E 61 72 67 73 00 D7 00 5F 63 getmainargs.?_c
00006070 6F 6E 74 72 6F 6C 66 70 00 00 EE 00 5F 65 78 63 ontrolfp..?_exc
00006080 65 70 74 5F 68 61 6E 64 6C 65 72 33 00 00 9A 00 ept_handler3..?
00006090 5F 5F 73 65 74 5F 61 70 70 5F 74 79 70 65 00 00 __set_app_type..
000060A0 87 00 5F 5F 70 5F 5F 66 6D 6F 64 65 00 00 82 00 ?__p__fmode..?
000060B0 5F 5F 70 5F 5F 63 6F 6D 6D 6F 64 65 00 00 F7 00 __p__commode..?
000060C0 5F 65 78 69 74 00 50 00 5F 58 63 70 74 46 69 6C _exit.P._XcptFil
000060D0 74 65 72 00 91 02 65 78 69 74 00 00 7C 00 5F 5F ter.?exit..|.__
000060E0 70 5F 5F 5F 69 6E 69 74 65 6E 76 00 3C 01 5F 69 p___initenv.<._i
000060F0 6E 69 74 74 65 72 6D 00 9C 00 5F 5F 73 65 74 75 nitterm.?__setu
00006100 73 65 72 6D 61 74 68 65 72 72 00 00 B7 00 5F 61 sermatherr..?_a
00006110 64 6A 75 73 74 5F 66 64 69 76 00 00 6F 6C 65 61 djust_fdiv..olea
00006120 75 74 33 32 2E 64 6C 6C 00 00 08 00 56 61 72 69 ut32.dll....Vari
00006130 61 6E 74 49 6E 69 74 00 02 00 53 79 73 41 6C 6C antInit...SysAll
00006140 6F 63 53 74 72 69 6E 67 00 00 06 00 53 79 73 46 ocString....SysF
00006150 72 65 65 53 74 72 69 6E 67 00 6F 6C 65 33 32 2E reeString.ole32.
00006160 64 6C 6C 00 FE 00 4F 6C 65 49 6E 69 74 69 61 6C dll.?OleInitial
00006170 69 7A 65 00 12 00 43 6F 43 72 65 61 74 65 49 6E ize...CoCreateIn
00006180 73 74 61 6E 63 65 00 00 15 01 4F 6C 65 55 6E 69 stance....OleUni
00006190 6E 69 74 69 61 6C 69 7A 65 00 00 00 00 00 00 00 nitialize.......
将unpack_HelloWorld.exe拖入OllyDbg,查看内存窗口:
00402000 >EB EE BE 77 4F EE C1 77 94 5C C0 77 7C 53 C0 77 腩緒O盍w擻纖|S纖
00402010 >DB F1 BE 77 A4 F1 BE 77 9A 9E C0 77 AE 2D C0 77 垴緒ゑ緒殲纖?纖
00402020 >7E 9E C0 77 F1 F1 BE 77 67 9D C0 77 95 D6 C1 77 ~灷w耨緒g澙w曋羨
00402030 >D8 23 C3 77 00 00 00 00 80 49 0F 77 05 4C 0F 77 ?脀....€IwLw
00402040 >80 48 0F 77 00 00 00 00 0A 1C 9B 76 D4 F1 9A 76 €Hw.....泇择歷
00402050 >7F 32 9E 76 00 00 00 00 01 DF 02 00 00 00 00 00 2瀡....?.....
00402060 C0 00 00 00 00 00 00 46 61 16 0C D3 AF CD D0 11 ?.....Fa.盈托
00402070 8A 3E 00 C0 4F C9 E2 6E FF FF FF FF 80 11 40 00 ?.繭赦n€@.
00402080 94 11 40 00 00 00 00 00 00 00 00 00 00 00 00 00 ?@.............
IAT表已修复完成,可以正常运行。