SQCTF-RE
RE
慕然回首,那人却在灯火阑珊处
查看迷宫问题
把迷宫导出来
查看代码x <= 8 && maze[10 * x + 10 + y]可得迷宫的尺寸是 9 行 和 10 列
用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
数组逐字节解密。
先看虚拟机如何处理一次“解密过程”:
LOAD 0, 16 寄存器 0 得到 memory[16]
,即加密数据的第 1 个字节:127
XOR 0, 85 对 127 异或 85,计算:
复制编辑
127 ^ 85 = 42
此时寄存器 0 变为 42
STORE 0, 32 将 42 存入内存地址 32
LOAD 1, 32 将内存地址 32 的值加载到寄存器 1,即 42
XOR 1, 170 对 42 异或 170,计算:
复制编辑
42 ^ 170 = 128
此时寄存器 1 变为 128
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 计算 结果 127 255 – 127 = 128 128 131 255 – 131 = 124 124 125 255 – 125 = 130 130 123 255 – 123 = 132 132 135 255 – 135 = 120 120 127 255 – 127 = 128 128 133 255 – 133 = 122 122 123 255 – 123 = 132 132 125 255 – 125 = 130 130 131 255 – 131 = 124 124 127 255 – 127 = 128 128 135 255 – 135 = 120 120 131 255 – 131 = 124 124 123 255 – 123 = 132 132 135 255 – 135 = 120 120 125 255 – 125 = 130 130
于是解密后的数据为:
复制编辑
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。
注意
虽然题目提供的虚拟机代码中只处理了一次操作,但根据描述,整个加密数据需要逐字节还原。
由于 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)
暂无评论