这一届的misc+crypto也太少了,一二血同队+垂直上分明显。
Misc
签到
下载附件EBCDIC.txt,根据文件名和内容,猜测为某种编码方式,搜索知为EBCDIC编码:
EBCDIC(广义二进制编码的十进制交换码,Extended Binary Coded Decimal Interchange Code),是字母或数字字符的二进制编码,是IBM为它的更大型的操作系统而开发的。它是为IBM的S/390上的IBMOS/390操作系统上使用的文本文件的编码,并且数千个公司为它们的遗留应用程序和数据库使用这种编码。在一个EBCDIC的文件里,每个字母或数字字符都被表示为一个8位的二进制数(一个0、1字符串)。256个可能的字符被定义(字母,数字和一些特殊字符)。
IBM的个人计算机和工作站操作系统不使用它们所有的EBCDIC编码。相反的,它们使用文本的工业标准编码,ASCII码。转化程序允许不同的操作系统从一种编码到另一种编码的转化。
找到在线解码网站,将16进制EBCDIC码解码为16进制ASCII码,再转为字符得到flag。
flag值:flag{we1c0me_t0_redhat2021}
Crypto
primegame
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
36
37
38
39
40
41
42
43
44 #!/usr/bin/env python3
from decimal import *
import math
import random
import struct
from flag import flag
assert (len(flag) == 48)
msg1 = flag[:24]
msg2 = flag[24:]
primes = [2]
for i in range(3, 90):
f = True
for j in primes:
if i * i < j:
break
if i % j == 0:
f = False
break
if f:
primes.append(i)
getcontext().prec = 100
keys = []
for i in range(len(msg1)):
keys.append(Decimal(primes[i]).ln())
sum_ = Decimal(0.0)
for i, c in enumerate(msg1):
sum_ += c * Decimal(keys[i])
ct = math.floor(sum_ * 2 ** 256)
print(ct)
sum_ = Decimal(0.0)
for i, c in enumerate(msg2):
sum_ += c * Decimal(keys[i])
ct = math.floor(sum_ * 2 ** 256)
print(ct)
597952043660446249020184773232983974017780255881942379044454676980646417087515453
425985475047781336789963300910446852783032712598571885345660550546372063410589918
代码逻辑:
将48长度的flag分为24长度两部分,生成90以内的素数列表primes
和前24个素数自然对数列表keys
,分别求出flag两部分的ascii值与key值乘积和。
容易看出
$S=\text{ct} \cdot 2^{256}=\sum\limits_{i=1}^{24}\Big(c_i \cdot (\text{key}_i \cdot 2^{256})\Big)=\sum\limits_{i=1}^{24}(c_i \cdot k_i)$
形式类似于0-1背包加密问题,其中公钥 $k_i$ 与密文 $S$ 已知,需解密得明文 $c_i \in [0,128)$。
由于明文数量不大,且背包密度 $d = \cfrac{n}{\log_2(\text{max}(k_i))} \approx 0.0968$,可采用低密度攻击方法(Lagarias&Odlyzko算法 或 CJLOSS算法)恢复明文,构造格:
$\left(\begin {array}{c} b_0 \newline b_1 \newline \vdots \newline b_n \newline b_{n+1} \end{array} \right) =\left(\begin {array}{c} 1 & 0 & \cdots & 0 & Nk_0 \newline 0 & 1 & \cdots & 0 & Nk_1 \newline \vdots & \vdots & \ddots & \vdots & \vdots \newline 0 & 0 & \cdots & 1 & Nk_n \newline 0 & 0 & \cdots & 0 & Nk_{n+1} \end{array} \right) $
1 | from itertools import combinations |
flag值:flag{715c39c3-1b46-4c23-8006-27b43eba2446}
hpcurve
你的数学学的怎么样?
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
36
37
38
39
40
41 #!/usr/bin/env sage
import struct
from random import SystemRandom
p = 10000000000000001119
R.<x> = GF(p)[]
y=x
f = y + y^7
C = HyperellipticCurve(f, 0)
J = C.jacobian()
es = [SystemRandom().randrange(p**3) for _ in range(3)]
Ds = [J(C(x, min(f(x).sqrt(0,1)))) for x in (11,22,33)]
q = []
def clk():
global Ds,es
Ds = [e*D for e,D in zip(es, Ds)]
return Ds
def generate():
u,v = sum(clk())
rs = [u[i] for i in range(3)] + [v[i] for i in range(3)]
assert 0 not in rs and 1 not in rs
q = struct.pack('<'+'Q'*len(rs), *rs)
return q
flag = "flag{xxxxxxx}"
text = 'a'*20+flag
t = ''
keys = generate()
leng = len(keys)
i = 0
for x in text:
t += chr(ord(keys[i%leng])^^ord(x))
i+=1
print t.encode('hex')
66def695b20eeae3141ea80240e9bc7138c8fc5aef20532282944ebbbad76a6e17446e92de5512091fe81255eb34a0e22a86a090e25dbbe3141aff0542f5
代码逻辑:
密文为flag与超椭圆曲线 $y^2=x+x^7$ 随机生成值异或得到,由于部分明文已知,通过随机生成器(RNG)部分的代码恢复剩余字符。
对于域 $K$,亏格为 $g$ 超椭圆曲线基本形式是 $C:y^2+h(x)y=f(x)$,其中 $h(x),f(x) \in K[x]$(多项式系数都在 $K$ 上),且 $\deg(h(x)) \leq g$,$\deg(f(x))=2g+1$。
超椭圆曲线密码体制是建立在超椭圆曲线的Jacobian群上的,有限域上超椭圆曲线的Jacobian群是一个有限交换群,Jacobian阶记为 $J(C)$。可以在 $J(C)$中定义归约除子的一个加法运算 。使得 $J(C)$成为一个交换群,这个有限交换群是超椭圆曲线密码体制的基础。
每个元素 $D \in J(C)$ 都可以唯一表示为 $K[x]$ 上的一个多项式元组 $\langle u(x),v(x) \rangle$,多项式满足:
- $u(x)$ 是首一多项式
- $u(x)$ 整除 $f(x)-h(x)v(x)-v^2(x)$
- $\deg(v(x)) \lt \deg(u(x)) \lt g$
这里 $h(x)=0,f(x)=x+x^7$,RNG部分生成三个随机数 $e_1,e_2,e_3$ 以及三个元素 $D_1,D_2,D_3 \in J(C)$,
RNG部分计算 $\langle u(x),v(x) \rangle=e_1D_1+e_2D_2+e_3D_3$ 并将系数转换为字节。
结合已知的a*20+flag
共24字节,可以恢复 $u(x)$。
对于 $v(x)$,根据 $D \in J(C)$ 的性质,有 $f(x)-h(x)v(x)-v^2(x) \equiv 0 \pmod {u(x)}$
如果 $x_i$ 是 $u(x)$ 的根($K$ 代数闭包下),有 $f(x_i)-h(x_i)v(x_i)-v^2(x_i) = 0 \Longrightarrow v^2(x_i)+h(x_i)v(x_i)=f(x_i)$,
说明 $(x_i,v(x_i))$ 是 $C$ 上的一个点。
又 $h(x_i)=0$,则 $v^2(x_i)=f(x_i) \Longrightarrow v(x_i) = \pm \sqrt{f(x_i)}$。
由于 $u(x)$ 次数为3,在$K$ 代数闭包下,可以找到三个根 $x_1,x_2,x_3$,即 $C$ 上的三个点 $(x_1,v(x_1)),(x_2,v(x_2)),(x_3,v(x_3))$,利用拉格朗日插值方法可以恢复 $v(x)$。
得到 $u(x)$ 和 $v(x)$,异或操作还原明文。
1 | import struct |
flag值:flag{1b82f60a-43ab-4f18-8ccc-97d120aae6fc}
Web
find_it
主页面没什么有用信息,扫描发现robots.txt
,访问提示:
1 | When I was a child,I also like to read Robots.txt |
访问1ndexx.php
报500 Internal Server Error,尝试看是否存在vim源码泄露,发现访问.1ndexx.php.swp
能回显源码:
1 | $link = mysql_connect('localhost', 'root'); |
代码逻辑:
将flag.php
文件内容读入变量$I_know_you_wanna_but_i_will_not_give_you_hhh
,并将传入的code
参数值与变量$I_know_you_wanna_but_i_will_not_give_you_hhh
一起写入hack.php
文件中。
对code
参数值过滤的关键字不少:
system|eval|exec|base|compress|chr|ord|str|replace|pack|assert|preg|replace|create|function|call|~|^|`|flag|cat|tac|more|tail|echo|require|include|proc|open|read|shell|file|put|get|contents|dir|link|dl|var|dump
用命令执行、文件读写等多种方式尝试向hack.php
写入php代码,以显示flag.php
文件内容,发现show_source()
函数可行。
payload: ?code=<?=show_source("fla"."g.php");
最后访问hack.php
,得到flag.php
内容:
1 |
|
Base32解码得flag。
flag值:flag{86d96843-83f1-4169-9d24-9674f396f103}
WebsiteManager
最新的网站测试器,作为非站长的你,能利用好它的功能吗?
查看网页源码发现image.php?id=1
,猜测存在sql注入,手工测试发现过滤了空格和双引号,且测试?id=-2/**/or/**/1=1
有图片显示,?id=-2/**/or/**/1=2
无图片显示,验证存在注入点,采用布尔盲注跑出登录用户名和密码:
1 | import requests |
用admin
和9ebab83595888e5a8bd57
直接登录,结合curl.php
猜测是SSRF,填入http://127.0.0.1/
得到访问结果回显验证猜测,尝试改用file伪协议直接读取根目录flag文件得到flag。
payload: file://127.0.0.1/flag
或 file:///flag
flag值:flag{f0d06b4c-954e-4a76-ad5d-95bd0227daea}