脱壳 ASProtect v1.31 (手动修复IAT乱序)

admin 2024年4月2日11:51:07评论5 views字数 8990阅读29分58秒阅读模式

工具:OD,PEID

找 OEP

  1. OD 载入程序, 忽略所有异常, F9 运行, 退出程序, 打开 LOG 窗口, 看一下有多少非法访问内存和 INT3中断:

0096F4FB 访问违例: 写入到 [00000000]
0096E78A 访问违例: 写入到 [00000000]
0096E8B9 访问违例: 写入到 [00000000]
7C8106F9 新线程 ID 000005E8 已创建
009646A6 访问违例: 写入到 [00000000]
0096EC10 访问违例: 写入到 [00000000]
009646E9 访问违例: 写入到 [00000000]
0096ED22 访问违例: 写入到 [00000000]
0096CB31 访问违例: 写入到 [00000000]
0096CC18 访问违例: 写入到 [00000000]
0096CCE7 访问违例: 写入到 [00000000]
0096CEFE 访问违例: 写入到 [00000000]
0096CFD2 访问违例: 写入到 [00000000]
0096D1A8 访问违例: 写入到 [00000000]
0096EE58 访问违例: 写入到 [00000000]
0096EF41 访问违例: 写入到 [00000000]
0096F122 访问违例: 写入到 [00000000]
0096C034 INT3 命令位于 0096C034
0096C721 访问违例: 写入到 [00000000]
0096C8F3 访问违例: 写入到 [00000000]
0096D27E 访问违例: 写入到 [00000000]
0096D52A 访问违例: 写入到 [00000000]
0096E01B 访问违例: 写入到 [00000000]
0096D5EB 访问违例: 写入到 [00000000]
0096D6CD 访问违例: 写入到 [00000000]

0096D7A2 访问违例: 写入到 [00000000]

0096D9B1 访问违例: 写入到 [00000000]

009654FC 访问违例: 写入到 [00000000]
0096DB8D 访问违例: 写入到 [00000000]
0096DC5D 访问违例: 写入到 [00000000]
0096DD13 访问违例: 写入到 [00000000]
0096F645 访问违例: 写入到 [00000000]
0096F7AE 访问违例: 写入到 [00000000]
0096FA88 访问违例: 写入到 [00000000]
0096FD28 访问违例: 写入到 [00000000]
0096FEFA 访问违例: 写入到 [00000000]
0097019F 访问违例: 写入到 [00000000]
0096C034 INT3 命令位于 0096C034
0096C096 INT3 命令位于 0096C096
0096E400 访问违例: 写入到 [00000000]
0096E56E 访问违例: 写入到 [00000000]

我们可以一下就看出来 INT3 中断只有 3 次,所以我们就有 INT3 中断来找我们的 OEP设置 OD,忽略 INT3 中断,重载OD,SHIFT+F9 按 3 次:

0096C097 90 nop
0096C098 EB 01 jmp short 0096C09B
0096C09A 6966 81 FE47467imul esp,dword ptr ds:[esi-7F],744647FE
0096C0A1 05 31C040EB add eax,EB40C031
0096C0A6 0231 add dh,byte ptr ds:[ecx]
0096C0A8 C031 DB sal byte ptr ds:[ecx],0DB
0096C0AB 64:8F03 pop dword ptr fs:[ebx]
0096C0AE 83C4 04 add esp,4
0096C0B1 EB 01 jmp short 0096C0B4
  1. 打开内存镜像,对代码段下 F2 断点, SHIFT+F9,来到 OEP:

00401000 6A 00 push 0
00401002 E8 0D010000 call ASProtec.00401114
00401007 A3 00304000 mov dword ptr ds:[403000],eax
0040100C 6A 00 push 0
0040100E 68 29104000 push ASProtec.00401029
00401013 6A 00 push 0
00401015 6A 65 push 65
00401017 FF35 00304000 push dword ptr ds:[403000]

修复 IAT

  1. CTRL+B 搜索:FF 25 ,我们来到这里:---------->(问题一:为什么这里要查找 FF25 型???)0040110E - FF25

08049C00 jmp dword ptr ds:[9C0408] ; kernel32.ExitProcess
00401114 E8 1BF25B00 call 009C0334
00401119 9A FF257004 9C0call far 009C:047025FF
00401120 E8 5F2C5C00 call 009C3D84
00401125 2AFF sub bh,bh
00401127 25 88049C00 and eax,9C0488
0040112C  FF25 F83D9C00 jmp dword ptr ds:[9C3DF8]
00401132  FF25 603E9C00 jmp dword ptr ds:[9C3E60]
00401138  FF25 982E9C00 jmp dword ptr ds:[9C2E98]
0040113E  FF25 DC419C00 jmp dword ptr ds:[9C41DC]
00401144  FF25 18449C00 jmp dword ptr ds:[9C4418]
0040114A  FF25 BC449C00 jmp dword ptr ds:[9C44BC]
00401150  FF25 40479C00 jmp dword ptr ds:[9C4740]
00401156  FF25 B84A9C00 jmp dword ptr ds:[9C4AB8]

好的现在我们看到只有第一个 API 函数没有被处理其他的都被处理了,首先,下面的 FF25 型的 jmp [xx]被壳处理为 E8 型的 call xx,然后我们看到下面的这些 FF25 jmp 虽然没有被壳处理,但是我们看到他的API 地址被壳转移到其他地方了,所以我们可以对第一处:0040110E,下内存写入断点。

  1. 重载 OD,忽略所有异常, 在反汇编窗口 Ctrl+G 搜索:0040110E,然后在 0040110E 到 0040115B 下内存写入断点------>(问题二:为什么这里是从 0040110E 到 0040115B 下内存写入断点???)

  2. 下好断点之后,我们 F9 运行 N 次,来到这里:

00965834 8928 mov dword ptr ds:[eax],ebp  ;将 ebp(API 地址)放在 eax
00965836 8B4424 0C mov eax,dword ptr ss:[esp+C]
0096583A 8906 mov dword ptr ds:[esi],eax ;停在这里->将 eax 放在 esi
0096583C 0FB74424 04 movzx eax,word ptr ss:[esp+4]
00965841 0143 08 add dword ptr ds:[ebx+8],eax
00965844 E9 D1FCFFFF jmp 0096551A
00965849 3C 03 cmp al,3
0096584B 0F85 97000000 jnz 009658E8
  • 现在注意寄存器窗口:

EAX 009C0408
ECX 7C937C51 ntdll.7C937C51
EDX 7C99E174 ntdll.7C99E174
EBX 009C04F4
ESP 0012FEFC
EBP 7C81CB12 kernel32.ExitProcess;这里是被调用 API 函数地址, 记下绿色标记的地址, 一会儿修复 IAT 用
ESI 00401110ASProtec.00401110 ;这里是被 PATCH 代码的地址
EDI 009C03F8
EIP 0096583A
  • 上面分析的两句代码就构成了:

0040110E FF25 08049C00 jmp dword ptr ds:[9C0408]
009C0408 7C81CB12 kernel32.ExitProcess
  1. 我们 F9 一次,来到这里:

0096369A C603 E8 mov byte ptr ds:[ebx],0E8 ;这里就是将(6 字节) FF25 型的 jmp [xx]处理为(5 字节) E8 型的 call xx
0096369D 43 inc ebx
0096369E 8903 mov dword ptr ds:[ebx],eax
009636A0 5B pop ebx
009636A1 C3 retn
  • 上面分析的这句代码就得到下面这个结构:

将 009636A1 - FF25 34039C00 jmp dword ptr ds:[9C0334]处理成:

00401114 E8 1BF25B00 call 009C0334
  • 注意此时寄存器窗口:

EAX 005BF21B
ECX 019C0334
EDX 005BF21B
EBX 00401114ASProtec.00401114
ESP 0012FEF4
EBP 7C80B741 kernel32.GetModuleHandleA  ;这是被调用的函数地址, 同样记下绿色标记的地址
ESI 00401116ASProtec.00401116
EDI 009C03F8
EIP 0096369A
  1. F9 运行两次,我们又来到了这里:

00965755 8906 mov dword ptr ds:[esi],eax
00965757 0FB74424 04 movzx eax,word ptr ss:[esp+4]
0096575C 0143 08 add dword ptr ds:[ebx+8],eax
0096575F E9 B6FDFFFF jmp 0096551A
00965764 3C 04 cmp al,4
  • 此时我们只需关心寄存器窗口的两个值:

EAX 009C0470
ECX 00000000
EDX 009C0470
EBX 009C04F4
ESP 0012FEFC
EBP 77D28FE9 user32.BeginPaint
ESI 0040111CASProtec.0040111CEDI 009C03F8
EIP 00965755
  1. 然后 F9 运行,同理,我们只需关心寄存器窗口的两个值:

EAX 005C25CB
ECX 029C36F0
EDX 005C25CB
EBX 00401120 ASProtec.00401120
ESP 0012FEF4
EBP 77D3B144 user32.DialogBoxParamA
ESI 00401122 ASProtec.00401122
EDI 009C03F8
EIP 0096369A
  • F9 运行:

EAX 009C0488
ECX 00000000
EDX 009C0488
EBX 009C04F4
ESP 0012FEFC
EBP 77D24A4E user32.EndDialog
ESI 00401128 ASProtec.00401128
EDI 009C03F8
EIP 00965755
  • F9 运行:

EAX 009C3240
ECX 00000000
EDX 009C3240
EBX 009C04F4
ESP 0012FEFC
EBP 77D28FFD user32.EndPaint
ESI 0040112EASProtec.0040112E
EDI 009C03F8
EIP 00965755
  • F9 运行:

EAX 009C324C
ECX 00000000
EDX 009C324C
EBX 009C04F4
ESP 0012FEFC
EBP 77D2473C user32.LoadBitmapA
ESI 00401134 ASProtec.00401134
EDI 009C03F8
EIP 00965755
  • F9 运行:

EAX 009C3258
ECX 00000000
EDX 009C3258
EBX 009C04F4
ESP 0012FEFC
EBP 77D2F3C2 user32.SendMessageA
ESI 0040113AASProtec.0040113A
EDI 009C03F8
EIP 00965755
  • F9 运行:

EAX 009C418C
ECX 00000000
EDX 009C418C
EBX 009C04F4
ESP 0012FEFC
EBP 77EF6F79 GDI32.BitBlt
ESI 00401140 ASProtec.00401140
EDI 009C03F8
EIP 00965755
  • F9 运行:

EAX 009C43C8
ECX 00000000
EDX 009C43C8
EBX 009C04F4
ESP 0012FEFC
EBP 77EF5FE0 GDI32.CreateCompatibleDC
ESI 00401146 ASProtec.00401146
EDI 009C03F8
EIP 00965755
  • F9 运行:

EAX 009C446C
ECX 00000000
EDX 009C446C
EBX 009C04F4
ESP 0012FEFC
EBP 77EF6E5F GDI32.DeleteDC
ESI 0040114C ASProtec.0040114C
EDI 009C03F8
EIP 00965755
  • F9 运行:

EAX 009C46F0
ECX 00000000
EDX 009C46F0
EBX 009C04F4ESP 0012FEFC
EBP 77EF6BFAGDI32.DeleteObject
ESI 00401152 ASProtec.00401152
EDI 009C03F8
EIP 00965755
  • F9 运行:

EAX 009C4A68
ECX 00000000
EDX 009C4A68
EBX 009C04F4
ESP 0012FEFC
EBP 77EF5B70 GDI32.SelectObject
ESI 00401158 ASProtec.00401158
EDI 009C03F8
EIP 00965755

F9,程序运行了,说明 IAT 处理完了。

  1. 整理一下刚才记下的值:

跳转表地址 API 地址 API 函数名

00401110 7C81CB12 kernel32.ExitProcess
00401116 7C80B741 kernel32.getModuleHandleA
0040111C 77D28FE9 user32.BeginPaint
00401122 77D3B144 user32.DialogBoxParamA
00401128 77D24A4E user32.EndDialog
0040112E 77D28FFD user32.EndPaint
00401134 77D2473C user32.LoadBitmapA
0040113A 77D2F3C2 user32.SendMessageA
00401140 77EF6F79 GDI32.BitBlt
00401146 77EF5FE0 GDI32.CreateCompatibleDC
0040114C 77EF6E5F GDI32.DeleteDC
00401152 77EF6BFA GDI32.DeleteObject
00401158 77EF5B70 GDI32.SelectObject

API 地址二进制:

12 CB 81 7C 41 B7 80 7C 00 00 00 00 E9 8F D2 77 44 B1 D3 77 4E 4A D2 77 FD 8F D2 77 3C 47 D2 77 C2 F3
D2 77 00 00 00 00 79 6F EF 77 E0 5F EF 77 5F 6E EF 77 FA 6B EF 77 70 5B EF 77
  1. 重载 OD,再次来到 OEP 处,查找 FF25 型 jmp[xx],来到这里:

0040110E - FF25 08049C00 jmp dword ptr ds:[9C0408] ; kernel32.ExitProcess
  1. 现在我们找一块空地种下我们刚才整理的 API 地址:

12 CB 81 7C 41 B7 80 7C 00 00 00 00 E9 8F D2 77 44 B1 D3 77 4E 4A D2 77 FD 8F D2 77 3C 47 D2 77 C2 F3
D2 77 00 00 00 00 79 6F EF 77 E0 5F EF 77 5F 6E EF 77 FA 6B EF 77 70 5B EF 77--------->(问题三:为什么 API 地址中间有 00 00 00 00???)

我这里是找的 00401160 这个地址,然后从 00401160 这个地址开始选中一部分复制上面的二进制代码:

00401160 12CB adc cl,bl
00401162 817C41 B7 807C0cmp dword ptr ds:[ecx+eax*2-49],7C80
0040116A 0000 add byte ptr ds:[eax],al
0040116C E9 8FD27744 jmp 44B7E400
00401171 B1 D3 mov cl,0D3
00401173 77 4E ja short ASProtec.004011C3
00401175 4A dec edx
00401176 D277 FD sal byte ptr ds:[edi-3],cl
00401179 8F ??? ; 未知命令
0040117A D277 3C sal byte ptr ds:[edi+3C],cl
0040117D 47 inc edi
0040117E D277 C2 sal byte ptr ds:[edi-3E],cl
00401181 F3: prefix rep:
00401182 D277 00 sal byte ptr ds:[edi],cl
00401185 0000 add byte ptr ds:[eax],al
00401187 0079 6F add byte ptr ds:[ecx+6F],bh
0040118A EF out dx,eax
0040118B 77 E0 ja short ASProtec.0040116D
0040118D 5F pop edi
0040118E EF out dx,eax
0040118F 77 5F ja short ASProtec.004011F0
00401191 6E outs dx,byte ptr es:[edi]
00401192 EF out dx,eax
00401193 77 FA ja short ASProtec.0040118F
00401195 6BEF 77 imul ebp,edi,77
00401198 70 5B jo short ASProtec.004011F5
0040119A EF out dx,eax
0040119B 77 11 ja short ASProtec.004011AE
0040119D 73 77 jnb short ASProtec.00401216
0040119F 4E dec esi
004011A0 AA stos byte ptr es:[edi]
004011A1 EC in al,dx
004011A2 0040 00 add byte ptr ds:[eax],al

然后右键数据窗口跟随:

00401160 7C81CB12 kernel32.ExitProcess
00401164 7C80B741 kernel32.GetModuleHandleA
00401168 000000000040116C 77D28FE9 user32.BeginPaint
00401170 77D3B144 user32.DialogBoxParamA
00401174 77D24A4E user32.EndDialog
00401178 77D28FFD user32.EndPaint
0040117C 77D2473C user32.LoadBitmapA
00401180 77D2F3C2 user32.SendMessageA
00401184 00000000
00401188 77EF6F79 GDI32.BitBlt
0040118C 77EF5FE0 GDI32.CreateCompatibleDC
00401190 77EF6E5F GDI32.DeleteDC
00401194 77EF6BFA GDI32.DeleteObject
00401198 77EF5B70 GDI32.SelectObject
0040119C 4E777311
  1. 现在我们就来 Patch 我们的 FF25 型 jmp:

0040110E FF25 60114000 jmp dword ptr ds:[401160] ; kernel32.ExitProcess
00401114 FF25 64114000 jmp dword ptr ds:[401164] ; kernel32.GetModuleHandleA
0040111A FF25 6C114000 jmp dword ptr ds:[40116C] ; user32.BeginPaint
00401120 FF25 70114000 jmp dword ptr ds:[401170] ; user32.DialogBoxParamA
00401126 FF25 74114000 jmp dword ptr ds:[401174] ; user32.EndDialog
0040112C FF25 78114000 jmp dword ptr ds:[401178] ; user32.EndPaint
00401132 FF25 7C114000 jmp dword ptr ds:[40117C] ; user32.LoadBitmapA
00401138 FF25 80114000 jmp dword ptr ds:[401180] ; user32.SendMessageA
0040113E FF25 88114000 jmp dword ptr ds:[401188] ; GDI32.BitBlt
00401144 FF25 8C114000 jmp dword ptr ds:[40118C] ; GDI32.CreateCompatibleDC
0040114A FF25 90114000 jmp dword ptr ds:[401190] ; GDI32.DeleteDC
00401150 FF25 94114000 jmp dword ptr ds:[401194] ; GDI32.DeleteObject
00401156 FF25 98114000 jmp dword ptr ds:[401198] ; GDI32.SelectObject

二进制代码:

FF 25 60 11 40 00 FF 25 64 11 40 00 FF 25 6C 11 40 00 FF 25 70 11 40 00 FF 25 74 11 40 00 FF 25 78 11 40 00 FF 25 7C 11 40 00 FF 25 80 11 40 00 FF 25 88 11 40 00 FF 25 8C 11 40 00 FF 25 90 11 40 00 FF 25 94 11 40 00 FF 25 98 11 40 00

上面绿色部分是我们刚才找的放 API 地址的地方

DUMP 程序

  1. 用 OD 自带插件 DUMP 程序

  2. 运行程序,程序能够运行

参考资料:Tortoiser脱壳系列培训教程

原文始发于微信公众号(0x00实验室):脱壳 ASProtect v1.31 (手动修复IAT乱序)

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年4月2日11:51:07
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   脱壳 ASProtect v1.31 (手动修复IAT乱序)http://cn-sec.com/archives/2622439.html

发表评论

匿名网友 填写信息