找到Hello World程序的main函数
- 编写HelloWorld.exe程序
#include "windows.h"
#include "tchar.h"
int _tmain(int argc, TCHAR *argv[])
{
MessageBox(NULL,
L"Hello World!",
L"www.reversecore.com",
MB_OK);
return 0;
}
- 使用OllyDbg打开HelloWorld.exe程序。
- 调试器停止的地点即为Hello World.exe执行的起始地址(0x004011A0),它是一段EP代码,其中有CALL与JMP两个指令,即先调用0x0040270C地址处的函数,再跳转值(JMP)0x0040104F地址处。
- OllyDbg基本指令的使用方法
- Ctrl+F2->重新开始调试
- F7->执行一句OP code,若遇到call指令,将进入函数代码内部
- F8->执行一句OP code,若遇到call指令,则执行函数自身,不跟随进入
- Ctrl+F9->一直再函数代码内部运行,知道遇到RETN命令,跳出函数。
- 执行F7指令,进入被调用函数内部。
- 在注释部分红色字体就是被调用的API函数名称,它们并不是我们在源代码中调用的函数,这些函数是Visual C++为了保证程序正常运行而自行添加的Visual C++启动函数。
- 4027A1地址处有一条RETN指令,它用于返回到函数调用者的下一条指令,一般是被调用函数的最后一句,即返回4011A5地址处。
- 我们在RETN语句处下一个断点,然后执行F9,程序会到断点处停下来,然后单步F7执行指令返回。
- 执行4011A5地址处的跳转命令JMP 0040104F,跳转至0040104F地址处。
- 上述有很多代码产生了很多函数调用,碰到一个函数调用我们进去查看是否是我们要找的main函数,如果不是返回继续查找。
- 在401000函数内部出现了调用MessageBoxW()API的代码,该API函数的参数为“www.reversecore.com”与“hello world”两个字符串,与源代码内容一致,由此可以断定,401000函数就是我们一致查找的main()函数。
使用打补丁方式修改Hello World字符串
- 代码逆向分析中,打补丁操作是不可或缺的重要主题,利用打补丁技术不仅可以修复已有程序中的Bug,还可以向程序中添加新功能,打补丁的对象可以是文件、内存,还可以是程序的代码、数据等。
- 我们将上述Hello World字符串更改为其他字符串,我们将main函数的起始地址401000处设置断点,然后F9执行程序,使程序停在这里。
- 修改字符串的两种办法。
- 直接修改字符串的缓冲区。
-
MessageBox函数的字符串参数“Hello World”保存在地址4092A0处的一段缓冲区中,只要修改这段内容,就可以修改MessageBox显示出的字符串,在Dump窗口中按Ctrl+G快捷键执行Go to命令,在弹出窗口中输入4092A0进入字符串缓冲区,然后使用鼠标选择4092A0地址处的字符串,按Ctrl+E快捷键打开编辑窗口。
-
在弹出的编辑窗口的UNICODE文本框中输入“Hello Reversing”字符串,修改只能在HEX文本框中进行,若新字符串的长度大于原有字符串,执行覆盖操作时可能损坏字符串后面的数据,所以一定要小心,特别时字符串后面又非常重要的数据时,覆盖操作导致数据损坏就会引发程序内存引用错误。
-
返回到Main函数中,查看结果。
-
虽然指令不变,但原字符串已经被新字符串取代,用作MessageBox()函数的参数,并且参数地址仍为4092A0,只是该地址空间中的内容发送了改变,按F9键运行程序。
-
这种方法的优点是使用起来十分简单,但缺点是它对新字符串的长度有限制,新字符串的长度不应该比原来字符串长。
-
上面的调试中,我们通过修改字符串缓冲区更改了程序显示的消息内容,但是这种更改只是暂时的,终止调试后,程序中的原字符串仍然没有改变,如果想要把这种更改保存下来,就要把更改后的程序另保存一个可执行文件。
-
在Dump窗口中,选中更改后的Hello Reversing字符串,点击鼠标右键,在弹出的菜单中选择Copy to executable file菜单。
-
在弹出的菜单中再次单击鼠标右键,选择Save file菜单,在对话框种输入程序的名字,即可完成保存。
-
- 在其他内存区域生成新字符串并传递给消息函数。
-
向MessageBox()函数传递字符串参数时,传递的是字符串所在区域的首地址,如果该变了字符串地址,消息框就会显示出变更后的字符串,在内存的某个区域新建一个长字符串,并把新字符串的首地址传递给MessageBox()函数,可以认为传递的是完全不同的字符串地址。
-
我们在方法1种修改字符串的地址为4092A0,再次在Dump窗口查看这部分,然后向下拖动滚动条,可以看到在末尾由NULL填充结束,最好将此处用作字符串缓冲区并传递给MessageBox函数,用快捷键Ctrl+E向结尾部分409F50开始写入字符串Hello Reversing World!!即可。
-
应用程序被加载到内存时有一个最小的内存分配大小,一般为1000,即使程序运行时只占用100内存,它被加载到内存时仍然会分到1000左右的内存,这些内存一部分被程序占用,其余部分为空余区域,全部被填充为NULL。
-
新建了缓冲区后,接下来就应该把新的缓冲区地址(409F50)作为参数传递给MessageBox()函数,为此,我们需要在代码窗口种使用汇编命令修改代码,将光标置于地址401007处,按空格键打开Assemble窗口,然后输入PUSH 409F50.
-
在OllyDbg中按F9键运行程序。
-