前几天看到h前辈破解了ExeCryptor 2.2.6
贴子在这里 http://bbs.pediy.com/showthread.php?s=&threadid=17286
南蛮妈妈不自量力 从看雪主页下载 ExeCryptor 2.2.5.1 来学习一下
下载在这里 http://www.pediy.com/tools/PACK/Protectors/EXECryptor/EXECryptor%20V2.2.5.1.zip
XPsp2 + DS3.2 + IceExt0.67 + flyOD1.1 + WinHex
过程比较乱, 更像是笔记, 希望得到您的指点
一 oep
运行主程序, 第一个区段是从401000到4C8000
所以我用 WinHex 的RAM编辑器, 打开EXECryptor的主要内存, alt-g 到4C8000, 向上找
因为是Delphi的程序, 所以向上翻翻,向下翻翻, 可以确定oep是 4C74D0
二 dump
这个东东我在OD下跑不起来, 在SI下也跑不起来, 但是在SI下似乎跑得更远
006DEE6A > E8 F7FEFFFF call EXECrypt.006DED66 //这个是ep
006DEE6F 05 272D0000 add eax,2D27
006DEE74 FFE0 jmp eax
006DEE76 E8 EBFEFFFF call EXECrypt.006DED66 //这个是TLS的CALLBACK, 比ep先执行
006DEE7B 05 DE220000 add eax,22DE
006DEE80 ^ FFE0 jmp eax
006DEE82 E8 04000000 call EXECrypt.006DEE8B
下2个断点
bpmb 6DEE6A x //在ep处下断
bpmb 6DEE76 x //在TLS的CALL下断
主程序跑起来
先断在6DEE76 这个时候d一下401000, u一下 4C74D0(oep)显然是空的
bd 掉 6DEE76这个断点, 继续跑
断在ep处,也就是6DEE6A
这个时候发现各个区段都已经解码了, 4C74D0(oep)处是
004C74D0 E9 A0C30D00 jmp 005A3875
bpmb 4C74D0 x
bpmb 5A3875 x
再跑
虽然没有断在 4C74D0 但断在了5A3875
这时候, ESP是 13FFC4, EBP是 13FFF0
13FFC4 的值是 7C816D4F 正好是接在kernel32的 CALL oep的后面
南蛮妈妈觉得到这儿可以dump了, 清掉所有断点
壳在TLS的CALL中创建了10几个线程
这个时候如果把当前eip改成jmp eip出来用LordPE dump是不行的
如果把线程都杀了, 写个int 3 ,让od接管来dump也不太稳定
用IceExt的!dump
总大小是 2DF000
理想的应该是!dump \??\f:\1.bin 400000 2DF000
但Windows管理内存是段页式的, 并不是所有的页都在内存中
找一块空地, r eip , 6DEF00
a 6DEF00
写一段话,保证要dump的都在内存中
006DEF00 B8 00104000 mov eax,EXECrypt.00401000
006DEF05 8B18 mov ebx,dword ptr ds:[eax]
006DEF07 05 00100000 add eax,1000
006DEF0C 3D 00804C00 cmp eax,EXECrypt.004C8000
006DEF11 ^ 7C F2 jl short EXECrypt.006DEF05
006DEF13 90 nop
006DEF14 90 nop
执行到6DEF13后, 就可以
!dump \??\f:\1.bin 400000 c8000 //PE头和CODE段
再从4C8000到519000过一遍
!dump \??\f:\2.bin 4c8000 51000 //DATA段到rsrc段
再是519000到5AF000
!dump \??\f:\3.bin 519000 96000 //m.2mwp5l段
最后是5AF000到6DF000
!dump \??\f:\4.bin 5af000 130000 //nt5pe0gm段
三 修复PE格式
把1.bin 2.bin 3.bin 4.bin 用WinHex 拼起来
然后用LordPE打开 拼起来的文件, 修一些东西
EntryPoint: 002DEE6A -> C74D0
SectionTable: 把每个ROffset 改成和 VOffset一样的值; RSize 改成和 VSize一样的值
TlsTable: (001AF110, 00000018) -> (F2000, 18)
得到 1.exe
四 输入表
随便找个delphi的程序把输入表扣出来, 贴到1.exe
贴的时候, 要选上新建IAT, 去掉修复ep to oep ,选上新增区段
南蛮妈妈借的是flashfxp
得到1_.exe, 这时可以用od载入1_.exe
看到IAT是在 4ED168开始
修复加密的输入表, 南蛮妈妈的处理方法是
随便找一个属于kernel32中的
eip改成到加密的地址的入口
对kernel32的.text段下内存访问断点
走着走着, 会看到,它把kernel32的导出函数地址一个一个拿出来加密, 和真实的api地址的密文比较
0056E485 3B45 F8 cmp eax,dword ptr ss:[ebp-8]
0056E488 ^ 0F85 8434FFFF jnz 00561912 ; 比较api加密的密文, 不等则跳上去计算下一个
0056E48E 8B45 EC mov eax,dword ptr ss:[ebp-14] ; 相等, 找到了, 这里可以下断
0056E491 E9 59530300 jmp 005A37EF ; 1_.005A37EF
再走着走着
004FFCCC 8B52 1C mov edx,dword ptr ds:[edx+1C]
004FFCCF 0355 FC add edx,dword ptr ss:[ebp-4] ;
004FFCD2 03C2 add eax,edx ;
004FFCD4 8B00 mov eax,dword ptr ds:[eax]
004FFCD6 0345 FC add eax,dword ptr ss:[ebp-4] ; 这一句做完后, eax即是真实的api地址
004FFCD9 - E9 E2C50700 jmp 0057C2C0 ; 1_.0057C2C0
004FFCDE C600 8B mov byte ptr ds:[eax],8B
在oep处写一段代码修复
004C74D0 > BE 68D14E00 mov esi,4ED168
004C74D5 81FE 10D94E00 cmp esi,4ED910
004C74DB 77 20 ja short 004C74FD ; 完成后跳走
004C74DD AD lods dword ptr ds:[esi] ; IAT中取一个出来
004C74DE 85C0 test eax,eax
004C74E0 ^ 74 F3 je short 004C74D5 ; 如果是0,取下一个
004C74E2 3D 00000001 cmp eax,1000000
004C74E7 ^ 77 EC ja short 004C74D5 ; 如果>1000000表示没有加密,放过
004C74E9 56 push esi ;
004C74EA 8BD4 mov edx,esp
004C74EC 83EA 04 sub edx,4
004C74EF 8915 10754C00 mov dword ptr ds:[4C7510],edx ; 保存esp
004C74F5 FFD0 call eax ; 加密的iat跑进去
004C74F7 5E pop esi ; 得到真实的api地址后写回去
004C74F8 8946 FC mov dword ptr ds:[esi-4],eax
004C74FB ^ EB D8 jmp short 004C74D5 ; 继续下一个
004C74FD 90 nop
004FFCD6 0345 FC add eax,dword ptr ss:[ebp-4] ; 这一句做完后, eax即是真实的api地址
004FFCD9 8B25 10754C00 mov esp,dword ptr ds:[4C7510] ; 恢复oep修复代码处的堆栈
004FFCDF C3 retn ; 返回oep处的修复代码
跑完后得到了,全部有效的IAT
可以用ImportREC 扣出来 再次修复原来的1.exe
得到2.exe
五 跨平台
修复跨平台累啊, 壳在oep前 对m.2mwp5l段的N个地方进行了初始化, 存放一些东西
有壳使用的加密的api地址, 有壳GlobalAlloc过的空间入口
南蛮妈妈必须把这些都找出来, 全部清0, 使脱壳后的程序跑到那些地方时好重新初始化
方法就是去掉内存访问异常, 在OD下跑, 一个一个追出来, 体力活
52E9C4 52E9A8 4FFE84 575D20 539A24 575D7C 575D70 52E9DC 52E9D0 575D50
4FFEC4 55E914 5A0704 5A06F8 5776FC 520558 52AED4 5776F0 54FDD8
大概还有一些南蛮妈妈可能没有找全, 找到的地址统统的清0
脱壳后程序启动时有三个线程地址空间, 有2个是anti 和校验的, 1个是检验注册码的
所以关掉2个, 一共3种情况, 都试一次,就知道nop 掉哪2个了
南蛮妈妈 Special Thanks to heXer
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)