# 思路

这个程序是一个 32 位的程序,并且是带了 asp 的壳,我还不会手动去壳,所以就用工具把壳去掉了,下面看到主函数

在点进去第一个函数之后就很明显,这是个 RC4 算法的题,而且不难看出,这个 dword_492040 [i] 就是 S 表,在这我将它的名字改位 S [i]

在看第二个函数,也很明显,这个 v1 应该就是密钥了,用 v1 来填充 k 表,但是这里的填充规则是有些改动的,我们需要知道 sub_41A038 的值才能进行计算,我们先不管这个

要注意的是,v1 密钥 “123456” 是字符串的形式,但我们填表是要用十进制的形式的,将 “123456” 转化为十进制之后是这样的

第三个函数是对 S 表的初始置换

第四个函数是计算新 K 表也就是密钥流,用来与明文进行异或运算的,这个 dword_492940 数组就是新 K 表

现在我们退出去,第一行有一个 v3,这个就是我们刚才需要知道的一个值,那它等于多少呢?根据逻辑关系,v3 的值是四个函数下面的 for 循环的限制条件(v3 也是明文的长度),也就是最后一步,即异或运算的循环次数,这个循环次数取决于 v2 数组的长度,而 v2 的长度是 42,所以 v3=42

在最后的 for 循环中,密文也就是 v2,等于 K 表的低位与明文进行异或然后再加 71,那么我们的脚本写出来就是把密文减 71 再与 K 表异或就是我们的明文了

# 脚本

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<iostream>
#include<stdint.h>
using namespace std;
int s[256];
char t[256];
int k[50];
void swap(int* a, int* b)
{
uint8_t tmp;
tmp = *a;
*a = *b;
*b = tmp;
}
void Rc4_Init(uint8_t* key, uint32_t klen)
{
int i, j;
for (i = 0; i < 256; i++)
{
s[i] = i;
t[i] = key[i % klen];
}
j = 0;
for (i = 0; i < 256; i++)
{
j = (j + s[i] + t[i]) % 256;
swap(&s[i], &s[j]);
//交换的函数(可以套用这个模板)
}
}

void __cdecl sub_401619()
{
int v3; // [esp+10h] [ebp-10h]
int v4; // [esp+14h] [ebp-Ch]
int v5; // [esp+18h] [ebp-8h]
int i; // [esp+1Ch] [ebp-4h]
int a2 = 42;
v4 = 0;
v5 = 0;
for (i = 0; a2--; k[v4++] = s[(s[v5] + s[i]) % 256])
{
i = (i + 1) % 256;
v5 = (v5 + s[i]) % 256;
v3 = s[i] + 66;
s[i] = s[v5] - 33;
s[i] ^= 2u;
s[v5] = 5 * v3;
s[v5] = s[i] - 10;
s[v5] += s[i];
s[i] -= 18;
} //加密部分的函数
}

int main()
{
uint8_t v2[42];
uint8_t ket[7] = {49,50,51,52,53,54};
Rc4_Init(ket, 6);
sub_401619();
v2[0] = -61;
v2[1] = -128;
v2[2] = -43;
v2[3] = -14;
v2[4] = -101;
v2[5] = 48;
v2[6] = 11;
v2[7] = -76;
v2[8] = 85;
v2[9] = -34;
v2[10] = 34;
v2[11] = -125;
v2[12] = 47;
v2[13] = -105;
v2[14] = -72;
v2[15] = 32;
v2[16] = 29;
v2[17] = 116;
v2[18] = -47;
v2[19] = 1;
v2[20] = 115;
v2[21] = 26;
v2[22] = -78;
v2[23] = -56;
v2[24] = -59;
v2[25] = 116;
v2[26] = -64;
v2[27] = 91;
v2[28] = -9;
v2[29] = 15;
v2[30] = -45;
v2[31] = 1;
v2[32] = 85;
v2[33] = -78;
v2[34] = -92;
v2[35] = -82;
v2[36] = 123;
v2[37] = -84;
v2[38] = 92;
v2[39] = 86;
v2[40] = -68;
v2[41] = 35;
for (int i = 0; i < 42; i++)
v2[i] = ((v2[i] - 71) ^ (k[i] & 0xff));
printf("%s",v2);
return 0;
}

//DASCTF{Welc0me-t0-j01n-SU-l0ve-suyug1eg1e}

题目来源:DASCTF × SU 2022 —— easyre