DASCTF 2024最后一战 RE wp

前言:期末周 要做课设 还要复习考试 所以今天才复现整理完wp

tryre

真正的签到题!ida打开附件 发现密文和更换的base64码表

img_dasctf1

随后继续看发现异或2

img_das2

所以解密就是异或2然后换码表解码 直接写脚本即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
enc='M@ASL3MF`uL3ICT2IhUgKSD2IeDsICH7Hd26HhQgKSQhNCX7TVL3UFMeHi2?'  
flag=[]
for i in range(len(enc)):
flag.append(ord(enc[i])^2)
print(chr(flag[i]),end='')
print()
import base64
import string
string = "OBCQN1ODbwN1KAV0KjWeIQF0KgFqKAJ5Jf04JjSeIQSjLAZ5VTN1WDOgJk0="
tableBase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
tableNew = "ZYXABCDEFGHIJKLMNOPQRSTUVWzyxabcdefghijklmnopqrstuvw0123456789+/"
flag = base64.b64decode(string.translate(str.maketrans(tableNew, tableBase64)))
print (flag)
b'DASCTF{454646fa-2462-4392-82ea-5f809ad5ddc2}'

黑客不许哭

ida打开附件 交叉引用一下输入的值

黑客不许哭wp

发现是对输入进行了*1.020123456789
往下翻找到比较的地方

黑客不许哭wp-1

最终比较的数据很大 猜测是对输入进行了乘法操作

黑客不许哭wp-2

写个脚本解一下

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
qword_7FF64E34A170 = [  
4358.58716, 6122.2983, 2158.74574, 5973.017537, 9173.840881,
6164.67827, 12293.528276, 4091.327439, 3360.696562, 2403.667017,
3199.455077, 4962.117508, 8266.407604, 2863.062918, 1044.626306,
1067.5308730000002, 3217.476319, 6260.942959, 3278.952568, 160.724197,
596.797742, 3277.973032, 6368.757598, 842.858109, 5925.142209,
3046.937162, 12752.384458, 2442.54747, 1827.164764, 4903.961921,
5619.869598, 3851.247916, 4472.987644, 13135.636855, 1640.630636,
975.429551, 2174.379531, 2289.845471, 2605.707441, 1488.586824,
12216.019619, 4588.270425, 4803.36317, 13035.30263
]
qword_7FF64E34A010 = [
60.51846366284686, 89.4737043286176, 24.031047113523933, 84.68873702464015,
104.66953644646323, 83.75627693648984, 96.41044018110416, 75.27071882034213,
60.33140727998576, 46.10475987767577, 56.28563000222285, 86.68936481373537,
80.87786332435297, 55.29894355978243, 9.261748448423328, 20.6272127322797,
31.189741971747896, 116.18656005122571, 30.859918262868042, 1.0633446004217317,
10.591447767777225, 55.64965261721374, 122.95044769452201, 7.140637105592679,
55.44977106531295, 62.827038867512506, 125.30574894504994, 45.94487116254584,
32.57185367060958, 92.37291765689986, 117.68050783530462, 63.422414786033976,
84.08593452538155, 125.30354189600813, 26.504600725852114, 15.6085145259943,
35.687075116213585, 37.67352051379848, 24.32434117146088, 25.692484908155073,
116.46382825728031, 86.30264794289376, 79.51984419851664, 100.65174601005425
]
qword_7FF64E34A000 = 1.020123456789
flag = []
for i in range(44):
value = (((qword_7FF64E34A170[i]) / qword_7FF64E34A000)-1) / qword_7FF64E34A010[i]
flag.append(chr(int(value)))
print("".join(flag))
#FCXEUH|56378d2n2e4h“792sh/c464.;4f<=;;h8f4;~

解不开 但是已知flag头是DASCTF 直接测试一下 发现和最终的结果差了100左右

黑客不许哭wp-3

修改一下脚本

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
  
test1 = (((ord("D")) * 1.020123456789) + 1) * 60.51846366284686
print(test1)
test2 = (((ord("A")) * 1.020123456789)+ 1) * 89.4737043286176
print(test2)
test3 = (((ord("S")) * 1.020123456789)+ 1) * 24.031047113523933
print(test3)

qword_7FF64E34A170 = [
4358.58716, 6122.2983, 2158.74574, 5973.017537, 9173.840881,
6164.67827, 12293.528276, 4091.327439, 3360.696562, 2403.667017,
3199.455077, 4962.117508, 8266.407604, 2863.062918, 1044.626306,
1067.5308730000002, 3217.476319, 6260.942959, 3278.952568, 160.724197,
596.797742, 3277.973032, 6368.757598, 842.858109, 5925.142209,
3046.937162, 12752.384458, 2442.54747, 1827.164764, 4903.961921,
5619.869598, 3851.247916, 4472.987644, 13135.636855, 1640.630636,
975.429551, 2174.379531, 2289.845471, 2605.707441, 1488.586824,
12216.019619, 4588.270425, 4803.36317, 13035.30263
]
qword_7FF64E34A010 = [
60.51846366284686, 89.4737043286176, 24.031047113523933, 84.68873702464015,
104.66953644646323, 83.75627693648984, 96.41044018110416, 75.27071882034213,
60.33140727998576, 46.10475987767577, 56.28563000222285, 86.68936481373537,
80.87786332435297, 55.29894355978243, 9.261748448423328, 20.6272127322797,
31.189741971747896, 116.18656005122571, 30.859918262868042, 1.0633446004217317,
10.591447767777225, 55.64965261721374, 122.95044769452201, 7.140637105592679,
55.44977106531295, 62.827038867512506, 125.30574894504994, 45.94487116254584,
32.57185367060958, 92.37291765689986, 117.68050783530462, 63.422414786033976,
84.08593452538155, 125.30354189600813, 26.504600725852114, 15.6085145259943,
35.687075116213585, 37.67352051379848, 24.32434117146088, 25.692484908155073,
116.46382825728031, 86.30264794289376, 79.51984419851664, 100.65174601005425
]
qword_7FF64E34A000 = 1.020123456789
flag = []
for i in range(44):
value = (((qword_7FF64E34A170[i]) / qword_7FF64E34A000)-1) / qword_7FF64E34A010[i]
flag.append(chr(int(value)))
print("".join(flag))
#DASCTF{34056b0c-a3d7-71ef-b132-92e8688d4e29}

得到flag

刻板印象

ida打开附件 乍一看逻辑很简单 只有一个异或

刻板印象

写脚本解一下 发现是fake的flag

This_is_clearly_a_fake_flag_so_try_to_find_more.

随后看一下汇编 发现有花 nop掉重新f5即可恢复原本的函数

刻板印象-1

刻板印象-2

发现是一个xtea+异或 写个脚本解一下 还是fakeflag

fakeflag_plz_Try_more_hard_to_find_the_true_flag

于是打算看看函数 发现了一个tls没有用到 起调试跑一下 发现从xtea出来进入了一个新的函数 那个新函数刚好是tls函数中的

刻板印象-3

单步运行到最后 发现跳转到一个新的地址 有很多一段一段的汇编

刻板印象-4

运行一会 问了一下gpt 大概是xxtea
发现密钥{What_is_this_?} delta是0x11451419

刻板印象-6

跑到最后还有一个xor 提取一下 所以总体逻辑就是 xor xtea xor xxtea xor
写逆向脚本即可

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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#define MX (((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4)) ^ ((sum ^ y) + (key[(p & 3) ^ e] ^ z)))
typedef unsigned char BYTE;
unsigned char aLaughterIsPois[] = "Laughter_is_poison_to_fear";
unsigned char xor_xtea_num[48] = {0xDA, 0x30, 0x23, 0xE3, 0xDC, 0x39, 0x82, 0x60, 0xA5, 0x44,
0x68, 0xC2, 0x43, 0x7A, 0xBB, 0xE4, 0x50, 0xE1, 0x02, 0xC2,
0x81, 0x59, 0xEA, 0x1E, 0xC6, 0x8B, 0x71, 0x38, 0x27, 0x83,
0x94, 0xD8, 0xF4, 0x8D, 0x1A, 0x2A, 0x56, 0x8A, 0x4A, 0xD4,
0x54, 0xDC, 0x24, 0x3F, 0xB9, 0xED, 0x7B, 0x9A};
unsigned char xor_xxtea_num[48] = {0x8f, 0x6c, 0xa6, 0x3f, 0x94, 0x3d, 0xf5, 0xd9, 0x36, 0x66, 0x51, 0xd7, 0x66,
0x2f, 0xb3, 0x8f, 0xc0, 0x61, 0x9e, 0xce, 0xe9, 0xd7, 0xe1, 0xbf, 0x13, 0x14,
0x16, 0x14, 0xc2, 0xe7, 0xc3, 0x3a, 0x7f, 0x94, 0xa1, 0xe7, 0x24, 0x0e, 0xa7,
0x5c, 0xd3, 0x77, 0xfe, 0x4f, 0x11, 0xdc, 0x69, 0x23};
void xtea_decrypt(unsigned char *data, size_t length)
{
for (int i = 0; i < 48; i++)
{
data[i] ^= xor_xtea_num[i];
}
unsigned int *v = (unsigned int *)data;
unsigned char key_xtea[] = "{you_find_it_!?}";
unsigned int *v8 = (unsigned int *)key_xtea;
for (int l = 0; l < 12; l += 2)
{
unsigned int v6 = v[l], v5 = v[l + 1], v4 = 0;
unsigned int delta = 0x61C88647;
v4 = -1 * 32 * delta;
for (int i = 0; i < 32; i++)
{
v5 -= (v8[(v4 >> 11) & 3] + v4) ^ (((v6 >> 5) ^ (16 * v6)) + v6);
v4 += delta;
v6 -= (v8[v4 & 3] + v4) ^ (((v5 >> 5) ^ (16 * v5)) + v5);
}
v[l] = v6;
v[l + 1] = v5;
}
for (int i = 0; i < 48; i++)
{
data[i] ^= aLaughterIsPois[i % 26];
}
}
void xxtea_decrypt(uint8_t *data)
{
for (int i = 0; i < 48; i++)
{
data[i] ^= xor_xxtea_num[i];
}
int n = -12;
uint32_t *v = (uint32_t *)data;
unsigned char *key_xxtea = "{What_is_this_?}";
uint32_t *key = (unsigned int *)key_xxtea;
uint32_t y, z, sum;
unsigned p, rounds, e;
unsigned int delta = 0x11451419;
if (n > 1)
{
rounds = 6 + 52 / n;
sum = 0;
z = v[n - 1];
do
{
sum += delta;
e = (sum >> 2) & 3;
for (p = 0; p < n - 1; p++)
{
y = v[p + 1];
z = v[p] += MX;
}
y = v[0];
z = v[n - 1] += MX;
} while (--rounds);
}
else if (n < -1)
{
n = -n;
rounds = 6 + 52 / n;
sum = rounds * delta;
y = v[0];
do
{
e = (sum >> 2) & 3;
for (p = n - 1; p > 0; p--)
{
z = v[p - 1];
y = v[p] -= MX;
}
z = v[n - 1];
y = v[0] -= MX;
sum -= delta;
} while (--rounds);
}
}
int main()
{
unsigned char data[48] = {0x18, 0x09, 0x1C, 0x14, 0x37, 0x1D, 0x16, 0x2D, 0x3C, 0x05,
0x16, 0x3E, 0x02, 0x03, 0x10, 0x2C, 0x0E, 0x31, 0x39, 0x15,
0x04, 0x3A, 0x39, 0x03, 0x0D, 0x13, 0x2B, 0x3E, 0x06, 0x08,
0x37, 0x00, 0x17, 0x0B, 0x00, 0x1D, 0x1C, 0x00, 0x16, 0x06,
0x07, 0x17, 0x30, 0x03, 0x30, 0x06, 0x0A, 0x71};
xxtea_decrypt(data);
xtea_decrypt(data, 48);
for (int i = 0; i < 48; i++)
{
printf("%c", data[i]);
}
}
#DASCTF{You_come_to_me_better_than_all_the_good.}

secret_of_inkey

ida打开附件 打开字符串发现key

img_das3

先放程序里跑一下 得到了别的格子的key 所以应该是每个格子有对应的key 某一个格子会给flag
在查找Please input the key 跟进到主要逻辑的函数

secret_of_inkey

向下翻找到加密函数

secret_of_inkey-1

跟进此函数

secret_of_inkey-2

这里是对密文进行处理 跟密钥与下标的异或值异或 随后进行aes加密 findcrypt也可看出
找密文 发现sub_402350里有大量的数据 计算一下刚好是960个 跟程序里的格子数一样 猜测是密文 写个脚本提取出数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import idc
import idaapi
import idautils
start_address = 0x0000000000420140
end_address = 0x000000000043E1BF
output_file = "1.txt"
def data(start, end, file_path):
with open(file_path, "w") as f:
current_address = start
while current_address <= end:
byte = idc.get_wide_byte(current_address)
f.write(f"{byte:02x}")
current_address += 1
if __name__ == "__main__":
data(start_address, end_address, output_file)

所以可以循环解密 发现密钥则更改密钥再次解密 直到爆破出flag 当时比赛做的时候这个脚本搓了好久没出 赛后看师傅们的wp才搓出来

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
from Crypto.Cipher import AES  
import re

def aes_decrypt(ciphertext, key):
cipher = AES.new(key.encode(), AES.MODE_ECB)
return cipher.decrypt(ciphertext)

def xor_with_key(data, key):
result = bytearray(data)
for i in range(len(data)):
result[i] ^= i ^ ord(key[i % len(key)])
return result

def process_encryption(enc, key):
enc_aes = [enc[i * 32:(i + 1) * 32] for i in range(len(enc) // 32)]
keys = key.copy()

blast = True
while blast:
blast = False
for key_id, key_value in list(keys.items()):
#print(f"{key_id},{key_value}")
de_aes = AES.new(key_value.encode(), AES.MODE_ECB)
for i in enc_aes[:]:
enc1 = xor_with_key(i, key_value)
dec = aes_decrypt(bytes(enc1), key_value)

if dec[:6] == b'key_of':
x = re.findall('key_of_(\d+)_is_"([0-9a-f]+)"', dec.decode())
if x and x[0][0] not in keys:
keys[x[0][0]] = x[0][1]
enc_aes.remove(i)
blast = True

return keys, enc_aes

def final_decrypt(enc_aes, keys):
for key_id, key_value in keys.items():
print(f"{key_id},{key_value}")
for i in enc_aes:
enc1 = xor_with_key(i, key_value)
dec = aes_decrypt(bytes(enc1), key_value)
if all(32 <= b <= 126 for b in dec):
print(f"Key {key_id}: {dec.decode()}")

enc = bytes.fromhex('c9ef...1797') # 这里应该填入密文
key = {'565': '9fc82e15d9de6ef2'}
keys, enc_aes = process_encryption(enc, key)
final_decrypt(enc_aes, keys)

爆破完就能看见各个选项里的值 找到key和flag

secret_of_inkey-3

参考博客:DASCTF 2024最后一战RE题wp-CSDN博客