Hackergame 2018

中国科学技术大学第五届信息安全大赛


12号之后就没交flag,除了看了那个数理,其他题目也就没管,算是弃赛了,名次最后不怎么样,不过比想象好一些,后四天没弄也没滑出前15(不过最开始维持了一段时间第一,比较happy)
题目质量还是很好的,简单记录做题时其中的几个脚本

喵咪克星

自己def一个返回为0的函数
接受到sleep这类干扰直接替换
而后eval,最后即得flag

calc

构造-2147483648/-1整数溢出来SIGFPE
打到执行后execlp命令和参数是同一个值
这里调用vim即可open文件

Brainfuck

先大致翻译一下brainfuck:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
key=",[->>+++++++>>+++++>>+++>>++>>++++>++++++<<+++<<+++++++++<<++++++++<<++++++<<++++++++<]>[->>+++++>>+++++++++>>+++++++++>>++>>++++<+++++++++<<++++<<++++<<++<<++<]<,[->>+++++>>++++++++>>++++++>>+++++++>>+++++++>++++++<<++++++<<++++++++<<+++<<+++<<++++++++<]>[->>++++++++>>+++>>+++++++>>++++>>+++++++++<++++++<<+++++++++<<++<<+++++++++<<++++++++<]<,[->>++++++++>>+++++++>>++>>++>>+++++++++>+++<<++++<<+++<<+++++<<++++++++<<++++++++<]>[->>++++>>++++++++>>++++++>>++++++>>+++++<++++<<+++++++++<<++++++++<<+++++++<<++++<]<,[->>+++++>>+++++++++>>+++>>++++>>++++>+++<<++++++++<<++++++<<+++++<<++++++<<++++++++<]>[->>++++++>>++++++>>+++++>>++++++++>>+++++++<++++++++<<++++++<<+++++<<+++<<+++++++<]<,[->>+++++++>>++++>>++++>>+++>>+++++++>+++++++<<+++++++++<<+++++<<+++++<<+++++++<<++++++++<]>[->>+++>>++++>>++++>>+++++>>++++++<++++<<+++<<++++++++<<+++++++<<+++++<]<,[->>+++++>>++>>++++>>+++>>++++++>++<<+++++++<<++++<<+++++++++<<+++++++<<++++++++<]>[->>++>>+++++++++>>+++++>>++++++++>>+++++++++<+++++++<<++<<++++<<+++<<++<]<,[->>++++++>>+++++++>>+++>>++++++>>++++++++>++<<++++<<+++<<++++++++<<++++++<<++++++++<]>[->>++++++>>++>>+++++++++>>++++>>++++++<+++++<<++++<<++++++++<<++++<<+++++++<]<,[->>+++++++++>>++++++++>>++++++>>+++++++>>+++++++++>++<<++++++++<<+++++<<+++++<<+++<<++++++++<]>[->>+++++++++>>+++++++>>+++++++++>>++++>>++<+++++++<<+++++++++<<++<<+++<<++++++++<]<,[->>++>>++++++++>>++>>++++++>>+++++>++++<<++++<<+++++++<<+++++++<<++++++++<<++++++++<]>[->>+++++++>>++>>++++++++>>+++++++>>++++<++<<+++<<+++++++<<+++++<<++<]<,[->>+++++++++>>+++++++>>+++++>>++++>>++>+++++<<+++++<<++<<++<<+++++<<++++++++<]>[->>++++++++>>++++++>>++>>+++++>>+++++++++<++++++++<<++++++++<<++++<<++++<<+++++++++<]>++.>++++++.>++++++++.>++++++++.>+++.>+++++.>+++++.>+++++++.>++++.>+++++++++."
ans=""
for i in key:
if i=="-":
ans+=" key[i]-=1\n"
if i==">":
ans+=" i+=1\n"
if i=="<":
ans+=" i-=1\n"
if i=="+":
ans+=" key[i]+=1\n"
if i=="[":
ans+="while(key[i]):\n"
if i=="]":
ans+="\n"
if i==",":
ans+="key[i]=input[i]\n"
if i==".":
ans+="print key[i]\n"
print ans

得到程序修改几处换行符
程序逻辑很简单,大致是要解一个十元同余方程
每次循环前控制下一轮输入值来得到10组系数
而后利用z3解方程即可:

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

key_final="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_/"
key1=[ 23, 46, 21, 80, 35, 81, 34, 19, 76, 38]
key2=[ 69, 67, 80, 27, 22, 64, 79, 38, 55, 78]
key3=[ 40, 40, 63, 69, 66, 51, 74, 52, 41, 43]
key4=[ 61, 54, 33, 53, 43, 46, 52, 72, 68, 59]
key5=[ 47, 31, 60, 37, 68, 37, 27, 49, 39, 55]
key6=[ 21, 23, 26, 81, 36, 44, 19, 71, 62, 74]
key7=[ 62, 54, 39, 24, 67, 75, 38, 36, 48, 50]
key8=[ 73, 75, 32, 61, 22, 77, 79, 40, 65, 18]
key9=[ 18, 64, 48, 23, 58, 71, 30, 60, 21, 36]
key10=[ 81, 69, 39, 50, 37, 18, 68, 45, 66, 77]
ans=[]//将结果经最后一步处理后每十位填入解一次,最终几次结果连接即是flag

def mod256(x):
return x%256

s = Solver()
a1,a2,a3,a4,a5,a6,a7,a8,a9,a10=BitVecs('a1 a2 a3 a4 a5 a6 a7 a8 a9 a10',8)


for i in range(10):
s.add(mod256(key1[i]*a1+key2[i]*a2+key3[i]*a3+key4[i]*a4+key5[i]*a5+key6[i]*a6+key7[i]*a7+key8[i]*a8+key9[i]*a9+key10[i]*a10)==ans[i])
print(s.check())
print(s.model())
mod=s.model()
key=[a1,a2,a3,a4,a5,a6,a7,a8,a9,a10]
flag=""
for i in key:
flag+=key_final[int(str(mod[i])
print flag

FLXG的小程序

定位中文字符串找到关键判断点
很清晰的思路
直接shift+e提取数据简单异或后再逆序解base64即可:

1
2
3
4
5
6
7
8
9
10
11
12
key =[
57, 101, 69, 84, 119, 95, 52, 95, 100, 95,
102, 104, 60, 52, 88, 85, 127, 67, 33, 75,
127, 32, 67, 118, 95, 32, 76, 77, 122, 83,
112, 125, 86, 77, 101, 71, 76, 93, 113, 67,
24, 111, 71, 72, 66, 24, 28, 77, 116, 69,
1, 105, 0, 77, 91, 109
]
ans=""
for i in range(len(key)):
ans+=chr(i^key[i])
print ans[::-1].decode("base64")

画图

记得有个画图,忘了题目名是啥了
大概就是根据字母画图就行:

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
from PIL import Image

MAX=2000

pic=Image.new("RGB",(MAX,MAX))

str="DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRDDDDDDDDDDDDDDDDDDDDLLLLLLLLLLLLLLLLLLDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUUULLLLLLLLLLLLRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRLLLLLLLLLLLLLLLLLLLLLLLLRRRRDDDDDDDDRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRUUUUUUUUUUUUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUURRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRUUUUUUUULLLLLLLLLLLLLLLLRRRRRRRRRRRRRRRRRRRRLLLLDDDDDDDDDDDDDDDDDDDDDDDDDDDDLLLLLLLLLLLLLLLLLLLLUUUUUUUUUUUUUUUURRRRRRRRRRRRRRRRRRRRUUUUUUUUUUUULLLLLLLLLLLLLLLLLLLLRRRRRRRRRRRRRRRRRRRRRRRRLLLLDDDDDDDDRRRRRRRRRRRRRRRRDDDDDDDDDDDDDDDDDDDDRRRRRRRRRRRRRRRRRRRRUUUUUUUUUUUUUUUUUUUUUUUUUUUULLLLLLLLLLLLLLLLLLLLDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUURRRRRRRRRRRRRRRRRRRRRRRRLLLLDDDDDDDDDDDDLLLLLLLLLLLLLLLLLLLLLLLLRRRRRRRRRRRRRRRRRRRRRRRRRRRRLLLLUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDDDRRRRRRRRRRRRRRRRRRRRRRRRRRRRUUUUUUUUUUUUUUUUUUUURRRRRRRRLLLLLLLLDDDDDDDDDDDDDDDDDDDDDDDDLLLLLLLLDDDDRRRRRRRRDDDDDDDDDDDDDDDDDDDDDDDDRRRRRRRRLLLLLLLLUUUUUUUUUUUUUUUUUUUUUUUULLLLLLLLUUUURRRRRRRRUUUURRRRRRRRRRRRRRRRRRRRRRRRDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUURRRRDDDDRRRRDDDDRRRRDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUURRRRRRRRUUUUUUUURRRRDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUURRRRRRRRRRRRUUUURRRRUUUURRRRRRRRRRRRRRRRDDDDRRRRDDDDRRRRDDDDDDDDLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLUUUURRRRUUUUDDDDLLLLDDDDDDDDRRRRDDDDRRRRDDDDRRRRRRRRRRRRUUUURRRRRRRRUUUUDDDDLLLLLLLLDDDDLLLLLLLLLLLLUUUULLLLUUUULLLLUUUUUUUURRRRUUUURRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRDDDDDDDDDDDDDDDDDRRRRRRRRRRRRRRRRRRRRRRRRRRRRUUUUUUUUUUUUUUUUUUUUUUUULLLLLLLLLLLLLLLLLLLLLLLLLLLLDDDDDDDDDDDDDDDDDDDDDDDDRRRRRRRRRRRRRRRRRRRRRRRRRRRRUUUUUUUUUUUUUUUURRRRRRRRUUUULLLLUUUUDDDDRRRRDDDDRRRRDDDDDDDDDDDDDDDDDDDDRRRRUUUUUUUUUUUURRRRUUUUUUUUDDDDDDDDRRRRDDDDDDDDDDDDRRRRUUUUUUUUUUUUUUUUUUUURRRRUUUURRRRUUUUDDDDLLLLDDDDRRRRRRRRRRRRUUUUUUUUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUURRRRDDDDRRRRDDDDRRRRDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUURRRRUUUURRRRUUUURRRRDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUDDDDUUUURRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRLLLLLLLLLLLLLLLLUUUULLLLUUUULLLLLLLLDDDDLLLLDDDDLLLLDDDDDDDDDDDDRRRRDDDDRRRRDDDDRRRRRRRRUUUURRRRRRRRUUUUDDDDLLLLLLLLDDDDLLLLLLLLUUUULLLLUUUULLLLUUUUUUUURRRRRRRRRRRRRRRRRRRRRRRRUUUULLLLUUUUDDDDRRRRRRRRRRRRRRRRRRRRDDDDDDDDDDDDDDDDRRRRRRRRRRRRRRRRRRRRUUUUUUUUUUUUUUUUUUUULLLLLLLLLLLLLLLLLLLLDDDDDDDDUUUUUUUURRRRRRRRRRRRRRRRRRRRDDDDRRRRRRRRRRRRUUUULLLLUUUUDDDDRRRRDDDDRRRRDDDDDDDDDDDDDDDDDDDDRRRRUUUUUUUUUUUUUUUURRRRUUUUUUUUDDDDDDDDRRRRDDDDDDDDDDDDDDDDRRRRRRRRUUUUUUUUUUUUUUUURRRRUUUUUUUURRRRUUUUDDDDLLLLDDDDRRRRRRRRRRRRRRRRRRRRUUUUUUUUUUUUUUUULLLLLLLLRRRRRRRRDDDDDDDDDDDDDDDDDDDDRRRRRRRRDDDDLLLLLLLLDDDDDDDDDDDDDDDDDDDDLLLLLLLL"

flagx=0
flagy=0
for y in range(0,MAX):
for x in range(0,MAX):
pic.putpixel([x,y],(255,255,255))
for key in str:
if key=="R":
for x in range(0,2):
pic.putpixel([flagx+x,flagy],(0,0,0))
flagx=flagx+2
if key=="D":
for x in range(0,2):
pic.putpixel([flagx,flagy+x],(0,0,0))
flagy+=2
if key=="L":
for x in range(0,2):
pic.putpixel([flagx-x,flagy],(0,0,0))
flagx-=2
if key=="U":
for x in range(0,2):
pic.putpixel([flagx,flagy-x],(0,0,0))
flagy-=2
print flagx,flagy
pic.show()

pic.save("flag.png")

Buy

忘记名字,就是买flag那一个
时间处存在整数溢出
构造足够大的时间
让取出年份变为负数直接取出即得flag

她的诗&&她的礼物

他的诗应该是类似base64隐写
我记得是没写脚本,直接一个在线网站解uuencode再与脚本解出的明文比对即可,不过好像要猜解最后一位
她的礼物是很简单的patch(至少我没去逆),nop掉几个输出和sleep,减小运行时间,只要最后的输出,参数是他的诗第十行,patch后程序传参秒得flag

伏羲卦

忘了题目名称了
根据64种卦象联想到base64
按顺序替换解base64即可
不过开始时候base64顺序写错卡了好久(因为之前做的逆向(记得是安恒杯9月赛)base64顺序改过,直接改的那个脚本结果顺序忘了变回来):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#-*-coding:utf-8-*-

key="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
key2=["坤","剥","比","观","豫","晋","萃","否","谦","艮","蹇","渐","小过","旅","咸","遁","师","蒙","坎","涣","解","未济","困","讼","升","蛊","井","巽","恒","鼎","大过","姤","复","颐","屯","益","震","噬嗑","随","无妄","明夷","贲","既济","家人","丰","离","革","同人","临","损","节","中孚","归妹","睽","兑","履","泰","大畜","需","小畜","大壮","大有","夬","乾"]
f=open("./flxg.txt","r")
f1=open("./final","w+")
ans=""
for i in f:
#print i
for j in range(64):
i=i.replace(key2[j],key[j])
i+="\n"
ans+=i
f1.write(ans)
f.close()
f1.close()

RSA

思路比较简单
就是简单的从低位到高位爆破:

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
key1=20177650286553319048656572431426864683972322616537528728644836950907654167144961938429509778926505938147163259147328872178897507791522569632637628576826135964471897661414351261453774090509205324220367785291196302551202990322952833839519685942136552490589504983264090018782888509594899124308485994909369157739590678421913334422763356613026472743079024933233557565198057398238454462971661266735075199307328588913060033329742394868127944469289321187036511972057975816136466581904044150309083660596527476198646767207896234322280486096803109351478982849399252765905154625449629131202246956928879278104313464399748896654335 
key2=int("0x1"+"0"*512,16)-20177650286553319048656572431426864683972322616537528728644836950907654167144961938429509778926505938147163259147328872178897507791522569632637628576826135964471897661414351261453774090509205324220367785291196302551202990322952833839519685942136552490589504983264090018782888509594899124308485994909369157739690798236942786515359420891819523078078001184938002588184640997371794236705658312351156161124668283889171041058024858239408724965303885485356611059740480075879221661858319606783376958758348179998879989787088907672913468336293174408246405953882533580841784122100084676690051777413318254860735992696612183461891
key_p=[0]
key_q=[0]
final_p=[]
final_q=[]
for bit in range(256):
for key in range(len(key_p)):
for i in range(0x10):
for j in range(0x10):
p=i*int("0x1"+"0"*bit,16)+key_p[key]
q=j*int("0x1"+"0"*bit,16)+key_q[key]
final_ans1=(p*q)^(p+q)
ans2=(p*q)^(p-q)
if ans2<0:
final_ans2=int("0x1"+"0"*512,16)+ans2
else:
final_ans2=ans2
check_ans1=hex(final_ans1).replace("L","")[-bit-1:]
check_ans2=hex(final_ans2).replace("L","")[-bit-1:]
true_ans1=hex(key1).replace("L","")[-bit-1:]
true_ans2=hex(key2).replace("L","")[-bit-1:]
if check_ans1==true_ans1 and check_ans2==true_ans2:
final_p.append(p)
final_q.append(q)
key_p=[]
key_q=[]
for k_p in final_p:
key_p.append(k_p)
for k_q in final_q:
key_q.append(k_q)
final_p=[]
final_q=[]
if bit>=254:
print key_p,key_q,bit

而后每一位情况稳定在2000左右(如果调试的时候没记错),类似剪枝效果,每一轮多种情况,但到下一轮便会只有能得到下一位的进入,因此情况没有指数爆炸
得到pq情况后,根据p*q^(p+q),并不影响n最高位来限制pq

1
2
3
4
5
6
7
a=[]//填入p情况
b=[]//填入q情况
key="0x9fd678aeb8043bb14310538"
for i in range(len(a)):
final=hex(a[i]*b[i])
if final[:6]==key[:6]:
print a[i],b[i]

得到p,q后正常rsa解一下即可解得flag
剩下一些不记得题目,一些脚本被删了(主要懒得重新做去截图),就不再写了,不过欢迎师傅们交流

PS:官方全部WP:

1
https://github.com/ustclug/hackergame2018-writeups