2023国赛华南赛区 部分题解
from XIerluo
被师傅们打烂了呜呜呜,最后就解出来一个签到RE题呜呜呜
但是面基师傅们很开心,我直接吃吃吃吃吃吃吃吃吃吃吃吃吃吃吃吃吃吃
茶歇区嘿嘿嘿……
RE
签个到
这题呢,主要由两个部分:RC4 和 Base64的 3个8位 转 4个6位 的加密构成
这部分看起来很复杂,其实就是用m128i来做rc4的box的初始化
最后一次swap用xor实现的
加密也没有用xor,而是简单的add
这一部分,认真看密文发现长度才57,根本走的不是上面那堆乱七八糟的东西
走的是下面的位转
v18 = put_data2 + 1;
*(v18 - 1) = v2 + 0x20;
if ( v2 )
{
now_index = 0LL;
do
{
v18 += 4;
data1 = input_str[now_index];
*(v18 - 4) = (data1 >> 2) + 0x20;
data2 = input_str[now_index + 1];
*(v18 - 3) = ((data2 >> 4) | (0x10 * data1) & 0x30) + 32;
data3 = input_str[now_index + 2];
now_index += 3LL;
*(v18 - 1) = (data3 & 0x3F) + 32;
*(v18 - 2) = ((data3 >> 6) | (4 * data2) & 0x3C) + 32;
}
while ( v2 > (int)now_index );
}
*v18 = 10;
第一位是加密后总长度+0x20
最后一位是10
中间加密段和b64的加密逻辑基本一模一样,虽然没有b64换表那一步,但也就是打乱了一点点
所以exp如下
def rc4(plain: list, key: str) -> list:
box = list(range(256))
j = 0
for i in range(256):
j = (j + box[i] + ord(key[i % len(key)])) % 256
box[i], box[j] = box[j], box[i]
print(box)
# print(type(box)) #for_test
# return box
res = []
i = j = 0
for s in plain:
i = (i + 1) % 256
j = (j + box[i]) % 256
box[i], box[j] = box[j], box[i]
t = (box[i] + box[j]) % 256
k = box[t]
res.append(chr((s - k) & 0xff))
return res
flag_base_data = [74, 35, 40, 61, 75, 70, 50, 73,
45, 48, 62, 70, 92, 46, 51, 51,
68, 74, 70, 77, 84, 42, 71, 39,
65, 82, 53, 53, 34, 32, 57, 58,
69, 93, 43, 42, 39, 44, 51, 85,
40, 94, 80, 50, 53, 61, 58, 95,
65, 92, 88, 83, 62, 59, 50, 93,
48]
print(len(flag_base_data))
get_str = ""
for i in flag_base_data[1:]:
get_str += bin(i - 32)[2:].zfill(6)
get_list = []
for i in range(0, len(get_str), 8):
get_list.append((int("0b" + get_str[i:i + 8], 2)))
print(get_list)
base_list = rc4(get_list, "CISCN_easy_reverse")
print("".join([i for i in base_list]))
flag:flag{2440c07c-a624-3603-3764-7ecb421f7f3c}