问题
在使用OD(OllyDbg)的过程中,我们可以使用断点开进行反汇编代码的暂停执行,通常在调试自己代码的时候我们会使用搜索expresion
的方式来在特定代码处下断点,但是有时候我们成功在所谓有效的expression
处下了断点之后执行代码,代码却没有暂停,直接运行到程序结束。这是为什么呢。
注:expression在这里表示一个可以被OD检测到的函数
答案
这是因为我们的代码在编译的过程中,由于
- 不同字符集的设置
- 编译器的优化过程
- 编译器的自主选择
在我们的代码编译之后,可执行文件并没有调用我们认为程序会调用的函数。
解决方法
- 在进行
expression
搜索的过程中或者bp expression
命令的时候采用对应字符集的expression
,例如在你编写程序的时候使用了MessageBox
函数,编译后就是unicode
字符集对应的窗口函数MessageBoxW
和ASCLL
字符集对应的窗口函数MessageBoxA
- 在使用
vs
系列编译器时,关闭c、c++
的编译优化选项,在使用gcc
、g++
命令时,使用-O
参数来关闭编译器优化,例如gcc -O0 a.c -o a.exe
- 某些时候即使你关闭了代码优化,你所使用的函数也不会成为最后编译器编译所使用的函数,例如在你仅仅使用
printf
函数来输出一串简单的字符时,你的编译器还是会将其替换为puts
函数。
例子
例1
程序a.c
如下
#include <windows.h>
int a = 1;
int main(void){
MessageBox(0,NULL,NULL,MB_OK);
// 需要调试的部分开始
a = 65536
// 需要调试的部分结束
return 0;
}
使用Mingw
编译
g++ -O0 a.c -o a.exe
正确姿势: 在OD
中你必须使用对应的字符集下的函数才能成功对MessageBox
函数调用处下断点,在gcc
、g++
中默认使用的是ASCLL
字符集,你必须在MessageBoxA
函数处下断点才能成功暂停程序。
例2
程序b.c
如下:
#include<cstdio>
void test(){
return;
}
int main(void){
printf("test start \n");
// 需要调试的部分开始
__asm__("nop");
test();
// 需要调试的部分结束
printf("test stop \n");
return 0;
}
使用Mingw
编译
g++ -O0 b.c -o b.exe
正确姿势: 在编译的过程中,虽然使用了-O0
停用编译优化,但是由于printf
函数用的太简单,编译器还会有可能使用puts
函数替换printf
函数,此时在puts
函数处下断点才可以正确中断程序。