《逆向工程核心原理》第2章——逆向分析HelloWorld!程序


逆向分析Hello World!程序

编辑源程序

注意编译时如果出现字符串无法转换的错误,解决方法:工程-设置-C/C++,在预处理程序定义处添加UNICODE,_UNICODE

此外创建工程时要创建Win32 Console Application控制台项目,否则build会报错。

另外补充一点:在虚拟机中打开VC++和OllyDbg要选择以管理员方式运行,否则VC++会导致程序link失败,OllyDbg中无法另存文件。

在这里插入图片描述

#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;
}

ctrl+F2 重新调试:EP(入口点)处

在这里插入图片描述

F8单步执行,前面的复杂代码是启动函数。

在这里插入图片描述

F7跳入函数,此处跳入401005处。

在这里插入图片描述
jmp执行执行跳转。

在这里插入图片描述

查看函数内部,可以看到API函数MessageBox,由此可知该处为主函数,且MessageBox函数调用处为402038。

此外:
F4 执行到光标处
F2 下断点
Ctrl+G 跳转到指定地址
F9 运行
Ctrl+F9 在函数内部运行知道retn处


快速查找指定代码的方法

字符串检索法

右键-search for-all referenced text strings

在这里插入图片描述

双击即可跳转。

检索可知字符串"hello world!"通过push入栈,地址为42101C。在hex dump处使用Ctrl+G跳转到该地址

在这里插入图片描述
可以看到对应字符串,是以UNICODE编码的,后面用NULL填充。

API检索法一

右键-search for-all intermodular calls

在这里插入图片描述

可以看到窗口列出了所有程序调用的API,观察程序行为特征:弹出窗口,即可推测出调用API并进行定位。

API检索法二

View-Memory菜单(Alt+M)打开内存映射窗口

使用压缩器或保护器对可执行文件进行压缩或保护后,文件结构会改变,此时ollydbg就无法列出API调用表了。这种情况下,可以直接向DLL代码库查找。

API是操作系统对用户程序提供的一系列函数,它实现与C:\Windows\systems32文件夹中的*.dll文件(如kernel32.dll、user32.dll、gdi32.dll等)内部。简而言之,我们编写的应用程序执行某种操作时(如各种O/I操作),必须使用OS提供的API向OS提出请求,然后与被调用API对应的系统DLL文件就会被加载到应用程序的进程内存

在这里插入图片描述
可以看到,内存映射窗口显示了部分HelloWorld.exe进程内存,底部可以看到USER32被加载到了内存。

Name in all modules命令列出被加载DLL文件中提供的所有API,单击Name按名称排序,用键盘敲出MessageBoxs后,光标会自动定位到对应处。

在这里插入图片描述

双击MessageBoxW函数,查看代码,在起始处F2下断点。

在这里插入图片描述

F9执行程序到该处,可以看到此时ESP值为12FEE8,它是进城栈的地址。查看右下角栈空间。

在这里插入图片描述

可以看到栈中12FEE8出存储着返回地址40103E,单步执行至retn处,

在这里插入图片描述

F7跳出函数,可以看到上条指令地址为401038,正是调用MessageBox函数的地方。


使用“打补丁”方式修改“Hello World!”字符串

在40102a处下断点,F9执行到断点处。
在这里插入图片描述
方法一:直接修改字符串缓冲区

上图可以看到,hello world!字符串地址为42101C。hex dump中Ctrl+G输入地址跳转,选中要修改的部分,Ctrl+E打开编辑窗口,用新字符覆写该区域。

在这里插入图片描述

注意:Unicode字符串必须以NULL结尾,它占两个字节(添加NULL不能直接在编辑窗口进行,而要在hex项目中添加),并且要注意新字符串长度,不能覆盖后面数据,否则可能导致程序内存引用错误。

此时F9运行程序将弹出下图窗口,可以看到新字符串。

在这里插入图片描述
接下来需要保存更改到可执行文件,选中更改后的字符串,右键–copy to executable file,打开如下窗口。
右键–save file–命名为helloreserving

在这里插入图片描述

运行helloreserving.exe文件,可以看到修改成功。

在这里插入图片描述

方法二:在其他内存区域新建字符串并传递给消息函数

如果替换字符串太长,方法一则不适用。

重新回到断点处,push 0042101c指令把地址42101c处的字符串以参数的形式传递给了MessageBox()函数。

向函数传递参数时,传递的是字符串所在区域的首地址。如果改变字符串地址,消息框就会显示变更后的字符串,因此可以在内存的某个区域新建一个长字符串,并将新字符串的首地址传递给MessageBoxW()函数。

在这里插入图片描述
在hex dump中向下查找空白内存,Ctrl+E编辑新的字符串。

在这里插入图片描述
可以看到新字符串被写入421FCC。接下来把新的缓冲区地址作为参数传递给MessageBox函数,在代码窗口修改代码即可,使用空格键打开assemble窗口。

在这里插入图片描述
F9运行程序,弹出窗口如下,可以看到修改成功。

在这里插入图片描述


小总结

整个函数的结构:

启动函数+主函数–主函数中的call MessageBox函数–进入–MessageBox函数内部,执行到retn返回–继续执行主函数中的call 指令后的指令

查找主函数:

可执行文件起始处是VC++启动函数(Ctrl+F2重新调试即可返回EP入口点),F7单步执行,依此跳转进入函数查看API调用,判断是否为主函数,若不是,Ctrl+F9执行到retn处跳出,直到跳入函数中看到MessageBox函数,即找到主函数位置。

查看内存映射窗口:

通过View-Memory可以查看内存映射窗口,单击Name排序,键入MessageBox找到函数,双击键入即可查看其代码。在该函数出下断点(F2),F9执行到断点处,继续执行至rtn跳出,可以看到上一条即为MessageBox函数的调用指令。

设置basecamp的方法:

  1. goto(Ctrl+F)命令
  2. F2下断点(view-breakpoint查看全部断点)
  3. 注释(右键-search for-user defined comment查看全部注释)
  4. 标签(右键-search for-user defined labels查看全部标签)

快速查找指定代码的方法:

  1. search for-all referenced text string查看所有引用字符串与调用API
  2. search for-all intermodular calls查看所有调用的API函数
  3. view-memory打开映射窗口, search for-name in all modules查看所有被加载DLL文件中提供的所有API函数

两种修改字符串的方法:

  1. 直接修改字符串缓冲区:Ctrl+E编辑数据(hex dump),右键-copy to executable file创建文本副本(修改的项目被保留)
  2. 在空白内存处编辑,并将函数参数入口地址修改为编辑处地址(空格键打开assemble修改汇编指令)
  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值