比赛入口地址:http://hack.lug.ustc.edu.cn/
题目存档:https://hack2018.lug.ustc.edu.cn/
官方 Writeup:https://github.com/ustclug/hackergame2018-writeups
第二年参加中科大的 Hackergame,今年多了许多大佬参加。
题目共 32 题,只解出 20 题。
比赛最终得分:3650;总排名:13;参赛组:其他;组内排名:11。
题外话
去贵阳玩了四天,在外面用手机把前面的 12 道题做出来了。
然后 MC 手机没法玩,还通宵去网咖玩 MC 把题做出来。
签到题 (Solved, 50pt)
直接访问 /?key=hackergame2018
,就能得到 Flag。
Flag:flag{Hackergame2018_Have_Fun!}
猫咪问答 (Solved, 100pt)
社工题,上网找答案吧。
1. 1958
出处:百度百科
2. 9211B026
出处:网上搜索“中国科大学号的演变史”
3. 9
出处:手工爆破一下
4. TP311.1/94
出处:中国科技大学图书馆网站
5. 3A202
出处:LUG@USTC官网 LUG活动 栏目
Flag:flag{G00G1E-is-always-YOUR-FRIEND}
游园会的集章卡片 (Solved, 100pt)
拼图题,在手机上拼一下就好了。
Flag:flag{H4PPY_1M4GE_PR0CE551NG}
猫咪和键盘 (Solved, 150pt)
cpp 里面的代码顺序被破坏了,找规律,写个脚本重新排一下。
lines=open('typed_printf.cpp','r').readlines()
for line in lines:
print line[0]+line[32:39]+line[1:7]+line[20:22]+line[8:20]+line[22:32]+line[39:-1]
观察一下代码就可以直接出 Flag
Flag:flag{FfQ47if9Zxw9jXE68VtGAJDk6Y6Xc88UrUtpK3iF8p7BMs4y2gzdG8Ao2gv6aiJ125typed_printf95}
Word 文档 (Solved, 150pt)
docx 格式,直接 zip 解压,就看到 flag.txt 文件了
Flag:flag{xlsx,pptx,docx_are_just_zip_files}
猫咪银行 (Solved, 150pt)
以为是“货币兑换”有漏洞,后来发现没什么问题。
然后尝试“买入分钟”改得很大,“取出时间”的年份异常大或者异常小,就感觉像是溢出。
换了几个数字,多试几遍,成功买到了 Flag。
正确操作流程:
用 CTB 兑换 6606 个 TDSU
买入理财产品。买入分钟:2333333333333333333;买入份额:1000
取出理财产品
用 TDSU 兑换 20 个 CTB
购买 FLAG
Flag:flag{Evil_Integer._Evil_Overflow.}
黑曜石浏览器 (Solved, 150pt)
访问黑曜石浏览器官网:https://heicore.com/
在官网网页源代码里找到 黑曜石浏览器 的 User-Agent:
Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) HEICORE/49.1.2623.213 Safari/537.36
直接在手机上用 curl 加上 User-Agent 去访问题目链接,就能得到 Flag。
Flag:flag{H3ic0re_49.1.2623.213_sai_kou}
回到过去 (Solved, 150pt)
题目给出键盘记录,直接复现一下就能看到 Flag。
Flag:flag{t4a2b8c44039f93345a3d9b2}
我是谁 (450pt)
哲学思考 (Solved, 150pt)
直接在手机上用 curl,看 HTTP 请求里的 Status Code,就得到答案:TEAPOT。
提交答案得到 Flag
Flag:flag{i_canN0t_BReW_c0ffEE!}
Can I help me? (Solved, 300pt)
根据 brew coffee 提示,找到 HTCPCP/1.0 协议
参考:RFC 2324 / RFC 7168
直接在手机上用 nc 发请求
Flag:flag{delivering_tea_to_DaLa0}
家里有矿 (750pt)
sha1 (Solved, 150pt)
Google 有个现成的 sha1 碰撞,是两个 pdf 文件。
pdf 文件下载:https://shattered.io/
直接将两个 pdf 文件作为 nonce1 和 nonce2 提交,就能得到 Flag。
import requests
import json
import hashlib
from base64 import *
url='http://202.38.95.46:12006'
s=requests.session()
r=s.post(url+'/getjob')
r=json.loads(r.text)
suffix=bytes(r['suffix'])
pdf1=requests.get('https://shattered.io/static/shattered-1.pdf').content
pdf2=requests.get('https://shattered.io/static/shattered-2.pdf').content
data={'nonce1':b64encode(pdf1),'nonce2':b64encode(pdf2),'coin':1}
r=s.post(url+'/submitjob',data)
print r.text
Flag:flag{sha1_21d0e7b1be5a3cae}
md5 (Solved, 150pt)
写个脚本跑,加上约束条件。开了 8 个 python 程序,跑了半个小时就出结果了。
import requests
import json
import time
import hashlib
from base64 import *
import random
import string
def NumberOf0(n,length1,length2,length3):
return bin(n)[2:].rjust(length1,'0')[length2:length3].count('0')
url='http://202.38.95.46:12006'
rand_list=''
for i in range(256):
rand_list+=chr(i)
match_nonce1=''
match_nonce2=''
while True:
nonce_table=[]
hash_table=[]
t=time.time()
s=requests.session()
r=s.post(url+'/getjob')
r=json.loads(r.text)
suffix=r['suffix']
print 'suffix: %s' % suffix
nonce1=''.join(random.sample(rand_list,8))
hash1=hashlib.md5(nonce1+bytes(suffix[:16])).hexdigest()
hash1=int(hash1,16)
nonce_table.append(nonce1)
hash_table.append(hash1)
match=0
while match<102 and t+60>time.time():
#print 'len: %d' % len(hash_table)
match=0
while True:
nonce2=''.join(random.sample(rand_list,8))
hash2=hashlib.md5(nonce2+bytes(suffix[:16])).hexdigest()
hash2=int(hash2,16)
if NumberOf0(hash1^hash2,128,0,20)<17: continue
break
for i in range(len(hash_table)):
match=NumberOf0(hash_table[i]^hash2,128,0,128)
if match>95: print match
if match<102: continue
match_nonce1=nonce_table[i]
match_nonce2=nonce2
break
nonce_table.append(nonce2)
hash_table.append(hash2)
if match<102: continue
data={'nonce1':b64encode(match_nonce1),'nonce2':b64encode(match_nonce2),'coin':0}
r=s.post(url+'/submitjob',data)
print r.text
break
Flag:flag{md5_7cfa0da2c09776ae}
sha256 (Unsolved, 350pt)
未解出
秘籍残篇 (550pt)
滑稽 Art (Unsolved, 150pt)
未解出
天书易解 (Unsolved, 400pt)
未解出
猫咪遥控器 (Solved, 200pt)
根据提示,猜测需要把给出的控制方向画出轨迹,直接在手机上画吧。
seq=[]
r=open('seq.txt').read()
now=[130,1]
for i in r:
if 'L'==i:
seq.append(now)
now=[now[0],now[1]-1]
if 'R'==i:
seq.append(now)
now=[now[0],now[1]+1]
if 'D'==i:
seq.append(now)
now=[now[0]-1,now[1]]
if 'U'==i:
seq.append(now)
now=[now[0]+1,now[1]]
op=''
for y in range(550):
for x in range(130):
if [x,y] in seq:
op+='A'
else:
op+=' '
op+='n'
print op
Flag:flag{MeowMeow}
她的诗 (Solved, 200pt)
这首诗经过 uuencode
编码,有点像 base64
的编码方式,可以在最后隐写字符。
from codecs import decode
lines = open("poem.txt", "r").readlines()
flag=''
for i in lines:
i=i[:-1]
j=1
s=''
while True:
a=i[j:j+4]
if len(a)<=0: break
a=a.ljust(4,' ')
b=chr((((ord(a[0])-32)<<2)&0xff)+((ord(a[1])-32)>>4))
c=chr((((ord(a[1])-32)<<4)&0xff)+((ord(a[2])-32)>>2))
d=chr((((ord(a[2])-32)<<6)&0xff)+(ord(a[3])-32))
s+=b+c+d
j+=4
data = "begin 666 <data>n" + i + " nendn"
decode_data = decode(data.encode("ascii"), "uu").decode("ascii")
flag+=s[len(decode_data):]
print flag
Flag:flag{STegAn0grAPhy_w1tH_uUeNc0DE_I5_50_fun}
猫咪克星 (Solved, 200pt)
给出 python3 表达式,只需要算出结果提交。然后不断循环 n 次,就能得到 Flag。
PS:话说,我用 python2 也可以解。
from pwn import *
context.log_level='debug'
io=remote('202.38.95.46', 12009)
io.recvline()
for i in range(200):
res=io.recvline()
if 'flag' in res:
print res
break
res=res.replace(b"__import__('time').sleep",b'')
res=res.replace(b'exit()',b'0')
res=res.replace(b'\x',b'')
res=res.replace(b'print',b'len')
res=str(eval(res))
io.sendline(res)
Flag:flag{'Life_1s_sh0rt_use_PYTH0N'*1000}
猫咪电路 (Solved, 200pt)
出门在外地,凌晨去网咖通宵做题,顺便把这题 mc 给秒了。
作为 mc 老玩家,觉得很简单啊,而且这个红石电路不算复杂。
Flag:flag{0110101000111100101111111111111111111010}
FLXG 的秘密 (550pt)
来自未来的漂流瓶 (Unsolved, 200pt)
未解出
难以参悟的秘密 (Unsolved, 350pt)
未解出
C 语言作业 (Solved, 250pt)
简单 pwn。程序看上去好像没什么问题。
后来发现触发 signal 可以任意命令执行。
那么可以输入 2147483648/-1
来触发 SIGFPE
信号。
带有 sh
的命令被黑名单,那么我们使用 vim
的命令执行功能来执行任意命令
然后执行 :!/bin/sh
打开 shell
发现 flag
文件被改名为 -
不过我们可以执行 vim -- -
打开它,然后就看到 Flag 了
Flag:flag{816484e67b21efd5de8f1661d180a007}
加密算法和解密算法 (Solved, 250pt)
由于是 BrainFuck 虚拟机指令,我直接上网找 BrainFuck To C 的转换。
得到 C 代码,分析,每 10 字节一分组进行加密。改动明文中的一位,都会影响加密结果的每一位。
加密过程可以整理出 10 条方程式,直接上 z3 求解。
from z3 import *
flag=''
table='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'
x=[BitVec('x%d' % i,8) for i in range(10)]
solver = Solver()
solver.add((x[0]*23+x[1]*5+x[2]*40+x[3]*61+x[4]*47+x[5]*21+x[6]*62+x[7]*9+x[8]*18+x[9]*17+2)%64==9)
solver.add((x[0]*46+x[1]*3+x[2]*40+x[3]*54+x[4]*31+x[5]*23+x[6]*54+x[7]*11+x[9]*5+6)%64==51)
solver.add((x[0]*21+x[1]*16+x[2]*63+x[3]*33+x[4]*60+x[5]*26+x[6]*39+x[7]*32+x[8]*48+x[9]*39+8)%64==17)
solver.add((x[0]*16+x[1]*27+x[2]*5+x[3]*53+x[4]*37+x[5]*17+x[6]*24+x[7]*61+x[8]*23+x[9]*50+8)%64==21)
solver.add((x[0]*35+x[1]*22+x[2]*2+x[3]*43+x[4]*4+x[5]*36+x[6]*3+x[7]*22+x[8]*58+x[9]*37+3)%64==15)
solver.add((x[0]*17+x[2]*51+x[3]*46+x[4]*37+x[5]*44+x[6]*11+x[7]*13+x[8]*7+x[9]*18+5)%64==34)
solver.add((x[0]*34+x[1]*15+x[2]*10+x[3]*52+x[4]*27+x[5]*19+x[6]*38+x[7]*15+x[8]*30+x[9]*4+5)%64==21)
solver.add((x[0]*19+x[1]*38+x[2]*52+x[3]*8+x[4]*49+x[5]*7+x[6]*36+x[7]*40+x[8]*60+x[9]*45+7)%64==41)
solver.add((x[0]*12+x[1]*55+x[2]*41+x[3]*4+x[4]*39+x[5]*62+x[6]*48+x[7]*1+x[8]*21+x[9]*2+4)%64==42)
solver.add((x[0]*38+x[1]*14+x[2]*43+x[3]*59+x[4]*55+x[5]*10+x[6]*50+x[7]*18+x[8]*36+x[9]*13+9)%64==40)
for i in range(10): solver.add(x[i] >= 0)
for i in range(10): solver.add(x[i] <= 63)
res=[]
while solver.check() == sat:
res=solver.model()
break
tmp_flag=''
for i in range(len(x)):
tmp_flag+=table[res[x[i]].as_long()]
flag+=tmp_flag
x=[BitVec('x%d' % i,8) for i in range(10)]
solver = Solver()
solver.add((x[0]*23+x[1]*5+x[2]*40+x[3]*61+x[4]*47+x[5]*21+x[6]*62+x[7]*9+x[8]*18+x[9]*17+2)%64==56)
solver.add((x[0]*46+x[1]*3+x[2]*40+x[3]*54+x[4]*31+x[5]*23+x[6]*54+x[7]*11+x[9]*5+6)%64==34)
solver.add((x[0]*21+x[1]*16+x[2]*63+x[3]*33+x[4]*60+x[5]*26+x[6]*39+x[7]*32+x[8]*48+x[9]*39+8)%64==3)
solver.add((x[0]*16+x[1]*27+x[2]*5+x[3]*53+x[4]*37+x[5]*17+x[6]*24+x[7]*61+x[8]*23+x[9]*50+8)%64==12)
solver.add((x[0]*35+x[1]*22+x[2]*2+x[3]*43+x[4]*4+x[5]*36+x[6]*3+x[7]*22+x[8]*58+x[9]*37+3)%64==60)
solver.add((x[0]*17+x[2]*51+x[3]*46+x[4]*37+x[5]*44+x[6]*11+x[7]*13+x[8]*7+x[9]*18+5)%64==28)
solver.add((x[0]*34+x[1]*15+x[2]*10+x[3]*52+x[4]*27+x[5]*19+x[6]*38+x[7]*15+x[8]*30+x[9]*4+5)%64==30)
solver.add((x[0]*19+x[1]*38+x[2]*52+x[3]*8+x[4]*49+x[5]*7+x[6]*36+x[7]*40+x[8]*60+x[9]*45+7)%64==37)
solver.add((x[0]*12+x[1]*55+x[2]*41+x[3]*4+x[4]*39+x[5]*62+x[6]*48+x[7]*1+x[8]*21+x[9]*2+4)%64==50)
solver.add((x[0]*38+x[1]*14+x[2]*43+x[3]*59+x[4]*55+x[5]*10+x[6]*50+x[7]*18+x[8]*36+x[9]*13+9)%64==46)
for i in range(10): solver.add(x[i] >= 0)
for i in range(10): solver.add(x[i] <= 63)
res=[]
while solver.check() == sat:
res=solver.model()
break
tmp_flag=''
for i in range(len(x)):
tmp_flag+=table[res[x[i]].as_long()]
flag+=tmp_flag
x=[BitVec('x%d' % i,8) for i in range(10)]
solver = Solver()
solver.add((x[0]*23+x[1]*5+x[2]*40+x[3]*61+x[4]*47+x[5]*21+x[6]*62+x[7]*9+x[8]*18+x[9]*17+2)%64==56)
solver.add((x[0]*46+x[1]*3+x[2]*40+x[3]*54+x[4]*31+x[5]*23+x[6]*54+x[7]*11+x[9]*5+6)%64==34)
solver.add((x[0]*21+x[1]*16+x[2]*63+x[3]*33+x[4]*60+x[5]*26+x[6]*39+x[7]*32+x[8]*48+x[9]*39+8)%64==3)
solver.add((x[0]*16+x[1]*27+x[2]*5+x[3]*53+x[4]*37+x[5]*17+x[6]*24+x[7]*61+x[8]*23+x[9]*50+8)%64==12)
solver.add((x[0]*35+x[1]*22+x[2]*2+x[3]*43+x[4]*4+x[5]*36+x[6]*3+x[7]*22+x[8]*58+x[9]*37+3)%64==60)
solver.add((x[0]*17+x[2]*51+x[3]*46+x[4]*37+x[5]*44+x[6]*11+x[7]*13+x[8]*7+x[9]*18+5)%64==28)
solver.add((x[0]*34+x[1]*15+x[2]*10+x[3]*52+x[4]*27+x[5]*19+x[6]*38+x[7]*15+x[8]*30+x[9]*4+5)%64==30)
solver.add((x[0]*19+x[1]*38+x[2]*52+x[3]*8+x[4]*49+x[5]*7+x[6]*36+x[7]*40+x[8]*60+x[9]*45+7)%64==37)
solver.add((x[0]*12+x[1]*55+x[2]*41+x[3]*4+x[4]*39+x[5]*62+x[6]*48+x[7]*1+x[8]*21+x[9]*2+4)%64==50)
solver.add((x[0]*38+x[1]*14+x[2]*43+x[3]*59+x[4]*55+x[5]*10+x[6]*50+x[7]*18+x[8]*36+x[9]*13+9)%64==46)
for i in range(10): solver.add(x[i] >= 0)
for i in range(10): solver.add(x[i] <= 63)
res=[]
while solver.check() == sat:
res=solver.model()
break
tmp_flag=''
for i in range(len(x)):
tmp_flag+=table[res[x[i]].as_long()]
flag+=tmp_flag
x=[BitVec('x%d' % i,8) for i in range(10)]
solver = Solver()
solver.add((x[0]*23+x[1]*5+x[2]*40+x[3]*61+x[4]*47+x[5]*21+x[6]*62+x[7]*9+x[8]*18+x[9]*17+2)%64==6)
solver.add((x[0]*46+x[1]*3+x[2]*40+x[3]*54+x[4]*31+x[5]*23+x[6]*54+x[7]*11+x[9]*5+6)%64==55)
solver.add((x[0]*21+x[1]*16+x[2]*63+x[3]*33+x[4]*60+x[5]*26+x[6]*39+x[7]*32+x[8]*48+x[9]*39+8)%64==4)
solver.add((x[0]*16+x[1]*27+x[2]*5+x[3]*53+x[4]*37+x[5]*17+x[6]*24+x[7]*61+x[8]*23+x[9]*50+8)%64==12)
solver.add((x[0]*35+x[1]*22+x[2]*2+x[3]*43+x[4]*4+x[5]*36+x[6]*3+x[7]*22+x[8]*58+x[9]*37+3)%64==10)
solver.add((x[0]*17+x[2]*51+x[3]*46+x[4]*37+x[5]*44+x[6]*11+x[7]*13+x[8]*7+x[9]*18+5)%64==34)
solver.add((x[0]*34+x[1]*15+x[2]*10+x[3]*52+x[4]*27+x[5]*19+x[6]*38+x[7]*15+x[8]*30+x[9]*4+5)%64==33)
solver.add((x[0]*19+x[1]*38+x[2]*52+x[3]*8+x[4]*49+x[5]*7+x[6]*36+x[7]*40+x[8]*60+x[9]*45+7)%64==51)
solver.add((x[0]*12+x[1]*55+x[2]*41+x[3]*4+x[4]*39+x[5]*62+x[6]*48+x[7]*1+x[8]*21+x[9]*2+4)%64==46)
solver.add((x[0]*38+x[1]*14+x[2]*43+x[3]*59+x[4]*55+x[5]*10+x[6]*50+x[7]*18+x[8]*36+x[9]*13+9)%64==7)
for i in range(10): solver.add(x[i] >= 0)
for i in range(10): solver.add(x[i] <= 63)
res=[]
while solver.check() == sat:
res=solver.model()
break
tmp_flag=''
for i in range(len(x)):
tmp_flag+=table[res[x[i]].as_long()]
flag+=tmp_flag
print 'Flag: flag{%s}' % flag
Flag:flag{h1ll-c1ph3r-w1th-10xr-w1th-10xbl3-matr1x}
王的特权 (Unsolved, 250pt)
未解出
她的礼物 (Solved, 250pt)
把文件里 call sleep
system
signal
alarm
的地方用 0x90
NOP 填充
把除了 输出 Key
之外无关 puts
和 printf
也用 0x90
NOP 填充
然后运行程序,把“她的诗”解密后第 10 行提交过去:
However, someday, someone will find it.
不用半分钟就能自动输出 Flag
Flag:flag{HowEVER,_Somedaj,_sOMe0NE_wILl_FiND_it.}
困惑的 flxg 小程序 (Unsolved, 250pt)
未解出
CWK的试炼 (650pt)
神庙设计图, Get! (Solved, 250pt)
用 Google 的 dwebp.exe
工具将 webp
图片转为 png
图片。
用 Stegsolve
打开 png
图片,Green
第 0 通道 隐写了一个 onion
地址,然后就想到 tor
。
Onion 地址:ustcctfbase7l74q.onion 2333
用 tor
代理 nc
连接这个 onion
地址,提示需要输入 blueprint
的 CRC32
才能继续。
然后还提示 blueprint
用类似的方法藏在图片内。
其实 blueprint
是一个 ELF
文件,经过 base64
编码后,逐 bit
以黑白代表 0
和 1
藏在了 Green
第 0 通道 中神庙的区域内。
经过处理,得到 webp.bmp
文件:
然后写个脚本把 blueprint
提取出来并算 CBC32
值。
from PIL import Image
from base64 import *
import binascii
im=Image.open('webp.bmp')
w=im.size[0]
h=im.size[1]
def bw(color):
if color==(0,0,0):
return 0
else:
return 1
coffset=[]
for i in range(615):
coffset.append([0,0,0])
i=0
for y in range(h):
for x in range(w):
if bw(im.getpixel((x,y)))==1:
coffset[i][0]=y
coffset[i][1]=x
i+=1
break
i=0
for y in range(h):
for x in range(w):
if bw(im.getpixel((w-x-1,y)))==1:
coffset[i][2]=w-x-1
i+=1
break
#print coffset
table='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
raw=''
i=0
for offset in coffset:
tmp_raw=''
data=''
y=offset[0]
for x in range(offset[1],offset[2]+1):
data+=str(bw(im.getpixel((x,y))))
#print data
if i==0:
raw+='0'+data
else:
match_1=0
for j in range(0,8):
tmp_raw=raw[len(raw)/8*8:]
tmp_raw+='0'*j+data
match_2=1
for k in range(len(tmp_raw)/8):
if chr(int(tmp_raw[k*8:k*8+8],2)) not in table:
match_2=0
break
if match_2==1:
match_1=1
raw+='0'*j+data
break
if match_1==0:
print 'error'
i+=1
s=''
for t in range(len(raw)/8):
s+=chr(int(raw[t*8:t*8+8],2))
length=len(s)/4*4
if length!=len(s): length+=4
s=s.ljust(length,'=')
s=b64decode(s)
open('trial.elf','wb').write(s)
print 'CRC32: %X' % (binascii.crc32(s) & 0xffffffff)
CRC32:3D6540C7
将 CRC32 提交过去,拿到 Flag
Flag:flxg{But_the_Sun_Also_Rises}
此小技耳 (Unsolved, 400pt)
未解出
Z 同学的 RSA (Unsolved, 300pt)
未解出
数理基础扎实的发烧友 (Unsolved, 300pt)
未解出
一些宇宙真理 (Unsolved, 300pt)
未解出
对抗深渊 (Unsolved, 350pt)
未解出
Source: impakho.com | Author:impakho
ISCC(ISCLab) Pwn3 Last updated:May.08, 2016 CST 16:17:16 前两天就写好了,整理了一下,现在发上来。没有写到exp那部分,只写了任意内存读写的module。 环境依旧是Python 2。 from pwn …
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论