用scanwithPEid扫描,看是否upx加过壳:
然后用OD打开此加壳文件,用upx脱壳的原理就是可以把壳代码想象成一个完整的函数,在刚进入,保存寄存器环境(PUSHAD)的时候下一个断点,然后单步执行,:
由于不清楚447000是个什么东西,因此可以查看内存,上面的M按钮:
是upx1的首地址。按c返回到汇编代码区域。push完EDI之后看寄存器EDI的值,401000,进入内存看一眼是什么意思:
401000是区段UPX0的首地址
然后这个时候可以去数据窗口跟随一下edi,看看edi里面存放了什么,原本是代码段的edi,现在什么都没有:
然后跟随esi看看:
edi是目的操作数,而esi是源操作数,因而他有可能会将esi里面的内容取出来赋值到edi里面
这里这个循环可以理解成一个小的函数或者功能,因为不清楚具体在做什么,猜测:
JNZ之后还在里面,所以这一定是一个具体的有效的功能在循环之后,edi本来是空的,逐渐被赋了值,因此edi这里可能会是个函数。
赋值完成之后反汇编查看到底是不是代码:
确实是代码。CTRL+G查看一下esi:
esi最初是从04这个位置开始赋值的:
然后继续单步执行,盯到输入和输出停下来,遇到什么加法之类的,直接过。
将获取到的00存入edi里
到这个地方的时候并没有从esi中取出一个字节放入到edi代码段中,而是在代码段中取出了一个字节往下继续做了一个重复的复制,一共有ecx保存的个数个nop:
每次取出一个字节之后拿去填充,然后增加EDI,EBX是很关键的,与下面的跳转JNZ有关,至于使用EBX的原因,应该与解压缩的算法有关
循环几次之后会发现:如果没有重复的,就从UPX1里面取,如果有重复的,就从UPX0里面去取,然后再填到对应的UPX0区段的位置
OEP一开始的地方其实是吧edi和esi进行了初始化,然后用esi从UPX1这个区段里面拿出东西,通过这个算法将其解压缩到UPX0这个区段里面。
1.初始化esi edi
2.解压缩代码
3.修复代码
之后右键-长型-地址
当不确定这个数值代表什么意思的时候,右键-Hex-第一个选项
可以看到,这里面都是函数名,在函数名的最后会出现PE信息!:
1.初始化
2.解压缩代码和数据
2.1修复代码
3.修复重定位(修复之后入口都是400000,所以可以不需要修复重定位了)
4.填充IAT
标准过程:dll_name=import[xx]
base=LoadLibraryA(dll name)
fun_name=int[xx]
GetProcAddress(base,fun)
iat【xx】=addr
上面做成一个循环,尽可能的还原这个过程
(在mov eax,dword【edi】那里就可以挺住,去查看edi寄存器了
前两个看起来都不像函数名,当遇到不知道是什么东西的时候,就右键-地址进去看看
01是函数开始的标志位,00是函数结束的标志位:
EDI=IATDataBase
dllOffset=【IATDataBase】
iatOffset=【IATDataBase+0x4】(IATDataBase前四个字节的偏移)
整个黄色的部分都是在填充IAT:
由于跟进去之后不知道40021F是做什么的,就跳转到首地址:400210处查看一下:
E0代表区段的属性,21F是E0。
这三条指令,修改了区段属性:
5.修正PE头中区段的属性
6.平衡堆栈
7.跳转到OEP