首页
论坛
专栏
课程

[原创]一个自写IAT加密壳的详细分析(含脱壳脚本)

2019-5-12 19:36 1022

[原创]一个自写IAT加密壳的详细分析(含脱壳脚本)

2019-5-12 19:36
1022

目录

概述

壳比较简单,但却是我在15pb学到的第二个壳。详细分析一下,还是能学到很多东西,现在这里将壳中的重点和难点在这里分析一下,并详细演示脱壳的思路,最后给出了OD的脱壳脚本。希望能对一些刚入门的同学一些帮助

知恩莫忘本,这这里要特别感谢一下15bp薛老师以及其他老师的谆谆教导。

由于本壳属于课件资源,因此未经老师许可,就不在这发了。

1. 功能

代码段加密,弹框提示,IAT加密

2. 难点

需要手动修复IAT,因为API被加密,且申请内存空间来保存解密的shellocode,并把内存空间首地址填充到IAT

3. 壳的流程

  1. 获取API的地址
  2. 修改内存属性
  3. 代码段解密
  4. 弹框提示
  5. 填充IAT表

    API地址获取到加密,然后开辟内存保存解密的shellocode,填充IAT表为shellcode 的地址

  6. 跳到原始OEP
    图片描述

壳代码反汇编分析

1. 获取壳代码所需要的API地址

  1. 通过FS[30]获得kernel32.dll的基地址
  2. 遍历kernel32.dll的导出表获得GetProAddress的地址
  3. 通过GetProcAddress获得LoadLibrary的地址
  4. LoadLibrary加载user32.dll
  5. 通过GetProcAddress获得其他API的地址
    Messagebox
    ExitPorcess
    GetMoudleHandleA
    VirtualProtect
    VirtualAlloc
    图片描述

2. 代码段解密:

图片描述

3. IAT解密与填充

  1. 通过INT获得模块名和导入API地址
  2. 对API地址进行异或加密

  3. 获得解密shellcode
    图片描述

  4. VirtualAlloc开辟内存用来存放shellcode
  5. 将申请的内存地址填充到IAT

下面汇编代码注释中给出了解释,如果有不明白或者解答不到位的可以在下面留言

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. 找到OEP

由于代码简单,可以用单步或者特征搜索法来找到OEP

2. 修复IAT

  1. 查看IAT发现和正常的IAT表不一样
    图片描述
    图片描述

  2. 在IAT表的内存下硬件写入断点,看哪个地方开始写入IAT表
    图片描述
    图片描述

  3. 找到填充IAT表的位置后,看上下反汇编代码是怎么填充的
    发现填充的是申请内存空间的首地址,这个地址里存的是一段异或解密的shellcode

    图片描述

  4. 那我们找到真正的api地址然后填充到IAT表
    图片描述

3. Dump

图片描述

4. ImportREC修复导入表

图片描述

5. 转储到刚才dump出来的文件中

写脱壳脚本

为了复习OD的脚本,虽然本壳简单,写脚本也当做复习了,脚本怎么写的就不说了,注释已经很详细

// 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!"

由于本人水平有限,其中不足之处,还请多多指教,多谢!



[推荐]看雪企服平台,提供安全分析、定制项目开发、APP等级保护、渗透测试等安全服务!

最后于 2019-5-13 18:24 被lcdxsun编辑 ,原因: 标题和内容更贴切
上一主题 下一主题
最新回复 (4)
泪落晨曦 2019-5-13 10:03
2
0
楼主太强了,能不能把demo也上传一下
大锅炖鲲 2019-5-13 17:38
3
0
66666
xingbing 2019-5-15 22:49
4
0
太强大了,学习。
lcdxsun 1 2019-5-16 17:54
5
0
本来想每条指令都写上注释的,但是这个壳的汇编实在简单,感觉没有必要,重要的是思路,壳代码的执行思路与脱壳思路,比如壳代码是如何找到API地址的,IAT是如何修复的等等
游客
登录 | 注册 方可回帖
返回