逆向分析之核心代码的定位

来源:互联网 发布:ubuntu查看分区挂载点 编辑:程序博客网 时间:2024/05/21 04:22

逆向一般是带有强烈的目的性的, 比如逆出一个程序的某种功能的实现函数,或者是逆出一个程序的流程等等.
要完成这样的功能就需要定位到具体的函数上, 然后才能分析其代码,否则在庞大的二进制流中, 信息的获取必定是极其艰难的.
在庞大的二进制流中找到一个地址未知的函数. 需要推测这个函数的一些特征,没有特征就很难定位到这个函数. 因为在庞大的二进制流中有着上万乃至数十万行以上的机器码,在这里面使用常规的方法找到几百行特定的机器码是非常耗时耗力的.
所以, 必须要推测出函数的一些特征,才能快速定位到核心代码处.
一般一个函数的特征会有:
• 这个函数将会完成什么样的功能,在完成这些功能的时候调用了什么 API.
• 使用了容易搜索出的字符串.
• 有一些特定的机器码等等.
• 读写了特定的地址.
• 只要是稍微异于其他代码的特征都可以.

对于第 1点特征, 可以使用堆栈回溯找到核心代码.
对于第 2点特征, 利用到的是字符串搜索找到核心代码.
对于第 3点特征, 利用到的是二进制字串搜索找到核心代码.
对于第 4点特征, 利用到的是硬件读写断点或软件读写断点.

1 关于堆栈回溯的原理:
有两个函数 UnKnownFunction(), 和 WellKnowFunction(), 其中, 已知条件有:
• UnKnownFunction 代码的地址是未知的.
• WellKnowFunction代码的地址是已知的.
• 在 UnKnownFunction函数的代码中, 有调用 WellKnowFunction函数的语句.
现在, 需要找出 UnKnownFunction 代码的地址.
• 从第3条已知条件中可以得到一个信息, 当 WellKnowFunction函数被调用时, 有可能就是在 UnlKnowFunction函数中调用的, 如果 WellKnowFunction函数被调用,那么在栈中就一定保存着返回地址(call WellKnowFunction时,call语句先把下一条语句的首地址压栈,然后才跳转到WellKnowFunction函数中), 这个返回地址将会返回到 WellKnowFunction函数被调用的地址.
• 根据第二条已知条件可知, WellKnowFunction函数的地址是已知的, 因此可以在这个函数中下断点. 当这个函数被中断时, 就可以根据栈中的返回地址找到这个函数执行完后将会返回到的地方(也就是调用这个函数的语句之后).
• 因此利用这一点可以找到程序的核心代码. 在一个程序中, 程序代码的函数地址是未知的. API的地址是已知的,所以只要能够推测在核心代码的中会调用什么 API,就可以在 API处下断,通过堆栈回溯找到核心代码.
这里写图片描述
2 关于字符串搜索的原理

如果核心代码中使用了字符串. 那么只要搜索到这个字符串.在 OD中就可以直接找到引用这个字符串的代码.

3 关于二进制字串搜索的原理
和字符串搜索的原理差不多 , 只不过字符串容易被搜索到, 但是二进制字串需要自行推测出才能够搜索到.
比如在一个函数中, 函数的内部会调用一个获取对话框子控件句柄的 API.则函数如下:

机器码     |    汇编代码    |    注释

———–+—————-+————————————
68ED010000 | push 0x1ED | ;子控件的 ID(随便给出的)
6811110000 | push 0x1111 | ;对话框的窗口句柄(随便给出的)
| call GeDlgItem | ;调用函数
在推测到核心代码会有这样的代码时, 就可以直接查找二进制字串 68ED01000 来查,当然在实际操作中如果前期分析到的信息过少,就难以猜测出具体的代码.所以这招想要用得好,前期详细的分析必不可少.

4 关于核心代码中读写了特定的地址,使用读写断点的原理

假设在前期的分析中, 已知核心代码处会对一个全局变量进行读写操作. 全局变量的地址在前期的分析中找到了,但是读写全局变量的代码很难找到.那么读写断点就很适用于这样的场景. 如果核心代码访问这个全局变量. 只要在这个全局变量的地址上设置一个读写断点. 当有代码读写这个全局变量的地址时就会断下来.

0 0
原创粉丝点击