Getright 5 手动脱壳和重建IAT--第二部分(图)
程序员文章站
2022-03-01 21:48:03
在本参考教程的第一部分我们学习了如何正确地转储(dump)Getright 5. 现在我们将要去找神奇跳转,这样IAT会被正确地转储下来,而不用手工修复了. 要完成这一点,我们需要打败程序中的一些... 08-10-08...
在本参考教程的第一部分我们学习了如何正确地转储(dump)getright 5. 现在我们将要去找神奇跳转,这样iat会被正确地转储下来,而不用手工修复了. 要完成这一点,我们需要打败程序中的一些陷阱, 并使它们即使在检测到被执行脱壳时也无所作为.
让我们开始吧!
第一步:如何找到iat的起始点和终点
在我们开始之前,先在安全的地方保存一份我们在先前第一部分教程中得到的转储文件的副本. 我将它命名为tute.exe记住这个名字.
用ollydbg载入tute.exe. 我们将要去寻找iat.
正如我们在上图中看到的,如果我们稍加跟踪,我们很容易发现一个
call [xxxxxx] 或者 jmp [xxxxxx] 间接地带有它们即将跳往iat中某处的内存地址值.在这张图中,我们可以看到 call [5e9d94]. 那意味着这个call将要前往这个内存地址,实际上就是iat表的入口值.在它的右边我们可以看到"kernel32.getversion" (黄色). 这就意味着这是一个可以在import recontructor上被找到的正确的入口值.
让我们看一下转储(dump)窗口.在转储(dump)窗口右击,选择"前往 表达 5e9d94".
这就是看上去很不错的iat. 正如你所看到的入口5e9d94指向77e5d142,那个值在我的机器里是api getversion.这个入口是正确的,此入口周围的其它一些入口也是指向类似7xxxxxxx的值.
注意在其它的机器上值7xxxxxx可能会有所不同.但是这些值都是相互类似的. 现在我们稍微往上看一看,去找此表的起始点.我们到达这里:
红线标记了此表的起始点.在此线的上面没有其它任何api值了.现在我们知道表从哪儿开始了
table starts= 5e99ec
现在到右下角转储区去找iat表的终止点.正如我们在图中看到的有两个可能的终止点. 如果我们吃不准最好选后面那个.但是我们有更好的方法.
选择任何一个不确认的值,然后将表向上翻页.停在401000.我们必须去找一个call [xxxxx]或者一个jmp [xxxxx].右击鼠标并选择search for binary string
我们将要去寻找那些不确认的入口中的一个,让我们试试5ea25c.记住逆序写这个值如下图所示.
到了这里
稍稍往上翻一下
我们看到那儿有一个使用此值的call,所以那些不确认的值也都是属于iat的.
现在我们知道了
end of table= 5ea2bc
终点值是用来计算表的长度的.这是很简单的一步:
length= end-start
length=5ea2bc-5e99ec
length= 8d0
在纸上写下oep,表的起始点和长度,在使用import reconstructor时你将用到这些值.
第二步:找出那些不指向任何api的错值.
当getright.exe正在进行转储时,这个问题变的很容易.然后选择view-memory你将看到哪些入口指向了dlls而哪些则指向了错误的地方.
无论如何如果我们尝试用revirgin或import reconstructor则会有很多入口无法解决.这就是我们为什么请出哈里波特带来一些魔法.
正如在表中看到的,还存在一些(黄色标记)没有解决的入口.通常对付这种情况的方法是从我开始转储起就跟踪,然后追踪每一个调用api的call,写下名字最后用import reconstructor.
如果*很少几处没有解决的入口这样做将非常简便,但是如果有很多的话,这项工作将令人难以忍受,所以让我们看看另一种方法.
第三步:如何去找出magic jump
这里说明一点:我们已经知道程序的父进程和他的子进程是相同文件,但要用不同的句柄装入两次,所以他们变成两个不同的进程。一方面父进程的oep是5f90b9,父进程从这里开始运行.
另一方面我们知道当子进程被转储时其oep是534e90,但我也要告诉你,子进程也是以相同的父进程的入口点5f80b9开始运行.子进程运行并且解出自己的iat然后跳到子进程引起错误的oep,我希望你记住这一点,我在第一部分曾经讲过.
如果你相信以上所说,我告诉你,跟踪父进程直到父进程开始转变为两个进程,父进程和子进程,找到那个地方,那非常有用.我已经找到了那个地方,那是个条件跳转,至于如何找到的,我以后再告诉你.
顺便一提它不是从父进程那复制 iat 到它的子进程,却是从子进程那解出自己的 iat。这应该是一大麻烦,因为我们不能在他从父进程脱离前用 ollydbg 进入子进程。
这是个烦恼,因为我不知道如何进入子进程去观察它如何解出自己的iat.
首先我尝试着从转储程序tute.exe中找一个错误的entry.
我选择了5e9c34但是你可以选择其它任何错误的entry.正如你所看到的,它的值为df5070.
按老规矩记住要将 isdebuggerpresent 的值设为零,清除所有以前的 bpx、bp waitfordebugevent 然后单击运行.
我们将停在此断点或者某个例外上.那时,打开pupe选择进程中2个进程中的上面一个(因为他是子进程,是我们需要的).右击进入parcheando窗口选择4字节,如图在地址里填入错误的entry offset 5e9c34.然后点击buscar. 你将会看到没什么变化,因为所有值都是零.
然后不断的在od中点击运行、在pupe中点击buscar,并检查字节窗口中的值.