gdb动态调试工具使用(使用pwndbg插件)

常用的gdb(pwndbg)命令

本文总阅读量

1、加载程序到gdb

 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
27
28
将可执行文件a.out加载到gdb调试工具中
$ gdb a.out

GNU gdb (Ubuntu 8.1.1-0ubuntu1) 8.1.1
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
pwndbg: loaded 191 commands. Type pwndbg [filter] for a list.
pwndbg: created $rebase, $ida gdb functions (can be used with print/break)
Reading symbols from a.out...(no debugging symbols found)...done.
pwndbg> 
输入Tab键可以查看所有命令
Display all 200 possibilities? (y or n) 输入y显示所有命令
!                                breakrva                         down-silently
+                                brva                             dprintf
-                                bt                               dps
<                                bugreport                        dq
... ...

2、运行程序

1
2
3
4
5
6
7
常用
pwndbg> start

pwndgb> run

# start的作用是将程序运行至入口点(此处入口点是gdb工具认为的入口点,不一定是main函数)
# run是直接将程序完全执行一遍

3、查看寄存器信息

1
2
3
4
pwndbg> i r
i: 查看的意思
r: 寄存器的意思
# 此命令在pwndbg插件中很少用,因为默认情况已显示寄存器的信息

4、显示指定范围的汇编指令

1
2
3
4
5
6
disassemble可简写成disass
# 1.显示main函数的汇编代码段
pwndbg> disassemble main
# 2.显示rip寄存器指向的汇编代码段
pwndbg> disassemble $rip
#要使用$符号指定寄存器

5、设置显示的汇编指令格式为intel

1
2
3
4
pwndbg> set disassembly-flavor intel
#此命令很少使用,因为在pwndbg工具中默认显示的指令格式为intel
#若要更改为amd指令,可设置为set disassembly-flavor att
#如果没有pwndbg插件的话,可以编辑~/.gdbinit文件,添加该命令

6、指令执行

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 1.执行单条汇编指令
pwndbg> ni
# 2.步入汇编指令
pwndbg> si

# ni和si的区别在于,ni不会进入函数内部,si会进入函数内部

# n s 和 ni si 的区别是,n s 针对的是源代码,ni si针对的是汇编指令

# n是next的意思
# ---------------------------------------------------
# 3.跳出函数
pwndbg> finish
当使用si进入某函数调试需要跳出当前函数时使用finish命令可以跳出

7、断点设置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
# 1.在0x000abc地址处设置断点
pwndbg> b * 0x000abc

# 通过偏移进行断点设置(如偏移值为0x00001124)
pwndbg> b *$rebase(0x00001124)

# 2.查看断点
pwndbg> i b

# 3.将程序运行至断点处
pwndbg> c

# 4.设置某断点失效
pwndbg> disable b id
id指的是断点的编号

# 5.恢复某失效的断点
pwndbg> enable b id

# 6.删除断点
pwndbg> d id

8、打印操作

 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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# 1.打印rip寄存器的值
pwndbg> print $rip 

# 2.打印rip-0x10的地址值
pwndbg> print $rip-0x10
print命令一般很少用

# 3.打印结构体
pwndbg> ptype stdout

使用x命令打印内容非常重要经常使用
# 1.打印rip寄存器指向的地址后20条指令
pwndbg> x/20i $rip
x:打印
20:打印的记录数
i:以指令的形式显示
	其中i可以替换为下面的形式
	x按16进制格式显示变量
  d按10进制格式显示变量
  u按10进制格式显示无符号整型
  o按8进制格式显示变量
  t按2进制格式显示变量
  a按16进制格式显示变量
  c按字符格式显示变量
  f按浮点格式显示变量


# 2.打印rip寄存器指向的地址后20条数据(包括rip的数据)
pwndbg> x/20b $rip
	b表示1字节
  h表示2字节
  w表示4字节
  g表示8字节

# 3.可以复合使用,如:打印rip寄存器后20条的数据(包括rip的数据),以1字节的方式输出(十六进制显示)
pwndbg> x/20bx $rip
# telescope:将指定内存空间按照stack命令的格式进行显示
pwndbg> telescope  0x555555558000 20
00:0000  0x555555558000 (data_start) ◂— 0x0
01:0008  0x555555558008 (__dso_handle) ◂— 0x555555558008
02:0010  0x555555558010 ◂— 0x0
03:0018  0x555555558018 ◂— 0x0
04:0020  0x555555558020 (stdout@GLIBC_2.2.5) —▸ 0x7ffff7e1b780 (_IO_2_1_stdout_) ◂— 0xfbad2084
... ...

9、设置内存值

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 1.设置0x00abc的内存值为0x61
pwndbg> set *0x00abc=0x61

# 2.通过寄存器的方式设置内存值
pwndbg> set * ((unsigned long)$rbp) = 0x61
若程序是64位则强制转换的类型为long若程序是32位则强制转换的类型是int

# 3.设置$rax+0x10的内存值为0xabcdef
pwndbg> set *((unsigned long)$rax+0x10)=0xabcdef
若程序是64位则强制转换的类型为long若程序是32位则强制转换的类型是int

10、打印函数地址

1
2
打印函数名为func的地址(有符号表就可以打印出来)
pwndbg> print &func

11、打印栈地址

1
2
3
4
5
6
# 1.打印栈信息
pwndbg> stack

# 2.打印栈地址附近的30条信息
pwndbg> stack 30
注意打印的第一条记录是rsp/esp指向的位置信息

12、cyclic构建字符

1
2
3
4
5
6
7
# 1.创建30个字符
pwndbg> cyclic 30
aaaabaaacaaadaaaeaaafaaagaaaha

# 2.计算生成的字符所在位置
pwndbg> cyclic -l iaaa
32

13、打印字符串的地址

1
2
# 1.打印字符串"/bin/sh"所在的地址
pwndbg> search "/bin/sh"

14.查看内存

1
pwndbg> vmmap

15.查看plt、got、elf

1
2
3
4
5
6
# 1、查看plt表
pwndbg> plt
# 2、查看got表
pwndbg> got
# 3、查看elf表
pwndbg> elf

16.子进程调试设置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# 1.设置调试父进程/子进程
set follow-fork-mode [parent|child]

# 2.查询当前fork模式
show follow-fork-mode

# 3.设置其它线程不执行,只有调试线程执行
set scheduler-locking [on|off|step]

# 4.显示线程
info thread

# 5.切换线程
thread id

# 6.GDB为特定线程设置断点
break location thread id

17.寻找TLS结构体地址

1
2
# 查找TLS结构体地址的gdb命令
fsbase

18、堆的相关操作

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 查看堆块内容情况
> vis

# 查看bins结构
> bins

# 查看分配的堆块
> heap

# 查看堆块状态
> par

w、pwndbg显示设置

若需要将pwndbg的显示放在第二个终端,则在~/.gdbinit文件处添加以下内容

1
set context-output /dev/pts/1

x、退出gdb调试

1
2
pwndbg> quit
或者可以直接简写q

后续有待补充… …