ACProtect Professional 1.3C 主程序脱壳(2)

 

By softworm

 

4. dump

 

根据脱US UnpackMe的经验,不能在false OEPdump,此时BSS section中许多数据已经初始化了。最好在第一句(push ebp)dump。可是那个push ebpfalse OEP很远L

 

Packer EP的初始化环境:

 


 

 

先看看发出第1call的壳代码:

 

可以看到(跟一下可以证实),call入原程序空间前,最后的异常是div 0。用现在的OllyDbg脚本(跟到737B63),停下后修改异常拦截选项:

 

试试能否拦截异常找到合适的dump位置。当前OllyScript脚本停下时的环境:

 

 

栈中为pushad的结果。

 

7div 0异常时:

 

 

注意ebp的值已经入栈了。Pushad的结果,对应寄存器值为:
esp = 12FFC0         (
原来为12FFC4)

ebp = 12FFC0 = esp (原来为12FFF0)

 

所以,在这里已经执行过了:

Push ebp

Mov ebp,esp

 
 

 

 

 


看看BSS section:

 

 

全为0,就在这里dump如果需要仔细跟stolen code,也可以从这里入手(可以从脚本停下的第6div 0异常处理后开始)

 

先用4D9DE4OEP

 

 

LoadPE查看节表:

 

先把CODEVsizeRsize加大,以避免修复stolen codes时空间不够。

 

 

重新跟到false OEP(4D9E37)。重建输入表。

 

 

用了Add new section,会不会有问题(好象有篇脱文里提到过这个)? 先这样处理。

IDA编译dumped_.exe,结果不错。

 

现在剩下stolen codereplaced code

 

 

5. 修复stolen code

 

既然不打算仔细跟,就只有猜了。对执行第1call以前的stolen code进行猜测,应该是安全的。后面的4call需要仔细看看。

 

1) call 406EDC

 

IDA中看dumped_.exe的结果:

 

先执行脚本,停下后只勾选div 0异常。直到73A9AF。经过一番遮遮掩掩的代码:

 

call前的寄存器:

 

堆栈:

 

call完后,下面的pushad为分界线,标识stolen code的结束。所以到这里的stolen code(对于不确定的,可以在Packer EP修改寄存器值,到这里核对):

Push ebp

Mov ebp,esp

Push edx

Push edi

Push ebx

Push eax

Mov eax,4D9BCC
call 406EDC

mov eax,dword ptr ds:[503B94]

 

 
 

 

 

 

 

 

 

 

 

 

 


Call完后,pushad前的环境:

 

 

2) call 46261C

 

 

 

到这里的stolen code:

Push ebp

Mov ebp,esp

Push edx

Push edi

Push ebx

Push eax

Mov eax,4D9BCC
call 406EDC

mov eax,dword ptr ds:[503B94]

 

mov eax,dword ptr ds:[eax]

call 46261C

push edi

mov ecx,dword ptr ds:[503938]

 

 

 
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


从这里开始,不能图省事了。要追出全部的stolen code,必须跟(必须确保上一次pushad和下一次popad时的环境一致,才不会丢代码)。先试直接拦截div 0异常,注意后面是否有popad。如果两次的环境不一致,则必须单步跟L

 

另外,stolen code不是一次完成的,所以有些图中寄存器和堆栈中的数据对不上,不必管它。

 

3) 0073BC47

 

 

 

 

 

 

 

 

 

 

Push ebp

Mov ebp,esp

Push edx

Push edi

Push ebx

Push eax

Mov eax,4D9BCC
call 406EDC

mov eax,dword ptr ds:[503B94]

 

mov eax,dword ptr ds:[eax]

call 46261C       

//这里去掉前面的push edi

mov ecx,dword ptr ds:[503938]

 

mov eax,dword ptr ds:[503B94]

mov eax,dword ptr ds:[eax]

push eax

push ecx  

mov ecx,47FCD8    //多余,前面push ecx,后面还会pop的吧?

mov eax,47FCD8

 
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


4) 0073C558

 

Push ebp

Mov ebp,esp

Push edx

Push edi

Push ebx

Push eax

Mov eax,4D9BCC
call 406EDC

mov eax,dword ptr ds:[503B94]

 

mov eax,dword ptr ds:[eax]

call 46261C       

mov ecx,dword ptr ds:[503938]

 

mov eax,dword ptr ds:[503B94]

mov eax,dword ptr ds:[eax]

 

mov edx,dword ptr ds:[47FCD8]

push edx

mov edx, 462634      //注意这是下一次call的地址

 

 
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


5) 1call 462634

 

这个函数有2个参数L

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Push ebp

Mov ebp,esp

Push edx

Push edi

Push ebx

Push eax

Mov eax,4D9BCC
call 406EDC

mov eax,dword ptr ds:[503B94]

 

mov eax,dword ptr ds:[eax]

call 46261C       

mov ecx,dword ptr ds:[503938]

 

mov eax,dword ptr ds:[503B94]

mov eax,dword ptr ds:[eax]

 

mov edx,dword ptr ds:[47FCD8]

 

call 462634

push eax

push esi

mov eax, 50385C

 
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


6) 2call 462634

Push ebp

Mov ebp,esp

Push edx

Push edi

Push ebx

Push eax

Mov eax,4D9BCC
call 406EDC

mov eax,dword ptr ds:[503B94]

 

mov eax,dword ptr ds:[eax]

call 46261C       

mov ecx,dword ptr ds:[503938]

 

mov eax,dword ptr ds:[503B94]

mov eax,dword ptr ds:[eax]

 

mov edx,dword ptr ds:[47FCD8]

 

call 462634

 

mov ecx,dword ptr ds:[50385C]

mov eax,dword ptr ds:[503B94]

mov eax,dword ptr ds:[eax]

mov edx,dword ptr ds:[47F948]

call 462634

mov eax,dword ptr ds:[503B94]

mov eax,dword ptr ds:[eax]

 

 
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


                                                            

 

 

这是最后一次后面存在popaddiv 0异常。看看是如何回到原程序的。

73D872忽略所有异常,code section下内存访问断点。中间在kernel32中有一次内存访问异常。

 

 

最后一次div ebx73DBE1。单步跟到这里:

 

73DE38破坏前面代码。

 

 

至此修复所有stolen codes,将前面的6部分和fasle OEP2call合在一起。

 

Push ebp

Mov ebp,esp

Push edx

Push edi

Push ebx

Push eax

Mov eax,4D9BCC
call 406EDC

mov eax,dword ptr ds:[503B94]

mov eax,dword ptr ds:[eax]

call 46261C       

mov ecx,dword ptr ds:[503938]

mov eax,dword ptr ds:[503B94]

mov eax,dword ptr ds:[eax]

mov edx,dword ptr ds:[47FCD8]

call 462634

mov ecx,dword ptr ds:[50385C]

mov eax,dword ptr ds:[503B94]

mov eax,dword ptr ds:[eax]

mov edx,dword ptr ds:[47F948]

call 462634

mov eax,dword ptr ds:[503B94]

mov eax,dword ptr ds:[eax]

call 4626B4

call 4049D8

lea eax, [eax+0]