但dump之前有一个问题,原始文件的大小是多少呢?
比如像下面这样,病毒解密出PE文件内容后将其分段写入其他进程。这里我们可以定位到PE文件在内存中的起始地址0x011860D0,可以看到“MZ”标志。现在的问题是,结束地址是什么?
图片
可以有3种方法:
直接往后拖,看到哪里像是文件末尾,就当做结束地址。这种方法需要非常丰富的逆向经验,适用于少数逆向大佬。
直接拖到内存块末尾,把它当做结束地址。这种方式也不是不可以,毕竟很多时候,解密出来的PE文件都是放在单独一块内存中的 ,而且就算dump出的文件末尾多了一些内容,也不会影响分析,但如果要提取文件的MD5的话就麻烦了。
根据PE结构计算出原始文件的大小。
图片
我们先看一下PE文件的结构及其在内存中的映射方式。PE文件主要分为DOS头部、PE文件头、块表、各区块以及文件末尾的不能映射部分(如调试信息等,在逆向时用处不大,而且很多时候都没有这部分)。
图片
其中除了不能映射部分,其他部分的大小我们都是可以通过解析PE文件获取到的。我们现在只是需要获取总的大小,可以先把DOS头部、PE文件头、块表这几部分dump出来。只需要找到块表的位置即可,在内存中很容易找,一般带有“.text”、“.data”这样的区块名字符串,这里由于dump对象加了upx壳,所以区块名是“UPX0”“UPX1”,也是同样的道理。
图片
如果不确定块表的结束地址的话,直接找到后面0x00结束的地方全部dump下来就可以了。这里是0x11864AA,大小为0x3DB。dump多了也没关系,这里不需要精准。
图片
用LoadPE dump下来。
图片
将dump下来的PE头放到DIE里面,主要关注“Offset”和“R.Size”两项,分别表示区块在文件中的偏移以及大小。我们直接找到最后一个区块“UPX2”的偏移以及大小:0x66a00,0x200。相加为0x66c00,即为需要dump文件除了文件末尾不能映射部分以外的大小。
图片
重新dump。
图片
Dump出的文件的hash值可以在VT中找到,说明这是一个完整的文件。
图片
由于在这个例子中,被dump的文件没有文件末尾的不能映射部分,所以能够精确dump。如果有这部分内容的情况下,就不能做到精确了,毕竟PE文件末尾的这部分大小是没有办法通过计算获取到的。不过对于被dump的文件,这部分内容对于分析它是没有影响的,只是会影响提取MD5。
图片
想要脱VMP的壳,首要工作当然是要找一个强OD。至于是什么版本的OD自己多试验几个,网上有很多,一般来说只要加载了你想脱的VMP加壳程序不关闭都可以。
其次,就是StrongOD.dll这个插件了,现在用的比较多的就是海风月影。下载回来后复制到你的OD程序所在的文件夹里面的plugin里。StrongOD的设置选项搞不懂就全部打钩。
接下来要做的工作就是搞清楚我们要脱壳的程序编程的语言了,可以用PEID或者fastscanner查看,如果在这里看不到也可以在OD载入以后通过里面的字符串判断了。例如VB的程序会出现MSVB----/VC的会出现MSVC---等等。这些都是程序运行所需要的windows链接文件。
做完这些预备工作接下来当然是用OD载入文件。文件载入后在反汇编窗口CTRL+G搜索VirtualProtect(注意V跟P要大写,至于为什么要搜索这个别问我)。一般来说搜索的结果会出现以下的类似:
7C801AE3 E8 75FFFFFF call kernel32.VirtualProtectEx
我们在这里下F2断点。然后F9运行到我们下的这个断点。接下来我们就要注意观察堆栈窗口了。一般来说当我们F9运行到我们上面下的断点的时候在堆栈窗口会出现以下类似:
0012F66C 00401000 |Address = TradeCen.00401000
0012F670 000280D1 |Size = 280D1 (164049.)
0012F674 00000004 |NewProtect = PAGE_READWRITE
0012F678 0012FF98 \pOldProtect = 0012FF98
我们要注意观察的就是在接下来我们F9运行的时候,ADDRESS和NEWPROTECT这两行的变化。按F9-速度别太快,直到NewProtect项变为PAGE_READONLY,这时候程序就释放完毕了。
0012F66C 0042A000 |Address = TradeCen.0042A000
0012F670 000069DE |Size = 69DE (27102.)
0012F674 00000002 |NewProtect = PAGE_READONLY
0012F678 0012FF98 \pOldProtect = 0012FF98
现在可以取消刚才我们下的断点了。接下来就是找OEP了。找OEP的时候我个人的一个经验就是OEP一般就在接近上面的ADDRESS地址的附近。例如上面的地址是0042A000,我一般就在这个基础上减到420000搜索程序的特征段,当然我们也可以直接跳到401000开始搜索。虽然我们搜索的范围比较大,但是因为我们搜索的是命令序列,所以工作量还不是很大。
CTRL+G--上面的地址,然后CTRL+S 查找命令序列。命令序列的内容就是我们用查到的编程语言的特征段。我们可以在特征段里面选择两三句固定不变的命令查找。例如VC++6.0的特征段是:
0046C07B U> 55 push ebp
0046C07C 8BEC mov ebp,esp
0046C07E 6A FF push -1
0046C080 68 18064C00 push UltraSna.004C0618
0046C085 68 F8364700 push UltraSna.004736F8
0046C08A 64:A1 00000000 mov eax,dword ptr fs:[0]
0046C090 50 push eax
0046C091 64:8925 00000000 mov dword ptr fs:[0],esp
0046C098 83EC 58 sub esp,58
0046C09B 53 push ebx
0046C09C 56 push esi
0046C09D 57 push edi
我们可以只搜索前三条命令。找到符合前三条命令的,我们在对照接下来的命令。只要命令相符那这个地址八九不离十就是OEP了。如果在ADDRESS地址附近找不到OEP,那就只好用笨办法,从401000开始找吧。
找到OEP地址后,我们在OEP处点鼠标右键《此处为新EIP》。接下来就可以dump啦。通常选择OD的dump插件脱壳要好点,用loadpe脱壳后要么程序不运行要么干脆没脱。用OD的dump插件脱壳的时候,脱壳窗口下面的(重建输入表)项前面的勾一定要去掉。
你这个问题真不好回答~~ 找到入口后一般有两种方法(我光知道两种),
一种就是OD的自带脱壳功能,这种脱壳好像没有修复,如果有些壳需要修复的话,这种脱壳方式就不够用了,不知道你是否用的是此种脱壳方式
另一种就是找到入口后使用两个工具 LordPE 和 ImpREC FINAL 1.7汉化版 (我只有这个版本,不知道还有更高的没有) 用前者,将需要脱壳的工具dump出来(此时od还加载着你正脱壳的程序),然后使用ImpREC FINAL 加载od调试着的程序,然后再ImpREC FINAL 界面上的oep处填写上地址,这个地址,在od脱壳的地方可以找到,填写完毕以后 点击ImpREC FINAL 上的 “自动查找IAT” 和“获取输入表”,如果能获取到输入表代表就可以了,如果没有的话,入口地址可能有错误,获取到输入表后看看ImpREC FINAL 提示的那些输入表有没有错误,如果有错误那么需要修复,往往删掉那些错误的项问题也不大,如此这般 *** 作以后 点ImpREC FINAL 上的 “转储到文件”找到你刚才用loadpe 工具dump出来的主程序打开就行了(说是打开,其实就是将刚才的一些修复指令附加到哪个主程序上,因为软件上的按钮是 打开 所以此处说打开)。
说了太多,不期望你能看明白,其实如果看 *** 作一次,就知道了,打这些问题都弄得我有些迷糊了,更甭说你看了~~ 将就些吧,除非你找一些脱壳视频看看~~还有本人只是菜鸟,大牛路过勿喷!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)