【文章标题】: 菜鸟手脱FSG2.0并修复导入表笔记
【文章作者】: firefly
【软件名称】: FSG加壳记事本
【下载地址】: 看雪工具下载
【加壳方式】: FSG2.0
【软件介绍】: winxp sp2,OllyICE,ODBGScript1.62
【作者声明】: 菜鸟脱壳学习笔记,失误之处烦请大家指正。
--------------------------------------------------------------------------------
【详细过程】
首先用FSG2.0将记事本加壳,然后用OD载入加壳的记事本, 如下所示:
代码:
01000154 > 8725 6CF40101 xchg dword ptr [101F46C], esp 0100015A 61 popad 0100015B 94 xchg eax, esp 0100015C 55 push ebp 0100015D A4 movs byte ptr es:[edi], byte ptr [esi] 0100015E B6 80 mov dh, 80 01000160 FF13 call dword ptr [ebx] 01000162 ^ 73 F9 jnb short 0100015D 01000164 33C9 xor ecx, ecx 01000166 FF13 call dword ptr [ebx] 01000168 73 16 jnb short 01000180 0100016A 33C0 xor eax, eax 0100016C FF13 call dword ptr [ebx] 0100016E 73 1F jnb short 0100018F 01000170 B6 80 mov dh, 80 01000172 41 inc ecx 01000173 B0 10 mov al, 10 01000175 FF13 call dword ptr [ebx] 01000177 12C0 adc al, al 01000179 ^ 73 FA jnb short 01000175 0100017B 75 3A jnz short 010001B7 0100017D AA stos byte ptr es:[edi] 0100017E ^ EB E0 jmp short 01000160 01000180 FF53 08 call dword ptr [ebx+8] 01000183 02F6 add dh, dh 01000185 83D9 01 sbb ecx, 1 01000188 75 0E jnz short 01000198 0100018A FF53 04 call dword ptr [ebx+4] 0100018D EB 24 jmp short 010001B3 0100018F AC lods byte ptr [esi] 01000190 D1E8 shr eax, 1 01000192 74 2D je short 010001C1 01000194 13C9 adc ecx, ecx 01000196 EB 18 jmp short 010001B0 01000198 91 xchg eax, ecx 01000199 48 dec eax 0100019A C1E0 08 shl eax, 8 0100019D AC lods byte ptr [esi] 0100019E FF53 04 call dword ptr [ebx+4] 010001A1 3B43 F8 cmp eax, dword ptr [ebx-8] 010001A4 73 0A jnb short 010001B0 010001A6 80FC 05 cmp ah, 5 010001A9 73 06 jnb short 010001B1 010001AB 83F8 7F cmp eax, 7F 010001AE 77 02 ja short 010001B2 010001B0 41 inc ecx 010001B1 41 inc ecx 010001B2 95 xchg eax, ebp 010001B3 8BC5 mov eax, ebp 010001B5 B6 00 mov dh, 0 010001B7 56 push esi 010001B8 8BF7 mov esi, edi 010001BA 2BF0 sub esi, eax 010001BC F3:A4 rep movs byte ptr es:[edi], byte ptr [esi] 010001BE 5E pop esi 010001BF ^ EB 9F jmp short 01000160 010001C1 5E pop esi ; 此处循环处理导入表 010001C2 AD lods dword ptr [esi] 010001C3 97 xchg eax, edi 010001C4 AD lods dword ptr [esi] 010001C5 50 push eax 010001C6 FF53 10 call dword ptr [ebx+10] ; kernel32.LoadLibraryA 010001C9 95 xchg eax, ebp 010001CA 8B07 mov eax, dword ptr [edi] 010001CC 40 inc eax 010001CD ^ 78 F3 js short 010001C2 010001CF 75 03 jnz short 010001D4 ; 这里跳到OEP 010001D1 FF63 0C jmp dword ptr [ebx+C] 010001D4 50 push eax 010001D5 55 push ebp 010001D6 FF53 14 call dword ptr [ebx+14] ; kernel32.GetProcAddress 010001D9 AB stos dword ptr es:[edi] 010001DA ^ EB EE jmp short 010001CA
用F8大概的走一哈,走到010001C6处可以看到这里调用LoadLibraryA,接下来又
调用GetProcAddress,并把地址保存,跟两边可以发现这里其实是一个循环,大
致可以确定这里是处理导入表的。观察这里的这个循环,可以看到
010001D1 FF63 0C jmp dword ptr [ebx+C]
是跳出该循环的,我们在这里下断,F9运行,果然中断在010001D1,可开心了:P
再F8一哈就到0100739D这里,多么熟悉的OEP啊,dump之,光偷着乐了。
代码:
0100739D . 6A 70 push 70 0100739F . 68 98180001 push 01001898 010073A4 . E8 BF010000 call 01007568 010073A9 . 33DB xor ebx, ebx 010073AB . 53 push ebx ; /pModule => NULL 010073AC . 8B3D CC100001 mov edi, dword ptr [10010CC] ; |kernel32.GetModuleHandleA 010073B2 . FFD7 call edi ; \GetModuleHandleA 010073B4 . 66:8138 4D5A cmp word ptr [eax], 5A4D 010073B9 . 75 1F jnz short 010073DA 010073BB . 8B48 3C mov ecx, dword ptr [eax+3C] 010073BE . 03C8 add ecx, eax 010073C0 . 8139 50450000 cmp dword ptr [ecx], 4550 010073C6 . 75 12 jnz short 010073DA
最后还摆一道。没办法。因为程序运行提示xxxx函数不能xxxx,就怀疑是导入表出了
问题。咋办,导入表我不专业啊,只好硬着头皮上了。谁让壳是咱加的,把原始的记
事本拿出来,看看导入表与加壳的有啥不同。这里我费了半天工夫,才发现,原来
FSG把导入表中的作为结束的00000000替换成了FFFFFF7F或者FFFFFFFF,只要重新改写
回来就OK了。由于记事本导入了多个函数,密密麻麻的一片,很不好搞,所以我就琢
磨着写了一个脚本,刚学的写脚本,可能有些地方写的不合理,还烦请大家指正。
代码:
/*****************************************\ * FSG 2.0 IAT Fix Script by firefly * * * \*****************************************/ VAR iat_addr VAR iat_size VAR con VAR i mov i, 0 ASK "Please Input the IAT Address" mov iat_addr, $RESULT ASK "Please Input the IAT Size" mov iat_size, $RESULT REP: mov con, [iat_addr], 3 cmp con, 0FFFFFF jne Next fill iat_addr, 4, 0 Next: add i, 4 cmp i, iat_size add iat_addr, 4 jbe REP MSG ":) Now you can dump it!"
另外这里再总结一哈如何找到导入表,随便找一个函数调用,如
代码:
010073AB . 53 push ebx ; /pModule => NULL 010073AC . 8B3D CC100001 mov edi, dword ptr [10010CC] ; |kernel32.GetModuleHandleA 010073B2 . FFD7 call edi ; \GetModuleHandleA
那10010CC处一定位于导入表中,上下翻一下,刚好,记事本的导入表位于一个段的开始,从01001000开始,
最后找到有8个字节0的地方,就是导入表结束,在OD中用鼠标选一哈,就可以知道其大小为0x350,如下所示。
代码:
C8 6F DA 77 F0 6B DA 77 7D 8F DC 77 FD D5 DC 77 83 78 DA 77 1B 76 DA 77 CC D7 DA 77 FF FF FF 7F 60 D2 18 77 FF FF FF 7F B1 DD F0 77 FF 3E F2 77 41 E0 F0 77 6F 6E EF 77 16 F1 F0 77 AD 7F EF 77 61 BE EF 77 1F 40 F2 77 97 9A EF 77 BC 7E EF 77 8F 4B F2 77 00 F5 F1 77 D1 61 EF 77 6F 83 EF 77 7A 5A EF 77 69 99 EF 77 0A 6C EF 77 C9 7D EF 77 EB 5E EF 77 EF D4 EF 77 03 3B F0 77 AC 3B F0 77 EA 99 EF 77 80 5B EF 77 FF FF FF 7F 28 97 80 7C 9C 92 80 7C 27 A4 80 7C D4 A7 80 7C 10 9F 80 7C 75 37 83 7C D3 3F 83 7C 19 FF 80 7C 82 FE 80 7C 6D 0C 81 7C 8E 93 80 7C E5 17 80 7C 16 1E 80 7C F5 DD 80 7C 7D 46 84 7C 77 1D 80 7C A1 B6 80 7C EE 1E 80 7C 2F FC 80 7C 62 15 81 7C 2F 99 80 7C 8D 99 80 7C 09 9A 80 7C B1 2E 83 7C 5E A3 80 7C 1D 2E 83 7C 46 96 87 7C 47 9B 80 7C 64 BA 80 7C 0E 18 80 7C 60 07 81 7C 96 A9 80 7C 20 99 80 7C A0 AD 80 7C 83 6F 81 7C 32 0F 81 7C D7 ED 80 7C E1 EE 80 7C 4C B7 80 7C CC A9 80 7C C6 97 80 7C EF B9 80 7C BC 25 83 7C 31 03 93 7C 87 0D 81 7C 40 03 93 7C D4 A0 80 7C 27 09 83 7C 8F 4B 83 7C 70 30 81 7C 44 20 83 7C 31 1F 83 7C 15 99 80 7C 74 B9 80 7C F8 9B 80 7C 05 B9 80 7C 2A 2E 86 7C FF FF FF 7F E0 70 64 7D 12 07 5E 7D AE AF 5F 7D 3B 24 63 7D FF FF FF 7F AE B6 D1 77 58 BF D1 77 9D 86 D1 77 C7 86 D1 77 5F 55 D2 77 85 3E D2 77 1E C2 D1 77 3C B3 D1 77 EA DA D1 77 3B 1F D3 77 A4 D8 D1 77 4B BE D1 77 27 BE D1 77 87 03 D3 77 D2 90 D1 77 36 9E D1 77 E0 12 D2 77 70 DB D1 77 7F AF D1 77 FE 2C D2 77 69 9D D1 77 4C D8 D2 77 25 FC D1 77 D5 EE D1 77 F0 BE D1 77 94 08 D2 77 36 BC D1 77 D1 E1 D2 77 34 AF D1 77 F9 D7 D1 77 10 F7 D2 77 9A DB D1 77 9B 92 D1 77 71 BE D1 77 7F DD D1 77 4F 7D D2 77 B6 CD D1 77 9C 8F D1 77 EC DB D1 77 F5 B5 D1 77 A4 19 D6 77 69 D8 D1 77 D5 86 D2 77 C8 BD D1 77 76 BD D1 77 92 52 D2 77 BA B8 D1 77 FE DA D1 77 7D 1A D3 77 25 02 D3 77 27 F1 D2 77 37 02 D3 77 8F 8F D2 77 87 F7 D1 77 8C 0C D2 77 7A 14 D3 77 0A 63 D6 77 2B D6 D1 77 A6 88 D1 77 CE 3D D2 77 60 DA D1 77 32 52 D2 77 B6 A9 D1 77 65 3D D2 77 C9 59 D2 77 2F B7 D1 77 6C 18 D3 77 01 8A D1 77 F6 8B D1 77 1E 94 D1 77 C2 D8 D2 77 CB 8C D1 77 C6 91 D1 77 B7 17 D3 77 FF FF FF FF 90 60 F7 72 90 53 F7 72 49 57 F7 72 FF FF FF 7F D6 48 34 76 96 86 33 76 29 9D 34 76 A9 C4 33 76 86 19 32 76 65 7C 33 76 CA 86 33 76 CE 00 33 76 F3 7C 33 76 FF FF FF 7F AE 2D C0 77 9A 9E C0 77 CE 9E C0 77 A3 AE C1 77 3D AB C1 77 B6 9E C0 77 36 D0 BE 77 94 5C C0 77 77 CE BE 77 2F 80 C1 77 0C FB C0 77 7E 9E C0 77 AC 17 C3 77 EB EE BE 77 67 9D C0 77 75 D6 C1 77 D8 23 C3 77 A4 F1 BE 77 DB F1 BE 77 7C 53 C0 77 2F EE C1 77 6B 80 C1 77 FF FF FF 7F 00 00 00 00 00 00 00 00
--------------------------------------------------------------------------------
【经验总结】
貌似对于一般的壳主要需要找到OEP,并且稍微处理一哈导入表,往了再哪看到的,一般的壳再处理完导入表时就会跳到OEP
。而一般的壳处理导入表都离不开LoadLibraryA和GetProcAddress两个函数。所以,在脱壳的时候时刻注意这两个函数。
--------------------------------------------------------------------------------
2008年01月30日 15:57:41