首页
社区
课程
招聘
[原创]对PeCompact 2.x--IAT加密壳详解
发表于: 2009-7-13 01:31 6902

[原创]对PeCompact 2.x--IAT加密壳详解

2009-7-13 01:31
6902

最近学习脱壳,看了那个对一个IAT加密壳的分析,发现有很多东西看的莫名其妙,,说实话水平不行的原因,所以写这个帮助跟我一样的初学者
附件去这个求助贴里下吧:http://bbs.pediy.com/showthread.php?t=92330
1.首先设置调试器,异常,取消内存访问异常的对勾,方便在那个向0地址写入的时候停下,F9。

看堆栈窗口:

00720F8C:异常处理回调函数地址,记下,先Ctrl+G,跳转到该地址,F2下断,防止跑飞。
2.shift+F7进入异常发生时的系统代码处

这时堆栈窗口:

3.F9,断在刚才的00720F8C异常处理回调函数
00720F8C    B8 11FD71F0     MOV EAX,F071FD11
00720F91    8D88 9E120010   LEA ECX,DWORD PTR DS:[EAX+1000129E]
00720F97    8941 01         MOV DWORD PTR DS:[ECX+1],EAX
00720F9A    8B5424 04       MOV EDX,DWORD PTR SS:[ESP+4]             ; 最后一个参数,EXCEPTION_RECORD结构
00720F9E    8B52 0C         MOV EDX,DWORD PTR DS:[EDX+C]             ; 取异常发生地址
00720FA1    C602 E9         MOV BYTE PTR DS:[EDX],0E9                ; 放入指令JMP
00720FA4    83C2 05         ADD EDX,5
00720FA7    2BCA            SUB ECX,EDX                              ; 跳转到00720FAF处,改变程序流程
00720FA9    894A FC         MOV DWORD PTR DS:[EDX-4],ECX             ; 写入jmp地址
00720FAC    33C0            XOR EAX,EAX
00720FAE    C3              RETN                                     ; 异常返回,跳转到新EIP处
00720FAF    B8 78563412     MOV EAX,12345678
00720FB4    64:8F05 0000000>POP DWORD PTR FS:[0]                     ; 恢复原来的SEH链
00720FBB    83C4 04         ADD ESP,4                                ; 平衡堆栈

反复看了好多次,终于知道为什么要在00720FAF处下断点了,高手写的文章,总是把我们菜菜弄的晕头转向
4.在00720FAF处F2下断,F9,向下拉:
里面有调用VirtualAlloc分配临时空间,有call edi,这就是有些脱壳教程中选择在VirtualAlloc处下断点,然后再搜索代码 call edi的原因了。
直接拉到最后的jmp eax处下断,F9,F8就到入口点了,这时候dump,IAT的kernel32.dll的部分是加密的,需要修复一下。
5.重新运行程序,在命令行处键入D 5d4090, 在此处下硬件写入断点,调试器设置那,把忽略“内存访问异常”对勾选上,F9,F9,F9.......最后跑飞的那个
6.在那个003D14A7处下硬件执行断点,重新运行后断在这里
003D14A7    C783 CC1A0010 0>MOV DWORD PTR DS:[EBX+10001ACC],0
003D14B1    8B02            MOV EAX,DWORD PTR DS:[EDX] ;edx就是那个OriginalFirstThunk指向的数组
003D14B3    85C0            TEST EAX,EAX
003D14B5    74 67           JE SHORT 003D151E
003D14B7    52              PUSH EDX
003D14B8    8983 CC1A0010   MOV DWORD PTR DS:[EBX+10001ACC],EAX
003D14BE    A9 00000080     TEST EAX,80000000 ;函数导入方式
003D14C3    74 09           JE SHORT 003D14CE
003D14C5    25 FFFFFF7F     AND EAX,7FFFFFFF
003D14CA    6A 00           PUSH 0
003D14CC    EB 0E           JMP SHORT 003D14DC
003D14CE    8B4D 08         MOV ECX,DWORD PTR SS:[EBP+8]
003D14D1    0341 08         ADD EAX,DWORD PTR DS:[ECX+8] ;eax是个rva+00400000=IMAGE_IMPORT_BY_NAME结构
003D14D4    33C9            XOR ECX,ECX
003D14D6    66:8B08         MOV CX,WORD PTR DS:[EAX]  ;取函数序号
003D14D9    51              PUSH ECX
003D14DA    40              INC EAX
003D14DB    40              INC EAX
003D14DC    50              PUSH EAX ;取函数名字符串
003D14DD    FF75 FC         PUSH DWORD PTR SS:[EBP-4]
003D14E0    FF93 0A210010   CALL DWORD PTR DS:[EBX+1000210A]  加密函数
003D14E6    5A              POP EDX
003D14E7    50              PUSH EAX    ;eax就是返回的要放入IAT的新地址
003D14E8    8B02            MOV EAX,DWORD PTR DS:[EDX]
003D14EA    A9 00000080     TEST EAX,80000000
003D14EF    75 18           JNZ SHORT 003D1509
;下面是一堆清零操作,把函数序号和函数名字符串都清零了,
003D14F1    8B4D 08         MOV ECX,DWORD PTR SS:[EBP+8]
003D14F4    0341 08         ADD EAX,DWORD PTR DS:[ECX+8]
003D14F7    C600 00         MOV BYTE PTR DS:[EAX],0
003D14FA    40              INC EAX
003D14FB    C600 00         MOV BYTE PTR DS:[EAX],0
003D14FE    40              INC EAX
003D14FF    8A08            MOV CL,BYTE PTR DS:[EAX]
003D1501    C600 00         MOV BYTE PTR DS:[EAX],0
003D1504    40              INC EAX
003D1505    84C9            TEST CL,CL
003D1507  ^ 75 F6           JNZ SHORT 003D14FF
003D1509    58              POP EAX
003D150A    85C0            TEST EAX,EAX
003D150C  ^ 0F84 3FFFFFFF   JE 003D1451
;在IAT处写入新地址
003D1512    8906            MOV DWORD PTR DS:[ESI],EAX
;把OringinalFirstThunk也改了
003D1514    8902            MOV DWORD PTR DS:[EDX],EAX
003D1516    83C2 04         ADD EDX,4
003D1519    83C6 04         ADD ESI,4
;循环
003D151C  ^ EB 89           JMP SHORT 003D14A7
003D151E    33C0            XOR EAX,EAX

注意:
下面是OriginalFirstThunk指向数组的内容:

加上00400000后指向下面的数组:

6.要修复IAT就要让加密函数返回正确的函数地址,所以在加密函数处跟进
003D00DD    55              PUSH EBP
003D00DE    8BEC            MOV EBP,ESP
003D00E0    83C4 FC         ADD ESP,-4
003D00E3    53              PUSH EBX
003D00E4    57              PUSH EDI
003D00E5    56              PUSH ESI
003D00E6    E8 00000000     CALL 003D00EB                            ; 返回函数字符串
003D00EB    5B              POP EBX
003D00EC    81EB FE103E00   SUB EBX,3E10FE
003D00F2    FF75 10         PUSH DWORD PTR SS:[EBP+10]               ; 函数序号
003D00F5    FF75 0C         PUSH DWORD PTR SS:[EBP+C]                ; 函数名
003D00F8    FF75 08         PUSH DWORD PTR SS:[EBP+8]                ; 7C800000
003D00FB    FF93 2F103E00   CALL DWORD PTR DS:[EBX+3E102F]
003D0101    8945 FC         MOV DWORD PTR SS:[EBP-4],EAX             ; 保存返回的函数真实地址
003D0104    8B8B 61103E00   MOV ECX,DWORD PTR DS:[EBX+3E1061]
003D010A    3B4D 08         CMP ECX,DWORD PTR SS:[EBP+8]
003D010D    75 63           JNZ SHORT 003D0172
003D010F    33C0            XOR EAX,EAX
003D0111    0383 43103E00   ADD EAX,DWORD PTR DS:[EBX+3E1043]        ; 注意
003D0117    74 0D           JE SHORT 003D0126
003D0119    05 07000000     ADD EAX,7
003D011E    3B83 47103E00   CMP EAX,DWORD PTR DS:[EBX+3E1047]
003D0124    72 25           JB SHORT 003D014B
003D0126    6A 40           PUSH 40
003D0128    68 00100000     PUSH 1000
003D012D    68 00100000     PUSH 1000
003D0132    6A 00           PUSH 0
003D0134    FF93 3F103E00   CALL DWORD PTR DS:[EBX+3E103F]           ; 分配缓冲区
003D013A    8983 43103E00   MOV DWORD PTR DS:[EBX+3E1043],EAX        ; 保存返回地址=加密的IAT地址
003D0140    05 00100000     ADD EAX,1000
003D0145    8983 47103E00   MOV DWORD PTR DS:[EBX+3E1047],EAX
003D014B    8DBB E9103E00   LEA EDI,DWORD PTR DS:[EBX+3E10E9]
003D0151    8BF7            MOV ESI,EDI
003D0153    81C7 01000000   ADD EDI,1
003D0159    8B45 FC         MOV EAX,DWORD PTR SS:[EBP-4]             ; 取真实函数地址
003D015C    AB              STOS DWORD PTR ES:[EDI]
003D015D    8BBB 43103E00   MOV EDI,DWORD PTR DS:[EBX+3E1043]        ; 取加密值
003D0163    8BC7            MOV EAX,EDI
003D0165    B9 07000000     MOV ECX,7                                ; 循环次数
003D016A    018B 43103E00   ADD DWORD PTR DS:[EBX+3E1043],ECX        ; 下一个双字
003D0170    F3:A4           REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[>; 加密地址里内容就是简单跳转到真实地址
003D0172    5E              POP ESI
003D0173    5F              POP EDI
003D0174    5B              POP EBX
003D0175    C9              LEAVE
003D0176    C2 0C00         RETN 0C
要绕过加密处理,我的方法是在003D015C处修改成jmp 003D0172,这样返回的EAX就是正确的函数地址了,不知道为什么前面的帖把绕过解密的步骤一笔带过,根本看不出所以然来,难道是考验新人
步骤:
重新运行,还使用刚才的那个003D14A7硬件执行断点,同时在达到OEP之前的那个jmp eax处下断,
F9运行,到达硬件断点后,ctrl+G 003D015C到修改处修改代码,删除硬件断点,F9.单步到OEP处,dump,fix即可。
写的比较乱,参照上个IAT加密帖看吧,高手飘过


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
  • 1.jpg (31.78kb,298次下载)
  • 2.jpg (27.93kb,297次下载)
  • 3.jpg (32.79kb,298次下载)
  • 4.jpg (17.72kb,298次下载)
  • 6.jpg (53.82kb,297次下载)
  • 7.jpg (56.07kb,297次下载)
收藏
免费 7
支持
分享
最新回复 (1)
雪    币: 48
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
哥们你说的也不是很清楚,照你的步骤跟踪,常常迷失方向!~  很多数据也没有说怎么得来的
2010-4-24 11:05
0
游客
登录 | 注册 方可回帖
返回
//