JNCTF-2025-wp
Web
1.eateateat

进来看到贪吃蛇,轻车熟路的看js文件

在这,flag为JNCTF{Th@t_is_@_f1ag}
2.test_your_php

php代码,php是世界上最好的语言(
第一关简单,intval($num, 0)会将$num转换为整数,0表示自动检测进制,不能等于2025就用八进制就好了,payload为?num=03751
第二关也是,parse_str($a, $b)会将$a解析为数组$b,$a=JNSEC=123等同于$b['JNSEC']=123,这个又等于c的md5值,直接$a=JNSEC=MD5($c)就好了,payload为"a=JNSEC=202cb962ac59075b964b07152d234b70&c=123"
第三关可以用md5碰撞,payload为d=240610708&e=QNKCDZO

下面的f是可以执行任意命令,可以f=system('ls /')

有flag.php,获取
flag在注释里
1 | |
另一个在环境变量里,phpinfo吧

最后得到flag为JNCTF{hhhhTh1s_Re@1_E@sy_P7P1111}
Misc
1.ez_pickle_jail
压缩包里点开src,有源码
1 | |
这是道沙盒逃逸的题目,漏洞为pickle.loads() 函数用于反序列化数据,但它会执行序列化数据中包含的任何代码。这意味着如果攻击者能够控制输入数据,就可以构造一个恶意的 pickle 数据来执行任意代码。
1 | |
攻击者可以将生成的 Base64 编码的 pickle 数据输入到程序中,程序在反序列化时会执行 open('/flag').read(),从而读取并输出 /flag 文件的内容。
题目有个实例,用nc连

这样就有flag了
2.logloglog
这题真的很麻烦了
这是题目,有三个日志文件,第一个要找第一次登录的源端口,在安全日志中用日志筛选事件ID为4624的信息,这就是登录日志,看日志的这个地方

一个一个找,找到了这个
54850就是第一题的答案。
第二题是看错误报告,事件ID为4625,要找ID,其实大多数事件都有,随便开一个
192.168.36.188就是
到第三关,问的是修改的用户名,要查找事件ID 4727、4738、4781,然后找着找着就找到了

为Adnimistartro,对了,这个时间是重点,是14:59
第四关在应用程序的日志文件里,一共就389个事件,找sql就好了,从最近的时间找,一直看到有sql的进程ID,还有就是事情发生在10/8,不在12/26.

看到第一个出的进程数就是,为8820
第五关在系统的日志文件里
事件ID为6005,6006,题目要求将黑客使用修改前的用户重启系统的次数,也就是在14:59前,还要注意一点,6006为关,6005为开,重启是时间很短,中间时间长的不是
所以看时间,有两次重启。
所以为54850-192.168.36.188-Adnimistartro-8820-2
flag为JNCTF{f5243f4a7fced6071ed84f9360278f6d}
3.stego
下载的文件是.qoi文件,转成png文件,flag在png文件的RGB中
这是图片内容,喜欢芙宁娜 :heart:

flag在这JNCTF{W0W_Y0u_c4n_wr1t3_C0d3_t0_50lv3_LSB!!!_stego}
4.流量的秘密
这道题是我最失败的一道题,花了极长的时间写脚本写不出来,最后用一个脚本把所有我我要的flag请求包和响应包都写出来
1 | |
请求的内容是sql布尔盲注的payload,我是一个一个的把所有响应为true的payload的提取出来,在用这个脚本解出来flag
1 | |
这其中的艰辛根本不想再说
总之flag为JNCTF{If_Y0u_do_NOT_wr1t3_A_5c1ipt_1t_1s_so0oOOo0o_HARD_4_U_2_f1nd_th15_flag}
Crypto
1.story
1 | |
这是字符频率攻击,我用这个网站解密https://quipqiup.com/
解密后得
1 | |
为一串可读明文,看到最后flag为JNCTF{frequency_analysis_in_cryptanalysis}
2.悲伤的故事
给的文件里有段文字,解密方法都在这段文字里了
1 | |
这道题是多段解密,有悲伤,大概是谐音base,又有栅栏,是要fence解密,还有名字是维吉,就说明要用维吉尼亚解密,又说钥匙,密钥就是key,这样解密
先base64得TDRwq@HXcRJr__m11@A{11G___},在fence解密得TRADJ{Rr1w_1q_G@m_H1_X1_c@},最后在维吉尼亚解密,密钥为key
得到flagJNCTF{Th1s_1s_W@i_J1_N1_y@}
3.熟悉的故人
就是简单的RSA,源码为
1 | |
payload为
1 | |
解出flag为JNCTF{Is_just_another_RSA}
Pwn
1.Signin
这道题解了也很久,主要是没仔细看源码
源码为
算了,太长了主要就是登录游戏
- **主程序 (
main)**:- 初始化一个
Game实例。 - 进入主循环,等待用户输入命令并处理。
- 初始化一个
- **日志模块 (
log)**:- 提供了
info!、warn!和error!宏,用于输出带时间戳的日志信息。
- 提供了
- **游戏模块 (
game)**:- 定义了
Game结构体,管理注册用户、当前用户状态和游戏逻辑。 - 提供了以下命令:
register <name> <password>:注册一个新用户。unregister <name>:注销一个用户(仅管理员可用)。sign_in <name> <password>:登录用户。sign_out:登出用户。become_admin:尝试提升为管理员。get_flag:获取 flag(仅管理员可用)。whoami:显示当前用户信息。help:显示帮助信息。quit:退出游戏。
- 定义了
- **用户角色 (
Role)**:Anonymous:未登录用户。Normal:普通用户。Admin:管理员。
- **用户信息 (
Player)**:- 包含用户名、密码和角色。
这是代码逻辑,有个逻辑漏洞
become_admin 逻辑缺陷:
在
become_admin函数中,检查当前用户名是否为root:rust
复制
1
2
3
4if let Some(name) = &self.current_player.name && name == "root" {
self.current_player.role = Role::Admin;
Ok(())
}如果攻击者能够以某种方式将
current_player.name设置为root,就可以绕过密码检查,直接提升为管理员。
这里有个函数是unregister ,虽然说是仅管理员可用,但实际上源码没有限制必须要admin,所以可以先删了root,在注册root
1 | |
得到flag
PRC
…不想写这个的wp
1.Compile it!
有个c文件,在Linux系统运行就好了
1 | |
就这样
2.Run it!
给了个py脚本,运行就有flag
1 | |
JNCTF{f00ffbffb628214bcd63f2b0d9286087}
3.whereisflag?
这是个系列题,有四个flag
先nc连靶机
1 | |
提示cat1在根目录
1 | |
得到flag1,提示用find命令找cat2
1 | |
得到cat2,提示cat3在/bin里,用grep去找
1 | |
得到flag3,最后一个在环境变量里,正常思路了
1 | |
得到cat4。
结束
