逆向工程核心原理-逆向基础(基于Ollydbg201与Hello World的逆向调试)

逆向工程核心原理-逆向基础

调试器与汇编语言

我们编写的源码经过编译转化为exe可执行文件,而exe则是二进制文件,在分析二进制文件时,为了更好地理解它,我们通过调试器进行反汇编处理,将二进制代码转化为汇编语言指令代码

OllyDbg的使用

窗口界面布局

逆向工程核心原理-逆向基础(基于Ollydbg201与Hello World的逆向调试)_第1张图片

  • 代码窗口:默认用于显示反汇编代码,还用于显示各种注释,标签,分析代码时显示循环等信息
  • 寄存器窗口:实时显示CPU寄存器的值,还可以用来修改寄存器
  • 数据窗口:用于显示进程的内存地址,也可以用来修改内存地址
  • 栈区窗口:实时显示ESP寄存器指向的进程栈内存,并且允许修改

而代码窗口中的内容又有以下布局:

004011A0 E8 6715000 CALL 0040270C
进程的虚拟内存地址 x86 CPU指令 反汇编代码 此部分空出为注释区,可自己添加

EP(EntryPoint):指的是可执行代码的入口点

常用的快捷键

快捷键 描述
CTRL+F2 终止当前进程,重新开始调试
F7 执行一句操作码,遇到call将会跳转进入函数
F8 执行一句操作码,遇到call执行函数,但是不会进入函数
CTRL+F9 一直在函数内部运行,直到retn指令跳出(和F8的区别在于,此指令是执行发起指令时所在函数的return,F8就是一个简单的跳过功能
CTRL+G 移动到指定地址,用来查看代码或内存(运行状态下不可用)
F4 执行到光标位置,直接跳转到要调试的地址
为当前位置填写注释
为当前位置填写标签
F2 设置或者取消断点
F9 一直运行,存在断点则停止在断点处
* 显示当前EIP指针的位置
- 显示上一个光标的位置
Enter 若存在call或者jmp则跟踪并显示相关地址
ALT+B 显示存在的断点列表

标记/进入特定地址的方法

  • 使用CTRL+G后在 enter expression to follow对话框中输入对应的地址即可
  • 在调试时,在需要标记的地址处设置断点,然后F9执行到断点处即可,在断点列表中双击也可以跳转到相应位置
  • 设置注释在指定语句中,寻找注释可以在右键菜单search for中找到all user comment中看到添加的所有注释,双击可以到达注释位置
  • 在指定位置添加标签,后在右键菜单search for中找到中user defined labls(目前的201版本貌似找不到这个功能了)看到添加的所有注释

快速查找指定代码

  • 代码执行法

我们已知目标可执行文件调用了MassageBox的API,则我们只需要执行到目标API中的函数即可,我们通常的思路是,按F7或者F8执行程序,遇到call或者jmp指令就使用F7执行进入函数(遇到非目标函数ctrl+F9)或者enter查看函数内容,非目标函数则使用-回到原来的的位置,按F8继续调试(留意可能的API调用或程序内容)

  • 字符串检索法

在ollydbg的右键菜单中使用search for中的all referenced strings其中内容是其在调试之初对程序使用的字符串和API都将被摘录出来成为列表

  • API检索法

在程序运行后,我们可以根据运行效果,猜测运行时调用了哪些API,可以直接使用ALL intermodular calls查看调用的所有API,不过在文件受到压缩或保护后,ollydbug就无法列出API列表了,此时我们要进行调试我们需要为加载进内存中的DLL代码库设置断点

压缩器(运行时压缩器):它可以将可执行文件的代码,数据,资源压缩,但是其压缩完成后仍是一个可执行文件

保护器:保护器具有压缩功能,并且还添加了反调试,反模拟,反转储,可有效保护进程

API的实现:API实际上是系统提供的一系列函数,他们位于系统提供的DLL库中,我们的程序进行的一系列操作必须通过系统的API向系统提出请求,系统才会将对应DLL文件加载到应用程序的进程内存

我们可以在ollydbg的view菜单(也可以ALT+M)中找到memory map打开内存映射窗口,看到程序请求的DLL库列表等,为了找到调用的API,我们使用search for中的name选项在其中寻找对应API,双击即可定位到该位置,注意是本可执行程序的name列表,有时候选定了一个地址name列表可能会是对应的DLL库中的name列表

修改程序中字符串

修改程序中的字符串有两种方式:

  • 修改字符串的缓冲区

我们在定位字符串后,找到字符串所在内存地址,然后在数据窗口查找该地址,然后选中要修改的字符串部分,使用ctrl+e进行快速编辑该字符串即可修改,需要注意,如果修改后字符串长度大于原有字符串,可能会导致程序后面的数据被覆盖,此时就有可能发生内存错误(不建议比原有字符串长),并且在修改时一定要注意unicode字符串的结尾是NULL占据两个字节。

如果要保存文件,我们则应该在数据窗口选中修改后的字符串,右键找到edit中的Copy to executable或Copy all modifications to executable,进入新的界面中选中save file,然后根据提示保存即可,在文件命名处要加上exe的可执行文件扩展名

注意:可执行文件在保存时一般会给字符串留出更多空间,所以有时候以更长的字符串覆盖也不会出问题

  • 在其他内存区域建立字符串,并传递给API

这种方法实际上是利用了一个特性,应用程序被加载到内存有一个最小内存分配大小,即使程序大小未达到分配内存大小,其他的内存也会被分配,并且以NULL填充

我们可以利用填充为NULL的内存,在其中添加需要的字符串,最后在传递字符串到API处,将PUSH的地址修改成我们修改处的地址起始点即可(选中对应指令后按空格键即可通过Assemble窗口修改)

逆向尝试

首先我们自己写一个和作者一摸一样的程序,尝试逆向它:

#include "windows.h"
#include "tchar.h"


int _tmain(int argc, TCHAR* argv[]) {

	MessageBox(NULL, L"Hello World",
		L"This is a test file",
		MB_OK);

	return 0;

}

修改字符缓冲区

首先我们通过all referenced strings找到我们的对应字符串(可以看到我这里字符串地址是B22100和B22128),然后打上断点过后按F9执行到断点处,然后在数据窗口找到字符串内存:

逆向工程核心原理-逆向基础(基于Ollydbg201与Hello World的逆向调试)_第2张图片

进行修改(注意keep size选项,保证修改不会超过范围),第一处改为测试通过,第二处改为大写字母:

逆向工程核心原理-逆向基础(基于Ollydbg201与Hello World的逆向调试)_第3张图片

逆向工程核心原理-逆向基础(基于Ollydbg201与Hello World的逆向调试)_第4张图片

调试后修改成功:

逆向工程核心原理-逆向基础(基于Ollydbg201与Hello World的逆向调试)_第5张图片

保存文件:

逆向工程核心原理-逆向基础(基于Ollydbg201与Hello World的逆向调试)_第6张图片

逆向工程核心原理-逆向基础(基于Ollydbg201与Hello World的逆向调试)_第7张图片

在其他区域建立字符串

我们重新调试文件,然后找到字符串,在填充为NULL的内存区域加入字符串内容(如下我们在283020处建立新字符串):

逆向工程核心原理-逆向基础(基于Ollydbg201与Hello World的逆向调试)_第8张图片

改变字符串载入地址:

逆向工程核心原理-逆向基础(基于Ollydbg201与Hello World的逆向调试)_第9张图片

进行调试,修改成功:

逆向工程核心原理-逆向基础(基于Ollydbg201与Hello World的逆向调试)_第10张图片

注意:此修改方法保存的可执行文件无法正常运行,当可执行文件加载进入内存时,通常来讲进程的内存仍然存在,但是对应的文件偏移并不存在,所以无法正常运行

文件偏移

文件偏移是指在计算机中对文件进行访问时,当前位置与文件开头之间的距离。每个文件都可以看作是一系列字节的集合,文件偏移表示从文件开头到当前位置所经过的字节数。

文件偏移常用于读取和写入文件的特定位置。通过设置文件偏移,可以确定下一个要读取或写入的位置,以便在文件中执行精确的操作。

在大多数编程语言和操作系统中,文件偏移以字节为单位进行计量。初始文件偏移通常为0,表示从文件的开头开始。随着读取或写入操作的进行,文件偏移会自动增加,指向下一个要操作的位置。

文件偏移对于处理文件的不同部分非常有用。通过更改文件偏移,可以在文件中前后移动,查找和更新特定位置的数据,或者追加新数据到文件末尾。

需要注意的是,在某些情况下,文件偏移可能以其他单位(如块或记录)进行计量,这取决于使用的文件系统或应用程序的要求。

你可能感兴趣的:(系统安全,网络安全,安全)