概述
脱壳是一项综合技术,结合PE文件格式、汇编指令的分析,调试加密的程序并将其还原的一个过程。
壳一般分为两种,加密壳和压缩壳,里面所使用的技术有,压缩算法、对代码加密、对IAT加密、对资源加密。
我们从简单入手-压缩壳。
脱壳三步法
1寻址OEP
2dump内存到文件
3修复文件
脱壳三步法-寻址OEP技巧
1堆栈平衡法(ESP定律)
壳代码就像一个函数,进入时会开辟堆栈、保存寄存器环境,退出时会恢复堆栈、恢复寄存器。所以应该是堆栈平衡的,那我们可以在壳代码操作了堆栈后对堆栈设置访问或写入断点,然后运行程序,当断点命中的时候,应该就是退出壳代码的时候。在其附近单步几次,应该就能到达程序的原始OEP。
2特征定位法
在我们熟悉的程序中,我们可以使用特征来定位程序原始OEP。特征有几种:
① 二进制特征
比如release版的VS2013是:
E8????????E9 call jmp
② API特征
比如vc6.0的第一个API调用是:
GetVersion
比如Delphi程序第一个API调用是:
GetModuleHandleA
3单步跟踪法
这种方法一般使用在分析自己加壳的程序或者是练习分析壳时。
脱壳-0.aspack.exe
1寻址OEP
ESP定律
2dump内存
3修复文件
image.png
注意:如果程序有随机基址,脱壳后需要把随机基址标志位置0.
壳代码的基本流程
① 保存寄存器环境
② 加载一些必要的API
③ 解密代码和数据
④ 修复重定位
⑤ 填充IAT
⑥ 恢复寄存器环境
=========================
分析壳代码-0.aspack.exe
① 壳OEP
image.png
② 加载必要API
image.png
③ 解密解压缩代码
image.png
④ 修复重定位
image.png
⑤ 修复IAT
001D726F 03F2 ADD ESI,EDX ; esi=导入表结构
001D7271 8B46 0C MOV EAX,DWORD PTR DS:[ESI+0xC] ; 获取模块DLL名称RVA
001D7274 85C0 TEST EAX,EAX
001D7276 0F84 0D010000 JE 00_aspac.001D7389
001D727C 03C2 ADD EAX,EDX ; 加上基地址,字符串VA
001D727E 8BD8 MOV EBX,EAX
001D7280 50 PUSH EAX
001D7281 FF95 A90F0000 CALL DWORD PTR SS:[EBP+0xFA9] ; 获取模块基地址
001D7287 85C0 TEST EAX,EAX
001D7289 75 07 JNZ SHORT 00_aspac.001D7292
001D728B 53 PUSH EBX
001D728C FF95 AD0F0000 CALL DWORD PTR SS:[EBP+0xFAD]
001D7292 8985 A9050000 MOV DWORD PTR SS:[EBP+0x5A9],EAX ; 保存模块基地址
001D7298 C785 AD050000>MOV DWORD PTR SS:[EBP+0x5AD],0x0
001D72A2 8B95 88040000 MOV EDX,DWORD PTR SS:[EBP+0x488] ; 获取基地址
001D72A8 8B06 MOV EAX,DWORD PTR DS:[ESI] ; 获取指向OrignalFirstThunk RVA
001D72AA 85C0 TEST EAX,EAX
001D72AC 75 03 JNZ SHORT 00_aspac.001D72B1
001D72AE 8B46 10 MOV EAX,DWORD PTR DS:[ESI+0x10]
001D72B1 03C2 ADD EAX,EDX ; 计算得出 OrignalFirstThunk VA
001D72B3 0385 AD050000 ADD EAX,DWORD PTR SS:[EBP+0x5AD] ; 0
001D72B9 8B18 MOV EBX,DWORD PTR DS:[EAX] ; 获取INT中的数据,即指向函数名称的 RVA
001D72BB 8B7E 10 MOV EDI,DWORD PTR DS:[ESI+0x10] ; 获取 FirstThunk
001D72BE 03FA ADD EDI,EDX ; 计算得出 IAT 地址
001D72C0 03BD AD050000 ADD EDI,DWORD PTR SS:[EBP+0x5AD] ; 0
001D72C6 85DB TEST EBX,EBX ; 判断结束
001D72C8 0F84 A5000000 JE 00_aspac.001D7373
001D72CE F7C3 00000080 TEST EBX,0x80000000 ; 判断是否是序号
001D72D4 75 04 JNZ SHORT 00_aspac.001D72DA
001D72D6 03DA ADD EBX,EDX ; 指向函数字符串结构=INT[i]+模块基地址
001D72D8 43 INC EBX ; 减去2,跳过字符串结构的序号
001D72D9 43 INC EBX
001D72DA 53 PUSH EBX ; 保存寄存器环境
001D72DB 81E3 FFFFFF7F AND EBX,0x7FFFFFFF ;去掉序号
001D72E1 53 PUSH EBX ; 压入字符串或是序号
001D72E2 FFB5 A9050000 PUSH DWORD PTR SS:[EBP+0x5A9]
001D72E8 FF95 A50F0000 CALL DWORD PTR SS:[EBP+0xFA5] ; 获取函数地址
001D72EE 85C0 TEST EAX,EAX
001D72F0 5B POP EBX ; 恢复寄存器环境
⑤ 修改属性,跳转原始OEP
image.png
网友评论