脱壳一个程序,首先要大体了解一下程序,然后寻找突破口,网上给出的一些关键api也是通过分析确认后的经验总结,不一定普适。
1、具体到这个小程序,先运行起来,附加进去,可以看到程序重新分配了内存0x400000,并释放代码其中执行。调试器执行不是每次都能成功,跟踪vitualalloc函数发现程序每次总是从0x400000申请内/8000内存,申请不成功就不会执行,因此可能断定,释放的代码没有重定位表,必须固定基址运行。
2、单开始是关键代码解密,注意esi edi寄存器操作指令,其他寄存器操作指令基本是垃圾代码,等跳到解密后的代码,程序逻辑就基本清楚了。vitualalloc设断点,返回后就是解密后的代码段,没有花指令,很好读懂。
[Asm] 纯文本查看 复制代码 mov eax, dword ptr ss:[ebp - 0x1D0]
add eax, dword ptr ss:[ebp - 0xC]
mov ecx, dword ptr ss:[ebp - 0xC]
pop esi
pop edi
pop ebx
leave
ret 0xC
往后翻翻代码,在最后就能看到这几行代码,前面的代码,简单读读就能看出,这段代码的主要功能就是模拟系统从磁盘加载文件的方式,从程序自身内部加载pe程序到0x400000基址,并对iat进行重定位,只有四个函数,然后跳转到程序入口开始执行。
3、释放的程序入口在4070FF,在程序最后一个区段,代码不多,也没花指令,主要功能是对text段代码解压缩,然后对iat重定位,再跳到入口执行。
[Asm] 纯文本查看 复制代码 popad
mov ecx, 0xFFC
mov ebx, dword ptr ds:[eax + ecx]
mov dword ptr ds:[ecx + <sub_401000>], ebx
loop 0x4071CC
nop
nop
mov edx, 0x400000
mov esi, 0x25B0
add esi, edx
mov eax, dword ptr ds:[esi + 0xC]
test eax, eax
je 0x407277
add eax, edx
mov ebx, eax
push eax
mov eax, <&GetModuleHandleA>
call dword ptr ds:[eax]
nop上面这个循环指令是完成解码后的text段写入,je之后的程序就是循环对iat重定位,脱过upx壳对这个会很眼熟,地址0x25b0是输入表开始地址,大小就是这个je执行跳转后,si的值减去25b0。
4、je跳转后没几行代码就跳转到程序入口了,这时就可以dump程序了,由于pe程序是从内存模拟磁盘加载的,dump时候需要选择内存,而不是进程dump,dump的时候最后一个区段可以抛弃。
5、dump出的程序不能运行,因为iat表错误,需要手工用前面计算的长度,首地址修改一下导入表即可,都不需要用重建! |