这是我的《逆向分析学习小纪》第二篇,这个系列主要介绍我的逆向分析学习过程,本篇涉及逆向分析中常用调试器的介绍,以及利用IDA工具完成简单的程序动态分析等内容。希望和大家多多交流,共同进步!
一. 调试器介绍
1. 调试器简介和特点
在软件开发过程中,程序员需要使用调试工具来验证程序的逻辑是否和自己的思路一致,或用调试工具快速高效地定位程序中是否存在错误和可以优化的地方。同开发过程一样,在逆向分析过程中,分析者也会利用一些调试工具来分析程序的逻辑和行为,从而验证自己的猜想。
调试器具备两个最最最基础的特征:断点设置和代码跟踪。
- 断点设置:允许选择程序中任意位置的某行代码,一旦程序运行到这行代码,就会将程序暂停运行,并且显示程序的即时状态。
- 代码跟踪:允许跟踪程序的执行情况,即程序可以单步运行后暂停并返回即时状态,并且允许用户观察甚至修改程序的变量、内容等部分。
2.常用调试器
根据大佬们的使用经验,常用的调试器包括:Ollydbg、x64dbg、Windbg和gdb等等。其中,Ollydbg用来调试Windows环境下的32位用户态程序;x64dbg用来调试Windosw环境下的64位应用程序;Windbg是微软官方提供的调试器,可以对用户程序及系统内核开展调试,但是其使用界面非常简陋,不太方便;gdb是Linux系统下的主要调试器。下面简单介绍一下Ollydbg和gdb。
(1)Ollydbg
Ollydbg简称OD,是Windows环境下,具有可视化功能和界面的用户态调试器。OD的GUI界面较为友好,容易上手,这里我也为大家搜集了破解版的Ollydbg,大家有需要可以自取。
链接:https://pan.baidu.com/s/1nODT-DcX-bigOZcp1FTUCw?pwd=3frs
提取码:3frs
a. 安装教程
破解版的Ollydbg安装十分简单,第一步先将安装包解压到固定目录下,然后运行根目录下的”路径修复工具.exe“文件,如下图所示。
第二步当出现“修复成功”弹窗时,就可以开启OD啦!
b. 程序主界面
- 反汇编窗口:加载程序之后,该窗口内显示程序反汇编后的源代码。
- 信息窗口:动态调试时,该窗口显示当前代码行的各个寄存器信息,或者API函数的调用和跳转等信息,辅助用户了解当前代码行的寄存器的运行情况。
- 数据窗口:默认十六进制(HEX)显示内存中数据。
- 寄存器窗口:动态显示CPU各个寄存器的内容,包括数据寄存器、指针和变址寄存器、段寄存器,及控制寄存器中的程序状态字寄存器。
- 堆栈窗口:显示堆栈内容。便于用户了解传递的参数等信息。
- 命令行(插件):支持调试时输入命令,一般是插入断点、清除断点等命令。
c. 断点操作介绍
动态调试时需要让程序在我们关注的代码处中断,然后根据显示的各项信息开展动态分析,这就必然需要支持断点操作,OD中的断点有一般断点、内存断点、硬件断点等类型,其中一般断点是最常用的。
- 一般断点:实际就是将断点地址第一个字节用INT3指令代替,当运行到断点地址,就会自动执行INT3指令,OD就会中断。如果需要设置一般断点,一是可以通过“F2”快捷键下断点,成功后会变成红色状态;二是可以通过命令行方式下断点,在命令行中输入bp命令,如bp “地址/函数”等。
- 内存断点:内存断点分为内存访问断点和内存写入断点,OD同时刻只允许一个内存断点存在。两者的区别是,前者是在程序运行时调用被选择的内存数据就会被OD中断,后者是程序运行时向被选择的内存地址写入数据就会被OD中断。如果要设置内存断点,可以在数据窗口的十六进制栏选择一部分内存数据,然后鼠标右键调出功能菜单→断点→内存访问/写入断点。
- 硬件断点:该方式不会将程序代码改为INT3指令,如果某些程序具有自校验功能,则可以使用硬件断点,最多可设置4个。如果要设置硬件断点,方式与内存断点一致,可选择硬件访问、硬件写入、硬件执行三种模式。
d. 代码跟踪操作介绍
这部分主要涉及一些常用快捷键,用于便捷跟踪程序:
- F9键:载入程序后,按该键可运行程序。
- F7键:单步跟踪(步入),即单条代码执行,遇到call语句时会跟着执行该语句调用地址的代码或调用函数的代码。
- F8键:单步跟踪(步过),与上条不同之处在于,遇到call语句不会进入。
- F4键:执行到所选代码处。
- ALT+F9键:执行到程序领空,如果进入引用的DLL模块领空,则可以按此键快速回到程序领空。
(2)gdb
gdb是由GNU开源组织发布的调试工具,其基于UNIX/Linux操作系统运行,是一个基于命令行的强大调试器。
a. 安装教程
基本在很多Linux发行版本系统中,gdb都是默认安装的,如果没有,例如在Ubuntu下可以通过apt-get直接安装,只需要在terminal中输入以下命令即可:
sudo apt-get install gdb
若需要调试其他架构的elf程序,可以安装gdb-multiarch,命令为:
sudo apt-get install gdb-multiarch
此外,目前gdb还有很多插件,比如peda、pwndbg、gef等等,这些插件集成了一些常用的逆向分析命令,可在Github上找到并根据对应的readme安装。
b. 基本操作
gdb调试用的基本操作及说明如下表所示:
类型 | 命令 | 功能 |
启动&结束 | gdb program | 启动gdb,开始调试program |
quit | 退出gdb | |
通用命令 | run arguments | 运行被调试程序(指定参数arguments) |
attach processID | 把调试器附加至PID为processID的进程上 | |
断点 | break *address | 下断点 |
info breakpoints | 查看所有断点 | |
delete number | 删除某个断点 | |
运行调试目标 | stepi | 执行一条机器指令,单步进入子函数 |
nexti | 执行一条机器指令,不进入子函数 | |
continue | 继续执行 | |
查看和修改 程序状态 | x/countFormatSize addr | 以指定格式Format打印地址address处的指定大小size、指定数量count的对象 Size:b(字节)、h(半字)、w(字)、g(8字节) Format:o(八进制)、d(十进制)、x(十六进制)、u(无符号十进制)、t(二进制)、f(浮点数)、a(地址)、i(指令)、c(字符)、s(字符串) |
info register | 查看寄存器 | |
backtrace | 打印函数调用栈回溯 | |
set $reg=value | 修改寄存器 | |
set *(type*)(address)=value | 修改内存地址addr为value | |
其他 | shell command | 执行shell命令command |
set follow-fork-mode parent|child | 当发生fork时,指示调试器跟踪父进程还是子进程 | |
handler SIGALRM ignore | 忽视信号SIGALRM,调试器接收到的SIGALRM信号不会发送给被调试程序 | |
target remote ip:port | 连接远程调试 |
二. 基于IDA动态分析程序
大家都知道,IDA用来静态分析效果十分拔群,在学习IDA和调试器的过程中,我不禁思考IDA的动态分析功能到底表现如何?因此本章就是我基于Windows环境下的IDA工具,对局域网内某机器(系统为Debian<linux>)上的程序开展动态分析的实战经历,可供大家参考~
1. IDA调试器的部署
首先我们要知道IDA的调试器在什么位置~如下图所示,当IDA安装好之后,在根目录下会生成一个dbgsrv目录,里面集成了各系统32/64位的调试器,可根据机器具体情况选择部署。
由于局域网机器是Debian系统,因此选择将linux系统对应的linux_server程序上传至Debian系统中,如下所示:
然后输入./linux_server64运行调试器:
到此IDA调试器在目标机器上已经部署成功了!
2. 基于IDA远程动态分析
第一步:调试器部署后,打开IDA工具,选择“Go”打开一个新的页面。
第二步:菜单栏中Debugger→Attach→Remote Linux debugger,远程连接Linux调试器。
第三步:Hostname和Password栏中分别输入Linux服务器的IP地址和root用户登录密码,此时应注意Port一定要和./linux_server64运行时listening的端口一致。
第四步:根据PID和Name找到我们需要动态调试的程序。
第五步:上图点击OK后,可在Linux中看到已经和IDA的机器连接上了。
第六步:此时已经可以在IDA上调试该程序了,需要注意的是,连接成功后该程序会暂停,我们可以根据需要在关键处打断点,具体调试方式和自己写代码一致。
此时就可以开始享受动态分析的过程啦~
三. 学习后记
经过学习我发现,调试器还是很有趣的,其实和写代码中的代码调试过程非常非常非常相似,在上一篇文章中我介绍了IDA的相关情况,因此本次也基于IDA做了一个简单的局域网内远程动态分析案例,如有不当之处请大家批评指正!
与诸君共勉~
参考: