内容简介:比赛入口地址:题目存档:官方 Writeup:
比赛入口地址: 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。
本题解持续更新,未解出题的题解后续发布。
最后更新时间:2018-10-16 14:00
题外话
去贵阳玩了四天,在外面用手机把前面的 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 + " \nend\n" 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)
后续发布
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 这位科学家研发鸟类面部识别技术
- 第五届NJSD全球软件大会推荐书单
- 第五届蓝桥杯Java B——分糖果
- 第五届蓝桥杯Java B——矩阵翻硬币
- 第五届蓝桥杯Java B——地宫取宝
- 第五届大学生RDMA编程挑战赛正式开赛
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。