ISCC2024-练武
不亏是国赛,人人都是全栈爷啊
web
还没想好名字的塔防游戏
傻逼题目
点进网页大标题的大写字母和提示的大写字母组合成18位
代码审计
from flask import Flask
from flask import request
import hashlib
import urllib.parse
import os
import json
app = Flask(__name__)
secret_key = os.urandom(16)
class Task:
def __init__(self, action, param, sign, ip):
self.action = action
self.param = param
self.sign = sign
self.sandbox = md5(ip)
if not os.path.exists(self.sandbox):
os.mkdir(self.sandbox)
def Exec(self):
result = {}
result['code'] = 500
if self.checkSign():
if "scan" in self.action:
resp = scan(self.param)
if resp == "Connection Timeout":
result['data'] = resp
else:
print(resp)
self.append_to_file(resp)
result['code'] = 200
if "read" in self.action:
result['code'] = 200
result['data'] = self.read_from_file()
if result['code'] == 500:
result['data'] = "Action Error"
else:
result['code'] = 500
result['msg'] = "Sign Error"
return result
def checkSign(self):
if get_sign(self.action, self.param) == self.sign:
return True
else:
return False
@app.route("/geneSign", methods=['GET', 'POST'])
def geneSign():
param = urllib.parse.unquote(request.args.get("param", ""))
action = "scan"
return get_sign(action, param)
@app.route('/De1ta', methods=['GET', 'POST'])
def challenge():
action = urllib.parse.unquote(request.cookies.get("action"))
param = urllib.parse.unquote(request.args.get("param", ""))
sign = urllib.parse.unquote(request.cookies.get("sign"))
ip = request.remote_addr
if waf(param):
return "No Hacker!!!!"
task = Task(action, param, sign, ip)
return (json.dumps(task.Exec())
@app.route('/'))
def index():
return open("code.txt", "r").read()
def scan(param):
try:
with open(param, 'r') as file:
content = file.read()
return content
except FileNotFoundError:
return "The file does not exist"
def md5(content):
return hashlib.md5(content.encode()).hexdigest()
def get_sign(action, param):
return hashlib.md5(secret_key + param.encode('latin1') + action.encode('latin1')).hexdigest()
def waf(param):
check = param.strip().lower()
if check.startswith("gopher") or check.startswith("file"):
return True
else: return False
if __name__ == '__main__':
app.debug = False
app.run()
分析:
/geneSign:网页获取登录所需cookie
/De1tal:根据cookie中action的值决定模式,为read时可以获取flag文件
解题:
由于/geneSign中固定了md5计算的后缀scan,不是read
而/De1tal中判断模式只是看‘str' in action,单纯action中是否有对应模式的子字符串,所以不用在乎read和scan的位置
所以/geneSign中param=flag.txtread,这样就可以构成flag.txtreadscan
/De1tal中param=flag.txt,cookie: action=readscan;sign=[md5]
第一步,生成md5
第二步:登录获取flag
原神启动
查看源码访问success.html,得到提示flag在flag.txt
目录扫描,flag.txt中为fakeflag
访问docs文件,发现tomcat版本8.5.32
百度搜索到有CVE-2020-1938,获取脚本:
https://github.com/sv3nbeast/CVE-2020-1938-Tomact-file_include-file_read/
根据之前提示flag在flag.txt中,使用脚本,获取flag
misc
FunZip
一把梭
时间刺客
提取usb数据部分
#提取usb数据部分
fi=open('usbdata.txt','w')
with open('usb.pcap', 'rb') as f:
k=1
while 1:
f.seek(24 + 16 * k + 35 * (k - 1))
data = f.read(35) # 读取数据包内容
if not data:
break
for i in range(27,len(data)):
fi.write("{:02X}".format(data[i]))
fi.write('\n')
k=k+1
#预处理
f=open('usbdata.txt','r')
fi=open('out.txt','w')
while 1:
a=f.readline().strip()
if a:
if len(a)==16: # 鼠标流量的话len改为8
out=''
for i in range(0,len(a),2):
if i+2 != len(a):
out+=a[i]+a[i+1]+":"
else:
out+=a[i]+a[i+1]
fi.write(out)
fi.write('\n')
else:
break
fi.close()
#处理
mappings = { 0x04:"A", 0x05:"B", 0x06:"C", 0x07:"D", 0x08:"E", 0x09:"F", 0x0A:"G", 0x0B:"H", 0x0C:"I", 0x0D:"J", 0x0E:"K", 0x0F:"L", 0x10:"M", 0x11:"N",0x12:"O", 0x13:"P", 0x14:"Q", 0x15:"R", 0x16:"S", 0x17:"T", 0x18:"U",0x19:"V", 0x1A:"W", 0x1B:"X", 0x1C:"Y", 0x1D:"Z", 0x1E:"1", 0x1F:"2", 0x20:"3", 0x21:"4", 0x22:"5", 0x23:"6", 0x24:"7", 0x25:"8", 0x26:"9", 0x27:"0", 0x28:"\n", 0x2a:"[DEL]", 0X2B:" ", 0x2C:" ", 0x2D:"-", 0x2E:"=", 0x2F:"[", 0x30:"]", 0x31:"\\", 0x32:"~", 0x33:";", 0x34:"'", 0x36:",", 0x37:"." }
nums = []
keys = open('out.txt')
for line in keys:
if line[0]!='0' or line[1]!='0' or line[3]!='0' or line[4]!='0' or line[9]!='0' or line[10]!='0' or line[12]!='0' or line[13]!='0' or line[15]!='0' or line[16]!='0' or line[18]!='0' or line[19]!='0' or line[21]!='0' or line[22]!='0':
continue
nums.append(int(line[6:8],16))
keys.close()
output = ""
for n in nums:
if n == 0 :
continue
if n in mappings:
output += mappings[n]
else:
output += '[unknown]'
print(output)
#FLAGPR3550NWARDSA2FEE6E0
压缩包密码就是PR3550NWARDSA2FEE6E0
压缩包内文件修改时间很有问题,查到一篇博客
import os
for i in range(18):
filename = ".\\46\\.{0}.txt".format(i)
file_attr = os.stat(filename)
create_time = str(file_attr.st_mtime)
print(chr(int(create_time[7:10])),end='')
#keDH7HrPXf4hytq3Dc
提交ISCC{keDH7HrPXf4hytq3Dc}
reverse
迷失之门
关键:
exp: 直接跟它爆了
a=[70,83,66,66,104,75,88,84,112,67,116,77,85,103,107,77,109,74,75,110,116,88,118,107,75,68,54]
v3=b'DABBZXQESVFRWNGTHYJUMKIOLPC'
v4=b'0123456789+/-=!#&*()?;:*^%'
v10=b'abcdefghijklmnopqrstuvwxyz'
ans=[]
for i in range(27):
for j in range(33,127):
v22=j-v3[i]
flag=0
if v22>0:
if v22>25:
if v22>51 :
flag=v4[v22-52]
else :
flag=v10[v22-26]
else :
flag=ord('A')+v22
if flag==a[i]:
ans.append(j)
for i in ans:
print(chr(i),end="")
#ISCC{bhX|Xs^knk`nbT|zbxsVS}
CrypticConundrum
查壳脱壳
直接看重点,进行了两次加密函数。但经过分析,mix没用,因为mix函数中又将v5 strcpy成了原来的值,所以不用管mix
先看数据,直接看汇编代码,发现应该是小端序存储,而且如果直接看汇编代码,会有重复覆盖的数值,这点是必须注意的。
查看Encryption加密函数,经过分析,NewEncryption中和加密函数中都又进行位置的对调,所以抵消之后可以不用考虑,接下来就是简单的运算操作了
但是,如果直接编写完脚本输出后会有问题,会发现有的值大于256,不在正常ascii范围内,经过测试,对大于256的值 模上256即可得到flag
EXP
v5=[0x97,0x87,0xd0,0x44,0x13,0x39,0x6e,0x99,0x35,0xf9,0xc1,0x84,0xf4,0x37,0x94,0x78,0xe5,0x29,0x95,0xaa,0xe2,0x34,0x87,0x71,0xfa,0x34]
v7=[0x49,0x53,0x43,0x43]
Str = "So--this-is-the-right-flag"
v10 = len(Str) # 26
for i in range(v10):
v5[i] = v5[i] - 10
for i in range(0,v10-1):
v5[i] = v5[i] + v5[i + 1]
for i in range(v10 - 1):
v5[i] = v5[i] ^ v7[2]
for i in range(0, v10, 2):
v5[i] = v5[i] ^ v7[i % 4]
for i in range(v10):
v5[i] = v5[i] + v7[i % 4]
print(v5)
"""try:
for i in v5:
print(chr(i), end="")
except:
pass"""
for i in v5:
if i>256:
print(chr(i%256),end="")
else:
print(chr(i),end="")
crypto
rsa_ku
不亏是放在misc里的密码
非预期:
笑死了n可以直接分解
预期:
解方程
s1 = (p-2)*(q-1) = pq-p-2q+2
s2 = (p-1)*(q-2) = pq-2p-q+2
s3 = s1-s2 = p-q
q = p-s3
n = p*(p-s3)
from Crypto.Util.number import *
from gmpy2 import *
n = 129699330328568350681562198986490514508637584957167129897472522138320202321246467459276731970410463464391857177528123417751603910462751346700627325019668100946205876629688057506460903842119543114630198205843883677412125928979399310306206497958051030594098963939139480261500434508726394139839879752553022623977
e = 65537
c = 79671417622863203790134201771403727501040623919447341148857390413114945657547483683496084856711621909580402488534439384610699065630556412669884735847728302698585205335825700281740418633221444675077781978038803125127642719914573970412875738100167515619227904660058420447041619894572445078978800847546643214713
#(p-2)*(q-1) = 129699330328568350681562198986490514508637584957167129897472522138320202321246467459276731970410463464391857177528123417751603910462751346700627325019668067056973833292274532016607871906443481233958300928276492550916101187841666991944275728863657788124666879987399045804435273107746626297122522298113586003834
#(p-1)*(q-2) = 129699330328568350681562198986490514508637584957167129897472522138320202321246467459276731970410463464391857177528123417751603910462751346700627325019668066482326285878341068180156082719320570801770055174426452966817548862938770659420487687194933539128855877517847711670959794869291907075654200433400668220458
#非预期
p=11104861498641160020551133747582851050482827883841239117180799157472078278661946047575808556331157873693827396366774529894387508349540416345196575506278923
q=11679509046055093484387585536769973960915016129595089156764897709796981174994469835617477280580153684696296947700908005372625963068761884667061288424062299
print(long_to_bytes(pow(c,invert(e,(p-1)*(q-1)),n)))
#预期解
s1 = 129699330328568350681562198986490514508637584957167129897472522138320202321246467459276731970410463464391857177528123417751603910462751346700627325019668067056973833292274532016607871906443481233958300928276492550916101187841666991944275728863657788124666879987399045804435273107746626297122522298113586003834
s2 = 129699330328568350681562198986490514508637584957167129897472522138320202321246467459276731970410463464391857177528123417751603910462751346700627325019668066482326285878341068180156082719320570801770055174426452966817548862938770659420487687194933539128855877517847711670959794869291907075654200433400668220458
from z3 import *
x=Int('x')
p=Solver()
p.add(x*(x-(s1-s2))==n)
p.check()
p=p.model()
p=p[x].as_long()
q=n//p
print(long_to_bytes(pow(c,invert(e,(p-1)*(q-1)),n)))
#b'ISCC{3pfzTcYhOYAMRFQeVE--}'