# 2) emoji -> hex order = sorted(set(emoji_text)) emap = {emj: format(i, 'x') for i, emj inenumerate(order)} hex_str = ''.join(emap[ch] for ch in emoji_text) data = binascii.unhexlify(hex_str) print("2:", data)
# 判断给定 ZIP 是否属于伪加密 defis_pseudo_encrypted(zp: Path) -> bool: defcan_read_any_member(source) -> bool: with zipfile.ZipFile(source, "r") as zf: for info in zf.infolist(): if info.is_dir(): continue with zf.open(info) as fh: fh.read(1) break returnTrue
with suppress(Exception): if can_read_any_member(zp): returnTrue
data = bytearray(zp.read_bytes()) flag_offset = -1 search_from = 0
with suppress(Exception): with zipfile.ZipFile(source, "r") as zf: zf.extractall(outdir) returnTrue
returnFalse
# 处理真加密 ZIP defextract_real_encrypted(zp: Path, outdir: Path) -> bool: with zipfile.ZipFile(zp, "r") as zf: members = [info for info in zf.infolist() ifnot info.is_dir()]
for info in members: name = Path(info.filename).name ifnot name: continue candidate = Path(name).stem if name.lower().endswith(".zip") else name if password isNone: password = candidate if name.lower().endswith(".zip"): password = candidate break
ifnot password: returnFalse
with suppress(Exception): with zipfile.ZipFile(zp, "r") as zf: zf.extractall(outdir, pwd=password.encode()) returnTrue
returnFalse
if __name__ == "__main__": bits: List[str] = [] current = ZIP_FILE.resolve() level = 0
if is_pseudo_encrypted(current): print("伪加密") succeeded = extract_pseudo_encrypted(current, layer_dir) bit = "0" else: print("真加密") succeeded = extract_real_encrypted(current, layer_dir) bit = "1"
ifnot succeeded: print(f"处理失败:{current}") break
bits.append(bit)
next_zip = None for base in (layer_dir / "tmp", layer_dir): ifnot base.exists(): continue for path in base.rglob("*.zip"): next_zip = path break if next_zip: break
Delta Action “is a multi platform and cross platform first person special operations officer tactical shooting game developed by the Linlang Tiantian team of Tencent Tianmei Studio and published by Tencent Games Difficulty: Normal
附件可以分离出一张jpg,一张png 和结尾的一段数据
hint3: Misc - SanJiaoZhou 文件尾是一个zip压缩包
将数据逐字节和zip头异或,发现规律
转成zip
1 2
t = bytes([i ^ 25for i inrange(256)]) open('1.zip', 'wb').write(open('1.bin', 'rb').read()[::-1].translate(t))
解压后得到两句话
1 2
Try the abbreviation, it will surprise you. I once heard that the "Heart Of Africa" is the most beautiful thing in the world.
cloacked-pixel解密得到flag
1 2 3
C:\Users\dr0n1\Desktop\0misc\cloacked-pixel-master>python2 lsb.py extract a.png 1.txt HOA [+] Image size: 800x1067 pixels. [+] Written extracted data to 1.txt.
Who’s Cat
Ouch! Who’s Cat there? Maybe its owner is Mr.Alpha and its name is Wednesday. Difficulty: Normal
猫脸变换
先将拉伸的长方形图片改为正方形
1 2 3 4 5 6 7 8 9 10 11 12 13 14
from PIL import Image
img = Image.open("encrypted.png")
w, h = img.size
if w > h: # 横向被拉伸 img_resized = img.resize((h, h)) else: # 竖向被拉伸 img_resized = img.resize((w, w))
import matplotlib.pyplot as plt import cv2 import numpy as np from PIL import Image
img = cv2.imread('out.png')
defarnold_decode(image, shuffle_times, a, b): """ decode for rgb image that encoded by Arnold Args: image: rgb image encoded by Arnold shuffle_times: how many times to shuffle Returns: decode image """ # 1:创建新图像 decode_image = np.zeros(shape=image.shape) # 2:计算N h, w = image.shape[0], image.shape[1] N = h # 或N=w
# 3:遍历像素坐标变换 for time inrange(shuffle_times): for ori_x inrange(h): for ori_y inrange(w): # 按照公式坐标变换 new_x = ((a * b + 1) * ori_x + (-b) * ori_y) % N new_y = ((-a) * ori_x + ori_y) % N decode_image[new_x, new_y, :] = image[ori_x, ori_y, :]
Golang is a statically typed, compiled programming language designed at Google. It is known for its simplicity, efficiency, and strong support for concurrent programming. Go is often used for building web servers, networking tools, and other performance-critical applications. Difficulty: Normal
type Account struct { id string pw string is_admin bool secret_key string }
type AccountClaims struct { Id string`json:"id"` Is_admin bool`json:"is_admin"` jwt.StandardClaims }
type Resp struct { Status bool`json:"status"` Msg string`json:"msg"` }
type TokenResp struct { Status bool`json:"status"` Token string`json:"token"` }
var acc []Account var secret_key = os.Getenv("KEY") var flag = os.Getenv("GZCTF_FLAG") var admin_id = os.Getenv("ADMIN_ID") var admin_pw = os.Getenv("ADMIN_PW")
funcclear_account() { acc = acc[:1] }
funcget_account(uid string) Account { for i := range acc { if acc[i].id == uid { return acc[i] } } return Account{} }
set :bind, '0.0.0.0' enable :sessions set :erb, :escape_html => true
con = SQLite3::Database.new "sqlite.db"
con.execute "CREATE TABLE IF NOT EXISTS threads( id INTEGER PRIMARY KEY AUTOINCREMENT, content TEXT, ip TEXT, username TEXT );"
con.execute "CREATE TABLE IF NOT EXISTS replies( id INTEGER PRIMARY KEY AUTOINCREMENT, content TEXT, ip TEXT, username TEXT, thread_id INTEGER );"
defget_threads(con) return con.execute("SELECT * FROM threads ORDER BY id DESC;") end
defget_replies(con, id) return con.execute("SELECT *, null, 0 as p FROM threads WHERE id=? UNION SELECT *, 1 as p FROM replies WHERE thread_id=? order by p", [id, id]) end
defis_allowed_ip(username, ip, config) return config["mods"].any? { |mod| mod["username"] == username and mod["allowed_ip"] == ip } end
get "/"do @threads = get_threads(con) erb :index end
post "/thread"do if params[:content].nil? or params[:content] == ""then raise"Thread content cannot be empty!" end if session[:username] then username = is_allowed_ip(session[:username], request.ip, config) ? session[:username] : nil end # con.execute("INSERT INTO threads (id, content, ip, username) # VALUES (?, ?, ?, ?)", [nil, params[:content], request.ip, username]) redirect to("/#{con.execute('SELECT last_insert_rowid()')[0][0]}") end
get "/flag"do if !session[:username] then erb :login elsif !is_allowed_ip(session[:username], request.ip, config) then return [403, "You are connecting from untrusted IP!"] else return config["flag"] end end
post "/login"do if config["mods"].any? { |mod| mod["username"] == params[:username] and mod["password"] == params[:password] } then session[:username] = params[:username] redirect to("/flag") else return [403, "Incorrect credentials"] end end
get "/:id"do @id = params[:id] @replies = get_replies(con, @id) erb :thread end
post "/:id"do if params[:content].nil? or params[:content] == ""then raise"Reply content cannot be empty!" end if session[:username] then username = is_allowed_ip(session[:username], request.ip, config) ? session[:username] : nil end @id = params[:id] # con.execute("INSERT INTO replies (id, content, ip, username, thread_id) # VALUES (?, ?, ?, ?, ?)", [nil, params[:content], request.ip, username, @id]) redirect to("/#{@id}") end
共有六个路由,功能分别如下
/:展示主题帖列表,从 threads 表读取所有帖子并渲染 index /thread:创建新主题帖,校验 content /flag:未登录渲染登录页;已登录但 IP 不可信返回 403;已登录且 IP 可信则返回 flag /login:处理登录,校验是否在 config[“mods”];成功写入会话并跳转到 flag 页面,失败返回 403 get /:id:展示指定帖详情,查询该帖及其所有回复(UNION 合并,帖子在前),渲染 thread post /:id:给指定帖回帖,校验 content 非空;若会话用户名且 IP 可信则记录用户名
# 将新的密文、IV、标签保持为 Base64 文本并拼接成最终 Cookie ct, iv, auth = map(base64.b64encode, [ct, iv, auth]) cookie = '--'.join(part.decode() for part in (ct, iv, auth)) print(cookie)
或者使用ruby的方式来伪造
1 2 3 4 5 6 7 8 9
require'sinatra'
use Rack::Protection::EncryptedCookie, :secret => "c089cdd0a034f5ad365ab3e809e5ac0ec2f6faa248800db6d87af7dff1b1aac16c14f6c2ccf01d7ecd2c8842cbdf6dcd8bb7d2a07eb3286679f66e1bd256845c"
get '/'do session[:username] = 'xxxx' "session: " + session.inspect end
con.execute "CREATE TABLE IF NOT EXISTS threads( id INTEGER PRIMARY KEY AUTOINCREMENT, content TEXT, ip TEXT, username TEXT );"
defget_replies(con, id) return con.execute("SELECT *, null, 0 as p FROM threads WHERE id=? UNION SELECT *, 1 as p FROM replies WHERE thread_id=? order by p", [id, id]) end
get "/:id"do @id = params[:id] @replies = get_replies(con, @id) erb :thread end
defdo(source_code): hook_code = ''' def my_audit_hook(event_name, arg): blacklist = ["popen", "input", "eval", "exec", "compile", "memoryview"] if len(event_name) > 4: raise RuntimeError("Too Long!") for bad in blacklist: if bad in event_name: raise RuntimeError("No!")
__import__('sys').addaudithook(my_audit_hook)
''' print(source_code) code = hook_code + source_code tree = compile(source_code, "run.py", 'exec', flags=ast.PyCF_ONLY_AST) try: if verify_secure(tree): withopen("run.py", 'w') as f: f.write(code) result = subprocess.run(['python', 'run.py'], stdout=subprocess.PIPE, timeout=5).stdout.decode("utf-8") os.remove('run.py') return result else: return"Execution aborted due to security concerns." except: os.remove('run.py') return"Timeout!"