BetaMao

调试器与反编译工具

字数统计: 3k阅读时长: 11 min
2017/02/18 Share

记录od,ida,windbg等的常用键~

ollydbg

快捷键

Ctrl+G 跳转到指定位置
Ctrl+E 编辑指定区域
space 编辑汇编代码
F4 执行到光标位置处
F2 Int3 断点
; 添加注释
: 添加标签名
* 返回到正在运行的地方
- 返回到上一个光标处
Enter 跟随跳转/跟入调用内部
F3 打开一个新的可执行程序
Ctrl+F2 重新运行当前调试的程序
Alt+F2 当前调试的程序
Alt+C 显示 CPU 窗口
Ctrl+P 显示补丁窗口
Alt+O 打开调试选项窗口
Alt+K 显示呼叫堆栈
Alt+B 显示断点窗口
F9 运行选定的程序进行调试
F12 暂时停止被调试程序的执行
F7 单步进入被调试程序的Call中
F8 步过被调试程序的Call
Ctrl+F11 跟入被调试程序的 Call 中
Ctrl+F12 跟踪时跳过被调试程序的 Call
Ctrl+F9 执行直到返回
Alt+L 显示记录窗口
Alt+E 显示模块窗口
Alt+M 显示内存窗口
### 断点
1. Int 3 断点:
即CC指令
2. 硬件断点:
DR0-DR3存储断点的线性地址,DR7设置断点控制,所以最多有四个:
3. 内存断点:
内存访问/写入断点是直接将其属性去除,发生异常时再比对是否是断点,由于每次发生异常都会判断,很影响速度,od只允许设置一个:
4. 内存访问一次性断点:
在显示内存布局时,可以使用F2下断点,首次读取/执行此区域会中断并清除断点:
5. 消息断点:
使窗口函数在接收到指定消息时中断,直接打开窗口界面,选定控件右键选择消息断点,指定消息类型即可:
6. 条件断点:
就是int3断点,遇到时会判断满足条件即中断:
0x1:按寄存器条件中断
eax==00000000
0x2:按存储器条件中断
[String [esp+4]]==”betamao.me”
7. 条件记录断点:
看中文意思就很明确了,不解释,实验下就知道,记录在log窗口显示:
8. Run trace:
使用 调试 打开或清除Run跟踪 即可,跟踪可以在调试选项里面设置:
它会记录所有暂停时的状态信息,使用+ -号可以前后翻动
9. Hit trace:
在所有选中部分添加int 3 断点来记录是否被执行过,实验时将所有已存在断点删除后,程序依然总是会崩溃。。。
## windbg ##
点击下载它是在WDK里面的,当然也可以单独下载,即在安装时只选择“Debugging Tools for Windows”,为方便调试,可以使用微软提供的符号文件,这样可以看到win程序的变量名和结构体定义,不必下载,可以配置为使用服务器,这样会自动匹配:srvc:\symbolshttps://msdl.microsoft.com/download/symbols
也可以放在环境变量里面,名为_NT_SYMBOL_PATH。
开启内核调试:
重启后生效,至于调试命令,需要的时候再看吧,太多了,在这里这里
调试程序,不会断在EP处,需要获取EP地址:
!dh命令用来查看PE头的,于是就可以跳转到这里了:
神奇的命令。。。就这样调试着走,不截图了,不停的走啊走,走到这里传入三个参数,然后一个规则的跳转,跟进去果然是main:
然而,看不懂主函数啊,什么鬼啊!!!!!!

qira

一个神奇的调试器,由geohot编写,安装:

1
2
3
4
cd ~/
git clone https://github.com/BinaryAnalysisPlatform/qira.git
cd qira/
./install.sh

注意,他需要Flask-SocketIO==2.9.1,将requirements.txt文件对应项改掉就行啦~
用法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
usage: qira.py [-h] [-s] [-t] [--gate-trace ADDRESS] [--flush-cache] [--pin]
[--host HOST] [--web-port PORT] [--socat-port PORT] [-S]
[--engine ENGINE]
binary [args [args ...]]

Analyze binary. Like "qira /bin/ls /"

positional arguments:
binary 要分析的程序地址
args 程序参数

optional arguments:
-h, --help
-s, --server 类似使用socat搭建服务,监听4000端口
-t, --tracelibraries 跟入所有libraries
--gate-trace ADDRESS 从指定位置开始trace
--flush-cache flush all QIRA caches
--pin 用pin做后端,需要安装:./pin_build.sh
--host HOST 设置web和socat的监听地址,默认 0.0.0.0
--web-port PORT web端口,默认 3002
--socat-port PORT socat端口,默认4000
-S, --static enable static2
--engine ENGINE static engine to use with static2 (builtin or r2)

看着一脸懵逼,最简单的就是./qira /bin/ls啦,此时它会监听3002,使用浏览器打开即可(若打开为空白,结束命令再启动,多试几次就好啦):

  1. 该区域为垂直时间线,从上至下记录着整个程序从开始追踪到当前执行到的位置(若程序已经结束则指向结束位置),它本来是绿色,颜色越深代表函数调用深度越深,当数据区(下面会提,即7区域)的光标指向某个地址时,该区域也会有不同的颜色变化,亮黄色代表该地址在那个时候被读过,暗黄色代表该在那个时候被写过,而代码区(即4区域)的光标指向的地址在这里以蓝色表示。通过鼠标左键拖动选中一块时间线可以缩小查看的范围,使用z键可以恢复该区大小,另外右键双击该区域能隐藏当前进程的时间线。

  2. 该区域为内存属性区域。

  3. 该区域有四个框:

    • 第一个代表指令序号,qira会为按执行顺序为每一条执行到的指令编号,数字以蓝色标记,可以在这个框里输入数据快速跳转到相应序号处。
    • 第二个代表子线程/进程编号,数字以灰色标记,通过它可以可以切换线程编号,当然左右方向键也有此功能。
    • 第三个代表指令地址,数字以红色标记,可以在此键入地址快速跳转,当然g键也可以快速跳转。
    • 第四个代表数据地址,数字以黄色标记,可以在此键入地址快速跳转。
  4. 该区域为指令区,第一列为指令序号,前面有提,调用者与被调用者左右不对齐,可以看出明显的层次关系,第二列为指令地址,第三列为反汇编语句,可以在这个框里使用很多按键:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    j -- 跳转到下次对当前指令调用的地址
    k -- 跳转到上次对当前指令调用的地址

    shift-j -- 跳转到下次对当前数据访问的地址
    shift-k -- 跳转到上次对当前数据访问的地址

    m -- 到当前函数结束处
    , -- 到当前函数开始处

    z -- 恢复垂直时间线

    left -- -1 切换前一个子进程
    right -- +1 切换后一个子进程
    up -- -1 查看前一条指令 鼠标滚轮上滑
    down -- +1 查看后一条指令 鼠标滚轮下滑

    esc -- 回到上一次光标所在位置

    shift-c -- 清除所有进程

    n -- 对指令重命名,一般用在函数入口处
    shift-n -- 对数据重命名
    : --对指令添加注释,其实就是';'符号
    shift-: -- 对数据添加注释,其实就是':'符号

    g -- 快速切换位置,可以输入地址,指令序号或者指令名
  5. 此区域为通用寄存器区域,不同的寄存器用了不同的颜色标记,里面的数据属于指令地址的用红色标记,属于数据地址的用黄色标记,其他事黑色,红色高亮的寄存器是上条指令改变的寄存器,最下行是当前指令的读写操作,暗黄色代表读,亮黄色为将右侧数据写入左侧地址。

  6. 此区域为当前所进行的系统调用。

  7. 此区域为数据dump。

另外它也支持与ida连接,由于它自己编译的插件是plw的,我这里就用ida6.8来配套使用,将./ida/bin下的windows下的两个插件放入ida的插件目录,启动ida,启动插件:

接着ida和qira就同步了,另外F5的伪代码也能定位,美滋滋:

需要注意:ida.js里面ida地址写的是localhost,若浏览器不在那台电脑上将会失败,改一下即可

gdb

Linux下首选,和windbg差不多都是命令行的,虽然有第三方的图形化界面,没用过。。。它的命令在没有冲突的情况下都可以简写,下面不特别记录了。

调试进程

在bash下可以新建也可以附加:

1
2
gdb bin
gdb -p pid

在gdb下可以新建也可以附加:

1
2
file <bin>
attach <pid>

对于附加进程,需要有权限,一般都是是root操作所以不存在问题,若普通用户需要权限可以百度。

断点

添加断点:

1
2
3
4
5
6
tbreak          //临时断点,参数同下
break [[-|+]N] //软中断
break <filename:line> //在源码文件 filename 的 line 行处打断点。
break <filename:function> //在源码文件 filename 的 function 函数入口处打断点。
break <address>
break ... if <cond> //设置条件断点

设置监视点:

1
watch [-l|-location] <expr> //-l表示表达式为地址

列出断点:

1
info breakpoints [lists...]     //list可指定断点编号

禁/启用断点:

1
2
3
4
disable [list…]                 
enable [list…]
enable once [list… ]
enable delete [list… ]

删除断点:

1
2
clear                           //用法同break作用相反
delete [list…]

执行

1
2
3
4
5
6
7
8
9
10
run                             //可使用set args <agr1 ...>设置参数
step [N] //单步步入,N可指定执行步数
reverse-step [N]
next [N] //步过
reverse-next [N]
return <expression> //直接返回函数
finish //运行到返回
until <location> //可用于过循环,location可用于指定执行到何处
continue [N] //继续执行直到下一个断点或结束
jump addr //改变eip

查看

1
2
3
4
5
6
7
8
9
10
11
12
disassemble expr,expr           //反汇编,使用 /m 可以将汇编代码与C代码结合
print /f [expr] //输出表达式值,可用于运算
print /f array[index]@num //输出数组的[index,num]元素
x/nfu <addr> //查看内存
display/fmt <addr>|<expr> //跟踪显示,当fmt为i、s时表达式被视为地址
info display
undisplay [N]
disable display [N]
enable display [N]
backtrace [full] [[+|-]n] //栈回溯
ptype typename //输出类型的定义
info something //info用于查看一些神奇的东西,例如寄存器[all-]register,signals

对于最常用到的x命令,格式如下:

n, f, 和 u 都是可选参数,用于指定要显示的内存以及如何格式化。 
addr 是要开始显示内存的地址的表达式。 
n 重复次数(默认值是 1),指定要显示多少个单位(由 u 指定)的内存值。 
f 显示格式(初始默认值是 x),显示格式是 print('x','d','u','o','t','a','c','f','s') 使用的格式之一,再加 i(机器指令)。 
u 单位大小,b 表示单字节,h 表示双字节,w 表示四字节,g 表示八字节。

信号

一般的ctf题都有定时信号

1
2
3
info signals                    //列出当前信号处理设置
handle signalname [stop|nostop]、[print|noprint]、[pass(noignore)|nopass(ignore)] //对信号所做操作
signal [signalname|signalnum] //对程序发送指定信号

设置

1
2
3
4
5
6
set var varName=varValue    //设置变量值
set print elements number-of-elements //设置print的输出限制
set print array-indexes on //打印数组时输出下标
set print pretty on //格式化输出结构体
set follow-fork-mode [child|parent] //跟踪父进程或子进程
set disassembly-flavor [intel|att] //设置汇编指令格式

这些设置在退出gdb后就会失效,若想长期生效可以将它们写入.gdbinit文件,这样在每次启动gdb时都会执行它们。

参考

[1]逆向工程核心原理
[2]黑客免杀攻防
[3]加密与解密第三版
[4]100个gdb小技巧

CATALOG
  1. 1. ollydbg
    1. 1.1. 快捷键
  2. 2. qira
  3. 3. gdb
    1. 3.1. 调试进程
    2. 3.2. 断点
    3. 3.3. 执行
    4. 3.4. 查看
    5. 3.5. 信号
    6. 3.6. 设置
  4. 4. 参考