xswolf 发表于 2015-4-12 22:24:06

FSG v1.10 (Eng) -> dulek/xt] [Overlay] *壳 求脱壳方法

求指导方法,自己尝试用通用的脱壳方法脱,脱不出来,网上这种壳的资料也少,找不到相关的方法。

lucky_789 发表于 2015-4-12 23:48:53

本帖最后由 lucky_789 于 2015-4-12 23:50 编辑

几年前分析过一个FSG2.0的壳,碰巧笔记还在,给你参考一下吧,1.1应该不会比2.0复杂。


【软件】加了FSG 2.0 -> bart/xt壳的win98记事本程序,由天草老师教程中提供。
【工具】OD、PEiD
【声明】未经本人同意,本文谢绝转载。

PEiD查看,是FSG 2.0 -> bart/xt,用OD载入。在开始分析之前,先了解一下该壳的概貌,在OD的数据窗口中看一下头部信息:

004000004D 5A 00 00 | 00 00 00 00 | 00 00 00 00 | 50 45 00 00MZ..........PE..
004000104C 01 02 00 | 46 53 47 21 | 00 00 00 00 | 00 00 00 00L.FSG!........
00400020E0 00 0F 01 | 0B 01 00 00 | 00 40 00 00 | 00 70 00 00? [email protected]..
0040003000 00 00 00 | 54 01 00 00 | 00 10 00 00 | 0C 00 00 00....T.........
0040004000 00 40 00 | 00 10 00 00 | 00 02 00 00 | 04 00 00 00..@..........
0040005000 00 00 00 | 04 00 00 00 | 00 00 00 00 | 00 50 01 00............P.
0040006000 02 00 00 | 00 00 00 00 | 02 00 00 00 | 00 00 10 00.............
0040007000 10 00 00 | 00 00 10 00 | 00 10 00 00 | 00 00 00 00.............
0040008010 00 00 00 | 00 00 00 00 | 00 00 00 00 | A8 44 01 00...........―.
0040009084 00 00 00 | 00 E0 00 00 | 90 33 00 00 | 00 00 00 00?...?.?......
。。。

我们可以看到:
1、这个压缩壳真是“压缩到了牙齿”:
其一,DOS头部被挤占,只剩下e_magic等前6个成员以及e_lfanew共16个字节。
其二,PE头被移到了0040000C处。(这样,PE头的BaseOfData成员--数据区段起始RVA--就与e_lfanew相重叠了,有影响吗?我们看到区段表表明只有2个区段,名称都被抹去了,再看看内存窗口,原来是代码段和资源(输入表)两个区段,并没有数据段,所以不会影响。)
其三,DOS头、PE头、区段表总大小被压缩为200h(512)字节,而程序入口点RVA为0000154,即壳的引导部分被插入到了文件头部区段表末尾的空白区,几乎没浪费一个字节,呵呵。
2、PE头的文件创建日期和时间字段被填充了壳标志“FSG!”。
3、输入表首地址RVA=000144A8,去004144A8看看,发现输入表只有一个IID,OriginalFirstThunk和FirstThunk都指向00414500,只有两个函数,即kernel32.LoadLibraryA和kernel32.GetProcAddress,紧随其后的是这两个函数的名称。

好了,大致了解了这些,正式开始分析。


00400154 F>8725 EC444100   xchg dword ptr ,esp               ; ds:处是加壳时存放的是指向8个预设值的指针
0040015A   61            popad                                       ; 用pop方式给8个寄存器传递预设值(但esp是不受预设值的影响)
0040015B   94            xchg eax,esp                              ; 恢复堆栈。eax中是正常程序入口时esp的值

下面开始解压代码:
0040015C   55            push ebp
0040015D   A4            movs byte ptr es:,byte ptr        ; ds:==00,es:==00
0040015E   B6 80         mov dh,80
00400160   FF13            call dword ptr
00400162   ^ 73 F9         jnb short FSG_2_0.0040015D
00400164   33C9            xor ecx,ecx
00400166   FF13            call dword ptr
00400168   73 16         jnb short FSG_2_0.00400180
0040016A   33C0            xor eax,eax
0040016C   FF13            call dword ptr
0040016E   73 1F         jnb short FSG_2_0.0040018F
00400170   B6 80         mov dh,80
00400172   41            inc ecx
00400173   B0 10         mov al,10
00400175   FF13            call dword ptr
00400177   12C0            adc al,al
00400179   ^ 73 FA         jnb short FSG_2_0.00400175
0040017B   75 3A         jnz short FSG_2_0.004001B7
0040017D   AA            stos byte ptr es:
0040017E   ^ EB E0         jmp short FSG_2_0.00400160
00400180   FF53 08         call dword ptr
00400183   02F6            add dh,dh
00400185   83D9 01         sbb ecx,1
00400188   75 0E         jnz short FSG_2_0.00400198
0040018A   FF53 04         call dword ptr
0040018D   EB 24         jmp short FSG_2_0.004001B3
0040018F   AC            lods byte ptr
00400190   D1E8            shr eax,1
00400192   74 2D         je short FSG_2_0.004001C1
00400194   13C9            adc ecx,ecx
00400196   EB 18         jmp short FSG_2_0.004001B0
00400198   91            xchg eax,ecx
00400199   48            dec eax
0040019A   C1E0 08         shl eax,8
0040019D   AC            lods byte ptr
0040019E   FF53 04         call dword ptr
004001A1   3B43 F8         cmp eax,dword ptr
004001A4   73 0A         jnb short FSG_2_0.004001B0
004001A6   80FC 05         cmp ah,5
004001A9   73 06         jnb short FSG_2_0.004001B1
004001AB   83F8 7F         cmp eax,7F
004001AE   77 02         ja short FSG_2_0.004001B2
004001B0   41            inc ecx
004001B1   41            inc ecx
004001B2   95            xchg eax,ebp
004001B3   8BC5            mov eax,ebp
004001B5   B6 00         mov dh,0
004001B7   56            push esi
004001B8   8BF7            mov esi,edi
004001BA   2BF0            sub esi,eax
004001BC   F3:A4         rep movs byte ptr es:,byte ptr
004001BE   5E            pop esi
004001BF   ^ EB 9F         jmp short FSG_2_0.00400160                  ; 循环
至此解压完毕。

下面开始填充IAT:
004001C1   5E            pop esi                                     ; 堆栈 =00406000,这里是加壳时保存的一张表,内容是输入表涉及的所有dll库名称及各dll对应的IAT指针。
004001C2   / AD            lods dword ptr                         ; 取IAT首地址
004001C3   | 97            xchg eax,edi                              ; IAT首地址->edi
004001C4   | AD            lods dword ptr                         ; 取dll库名称
004001C5   | 50            push eax                                    ; /dll库名称(如ASCII "SHELL32.dll")
004001C6   | FF53 10         call dword ptr                      ; \kernel32.LoadLibraryA
004001C9   | 95            xchg eax,ebp                              ; dll库句柄->ebp
004001CA   |/8B07            mov eax,dword ptr                      ; /取函数名地址
004001CC   ||40            inc eax                                     ; |函数名地址(如ASCII "DragFinish")
004001CD   \|78 F3         js short FSG_2_0.004001C2                   ; |FSG壳在这里做了小动作,正常情况下不同dll的IAT之间是用00000000分隔,而我们从数据窗口可以看到,处是用7FFFFFFF来分隔的,最后一个dll的IAT末尾是FFFFFFFF,许多朋友脱壳后不能运行,原因就在这里!当处是7FFFFFFF时表示还有dll的函数没处理完,在这里跳去处理下一个dll的函数。
004001CF    |75 03         jnz short FSG_2_0.004001D4                  ; |是结束标志(FFFFFFFF+1=0)则跳出循环,否则就是函数名地址,需要继续填充。
004001D1    |FF63 0C         jmp dword ptr                      ; |全部填充完毕,则到这里跳往OEP
004001D4    |50            push eax                                    ; |/参数2:函数名。ASCII "DragFinish"
004001D5    |55            push ebp                                    ; ||参数1:动态库句柄
004001D6    |FF53 14         call dword ptr                      ; |\kernel32.GetProcAddress
004001D9    |AB            stos dword ptr es:                     ; |填充IAT
004001DA   ^\EB EE         jmp short FSG_2_0.004001CA                  ; \循环处理下一个函数
004001DC   33C9            xor ecx,ecx                                 ; 这里是前面解压子函数的入口。不用管
004001DE   41            inc ecx                                     ; 这里是前面解压子函数的入口。不用管
004001DF   FF13            call dword ptr
004001E1   13C9            adc ecx,ecx
004001E3   FF13            call dword ptr
004001E5   ^ 72 F8         jb short FSG_2_0.004001DF
004001E7   C3            retn

004010CC   55            push ebp                                    ; 这里就是OEP
004010CD   8BEC            mov ebp,esp
004010CF   83EC 44         sub esp,44
004010D2   56            push esi
004010D3   FF15 E4634000   call dword ptr                      ; kernel32.GetCommandLineA
004010D9   8BF0            mov esi,eax

下面就是脱壳了。直接用OD的OllyDump插件脱壳,运行会报错,原因很简单,就是上面分析中提到的IAT分隔标志问题。解决办法也很简单,在到达OEP后,在反汇编窗口中找一个API函数,如“004010D3 call dword ptr ; kernel32.GetCommandLineA”,在这行右键-在数据窗口中跟随-内存地址,数据窗口中上下看看,将IAT中的所有7FFFFFFF和FFFFFFFF修改成00000000,再dump即可运行,无需ImportREC修复。


小结:
FSG 2.0 -> bart/xt是一个早期的压缩壳,简单的作了一点保护措施。
一、本壳的压缩方面
1、该壳删除了文件的DOS头,只保留了必要的16个字节,壳自解压代码全部存放文件头中。

2、该壳将文件包含代码段在内的全部区段合并在一起,将压缩的数据放入一个新增加的段中,同时将原文件的代码、数据、资源等所有内容抽掉,连原各段的名称也在文件头中抹掉。

3、壳代码在运行时,直接将整个压缩的数据解压到代码段中,然后填充IAT,再跳往OEP。

二、输入表处理方面
1、将输入表指向了一个壳中的伪输入表,伪输入表中只保留了1个IID且除NAME和FIRSTTHUNK外的其他3个成员为空,而dll名称(KERNEL32.dll)则附在了文件头中壳代码结束处,IAT只有两个函数,即kernel32.LoadLibraryA和kernel32.GetProcAddress,供壳使用。

2、加壳时破坏了原输入表,取而代之的是一张信息表,保存的信息是IAT首地址和它对应的dll库名称指针。IAT中填充的是处理过的函数名地址,壳在运行时,先根据信息表中的指针取出dll库名称,再LoadLibraryA调入该库,获得句柄;然后根据信息表中对应的IAT首地址,取出一个地址,该地址+1后即得到函数名,然后GetProcAddress获取函数地址,最后覆盖被篡改的IAT。

3、该壳在给文件加壳时,就对IAT除篡改函数地址外,还将不同dll的IAT数组之间的结束标志篡改,最后一个dll的IAT末尾由FFFFFFFF替代00000000,而前面的dll的IAT之间用的是7FFFFFFF。壳在装载函数时,根据这两个数+1的结果(而不是直接根据信息表)来判断是继续填充下一IAT数组还是结束填充,如果是继续填充,则从信息表中取出dll库名称地址和IAT首地址,循环处理。为何要搞的这么麻烦?相信你已经明白了--那就是反脱壳。许多新手朋友在顺利脱掉这个壳后,程序却不能运行,软件作者要的就是这个结果,呵呵。我们的对策也很简单,上面已作了说明,就是在填充完IAT后,将那些7FFFFFFF和FFFFFFFF恢复成00000000,程序就跑起来了。

4、该壳没有采取反调试措施,只是一个小技巧将跳往OEP的指令夹在处理IAT的循环代码中间,信奉“不往回跳”的新手朋友,往往就容易跑飞了。但壳代码除解压代码外,总共才十几行指令,也隐藏不了什么秘密,毕竟只是压缩壳。




xswolf 发表于 2015-4-13 22:30:29

本帖最后由 xswolf 于 2015-4-13 22:31 编辑

lucky_789 发表于 2015-4-12 23:48
几年前分析过一个FSG2.0的壳,碰巧笔记还在,给你参考一下吧,1.1应该不会比2.0复杂。



谢谢了,不过看了你发的资料,跟你那分析的过程差别太大了。没头绪。这个是原文件你分析看看,这种应该要怎么入手好。不是求破的,自己学习的 下载地址 奇易QQ6.67版      http://pan.baidu.com/s/1i35Wkdf

brightsm 发表于 2015-6-16 20:44:27

我看一下。

brightsm 发表于 2015-6-16 21:37:48

xswolf 发表于 2015-4-13 22:30
谢谢了,不过看了你发的资料,跟你那分析的过程差别太大了。没头绪。这个是原文件你分析看看,这种应该要 ...

有木马呀,杀毒软件报木马
页: [1]
查看完整版本: FSG v1.10 (Eng) -> dulek/xt] [Overlay] *壳 求脱壳方法