壳比较简单,但却是我在15pb学到的第二个壳。详细分析一下,还是能学到很多东西,现在这里将壳中的重点和难点在这里分析一下,并详细演示脱壳的思路,最后给出了OD的脱壳脚本。希望能对一些刚入门的同学一些帮助
知恩莫忘本,这这里要特别感谢一下15bp薛老师以及其他老师的谆谆教导。
由于本壳属于课件资源,因此未经老师许可,就不在这发了。
代码段加密,弹框提示,IAT加密
需要手动修复IAT,因为API被加密,且申请内存空间来保存解密的shellocode,并把内存空间首地址填充到IAT
API地址获取到加密,然后开辟内存保存解密的shellocode,填充IAT表为shellcode 的地址
对API地址进行异或加密
获得解密shellcode
下面汇编代码注释中给出了解释,如果有不明白或者解答不到位的可以在下面留言
由于代码简单,可以用单步或者特征搜索法来找到OEP
查看IAT发现和正常的IAT表不一样
在IAT表的内存下硬件写入断点,看哪个地方开始写入IAT表
找到填充IAT表的位置后,看上下反汇编代码是怎么填充的
发现填充的是申请内存空间的首地址,这个地址里存的是一段异或解密的shellcode
那我们找到真正的api地址然后填充到IAT表
为了复习OD的脚本,虽然本壳简单,写脚本也当做复习了,脚本怎么写的就不说了,注释已经很详细
由于本人水平有限,其中不足之处,还请多多指教,多谢!
004384E0 53 PUSH EBX
004384E1 8BDC MOV EBX,ESP
004384E3 83EC 08 SUB ESP,0x8
004384E6 83E4 F0 AND ESP,0xFFFFFFF0
004384E9 83C4 04 ADD ESP,0x4
004384EC 55 PUSH EBP
004384ED 8B6B 04 MOV EBP,DWORD PTR DS:[EBX+0x4]
004384F0 896C24 04 MOV DWORD PTR SS:[ESP+0x4],EBP
004384F4 8BEC MOV EBP,ESP
004384F6 83EC 48 SUB ESP,0x48
004384F9 A1 20804300 MOV EAX,DWORD PTR DS:[0x438020]
004384FE 33C5 XOR EAX,EBP
00438500 8945 FC MOV DWORD PTR SS:[EBP-0x4],EAX
00438503 56 PUSH ESI
00438504 8B35 40804300 MOV ESI,DWORD PTR DS:[0x438040] ; 02-hello.00400000
0043850A 8D45 C8 LEA EAX,DWORD PTR SS:[EBP-0x38]
0043850D 57 PUSH EDI
0043850E 8B3D 54804300 MOV EDI,DWORD PTR DS:[0x438054]
00438514 50 PUSH EAX
00438515 A1 5C804300 MOV EAX,DWORD PTR DS:[0x43805C]
0043851A 6A 40 PUSH 0x40
0043851C FF35 60804300 PUSH DWORD PTR DS:[0x438060]
00438522 03C6 ADD EAX,ESI
00438524 8975 CC MOV DWORD PTR SS:[EBP-0x34],ESI
00438527 50 PUSH EAX
00438528 C745 C8 0000000>MOV DWORD PTR SS:[EBP-0x38],0x0
0043852F FF15 C0924300 CALL DWORD PTR DS:[0x4392C0] ; VirtualProtect 422000 rwe
00438535 833C37 00 CMP DWORD PTR DS:[EDI+ESI],0x0
00438539 0F84 D7000000 JE 02-hello.00438616
0043853F 8B55 CC MOV EDX,DWORD PTR SS:[EBP-0x34]
00438542 83C6 10 ADD ESI,0x10
00438545 03F7 ADD ESI,EDI
00438547 8975 C4 MOV DWORD PTR SS:[EBP-0x3C],ESI
0043854A 8D9B 00000000 LEA EBX,DWORD PTR DS:[EBX]
00438550 8B46 FC MOV EAX,DWORD PTR DS:[ESI-0x4] ; 遍历INT的模块
00438553 03C2 ADD EAX,EDX
00438555 50 PUSH EAX
00438556 FF15 C8924300 CALL DWORD PTR DS:[0x4392C8] ; LoadLibraryA加载模块地址
0043855C 8B3E MOV EDI,DWORD PTR DS:[ESI]
0043855E 8B55 CC MOV EDX,DWORD PTR SS:[EBP-0x34]
00438561 03FA ADD EDI,EDX
00438563 8945 C0 MOV DWORD PTR SS:[EBP-0x40],EAX
00438566 8B0F MOV ECX,DWORD PTR DS:[EDI]
00438568 85C9 TEST ECX,ECX
0043856A 0F84 93000000 JE 02-hello.00438603
00438570 8BF7 MOV ESI,EDI
00438572 8B07 MOV EAX,DWORD PTR DS:[EDI] ; 遍历模块的api
00438574 83C0 02 ADD EAX,0x2
00438577 85C9 TEST ECX,ECX
00438579 78 75 JS SHORT 02-hello.004385F0
0043857B 03C2 ADD EAX,EDX
0043857D C745 D0 E801000>MOV DWORD PTR SS:[EBP-0x30],0x1E8
00438584 50 PUSH EAX
00438585 FF75 C0 PUSH DWORD PTR SS:[EBP-0x40]
00438588 C745 D4 00E958E>MOV DWORD PTR SS:[EBP-0x2C],0xEB58E900 ; 这是一段解密IAT的shellcode
0043858F 66:C745 D8 01E8 MOV WORD PTR SS:[EBP-0x28],0xE801
00438595 C645 DA B8 MOV BYTE PTR SS:[EBP-0x26],0xB8
00438599 C745 DF EB01153>MOV DWORD PTR SS:[EBP-0x21],0x351501EB
004385A0 C745 E3 1515151>MOV DWORD PTR SS:[EBP-0x1D],0x15151515
004385A7 C745 E7 EB01FF5>MOV DWORD PTR SS:[EBP-0x19],0x50FF01EB
004385AE C745 EB EB02FF1>MOV DWORD PTR SS:[EBP-0x15],0x15FF02EB
004385B5 C645 EF C3 MOV BYTE PTR SS:[EBP-0x11],0xC3
004385B9 FF15 CC924300 CALL DWORD PTR DS:[0x4392CC] ; kernel32.GetProcAddress
004385BF 6A 40 PUSH 0x40
004385C1 68 00300000 PUSH 0x3000
004385C6 6A 20 PUSH 0x20
004385C8 35 15151515 XOR EAX,0x15151515 ; iat异或加密
004385CD 6A 00 PUSH 0x0
004385CF 8945 DB MOV DWORD PTR SS:[EBP-0x25],EAX ; 将地址保存到局部变量[ebp-0x25]
004385D2 FF15 B4924300 CALL DWORD PTR DS:[0x4392B4] ; kernel32.VirtualAlloc
004385D8 F30F6F45 D0 MOVDQU XMM0,DQWORD PTR SS:[EBP-0x30]
004385DD 8B55 CC MOV EDX,DWORD PTR SS:[EBP-0x34]
004385E0 F30F7F00 MOVDQU DQWORD PTR DS:[EAX],XMM0
004385E4 F30F6F45 E0 MOVDQU XMM0,DQWORD PTR SS:[EBP-0x20]
004385E9 F30F7F40 10 MOVDQU DQWORD PTR DS:[EAX+0x10],XMM0
004385EE 8907 MOV DWORD PTR DS:[EDI],EAX ; 将api地址保存到iat中
004385F0 8B4E 04 MOV ECX,DWORD PTR DS:[ESI+0x4]
004385F3 83C6 04 ADD ESI,0x4
004385F6 8BFE MOV EDI,ESI
004385F8 85C9 TEST ECX,ECX
004385FA ^ 0F85 72FFFFFF JNZ 02-hello.00438572
00438600 8B75 C4 MOV ESI,DWORD PTR SS:[EBP-0x3C]
00438603 83C6 14 ADD ESI,0x14
00438606 8975 C4 MOV DWORD PTR SS:[EBP-0x3C],ESI
00438609 837E F0 00 CMP DWORD PTR DS:[ESI-0x10],0x0
0043860D ^ 0F85 3DFFFFFF JNZ 02-hello.00438550
00438613 8B75 CC MOV ESI,DWORD PTR SS:[EBP-0x34]
00438616 8D45 C8 LEA EAX,DWORD PTR SS:[EBP-0x38]
00438619 50 PUSH EAX
0043861A FF75 C8 PUSH DWORD PTR SS:[EBP-0x38]
0043861D A1 5C804300 MOV EAX,DWORD PTR DS:[0x43805C]
00438622 FF35 60804300 PUSH DWORD PTR DS:[0x438060]
00438628 03C6 ADD EAX,ESI
0043862A 50 PUSH EAX
0043862B FF15 C0924300 CALL DWORD PTR DS:[0x4392C0] ; kernel32.VirtualProtect
00438631 8B4D FC MOV ECX,DWORD PTR SS:[EBP-0x4]
00438634 5F POP EDI
00438635 33CD XOR ECX,EBP
00438637 5E POP ESI
00438638 E8 07000000 CALL 02-hello.00438644
0043863D 8BE5 MOV ESP,EBP
0043863F 5D POP EBP
00438640 8BE3 MOV ESP,EBX
00438642 5B POP EBX
00438643 C3 RETN
// 1. 定义变量
VAR dwWriteIATAddr // 填充IAT地址的下一行地址
VAR dwGetAPIAddr // 获取到了API地址下一行地址
VAR dwOEP // 原始OEP
VAR dwTmp // 临时变量
// 2. 初始化变量
MOV dwOEP, 00409486
MOV dwWriteIATAddr,4385f0
MOV dwGetAPIAddr, 4385bf
// 3. 清除所有断点
BPHWC
BPMC
BC
// 4. 设置断点
BPHWS dwWriteIATAddr, "x"
BPHWS dwGetAPIAddr, "x"
BPHWS dwOEP, "x"
// 5. 循环判断
LOOP0:
RUN
CMP eip,dwGetAPIAddr
JNZ NEXT1
MOV dwTmp,eax
JMP LOOP0
NEXT1:
CMP eip,dwWriteIATAddr
JNZ NEXT3
MOV [edi],dwTmp
JMP LOOP0
NEXT3:
CMP eip,dwOEP
JNZ LOOP0
MSG "到达OEP!"
壳比较简单,但却是我在15pb学到的第二个壳。详细分析一下,还是能学到很多东西,现在这里将壳中的重点和难点在这里分析一下,并详细演示脱壳的思路,最后给出了OD的脱壳脚本。希望能对一些刚入门的同学一些帮助
知恩莫忘本,这这里要特别感谢一下15bp薛老师以及其他老师的谆谆教导。
由于本壳属于课件资源,因此未经老师许可,就不在这发了。
API地址获取到加密,然后开辟内存保存解密的shellocode,填充IAT表为shellcode 的地址
- 获取API的地址
- 修改内存属性
- 代码段解密
- 弹框提示
- 填充IAT表
API地址获取到加密,然后开辟内存保存解密的shellocode,填充IAT表为shellcode 的地址
- 跳到原始OEP
- 通过FS[30]获得kernel32.dll的基地址
- 遍历kernel32.dll的导出表获得GetProAddress的地址
- 通过GetProcAddress获得LoadLibrary的地址
- LoadLibrary加载user32.dll
- 通过GetProcAddress获得其他API的地址
Messagebox
ExitPorcess
GetMoudleHandleA
VirtualProtect
VirtualAlloc
- 通过INT获得模块名和导入API地址
-
对API地址进行异或加密
-
获得解密shellcode
- VirtualAlloc开辟内存用来存放shellcode
- 将申请的内存地址填充到IAT
-
查看IAT发现和正常的IAT表不一样
-
在IAT表的内存下硬件写入断点,看哪个地方开始写入IAT表
-
找到填充IAT表的位置后,看上下反汇编代码是怎么填充的
发现填充的是申请内存空间的首地址,这个地址里存的是一段异或解密的shellcode
-
那我们找到真正的api地址然后填充到IAT表
概述
1. 功能
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
最后于 2019-5-13 18:24
被21花生编辑
,原因: 标题和内容更贴切