脱壳——UPX脱壳原理
脱壳步骤
1 找到OEP
2 dump(导出)内存文件
3 修复
1 找到OEP
1 程序运行先从壳代码运行,壳代码执行完之后会跳转到真正的OEP,也就是是说第一步,首先要找到真正的OEP
如何找到OEP
大部分情况下,壳代码会在一个单独的区段里面,壳代码执行完一定会跳转到原来的.text段去执行,跳转之后的地址就是这个程序原始的OEP
根据OEP特征码来判断是否是原始的OEP
不同程序、不同版本编译器编译出来的程序OEP各不相同,但是大致有共同的特点:
例如:
vc6.0的OEP处的第一个API调用是GetVersion
VS2013是GetSystemTimeAsFileTime
Delphi是GetModuleHandleA
2 dump内存文件
就是把得到的新的源文件给它保存下来,可以采用从头到最后一个区段的手动复制下来,也可以用工具
3 修复
对于手动扒拉下来的内存文件,肯定还有一些问题,这里需要对PE文件进行修复
第一次脱壳
加壳程序下载链接:
https://download.csdn.net/download/weixin_43916597/18353951?spm=1001.2014.3001.5503
使用到的软件:
Peid:(吾爱破解上可以下载)
查看程序信息
首先先查看程序的信息,先了解敌人:
采用PEID来查看程序的信息:
将程序拖进PEID后:
这里很明显是一个UPX加壳后的程序,采用的是UPX壳代码
连接器版本6.0 也就是vc6.0的
开始脱壳
1 找到OEP
首先采用od加载exe
这里跟之前我们想的加壳是一样的,就是先pushad,然后再处理自己想处理的,最后popad,再跳转回到真正的OEP里面
pushad
• //壳代码
• popad
• jmp xxxx
但是这里没有popad,所以需要找一下popad,在pushad执行完之后,esp指向的是栈顶的位置,popad的话会让esp移动,所以可以直接给esp打一个断点
这里来一个esp断点,也可以通过别的,比如在command中访问到esp的地址,然后选择,来一个硬件断点
需要注意的是在esp往上两个来一个硬件访问的dword断点才行
然后把这个程序跑起来,就会停在我们打的断点这里了
这里的话是停在了这里,这里恰好有一个popad(注:硬件访问是在这个断点运行了之后再停下来)
这里popad完之后就可以寻找jmp指令了,但是如何判断这个jmp是不是真正的jmp到oep呢
可以看到这里的jmp跳转到了非常远的距离,那么到底是不是跳转到真正的OEP呢?
点击od的m这个按钮来查看PE文件的各种属性
431B7C肯定是在这个区段里面的从这里跳转到了402680也就是上一个区段,这里就可以知道了,这里其实是跳转到了第一个区段也是加壳最常用的.text区段
然后跟入跳转到402680
可以看到这里的第一个api确实是GetVersion,所以这里肯定就是真正的OEP了
2 dump(导出)内存文件
需要再刚进入OEP的第一条指令就dump出来,因为不知道后面的代码逻辑是什么,万一有什么修改呢
od中可以直接调用OllyDump脱壳调试进程
手动dump:利用M按钮里面的PE文件加载情况,将主程序.exe文件的内存文件一点一点复制粘贴出来
利用010Editor创建一个hex文本类型文件
然后从od 的m按钮里面一块一块的复制文件过来
首先处理PE头
双击进入,然后修改为16进制类型
对整个内容进行二进制复制
然后再到010Editor中采用Ctrl+shift+v复制,不要采用Ctrl+v复制,这样才能直接复制16进制的内容进去
然后就是UPX0和UPX1还有.rsrc三个字段也复制进去
最后保存下来,随便一个文件然后以.exe结尾就好
3 修复
dump出来的exe文件不能使用的,因为还有一些PE文件的内容没有修复,这个时候再用010Editor来加载dump出来的pe文件进行修复
它里面就会有一些PE的提示
需要修改的信息:
区段头信息
导入表
修复区段头
这里里面很多区段头的信息都没有,因为这里应该是PE文件来处理的,但是我们是dump复制出来的,所以这里我们需要自己添加没有的信息
Name不用改
Misc表示未对齐的真实内存中的大小也不用改
VirtualAddress内存中的一个rva也不用改
SizeOfRawData文件中的对齐大小这个由于我们是从加载到内存中再Dump出来的,所以文件和内存已经没有必要区分开了,直接和Msic值一样就好
PointerToRawData表示foa,这里也直接用rva就好了
后面的可以不用处理
这样把三个区段头都修改好
修复好了三个区段头后,可以很清楚得看到程序的变化
图标回来了!虽然这个时候还无法运行
修复导入表
上面修复了PE文件的区段头,但是由于导入表没有修复还是无法使用,这里用LordPE查看该exe的导入表就可以看到dll的导入表是错的
正常的导入表是通过操作系统对字符串来处理然后得到该字符串的函数名称对应的函数地址变成地址给exe使用
但是这里由于我们是把exedump出来了,所以就是把操作系统变成的函数地址给弄了出来,而不是函数名称字符串,所以这里还需要修复,把地址修复改成函数名称
手动修复导入表:从od里面把原来的导入表地址函数名称全部提出来,然后再在dump出来的exe里面开辟一个字段来存储导入表,再把PE文件里面的导入表指向指到开辟的导入表里面就好了
在硬编码里面,有几种对于call函数的编码,但是如果编码的开始是FF15 xxx的就表明是对导入表里面的函数调用
这里可以很明显的看出来
然后再进入到FF15的call的地址里面查看
可以很明显得看到各种各种的导入表函数,拿到之后再按照前面的方式添加进去就好了
根据导入表的性质来修复
这里采用一个工具来处理
https://down.52pojie.cn/Tools/PEtools/ImportREConstructor%201.7e.zip 解压密码:www.52pojie.cn
添加进程,修改OEP和大小,然后获取导入表,同时还需要进入OD用刚刚的办法查看是否把所有的dll都包含了,这里是确实只有两个dll,如果没有可以尝试修改大小来处理
然后使用转存到我们刚刚弄的.exe文件就好了,正常的话下面会出现一个保存成功
这次再查看导入表
就是很正常的了
再查看它的区段
可以看到多了个区段,和我们前面想的一样手动添加了一个区段来专门修复导入表.
总结 UPX脱壳
首先采取找到OEP,然后呢对整个PE文件进行dump出来,然后再修复,修复需要修复PE的区段头和导入表