如何到达此壳的oep?
一个非常老的壳,论坛脱壳练习用的例子,只能在XP上运行,请在xp虚拟机上测试。求助以下问题:
1
如图:
https://im.gurl.eu.org/file/3103c5244311a387a4c77.png
“在访问上设置中断(F2)”和下方的那个“设置内存访问断点”这两者有什么区别?
2
如何到达OEP?使用什么方法,并说明为什么要使用这个方法。
3
以本例这个壳来说,如何分析它到达OEP,大佬们都是如何下手分析的?
链接:https://www.123pan.com/s/YL29-ggVOh.html
谢谢各位大佬。
本帖最后由 solly 于 2024-3-9 17:33 编辑
朱朱你堕落了 发表于 2024-3-9 15:20
solly老师,怎么分析出来是分段解密的?
1
“先在0x00401200, 0x00401400, 0x00401800, 0x00401A00 下4 ...
1、执行一段代码就可看出来,大概就是解密一段,执行一段的意思,先解密一部分壳代码,再执行这段代码解密另一部分代码。。。。。。最后才解密crackme的代码。
2、因为代码段在0x00401000~0x00402000之间,所以比较均匀地选4个地址呀,这跟那个猜数字游戏一个意思(硬件断点最多也只能选4个)。后面选3个也是一个意思,选几个随意,范围小了就少选一点,只要能最后确定最终解密点就可以了,这样操作跟踪量小很多。
3、选地址就是为了缩小并最终确定范围,怎么选没规定,一般是均匀分布。
4、这种操作并不是适于所有壳,每种壳都有相应的不同办法。 本帖最后由 solly 于 2024-3-8 20:22 编辑
我是在x32dbg中直接运行,然后在 ExitProcess 下断点,然后关闭crackme,断在ExitProcess,然后在堆栈中回溯,就可定位msvcrt的exit()函数调用处(0x00401838),往上走一点就是OEP:0x00401700,填好OEP,点“IAT自动搜索”,当询问普通和高级搜索结果不一致时,选择高级搜索就可找到IAT,再点“获取导入”就有了。然后就是dump出来修复一下即可:UnPackMe4_dump_SCY.exe,这个就是可运行的了。 solly 发表于 2024-3-8 20:10
我是在x32dbg中直接运行,然后在 ExitProcess 下断点,然后关闭crackme,断在ExitProcess,然后在堆栈中回 ...
经测试,大佬的方法可行,只是为什么要下ExitProcess断点?而不是其他API函数呢? 其它的不好激活呀,退出是最好激活的,并且Vc的exit()调用前面就是调用main(),再往前是C的初始化,再往往前就是OEP了。 solly 发表于 2024-3-8 21:09
其它的不好激活呀,退出是最好激活的,并且Vc的exit()调用前面就是调用main(),再往前是C的初始化,再往往 ...
solly老师是每年春节的出题者,C++编程水平自然了得,从VC程序自身特点特殊函数下手来找OEP,是个巧妙的方法,不过,如果这个程序本身是VB或delphi程序,那么ExitProcess这种方法是否还行?
如果不行的话,那么只能针对壳来搞了,我也想知道如何从壳的角度来到达OEP。 本帖最后由 solly 于 2024-3-9 10:54 编辑
这是一个分段解密的壳,看程序节信息,只有0x00401000~0x00402000之间是可执行,所以在先在0x00401200, 0x00401400, 0x00401800, 0x00401A00 下4个硬件写入断点,然后执行crackme,最终前面3个会断下来,最后一个没有断下来,表示没有用到,所以确定解密过程在 0x00401800~00401A00之间结束,在这个区间内继续下3个硬件断点再来一次:如 0x00401880, 0x00401900, 0x00401980,最后又是前2个断下来了,再就是在 0x00401900~0x00401980内下断点了,可以看到这个区间后面都是0了,应该是代码段要结束了,所以在最后一个非0字节下一个断点吧,然后执行,断在如下处:
004093F0 | C00A 03 | ROR BYTE PTR DS:,3 |
004093F3 | 87DD | XCHG EBP,EBX |
004093F5 | 56 | PUSH ESI |
然后F7一路逢call必进,到下面这里:
0040958D | 40 | INC EAX |
0040958E | 60 | PUSHAD |
0040958F | 56 | PUSH ESI |
00409590 | 83EC FC | SUB ESP,FFFFFFFC |
00409593 | 83C4 20 | ADD ESP,20 |
00409596 | 48 | DEC EAX |
00409597 | 83C2 01 | ADD EDX,1 |
0040959A | 83C1 FF | ADD ECX,FFFFFFFF |
0040959D | 75 8B | JNE unpackme4.40952A |
这里是恢复 IAT 了,一个循环,EAX++,ECX--,在下面下断点:
0040959F | 68 2386F7DA | PUSH DAF78623 |
F9执行。断下后又是一路F7,来到这里:
00409676 | 40 | INC EAX |
00409677 | 48 | DEC EAX |
00409678 | 83C4 20 | ADD ESP,20 |
0040967B | 48 | DEC EAX |
0040967C | C00A 04 | ROR BYTE PTR DS:,4 |
0040967F | E8 01000000 | CALL unpackme4.409685 |
00409684 | 5B | POP EBX |
00409685 | E8 00000000 | CALL unpackme4.40968A | call $0
0040968A | C70424 2B1BEB32 | MOV DWORD PTR SS:,32EB1B2B | :&L"ALLUSERSPROFILE=C:\\Documents and Settings\\All Users"
00409691 | 81C0 92CD3C56 | ADD EAX,563CCD92 |
00409697 | 81E8 92CD3C56 | SUB EAX,563CCD92 |
0040969D | 83EC FC | SUB ESP,FFFFFFFC |
004096A0 | 83EC FC | SUB ESP,FFFFFFFC |
004096A3 | 83C2 01 | ADD EDX,1 |
004096A6 | 83C1 FF | ADD ECX,FFFFFFFF |
004096A9 | 0F85 74FFFFFF | JNE unpackme4.409623 |
004096AF | 68 F864F7B8 | PUSH B8F764F8 |
又是一个循环,EAX++,ECX--,又在循环后下面F2断点,F9执行,断下后又是一路F7,逢call必进,来到这里:
004097F0 | C70424 2DC2EB67 | MOV DWORD PTR SS:,67EBC22D | :&L"ALLUSERSPROFILE=C:\\Documents and Settings\\All Users"
004097F7 | 83EC FC | SUB ESP,FFFFFFFC |
004097FA | 4B | DEC EBX |
004097FB | 81EA 38A9741A | SUB EDX,1A74A938 |
00409801 | 83EA FF | SUB EDX,FFFFFFFF |
00409804 | 83C1 FF | ADD ECX,FFFFFFFF |
00409807 | 85C9 | TEST ECX,ECX |
00409809 | 0F85 36FFFFFF | JNE unpackme4.409745 |
0040980F | 57 | PUSH EDI |
00409810 | 56 | PUSH ESI |
00409811 | E8 D8000000 | CALL unpackme4.4098EE |
00409816 | A1 58214000 | MOV EAX,DWORD PTR DS: |
0040981B | C3 | RET |
0040981C | 90 | NOP |
最后一个循环了吧,在循环后面(0x0040980F)下 F2 断点,F9执行,断下后,F7进入 call 0x004098EE:
004098EE | 5E | POP ESI |
004098EF | BF 00104000 | MOV EDI,<unpackme4.EntryPoint> | edi:EntryPoint
004098F4 | B9 36000000 | MOV ECX,36 | 36:'6'
004098F9 | F3:A5 | REP MOVSD |
004098FB | 5E | POP ESI |
004098FC | 5F | POP EDI | edi:EntryPoint
这里进行壳的入口代码恢复为crackme的原始代码。F8一路执行,来到这里:
0040990F | 3E:8B45 0C | MOV EAX,DWORD PTR DS: |
00409913 | 05 00004000 | ADD EAX,unpackme4.400000 |
00409918 | 50 | PUSH EAX |
00409919 | FFD7 | CALL EDI |
0040991B | 83EC 04 | SUB ESP,4 |
0040991E | 50 | PUSH EAX |
0040991F | 33DB | XOR EBX,EBX |
00409921 | 8B45 00 | MOV EAX,DWORD PTR SS: |
00409924 | 8B8418 00004000 | MOV EAX,DWORD PTR DS: |
0040992B | A9 00000080 | TEST EAX,80000000 |
00409930 | 74 07 | JE unpackme4.409939 |
00409932 | 25 FFFF0000 | AND EAX,FFFF |
00409937 | EB 09 | JMP unpackme4.409942 |
00409939 | 85C0 | TEST EAX,EAX |
0040993B | 74 1D | JE unpackme4.40995A |
0040993D | 05 02004000 | ADD EAX,unpackme4.400002 |
00409942 | 894424 04 | MOV DWORD PTR SS:,EAX |
00409946 | FFD6 | CALL ESI |
00409948 | 83EC 08 | SUB ESP,8 |
0040994B | 8B4D 10 | MOV ECX,DWORD PTR SS: |
0040994E | 898419 00004000 | MOV DWORD PTR DS:,EAX |
00409955 | 83C3 04 | ADD EBX,4 |
00409958 | EB C7 | JMP unpackme4.409921 |
0040995A | 83C4 08 | ADD ESP,8 |
0040995D | 83C5 14 | ADD EBP,14 |
00409960 | 837D 10 00 | CMP DWORD PTR SS:,0 |
00409964 | 75 A9 | JNE unpackme4.40990F |
这里是加载DLL的导出函数的入口地址了。在大循环后面(0x00409966)下 F2 断点,F9执行,再一路 F7 来到这里:
00409995 | EB 05 | JMP unpackme4.40999C |
00409997 | 41 | INC ECX | ecx:"姍@"
00409998 | F6F9 | IDIV CL |
0040999A | 2F | DAS |
0040999B | 55 | PUSH EBP |
0040999C | 83EC FC | SUB ESP,FFFFFFFC |
0040999F | 83EC E0 | SUB ESP,FFFFFFE0 |
004099A2 | C3 | RET |
一路F8, ret 后到这里:
0040998A | 60 | PUSHAD |
0040998B | E8 05000000 | CALL unpackme4.409995 |
00409990 | 83B40D 6A18EB05 41 | XOR DWORD PTR SS:,41 |
然后还是一路 F7 ,ret 和call几次后,就会到这里:
00407000 | 0F31 | RDTSC |
00407002 | 33C9 | XOR ECX,ECX |
00407004 | 03C8 | ADD ECX,EAX |
00407006 | EB 58 | JMP unpackme4.407060 |
这里是时钟反调试,后面还有一个 RDTSC 。还是一路 F7 到这里:
00407060 | 0F31 | RDTSC |
00407062 | 2BC1 | SUB EAX,ECX |
00407064 | 3D FF0F0000 | CMP EAX,FFF |
00407069 | 0F83 A3000000 | JAE unpackme4.407112 |
0040706F | E9 84000000 | JMP unpackme4.4070F8 |
这里的 JAE跳转是反调试用的,不能跳转,下面的那个 JMP 才是正确的线路。执行这个 JMP 0x004070F8,来到这里:
004070F8 | B8 00174000 | MOV EAX,unpackme4.401700 |
004070FD | 33F6 | XOR ESI,ESI | esi:&L"ALLUSERSPROFILE=C:\\Documents and Settings\\All Users"
004070FF | 33DB | XOR EBX,EBX |
00407101 | 8A1C06 | MOV BL,BYTE PTR DS: |
00407104 | 80EB FF | SUB BL,FF |
00407107 | 881C06 | MOV BYTE PTR DS:,BL |
0040710A | 46 | INC ESI | esi:&L"ALLUSERSPROFILE=C:\\Documents and Settings\\All Users"
0040710B | 83FE 32 | CMP ESI,32 | esi:&L"ALLUSERSPROFILE=C:\\Documents and Settings\\All Users", 32:'2'
0040710E | 75 F1 | JNE unpackme4.407101 |
00407110 | FFE0 | JMP EAX |
就可以看到 OEP 了。执行最后那条指令:
00407110 | FFE0 | JMP EAX |
你就到 OEP 去了。
另外,delphi 和 VB 的入口也很好找的,特征都很明显。
@solly
分析的太好了,有点有据,充分暴露了各个阶段该提取的程序特性。
强烈建议加精华。 solly 发表于 2024-3-9 10:06
这是一个分段解密的壳,看程序节信息,只有0x00401000~0x00402000之间是可执行,所以在先在0x00401200, 0x0 ...
solly老师,怎么分析出来是分段解密的?
1
“先在0x00401200, 0x00401400, 0x00401800, 0x00401A00 下4个硬件写入断点”
这四个地址是程序中固定的,还是自己随便定义的,只是为了方便自己确定是哪些段解密。
如果是自己随便定义,那么是否我也可以这么设置,如:
00401100, 0x00401500, 0x00401700, 0x00401B00,只要分成几段,缩小范围就行了?
2
同样,这三个“0x00401880, 0x00401900, 0x00401980”是怎么来的?也是和上面一样吗?
页:
[1]