Warning: opendir(/www/wwwroot/liuye.space/wp-content/cache/db/singletables//76b/dcd): Failed to open directory: No such file or directory in /www/wwwroot/liuye.space/wp-content/plugins/w3-total-cache/Util_File.php on line 158
SQCTF-RE - 烨的小世界 ❤ 烨的小世界
boxmoe_header_banner_img

欢迎来到烨的世界~

加载中

文章导读

SQCTF-RE


avatar
liuye 2025年4月21日 21

RE

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

查看迷宫问题

把迷宫导出来

查看代码x <= 8 && maze[10 * x + 10 + y]可得迷宫的尺寸是 910

用python打印出来

# 迷宫字符串
maze_str = (
    "S**#########*########**#########**#########*###**##***###**##*#####**##*#####*E##*******############"
)

# 每行的字符数
characters_per_row = 10

# 打印迷宫
for i in range(0, len(maze_str), characters_per_row):
    print(maze_str[i:i+characters_per_row])

迷宫如下,不算复杂,手对照解

S**#######

##*#######

#**#######

##**######

###*###**#

#***###**#

#*#####**#

#*#####*E#

#*******##

ezRe

pyinstxtractor.py 33.exe

在线网站反编译pyc

https://tool.lu/pyc

Base64解密5ed2be45-2e83-48d2-b631-c088e51ee964

鹅鹅鹅,曲项向天歌

pyinstxtractor.py eee.exe

在线网站解码pyc

https://tool.lu/pyc

简单逆向

def decrypt_flag():
    ciphertext = 'itd~tzw_know_sanmenxbZ8'
    part2_1_enc = ciphertext[:7]
    part2_2_enc = ciphertext[7:20]
    part2_3_enc = ciphertext[20:]
    part2_1 = ''.join([chr(ord(c) - 5) for c in part2_1_enc])
    part2_2 = part2_2_enc
    part2_3 = ''.join([chr(ord(c) + 7) for c in part2_3_enc])
    part2 = part2_1 + part2_2 + part2_3
    flag = 'SQCTF{' + part2 + '}'
    return flag

decrypted_flag = decrypt_flag()
print("解密后的flag是:", decrypted_flag)
# SQCTF{do_your_know_sanmenxia?}
 

圣人当仁不让

分析代码先经过vm_execute加密再经过base64加密

Exp:

import base64

def reverse_vm_execute(data):
    decrypted_data = bytearray(data)
    for i in range(min(len(decrypted_data), 17)):
        decrypted_data[i] = (decrypted_data[i] + 2) % 256
        decrypted_data[i] = (decrypted_data[i] - 5) % 256
        decrypted_data[i] = decrypted_data[i] ^ 0xAA
    return bytes(decrypted_data)

encoded_str = "/P7sAe/U0s7c1vjb0vjfyt=="
decoded_data = base64.b64decode(encoded_str)
final_data = reverse_vm_execute(decoded_data)
print("Decrypted Data:", final_data.decode('utf-8', 'ignore'))

往事暗沉不可追

Ai一把梭

分析 VM 代码

题目提供了一个简单的虚拟机(SimpleVM),它支持三条指令:

  • LOAD reg, addr:将内存地址 addr 的值加载到寄存器 reg
  • XOR reg, value:将寄存器 reg 的值与 value 异或
  • STORE reg, addr:将寄存器 reg 的值写回内存地址 addr

程序执行的 bytecode 为:

vbnet
复制编辑
LOAD  0, 16
XOR   0, 85
STORE 0, 32
LOAD  1, 32
XOR   1, 170
STORE 1, 48

并且题目将一个 16 字节的数组

ini
复制编辑
encrypted_data = [127, 131, 125, 123, 135, 127, 133, 123, 125, 131, 127, 135, 131, 123, 135, 125]

加载到了内存地址 16 开始的位置。

分步模拟指令

注意:题目的代码中 execute 函数并没有用循环处理所有指令,而只执行了一组指令(实际上只处理了第一条数据)。但根据题目的描述,“解密后的数据就是 flag”,很可能是要求对整个 encrypted_data 数组逐字节解密。

先看虚拟机如何处理一次“解密过程”:

  1. LOAD 0, 16
    寄存器 0 得到 memory[16],即加密数据的第 1 个字节:127
  2. XOR 0, 85
    对 127 异或 85,计算:
复制编辑
127 ^ 85 = 42

此时寄存器 0 变为 42

  1. STORE 0, 32
    将 42 存入内存地址 32
  2. LOAD 1, 32
    将内存地址 32 的值加载到寄存器 1,即 42
  3. XOR 1, 170
    对 42 异或 170,计算:
复制编辑
42 ^ 170 = 128

此时寄存器 1 变为 128

  1. STORE 1, 48
    将 128 存入内存地址 48

观察这两次 XOR 操作:

  • 第一次 XOR 用的是 85
  • 第二次 XOR 用的是 170

实际上,对于任意一个字节 x,有
  (x ^ 85) ^ 170 = x ^ (85 ^ 170)
而 85 ^ 170 = 255
因此整体操作相当于:
  decrypted = encrypted ^ 255

注意到 8 位数与 255 异或,相当于按位取反(即 ~x,对于 8 位数据,~x = 255 – x)。

应用于整个 encrypted_data

题目中有 16 个字节,加密数据为:

复制编辑
127, 131, 125, 123, 135, 127, 133, 123, 125, 131, 127, 135, 131, 123, 135, 125

对每个字节 x 进行操作 x ^ 255 得到:

加密字节 x计算结果
127255 – 127 = 128128
131255 – 131 = 124124
125255 – 125 = 130130
123255 – 123 = 132132
135255 – 135 = 120120
127255 – 127 = 128128
133255 – 133 = 122122
123255 – 123 = 132132
125255 – 125 = 130130
131255 – 131 = 124124
127255 – 127 = 128128
135255 – 135 = 120120
131255 – 131 = 124124
123255 – 123 = 132132
135255 – 135 = 120120
125255 – 125 = 130130

于是解密后的数据为:

复制编辑
128,124,130,132,120,128,122,132,130,124,128,120,124,132,120,130

题目说明“解密后的数据就是 flag,用逗号隔开”,并且要求 flag 的格式为 SQCTF{...}

得出 flag

综合上述步骤,最终 flag 就是将解密后的数字直接用逗号分隔后放在 SQCTF{} 内:

复制编辑
SQCTF{128,124,130,132,120,128,122,132,130,124,128,120,124,132,120,130}

这就是本题的 flag。


注意

  1. 虽然题目提供的虚拟机代码中只处理了一次操作,但根据描述,整个加密数据需要逐字节还原。
  2. 由于 XOR 的结合律,先 XOR 85 后 XOR 170 相当于直接 XOR 255,即对每个字节取反。

你可以用 Python 快速验证:

python
复制编辑
encrypted_data = [127, 131, 125, 123, 135, 127, 133, 123, 125, 131, 127, 135, 131, 123, 135, 125]
decrypted = [x ^ 255 for x in encrypted_data]
print(decrypted)
# 输出: [128, 124, 130, 132, 120, 128, 122, 132, 130, 124, 128, 120, 124, 132, 120, 130]

最终提交 flag 为:

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

春风也有春风愁

Ida分析

v7 = (v8 ^ 0xA5) + 55然后和v6去比较

v6=70FBF715FA08FD0B0D0F0E011431130DFB

但是解出来的值不对

回去尝试用前半段去解

发现解出来是逆逆序,sqctf{ea

后一段逆序解出来的是asy_xor}

猜测可能是sqctf{easy_xor}

v6_hex = “70FBF715FA08FD0B0D”
v7_hex = “0F0E011431130DFB”
v6_bytes = bytes.fromhex(v6_hex)
v7_hex = bytes.fromhex(v7_hex)

flag = “”
flag1 = “”
for b in v6_bytes:
    decrypted = ((b – 55) % 256) ^ 0xA5
    flag += chr(decrypted)
flag=flag[::-1]

for b in v7_hex:
    decrypted = ((b – 55) % 256) ^ 0xA5
    flag1 += chr(decrypted)

flag1=flag1[::-1]
print(“Recovered flag:”, flag,flag1)

回想了一下应该是段序问题,当时64位一看没想过这个问题

遇事不决,可问春风

有个亦或函数result.append((char) (c ^ 'B'));

拼接了一个字符串

“SQCTF{i_am_a_” + password + FLAG_SUFFIX;

Key给了=66

encrypted_parts = [“5”, “#”, “)”, “7”, “5”, “#”, “)”, “7”]
encrypted = ”.join(encrypted_parts)
xor_key = 66
decrypted = ”.join([chr(ord(c) ^ xor_key) for c in encrypted])
flag = f”SQCTF{{i_am_a_{decrypted}}}”
print(“Flag 是:”, flag)

你若安好便是晴

题目提示喝杯

用findcrypt识别一下

分析一下代码,先经过tea再经过sub_100

查看tea发现有挺多魔改

魔改了魔数和加密过程还有加密符号

再查看sub_100是一个亦或算法

回去查看main函数,发现没有比较,下个断点flag就出来了

人生自古谁无死

分析一下代码,程序没有输入判断,猜测程序可能存在自解密

但是有反调试

看了一下加密逻辑主要在handle_strings

Puts是个输出函数

在check之前下个断点

把rip栈针改到handle_strings()的位置

在ret的位置下个断点

运行一下,v13就是flag

天下谁人不识君

简单逆向爆破所有字符去做比较

s = ‘wesyvbniazxchjko1973652048@$+-&*<>’
result = ‘v7b3boika$h4h5j0jhkh161h79393i5x010j0y8n$i’

flag = ”

for i in range(0, len(result), 2):
    c1 = result[i]
    c2 = result[i+1]
    index = i // 2
    found = False
    for c in range(32, 127):
        s1 = c // 17
        s2 = c % 17
        e1 = s[(s1 + index) % 34]
        e2 = s[-(s2 + index + 1) % 34]
        if e1 == c1 and e2 == c2:
            flag += chr(c)
            found = True
            break
    if not found:
        flag += ‘?’  # 标记未匹配的字符

print(‘Recovered flag:’, flag)

不劳春风解我忧

Xxtea_encrypt字符没有删除,猜测xxtea

V=是key

Block是密文

直接上板子出来了

#include <stdio.h>

#include <stdint.h>

#include <string.h>

#define DELTA 0x9e3779b9

void xxtea_decrypt(uint32_t *v, int n, uint32_t *key) {

    uint32_t y, z, sum;

    int p, rounds, e;

    rounds = 6 + 52 / n;

    sum = rounds * 0x9E3779B9; 

    y = v[0];

    do {

        e = (sum >> 2) & 3;

        for (p = n – 1; p > 0; p–) {

            z = v[p – 1];

            v[p] -= ((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4)) ^ ((sum ^ y) + (key[(p & 3) ^ e] ^ z));

            y = v[p];

        }

        z = v[n – 1];

        v[0] -= ((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4)) ^ ((sum ^ y) + (key[(p & 3) ^ e] ^ z));

        y = v[0];

        sum -= 0x9E3779B9; 

    } while (sum != 0); 

}

int main() {

    uint32_t key[4] = {0x12345678 ,0x9ABCDEF0 ,0xFEDCBA98 ,0x87654321};

    uint32_t data[] = {0x8F748963 ,0xCB1D96A8};

    int data_len = sizeof(data) / sizeof(data[0]);

    printf(“Original Data:\n”);

    for (int i = 0; i < data_len; i++) {

        printf(“%u\n”, data[i]);

    }

    xxtea_decrypt(data, data_len, key);

    printf(“Decrypted Data (Printable Characters):\n”);

    for (int i = 0; i < data_len; i++) {

        char c = (char)data[i];

       printf(“%c%c%c%c”,*((char*)&data[i]+0),*((char*)&data[i]+1),*((char*)&data[i]+2),*((char*)&data[i]+3));//这个地方也是很重要的

    }

    printf(“\n”);

    return 0;

}

即随本心

pyinstxtractor.py 即随本心.exe

丢在线网站

https://tool.lu/pyc

简单看了一下,经过aes再经过base64

Key和iv都给了,直接上脚本

from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
import base64

# 给定的数据
expected_encrypted_data = ‘MTIzNDU2Nzg5MGFiY2RlZpOn0SHxbVMvaa7jQztMCBtCCiuX+ZRBzSfcL01St5Bmi8BjGeuXliictrjqzSpCGw==’

# 解码base64
decoded_data = base64.b64decode(expected_encrypted_data)

# 提取IV和密文
iv = decoded_data[:16]  # 前16字节是IV
ciphertext = decoded_data[16:]  # 剩余部分是密文

# 使用相同的密钥
key = b’1234567890abcdef’

# 创建AES解密器
cipher = AES.new(key, AES.MODE_CBC, iv)

# 解密
padded_plaintext = cipher.decrypt(ciphertext)

# 去除填充
try:
    plaintext = unpad(padded_plaintext, AES.block_size)
    print(“解密成功!Flag是:”, plaintext.decode(‘utf-8’))
except ValueError:
    print(“解密失败,可能是填充不正确”)

唧唧复唧唧,木兰当户织

Ida打开看了一下有upx

Upx-d 唧唧复唧唧,木兰当户织.exe

查看代码,就一个base64

随波逐流SQCTF{xixibuxixi,mulandanghuzhi}把中文字改成英文字符

看山不是山

pyinstxtractor.py 看水不是水.exe

丢在线网站https://tool.lu/pyc/

可以看出是伪随机,没学过,ai一把梭

def decrypt(encrypted_data):
    result = []
    key = 439041101  # 0x1A2B3C4D
    for i in range(len(encrypted_data)):
        byte = encrypted_data[i]
        # 逆向加法操作
        byte = (byte - i) & 255
        # 逆向异或操作
        byte = (byte ^ (key >> ((i % 4) * 8))) & 255
        result.append(byte)
    return bytes(result)

# 目标加密数据
target = bytes.fromhex('738495a6b7c8d9e0f123456789abcdef')

# 解密得到原始输入
original_data = decrypt(target)
print("原始输入:", original_data)
print("十六进制:", original_data.hex())

SQCTF{3ebfb8b9fefff8c3a426104630a294fa}

击败abyssun

呜呜呜,被游戏逆向思维误导了

一直搁那搜血量,干了一个小时

后面搜红温了才想起来flag头固定

直接用CE搜SQCTF

拉下来改长度50



评论(0)

查看评论列表

暂无评论


发表评论