- UID
- 35582
注册时间2007-8-28
阅读权限20
最后登录1970-1-1
以武会友
该用户从未签到
|
【文章标题】: PEBundle3.2的高级捆缚分析
【文章作者】: iawen
【作者主页】: www.iawen.com
【软件名称】: EdrTest.exe
【下载地址】: 自己搜索下载
【加壳方式】: 加壳
【保护方式】: 加壳
【使用工具】: OD、LoadPE、ImportRec
【操作平台】: Xp Sp3
【软件介绍】: 一个UnpackMe,呵呵
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
先用PEid查一下壳,显示为:PEBundle 2.0b5 - 3.0x -> Jeremy Collake
因为朋友自己加的,所以知道是PEBundle 3.2版的,呵呵!
主要是分2步:
1、Dump出完整的主程序
2、Dump出**的DLL
好了,不多说了,直接用OD载入,先来Dump出主程序吧:
- 00418000 Ed> 9C pushfd
- 00418001 60 pushad
- 00418002 E8 02000000 call EdrTest.00418009
- 00418007 33C0 xor eax,eax
- 00418009 8BC4 mov eax,esp
-
复制代码 我们单步到00418002时,看一下ESP,下断点:hr 0013FFA0
然后F9运行,就到了这里:
- 004181A7 9D popfd
- 004181A8 68 4F154000 push EdrTest.0040154F
- 004181AD C3 retn
-
复制代码 F8单步几下,很快就到了OEP位置了,呵呵,VC写的程序:
- 0040154F 55 push ebp
- 00401550 8BEC mov ebp,esp
- 00401552 6A FF push -1
- 00401554 68 58714000 push EdrTest.00407158
- 00401559 68 D0264000 push EdrTest.004026D0
- 0040155E 64:A1 00000000 mov eax,dword ptr fs:[0]
- 00401564 50 push eax
- 00401565 64:8925 0000000>mov dword ptr fs:[0],esp
- 0040156C 83EC 58 sub esp,58
- 0040156F 53 push ebx
- 00401570 56 push esi
- 00401571 57 push edi
- 00401572 8965 E8 mov dword ptr ss:[ebp-18],esp
- 00401575 FF15 A0704000 call dword ptr ds:[4070A0] ; kernel32.GetVersion
-
复制代码 我们先看一下IAT,在00401575上,右键--数据窗口跟随--内存地址,发现有IAT加密:
- 00407098 7C801EF2 kernel32.GetStartupInfoA
- 0040709C 00419377 EdrTest.00419377================加密了的
- 004070A0 7C81126A kernel32.GetVersion
- 004070A4 00419501 EdrTest.00419501================加密了的
- 004070A8 00418F79 EdrTest.00418F79================加密了的
- 004070AC 7C801E1A kernel32.TerminateProcess
- 004070B0 7C80DE85 kernel32.GetCurrentProcess
-
复制代码 我们重新载入程序,下断:hr 0040709C,然后F9运行,中断在了:
- 00418E14 8B19 mov ebx,dword ptr ds:[ecx]
- 00418E16 83C1 04 add ecx,4
- 00418E19 85DB test ebx,ebx
- 00418E1B 74 33 je short EdrTest.00418E50
- 00418E1D 8BC3 mov eax,ebx
- 00418E1F F7C3 00000080 test ebx,80000000
- 00418E25 74 08 je short EdrTest.00418E2F
- 00418E27 81E3 FFFF0000 and ebx,0FFFF
- 00418E2D EB 04 jmp short EdrTest.00418E33
- 00418E2F 43 inc ebx
- 00418E30 43 inc ebx
- 00418E31 03DA add ebx,edx
- 00418E33 51 push ecx
- 00418E34 52 push edx
- 00418E35 899D C2214000 mov dword ptr ss:[ebp+4021C2],ebx
- 00418E3B 53 push ebx
- 00418E3C FFB5 BA214000 push dword ptr ss:[ebp+4021BA]
- 00418E42 E8 32010000 call EdrTest.00418F79
- 00418E47 5A pop edx
- 00418E48 59 pop ecx
- 00418E49 85C0 test eax,eax
- 00418E4B 74 05 je short EdrTest.00418E52
- 00418E4D AB stos dword ptr es:[edi]
- 00418E4E ^ EB C4 jmp short EdrTest.00418E14=========中断在这里了,呵呵
-
复制代码 这是一个循环,我们耐心的单步,单步这里:
- 00418E3C FFB5 BA214000 push dword ptr ss:[ebp+4021BA] ; 这里是DLL的基址
- 00418E42 E8 32010000 call EdrTest.00418F79
-
复制代码 我们发现dword ptr ss:[ebp+4021BA]里加载的是DLL的基址,于是我们跟进去看:
- 00418F79 C8 000000 enter 0,0
- 00418F7D 55 push ebp
- 00418F7E 56 push esi
- 00418F7F E8 00000000 call EdrTest.00418F84
- 00418F84 5E pop esi
- 00418F85 81EE 842F4000 sub esi,EdrTest.00402F84
- 00418F8B 8B86 B2214000 mov eax,dword ptr ds:[esi+4021B2]
- 00418F91 3945 08 cmp dword ptr ss:[ebp+8],eax
- 00418F94 75 1B jnz short EdrTest.00418FB1
- 00418F96 55 push ebp
- 00418F97 51 push ecx
- 00418F98 52 push edx
- 00418F99 57 push edi
- 00418F9A 53 push ebx
- 00418F9B FF75 0C push dword ptr ss:[ebp+C]
- 00418F9E FF75 08 push dword ptr ss:[ebp+8]
- 00418FA1 E8 AEFEFFFF call EdrTest.00418E54
- 00418FA6 5B pop ebx
- 00418FA7 5F pop edi
- 00418FA8 5A pop edx
- 00418FA9 59 pop ecx
- 00418FAA 5D pop ebp
- 00418FAB 5E pop esi
- 00418FAC 5D pop ebp
- 00418FAD C9 leave
- 00418FAE C2 0800 retn 8
- 00418FB1 5E pop esi
- 00418FB2 5D pop ebp
- 00418FB3 FF75 0C push dword ptr ss:[ebp+C]
- 00418FB6 FF75 08 push dword ptr ss:[ebp+8] ; 这里加载函数名
- 00418FB9 FF15 E9884100 call dword ptr ds:[<&KERNEL32.GetProcA>; kernel32.GetProcAddress
- 00418FBF 85C0 test eax,eax ; 这里开始获取函数的地址了
- 00418FC1 74 25 je short EdrTest.00418FE8 ; 地址为0则返回
- 00418FC3 51 push ecx
- 00418FC4 56 push esi
- 00418FC5 50 push eax
- 00418FC6 E8 00000000 call EdrTest.00418FCB
- 00418FCB 5E pop esi
- 00418FCC 81EE CB2F4000 sub esi,EdrTest.00402FCB
- 00418FD2 8D8E 2B234000 lea ecx,dword ptr ds:[esi+40232B]
- 00418FD8 50 push eax ; EAX里是真实的函数地址
- 00418FD9 51 push ecx ; ECX里则是一个将要加密的地址
- 00418FDA E8 97FBFFFF call EdrTest.00418B76
- 00418FDF 85C0 test eax,eax
- 00418FE1 74 02 je short EdrTest.00418FE5
- 00418FE3 59 pop ecx
- 00418FE4 50 push eax
- 00418FE5 58 pop eax
- 00418FE6 5E pop esi
- 00418FE7 59 pop ecx
- 00418FE8 C9 leave
- 00418FE9 C2 0800 retn 8
-
复制代码 然后我们继续跟进 call EdrTest.00418B76:
- 00418B76 C8 040000 enter 4,0
- 00418B7A 53 push ebx
- 00418B7B 57 push edi
- 00418B7C 56 push esi
- 00418B7D E8 00000000 call EdrTest.00418B82
- 00418B82 5B pop ebx
- 00418B83 81EB 822B4000 sub ebx,EdrTest.00402B82
- 00418B89 C745 FC 0000000>mov dword ptr ss:[ebp-4],0
- 00418B90 8B75 08 mov esi,dword ptr ss:[ebp+8]
- 00418B93 833E 00 cmp dword ptr ds:[esi],0
- 00418B96 74 34 je short EdrTest.00418BCC
- 00418B98 56 push esi
- 00418B99 8B7E 08 mov edi,dword ptr ds:[esi+8]
- 00418B9C 03FB add edi,ebx
- 00418B9E 8B76 0C mov esi,dword ptr ds:[esi+C]
- 00418BA1 03F3 add esi,ebx
- 00418BA3 8B45 0C mov eax,dword ptr ss:[ebp+C]
- 00418BA6 833F FF cmp dword ptr ds:[edi],-1
- 00418BA9 74 13 je short EdrTest.00418BBE
- 00418BAB 8B0F mov ecx,dword ptr ds:[edi]
- 00418BAD 85C9 test ecx,ecx
- 00418BAF 74 05 je short EdrTest.00418BB6
- 00418BB1 390419 cmp dword ptr ds:[ecx+ebx],eax ; kernel32.FreeEnvironmentStringsW
- 00418BB4 74 0E je short EdrTest.00418BC4 ; 注意这个比较,EAX里真实的IAT地址
- 00418BB6 83C7 04 add edi,4 ; 而ds:[ecx+ebx]里是什么呢?
- 00418BB9 83C6 04 add esi,4
- 00418BBC ^ EB E8 jmp short EdrTest.00418BA6
- 00418BBE 5E pop esi
- 00418BBF 83C6 10 add esi,10
- 00418BC2 ^ EB CF jmp short EdrTest.00418B93
- 00418BC4 8B06 mov eax,dword ptr ds:[esi]
- 00418BC6 03C3 add eax,ebx
- 00418BC8 8945 FC mov dword ptr ss:[ebp-4],eax
- 00418BCB 5E pop esi
- 00418BCC 5E pop esi
- 00418BCD 5F pop edi
- 00418BCE 5B pop ebx
- 00418BCF 8B45 FC mov eax,dword ptr ss:[ebp-4]
- 00418BD2 C9 leave
- 00418BD3 C2 0800 retn 8
-
复制代码 关键在于这个比较了: cmp dword ptr ds:[ecx+ebx],eax
EAX里真实的IAT地址,而ds:[ecx+ebx]里是什么呢?我们右键跟随,在数据窗口里,我们看到了这些:
- 004188B9 00000000
- 004188BD >7C809BD7 kernel32.CloseHandle
- 004188C1 >7C801A28 kernel32.CreateFileA
- 004188C5 >7C8106C7 kernel32.CreateThread
- 004188C9 >7C831EC5 kernel32.DeleteFileA
- 004188CD >7C81CAFA kernel32.ExitProcess
- 004188D1 >7C80C0E8 kernel32.ExitThread
- 004188D5 >7C80AC6E kernel32.FreeLibrary
- 004188D9 >7C80DE85 kernel32.GetCurrentProcess
- 004188DD >7C8099B0 kernel32.GetCurrentProcessId
- 004188E1 >7C80B55F kernel32.GetModuleFileNameA
- 004188E5 >7C80B731 kernel32.GetModuleHandleA
- 004188E9 >7C80AE30 kernel32.GetProcAddress
- 004188ED >7C861807 kernel32.GetTempFileNameA
- 004188F1 >7C835DE2 kernel32.GetTempPathA
- 004188F5 >7C812B6E kernel32.GetVersionExA
- 004188F9 >7C801D7B kernel32.LoadLibraryA
- 004188FD >7C801D53 kernel32.LoadLibraryExA
- 00418901 >7C8309D1 kernel32.OpenProcess
- 00418905 >7C802213 kernel32.WriteProcessMemory
- 00418909 >7C809AE1 kernel32.VirtualAlloc
- 0041890D >7C809B74 kernel32.VirtualFree
- 00418911 >7C810E17 kernel32.WriteFile
- 00418915 00000000
-
复制代码 这里都是要加密的函数了!
所以我们只需要把这句:00418B96 74 34 je short EdrTest.00418BCC
改成无条件跳转,跳过就OK了:jmp short EdrTest.00418BCC
好了,我们重新载入程序,直接来到刚刚找到位置,把je改成jmp,然后用ESP快速来到OEP
然后查看一下IAT:
- 00407098 7C801EF2 kernel32.GetStartupInfoA
- 0040709C 7C812FAD kernel32.GetCommandLineA
- 004070A0 7C81126A kernel32.GetVersion
- 004070A4 7C81CAFA kernel32.ExitProcess
- 004070A8 7C80AE30 kernel32.GetProcAddress
- 004070AC 7C801E1A kernel32.TerminateProcess
- 004070B0 7C80DE85 kernel32.GetCurrentProcess
- 004070B4 7C863E6A kernel32.UnhandledExceptionFilter
-
复制代码 好了,我用LoadPE来Dump出程序,然后修复IAT(有一个无效指针,我们直接CUT掉就行了),一切OK,程序也能跑起来了,呵呵!
难道就此OVER了??也没见什么**的DLL啊!我发朋友一看,XP SP2的,NO,NO,直接出错~!
原来是没有DLL,导致跨平台出错!
所以我们现在就是提取出DLL了,哈,我们再次载入OD,Alt+M打开内存镜像:
如图,大家看到了那些区段了吧,呵呵!这个壳很有意思,把DLL的所有区段,连名称都没变,就直接**到主程序的区段里了!
好了,我们也不先运行了,直接DUMP吧,用LoadPE的部分Dump功能,地址填写:0040B000,大小是C000,大家可以自己累加一下!
然后将DUMP的文件名直接改成DLL名:EdrLib.dll
这个DLL名,我们可以通过下:bp GetModuleHandleA断点来找到,如下:
- 0013FF7C 00419196 /CALL 到 GetModuleHandleA 来自 EdrTest.00419190
- 0013FF80 00407954 \pModule = "EdrLib.dll"
-
复制代码 我找了一个需要DLL 的主程序来测试,运行,NO,提示EdrLib.dll无效!看来DLL有修改!
好了,我们在.pe区段上双击进去,然后指定用PE头的格式来查看,一个个看下去,发现(如图):
.text区段的PointerToRawData怎么会是1200??应该是1000啊,因为PE头占了1000字节
继续往下看:发现.rdata、data、reloc等区段都多了200字节!而且reloc的虚拟地址也不对,多了1000字节!
先不管了,我们把这些修改过来:
1000、7000、 8000、B000后,再BDUMP一份,测试运行,依然NO!这是为什么??
想到了.reloc区段的虚拟地址多出了1000,这样我们在Dump时,因为大小是C000,所以没有包含上这个地址!
用HexWork打开一个,果然,全部是0!
好了,知道原因了,我们先好着手DUMP出DLL了,将上面的值一一修改过来!
注意.reloc的PointerToRawData是C000,呵呵!不能只简单的改为B000哦!
然后再部分Dump,如图:
大小增加了1000字节!
测试OK了,哈!
--------------------------------------------------------------------------------
【版权声明】: 转载请注明作者并保持文章的完整, 谢谢!
2009年01月30日 20:36:46 |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?加入我们
x
|