作者:_观众
来源:CSDN
原文:https://blog.csdn.net/qq_30145355/article/details/78965948
版权声明:本文为博主原创文章,转载请附上博文链接!
一、手动单步跟踪法
主要使用的两个快捷键F8与F4
F8:单步步过
F4:运行到指定位置(右键->断点->运行到指定位置F4)
1、逐步F8往下单步跟踪,遇到往回跳转的循环时,使用F4跳到要进行循环的下一条指令。
解释:在地址0x0055B849处遇到往回跳转的指令,此时我们用鼠标点击地址0x0055B84B,然后再点击F4,程序就运行到了地址0x0055B84B处。然后我们继续往下F8往下跟踪即可。
2、有时候直接在循环的下一条指令进行F4不一定可以成功,此时我们就需要自习分析下循环跳出时会跳在哪条指令处。
我们通过分析0x0055B98F处的jmp指令发现,结束循环的指令在0x0055B950处,je跳出到的地址在jmp后的第二条指令。这与我们通常的第一条指令不同,因为普通的jmp结束循环后通常在jmp后的第一条指令,但是这个循环不同,那我们怎么解决类似的问题呢?
(1)养成好的分析习惯,可以跟进循环判断下这个循环跳出的指令在哪里。
(2)可以在jmp后的后几个指令里面选择一个F4,而不是接下来直接的第一个,例如图片中的最后一个红框里面的指令进行F4就可以避免这种问题发生。
注:类似的情况还有jmp后的指令为nop指令时,如果我们在nop指令上进行F4,是无法实现的,此时程序就会跑飞,解决的方法同上。
3、加壳的程序进行运行的时候,会先进行解压缩的操作,实现代码和数据的解密,并对IAT进行修复,这些操作在一个区段里面完成,完成之后就会实现跳转到原始程序入口点OEP进行运行,这个跳转往往为区段的跳转。
所以,我们碰到一个大的地址的跳转时,那它就可能为一个区段的跳转,更可能为跳转到OEP的指令。
例如:
该指令就是跳转到OEP的指令语句,为一个跨区段的跳转。
查看区段信息:
区段UPX0范围:0x00401000~0x004EE000
区段UPX1范围:0x004EE000~0x0055C000
可以看出,0x0055B9D4属于UPX1区段,0x004E53C2属于UPX0区段。
二、根据ESP定律方法
该方法对于大多数的压缩壳通用
ESP定律是什么?
每一个函数的调用在堆栈里都有一个栈帧,在整个函数刚刚进入的时候,它需要把EBP(始终指向栈底的指针)保存到堆栈里面,然后把当前的最顶上的ESP(始终指向栈顶的指针)往上进行移位,留出适当的栈帧来供子函数进行使用,子函数执行完毕后会进行堆栈平衡,对栈帧进行还原,并使得ESP恢复为调用函数之前的状态。简单的理解ESP定律就是栈帧及堆栈平衡原理。
ESP定律使用的原理?
通过了解ESP定律的原理,我们知道,函数执行完成后,ESP指针会进行还原为先前的状态。既然如此,我们就可以对ESP寄存器下一个硬件断点,使得ESP还原为调用函数之前状态的时候断下来,也就是函数执行完毕的时候断下来。
于是,我们可以将一个壳的解压缩的方式当作一个函数的调用。比如加了UPX壳的程序在运行的时候,开始运行的就是UPX解压缩的函数,此时它会保存EBP,然后移动ESP,给函数留出足够的栈帧,当所有的解压缩完成后,它需要把所有的栈帧再进行还原,使得ESP恢复为调用函数之前的状态,此时的硬件断点就会断下来,正好为解压缩函数执行完毕的时候,而解压缩完成后,就会进行跳转到OEP,此时我们只需要F8往下跟几步,就能很快的找到OEP了!!!
ESP定律的使用
1、第一条指令为pushad指令,先F8运行到下一条指令,才能将我们的通用寄存器压入到堆栈中(包含我们即将下硬件断点的ESP寄存器)。
2、对ESP寄存器下硬件断点
方法一:鼠标操作的方式
首先在数据窗口中跟随
然后再数据窗口中,进行下一个硬件断点,这里下的时硬件访问断点DWORD 。
方法二:通过命令下硬件断点
HR:下硬件访问断点的命令
3、F9直接运行程序,直到断下来,再F8跟几步,就到达跨段跳转到OEP的jmp指令的地方。
不难发现,硬件断下来的地方,举例我们的跨段跳转只有几步的差距,只需要简单的F8跟几步即可。
注意:此时我们找到OEP后需要删除硬件断点,否则它以后调用完函数还要断下来。
在“调试”中选择硬件断点,随后删除硬件断点即可
三、内存二次断点法
假设你是一个壳的作者,壳的解压缩代码如何来进行解压缩?
先解压缩代码,再解压缩资源…再解压缩其他的一些东东…也就是按照区段来进行解压。既然如此,我们就可以将区段看作为一个关键点,利用对区段下断点来进行查找OEP。
注:通常的壳解压缩都是一部分一部分的解压缩(也就是按区段进行解压),而不是几行代码几行代码的解压缩(这样会比较耗时,涉及到解压缩效率的问题)。
内存二次断点法的原理
(1)首先在资源段上下一个断点,那么在解压缩代码的时候,程序依旧可以正常的运行,因为是先解压缩代码再解压缩资源的。当开始解压缩资源的时候,程序就会中断下来,因为我们在资源段上下了一个断点,此时中断的时候,代码已经全部解压,资源段正在准备解压…
(2)再在代码段上下一个断点,再继续运行,此时程序开始解压缩资源和其他的一些内容,等到全部解压缩完成以后,解压缩程序就需要跳转到OEP上运行,即跳转到代码段上运行,此时中断下来。
(3)再手动F8往下跟几步,就到达跨段跳转到OEP的指令位置。
内存二次断点法的实际使用
1、点击模块的缩写M,在模块窗口中找到我们自身程序所对应的模块。此示例中为upx模块
注:其他的是一些动态链接库的模块,如果模块找错的话,自然断点也就下错了!!!
2、在资源段(.rsrc)上按F2下一个断点,或者右键选择“在访问上设置中断”
然后点击F9,让程序运行起来
3、此时程序中断下来(中断在资源段上),我们不必关系程序在哪里中断下来,接下来我们只需要再在代码段上按F2下一个断点。
然后点击F9,再次让程序运行起来
4、此时程序再次中断下来(中断在代码段上)
中断的地方:
跨段跳转的位置:
接下来我们只需要在中断下来的位置再进行手动往下跟踪即能很简单的到达跨段跳转的地方。
不难看出,中断下来的地址与跨段跳转的地址相差很小,只需要简单的手工跟踪即可找到OEP。
注:本文中寻找OEP的方法,对于压缩壳一般都适用,但是对于一些保护壳就不适用了。