指令 | 快捷键 | 含义 |
---|---|---|
Go to | ctrl + G | 移动到指定地址,用来查看代码或内存,运行时不可用 |
Execute till Cursor | F4 | 执行到光标位置,也就是直接转到要调试的地址 |
Set/Reset Break Point | F2 | 设置或者取消断点 |
Comment | ; | 添加注释 |
Label | : | 添加标签 |
Goto命令
如果要将光标定位到某处,可以执行Go to命令(ctrl + G)如果要将代码定位到 40104F 可以使用这个命令
之后配合F4可以将程序运行到此处。
设置断点
在调试代码的时候可以使用F2设置BP(断点)在设置断点之后,当程序运行到断点的时候,程序将会暂停
使用快捷键 ALT + B 可以调出断点框,列出设置的所有断点,双击这个位置就可以直接跳转到相应的设置断点的位置
添加注释
使用 ‘;’ 可以在相应的地址添加注释,并且添加后的注释可以通过查找命令找到,这里的命令必须在英文状态下
在调试代码的时候添加注释可以让调试过程变得较为简便,如果需要查找注释,可以在界面右键显示的菜单中选择 search for -> User-defined comment 中查看所定义的注释,双击注释姐可以定位到相应位置:
添加标签
可以通过标签提供的功能在指定的地址添加特定的功能,通过 ‘:’ 符号添加标签,即 shift + ;
添加标签后,可以右键显示的菜单界面选择 search for -> User-defined label 查看添加的标签
在逆向反编译代码的时候找到主函数是至关重要的,但是在反编译代码的时候 main() 函数并不直接位于可执行文件的 EP 位置上,首先出现的是开发工具自动生成的启动函数,因此可能真正需要的主函数距离开始的位置很远,因此,我们需要一些方法来快速的查找到主函数
1.代码执行法
我们来看下面的代码编译出的程序(根据原书程序重新编写的代码)
源代码如下:
#include
#include
#include
#include
using namespace std;
int main() {
MessageBox(NULL, L"Hello World", L"Lpy_Now", 0);
return 0;
}
运行程序后输出 MeaasgeBox:
接下来反编译代码,将代码放到 OD 里面运行,一直按 F8 跳过一些步骤,直到程序弹出这个MessageBox
程序到这一行 1111E2 这里调用了函数 111000 说明这里就是主函数,我们使用 ctrl + G 进入 111000 这个函数
这就是我们要找的主函数
在地址 111002 和 111007 这两个地方分别有一条 PUSH 语句,这两句分别将 Titlie = “Lpy_Now”, Text = “Hello World” 保存到栈中,并作为参数传递给 MessageBox ,通过上面的方法也能成功的找到主函数。
2.字符串检索法
OD在第一次载入待调试的程序的时候,都会经历一个预分析的过程,在这个过程中会查看进程内存,程序中引用的字符串和调用的 API 都会被摘录出来,并被整理到另外的一个列表中,查找字符串对天十程序很有用。
右键,在弹出的窗口中点击 Search for -> All referenced text strings 可以看到如下窗口:
双击即可进入所对应的代码行,
通过上面的方式也成功的找到了主函数
3.API 检索法(1):在调用代码中设置断点
在 Windows 中,如果需要向显示器显示内容,需要使用 Win32 API 向 OS 请求显示输出,换言之,应用程序向显示器的画面输出内容的时候,需要在程序的内部调用 Win32 API 当我们观察一个程序的功能后,就可以大致得推测出程序运行时调用的 API ,如果能进一步查到调用的 Win32 API,就会为我们得程序调试带来很大的便利,上面的程序运行后会弹出一个消息窗口,那么我们就可以推断出这个程序运行时调用的是 user.MessageBoxW()API
在前面的描述中说过在 OD 对程序的预分析中不仅可以分析出程序使用的字符串,还能摘录出程序运行时调用的 API 函数列表。如果我们只想查看程序代码中调用了哪些 API 函数,我们可以直接使用 All intermodular calls 命令,即右键在出现的菜单中点击 Search for -> All intermodual calls 点击后
由于我们要找的是 MessageBox 这样的指令,因此在第一行就是这个指令,双击这里也可以找到主函数,因此观察一个程序的行为特征,如果我们能事先推测出代码使用的 API ,那么上面同样是一种不错的找到主函数的方法。
4. API 检索法(2):在 API 代码中设置断点
尽管在之前的介绍中有介绍 OD 可以为可执行文件列出 API 函数调用列表,但是如果使用压缩器/保护器对可执行文件进行压缩或者保护之后,可执行文件的结构就会发生高边,这时 OD 就无法列出 API 调用列表了(甚至会让调试过程变得十分困难)
压缩器(Run time Packer,运行时压缩器):压缩器是一个实用压缩工具,能够压缩可执行文件的代码,数据,资源等等,与普通的压缩一样,经过压缩器压缩后的文件本身就是一个可执行文件
保护器:保护器不仅具有压缩功能,还添加了反调试,反模拟,反转储等功能,能够有效保护进程,如果想仔细分析保护器,那么分析者需要一些高级逆向分析知识
在这种情况下,DLL 代码库被加载到进程内存后,我么你可以直接想 DLL 代码库添加断点,API 是操作系用对用户的应用程序提供的一系列函数,用于实现一些文件。简言之,我们编写的应用程序执行某种操作的时候,必须使用 OS 提供的 API 向 OS 提供请求,然后与被调用的 API 对应的系统 dll 文件就会被加载到应用程序的进程内存
在 OD 中我们可以先尝试查看内存映射,在菜单栏中点击 View -> Memory(或 alt + M) 打开内存映射窗口
我们可以看到 USER32 库被加载到内存中,我们接下来右键的窗口中点击 Search for -> Name in all modules 可以打开 All names 窗口,点击 Name 栏目按名称进行排序
在这里搜索 MessageBoxW
在箭头所指的地方,双击这个函数,就会显示这里的代码,它在 USER32.dll 中实现。
观察这里的地址发现这里与我们的可执行文件的地址完全不同,我们尝试在这里设置断点(F2),之后继续执行代码(F9)
代码执行到这里就停了下来,在 1 处的箭头寄存器窗口中的 ESP 的值为 00EFF874 它是进程栈的地址,在 2 处的箭头的栈窗口中可以看到更为详细的信息 ESP 地址的 00EFFBB8 处对应一个地址 00FE1014 ,也就是主函数调用完 MessageBox 函数后,程序执行流将返回到这个地址,我们按 ctrl + G 到达这里
我们发现这段代码的上面就是我们要找的主函数
B8 处对应一个地址 00FE1014 ,也就是主函数调用完 MessageBox 函数后,程序执行流将返回到这个地址,我们按 ctrl + G 到达这里
我们发现这段代码的上面就是我们要找的主函数
以上就是快速查找代码的四种方式