天天看点

[系统安全] 逆向分析之高级动态分析技术笔记

文章目录

  • ​​动态调试必备知识点​​
  • ​​程序执行中的三类断点​​
  • ​​首次和二次异常处理​​
  • ​​OllyDbg​​
  • ​​打开程序和附加进程、面板说明​​
  • ​​OD的基本使用​​
  • ​​WinDbg Preivew​​

动态调试必备知识点

程序执行中的三类断点

软件执行断点

调试器通过使用0xCC,即指令INT 3的机器码,重写指令的首个字节来实现软件断点,0xCC被设计来供调试器使用。当0xCC指令执行后,操作系统会产生一个异常,然后控制权转到调试器。

内核模式中会限制软件断点的数量,但是在用户态模式下可以无限制的设置软件断点。

硬件执行断点

利用专门的硬件寄存器,x86结构可以支持硬件执行断点。处理器每次执行一个指令时,硬件都会检测指令的指针是否与断点地址相等。与软断点不同的是,硬断点并不关心断点地址存储哪些字节。

只有四个硬件寄存器存储断点的地址。

条件断点

条件断点是软件断点的一种,它在某些条件满足时才会被触发。例如,在函数GetProcAddress上设置了一个断点。每次调用函数GetProcAddress时都会产生中断。

首次和二次异常处理

调试器通常有两次机会来处理同一个异常:首次处理异常和二次处理异常。

调试器第一次附加到进程时,会发生一个异常,然后被调试的程序停止执行,此时调试器开始获得控制权。调试器可以自己处理异常,也可以将异常转给被调试的应用程序处理。

如果程序注册了一个异常处理函数,它会在调试器处理异常后,获得处理异常的权限。

如果应用程序没有处理异常,调试器将获得第二次处理它的机会——二次异常处理。调试器接收到一个二次处理的异常后,意味着如果程序没有附加到调试器就会崩溃。为了让应用程序正常运行,调试器必须处理异常。

为使程序难以调试,恶意代码也许有意地产生首次异常处理。

二次异常处理不能被忽略,因为忽略以后程序将不能正常运行。如果在调试恶意代码时遇到了二次异常处理,则说明恶意代码中可能存在使它自身崩溃的Bug,但更为可能的是恶意代码并不想在当前环境中运行。

OllyDbg

打开程序和附加进程、面板说明

OD中可以选择一些参数来启动一个可执行文件,如下所示。

[系统安全] 逆向分析之高级动态分析技术笔记

也可以选择一个正在执行的程序附加到进程身上,如下所示。

[系统安全] 逆向分析之高级动态分析技术笔记

OD面板分为四个大的部分,示意图如下。

[系统安全] 逆向分析之高级动态分析技术笔记

OD的基本使用

内存映射

View=>Memory显示被调试程序分配的内存块,可以用来粗略查看程序在内存中的布局。

[系统安全] 逆向分析之高级动态分析技术笔记

查看线程

view=> Threads可以查看一个进程中开启的所有线程,但是由于OD是单线程,所以同一时间只能查看其中的一个线程。执行代码

OD中的多种代码执行方式如下

[系统安全] 逆向分析之高级动态分析技术笔记

单步跳入F7,单步跳过F8。

设置断点

当关闭或者终止一个程序时,OD会保存在程序中设置的断点的位置,下次调试时就使用相同的断点。设置断点的示意图表如下

功能 右键 => breakpoints
软件断点 Toggle
条件断点 Conditional
硬件断点 Hardward,on execution
内存访问断点 Memory,on access
内存写断点 memory,on write

加载dll

OD使用一个名为loaddll.exe的虚拟是程序加载dll文件,一旦dll被加载,OD会在其入口点DllMain处中断。

跟踪

OD支持三种跟踪技术:标准回溯跟踪、堆栈调用跟踪、运行跟踪。

标准回溯跟踪:在反汇编窗口执行单步进入和单步跳过时,OD都会记录下来,可以按-回退到上一步运行的指令,可以按+执行下一条指令。

堆栈调用跟踪:可以查看一个给定函数的执行路径,View=>call stack。

运行跟踪:OD会保存所有运行过程中的指令,以及运行过程中对寄存器和标志做出的改变。

高亮反汇编代码跟踪的那一行,右键=>run trace => add selection,代码运行后view=>run trace查看

运行过的指令,加号和减号键上下浏览代码。

修改原pe文件

反汇编窗口 => copy to executable => all modifications => save file。

WinDbg Preivew

WinDbg Preivew调试win7内核的环境搭建前面文章已经记录,这里进一步记录一些常用的命令。

从内存中读取数据示例​

​da 0x401020​

da 读取内存数据,以ascii格式显示
du 读取内存数据,以unicode格式显示
dd 读取内存数据,以32位双字显示

向内存写入数据示例​

​ea 0x401020 "hello"​

​,选项和上面的读数据的a、u、d一样。

解引用一个指针,并查看指针处的值示例​

​du dwo (esp+4)​

​,dwo用来解引用指针。

设置断点​

​bp​

使用​

​go(g)​

​​命令,在断点处执行一个动作之后继续执行,而不等待用户操作。示例:在不中断程序执行的前提下打印调用GetProcAddress 的第二个参数(即执行的函数名)​

​bp GetProcAddress "da dwo(esp+8); g​

​"

列举加载到进程空间的所有模块​

​lm​

windbg中符号格式为​

​moduleName!symbolName​

​​,moduleName表示exe、dll、sys格式的文件名(但是不包括后缀名),sysbolName是与这个地址相关联的名字。一个特例​

​ntoskrnl.exe​

​​的moduleName为​

​nt​

​bu​

​​命令可以用符号在没有加载的代码中设置一个延迟断点,仅当加载一个名字匹配的模块时,延迟断点才会被设置。例如​

​bu myModule!myFunction​

​知识windbg一旦myModule模块加载,就在myFunction上设置断点。

分析内核模块时,可以用​

​$imnet​

​​确定一个给定模块的入口点,比如​

​bu $iment(driverName)​

​在任何驱动程序代码运行前在其入口点设置一个断点。

继续阅读