OllyDBG和x64DGB
OllyFDBG和X64DGB都是调试Windows平台可执行文件的调试器
x64DGB支持32位和64位程序的调试,并且不断开发和添加新的功能
为OD仅支持32位程序
1.打开文件
打开调试器后,可以发现两个调试器的界面分布大致相同
用户可以将文件拖入主界面,也可以使用菜单栏打开文件
x64DBG和OD的布局相同,左上区域为反汇编结果的显示区域,左下角区域为浏览器内存数据的区域,右下角区域为栈数据的显示区域,右上区域为寄存器的显示区域
2.控制程序运行
Ctrl+G组合键,可以跳转到目标地址;在反汇编窗口中,F2键为切换当前地址的断点状态,F8键为单步步过,F7为单步步入,按F4键为运行到光标位置,F9键为运行,同时多次重复F9可以运行到下一个断点
常见的断点位置包括程序内的某个地址、程序调用的某个API
此外,可以让程序在操作(读取/写入/执行)特定的某一小段内存时中断,其原理为使用CPU内建的硬件断点机制或使用Windows提供的异常处理机制的内存断点
当然硬件断点的效率更高,但是数量有限
具体操作,在x64DBG在内存窗口/栈窗口中选定目标地址,然后单机右键,在弹出的快捷菜单中选择 ”断点->硬件断点“ 或 ”读取/写入->选择长度“,可以设置硬件读取和硬件写入断点
在反汇编窗口中,右击目标地址,在弹出的快捷菜单中选择”Breakpoint->Set hardware on execution“,设置硬件执行断点
3.简单的脱壳
Windows下调试的一大特殊应用场景就是脱壳
”壳“是一种特殊的程序,对另一个程序进行变化后,利用变换的结果重新生成可执行文件
在运行时,它全部或部分还原存储在可执行文件中的变换结构,然后恢复原程序的执行
壳的存在主要两方面的需求:
- 压缩壳为了减小程序体积
- 加密壳则是为了加大破解者的逆向难度
通常,加密壳需要配合压缩壳,加密壳会导致程序体积变大
按照变换操作的不同,壳的种类如下
- 有的壳注重对代码的压缩,从而生成更小的可执行文件,如UPX、ASPack等
- 有的壳注重对代码的保护,以阻碍逆向者进行分析为目的,如VMP、ASProtect等
将这样的壳出去,还原为最初的样子,这就叫脱壳
这里主要说一下最广泛的upx壳
静态脱壳:UPX本生就是脱壳器,使用命令-d参数
之前我写这里面有讲解
https://blog.csdn.net/m0_72827793/article/details/135768690
动态方法:
虽然UPX本省可以脱壳,但是UPX是基于加壳后可执行文件内存储的标识来查找并操作的,由于upx是开源的,软件保护者可以修改这些标识,从而导致官方标准版的UPX脱壳失败
因为UPX中可以改动的地方太多,所以人们在这种情况下采用动态脱壳
可执行文件被操作系统载入后开始执行前,寄存器内会存放一些操作系统预先填充好的值,栈的数据也会被设置,壳程序要保留这些数据(状态),以免其被壳代码不经意间地破坏,在转交控制权前壳需要恢复这些数据,才能让原来的程序正常运行
一般情况下,由于已有栈的内容是不应更改的,简单的壳会选择将这样的信息压入栈(在栈上开辟新的空间),x86的汇编指令pushad可以轻松地将所有寄存器一次性压入栈,UPX也是使用了同样地方式,被形象地称为”保护现场“
载入后可以发现,程序地的最开始为pushad指令
如果pushad执行后,栈顶下硬件读取断点,那么程序执行完后续的还原代码操作,使用popad指令恢复寄存器时就会中断
于是先单步执行pushad指令F8键,再设置硬件读取断点
在OllyDGB中,右击寄存器区域,在弹出的快捷菜单中选择”HW break[ESP]”即可
在 OllyDbg 中,右击寄存器区域,在弹出的快捷菜单中选择 “HW break[ESP]” 可以设置一个硬件断点,当 ESP 寄存器的值发生变化时触发断点。
ESP 寄存器是堆栈指针,指向堆栈的顶部。当程序执行函数调用时,ESP 寄存器的值会减小,以分配空间来存储函数的参数和局部变量。当程序返回时,ESP 寄存器的值会增加,以释放这些空间。
因此,设置 HW break[ESP] 可以让我们在程序执行函数调用或返回时触发断点,从而方便我们调试程序。
具体来说,HW break[ESP] 命令可以用于以下目的:
- 跟踪函数调用的过程
- 检查函数的参数和局部变量
- 分析函数的返回值
以下是一个使用 HW break[ESP] 命令的示例:
// 函数 f
int f(int a, int b) {
int c = a + b;
return c;
}
// 主函数
int main() {
int x = 1;
int y = 2;
int z = f(x, y);
return 0;
}
在 OllyDbg 中,我们可以设置一个 HW break[ESP] 断点,并在函数 f 的入口处触发断点。断点触发后,我们可以查看 ESP 寄存器的值,发现它指向了函数 f 的堆栈帧。
我们还可以查看函数 f 的参数和局部变量。在 OllyDbg 的寄存器窗口中,我们可以看到参数 a 和 b 的值分别为 1 和 2。我们还可以看到局部变量 c 的值,它是由参数 a 和 b 相加得到的。
最后,我们可以检查函数 f 的返回值。在 OllyDbg 的调用堆栈窗口中,我们可以看到函数 f 的返回值为 3。
通过使用 HW break[ESP] 命令,我们可以有效地调试程序,从而更好地理解程序的运行过程。
x64DBG则直接在栈窗口利用右键快捷菜单设置
设置完成后,按F9键,再次中断在一个不同的地址
实际上,这是一个将栈空间向上清零0x80长度的循环,并不是真实的程序代码,后面紧跟着一个向前的较远的跳转,这样跳到原代码的跳转
壳程序一般与程序原来的代码在不同区段,故相隔较远
接下来,我们需要删除硬件断点,以防后续触发
在OD菜单栏选择“调试->硬件断点”,列出所有的硬件断点,删除即可
将光标移至最后的jmp,按F4键,使得程序执行到光标,再按F8执行跳转
此时出现了正常的函数开头和结尾
这时对程序进行dump,在OD中选择“插件->OllyDump->脱壳正在调试的进程”菜单命令
单击“获取EIP作为OEP”按钮,再单击“脱壳”按钮,保存后即可完成脱壳运行程序,可以发现正常了
至此脱壳结束
本应该在Winows XP系统下完成
- Windows XP后的系统中带有ASLR(地址空间随机化),程序每次启动需要重定位(将地址引用修复到正确的位置)才可以正常运行,而恢复重定位信息难度较大
- 从Windows Vista开始,NT内核开始引用MinWin,出现了大量的api-ms-XXXXXXX的dll,这导致了相当一部分依赖与NT内核特征的工具出现问题,如Dump时使用OllyDump的导入表搜索会受此影响
- 从Windows 10 开始,部分API有所更改,导致OllyDump的基址无法被正确填入
X64DBG解决了其中除重定位以外的问题,硬件断点可以在页面进行删除,对应的脱壳工具通过“插件->Scylla”菜单命令打开
单击“IATAutosearch”(IAT自动搜索)按钮,再单击“Get Imports”(获取导入),在“Imports”中选中有红叉的,按Delete键
然后单机“Dump”(转储)按钮,将内存转为可执行文件,单击“Fix Dump”(修正转储),将导入表修复,完成修复在IDA中加载
这样生成的程序虽然可以在IDA中分析,但不能运行,因为程序的重定位信息并没有被修复
其实并不一定需要修复重定位的信息,可以通过CFF Explorer等工具修改Nt Header的“Characteristics”,勾选“Relocation info stripped from file",可以组织系统对这个程序进行ASLR导致重定位,就可以正常运行了