June 11, 2023

SYCTF2023 BabySnake

BabySnake

0x00 Routine Check Shell

无壳32位

image-20230611205224921

0x01 Analyze

main

首先是main函数,重要的其实就三个地方

第一处

生成了固定的种子,目的是为之后的food出现的位置

image-20230611205736620

第二处

sub_7614B0 函数,该函数是我们玩贪吃蛇的主要逻辑,其中我们关心的点就是由我们吃食物生成的数据序列

第三处

而该数据序列会在 sub_7612D0 函数 MD5 后跳flag

sub_7614B0

那么分析明白该函数即可,当然也不用全部分析,只需要分析是如何生成出我们所要的数据序列即可

那么分析该数据序列的心路历程大概是这样

  1. 发现分数到了361随即return
  2. 发现分数是由 sub_761E40 函数返回
  3. sub_761E40 函数是判断蛇是否吃到了food,而就在该函数处理了数据序列(代码在Handler里)
  4. 审计与调试发现数据序列每次都会RC4一遍(密钥是每次的食物位置),同时数据序列的最后两位生成一个新的数据

于是 sub_761E40 函数代码分析为

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
int __thiscall judge_snake_food(_DWORD *this)
{
char v1; // al
_DWORD *v2; // esi
int data_len; // edi
int v4; // ecx
bool v5; // zf
int *v6; // ecx
int *v7; // edx
int v8; // ecx
int v9; // eax
_DWORD *new_tail; // edx
int v11; // eax
int v12; // ecx
int v14; // [esp+0h] [ebp-28h] BYREF
_DWORD *v15; // [esp+10h] [ebp-18h]
char v16; // [esp+16h] [ebp-12h]
char pExceptionObject; // [esp+17h] [ebp-11h]
int *v18; // [esp+18h] [ebp-10h]
int v19; // [esp+24h] [ebp-4h]

v18 = &v14;
v15 = this;
v1 = map[0x14 * this[1] + this[2]];
v19 = 0;
if ( v1 == '$' )
{
socre += 300;
dword_76DEA4[0] = 0;
pExceptionObject = 35;
if ( v16 == 35 )
{
v2 = v15;
data_len = 1;
data[0] = v15[5];
if ( v15[6] )
{
v4 = v15[6];
do
{
data[data_len++] = *(v4 + 20); // data更新为正序蛇身
v4 = *(v4 + 24);
}
while ( v4 );
}
RC4(data_len, food_location); // 根据食物坐标加密
v5 = v2[6] == 0;
v2[5] = LOBYTE(dword_76DEA4[data_len]);


if ( !v5 )
{
v6 = v2 + 6;
v7 = &dword_76DEA4[data_len];
do
{
v8 = *v6;
*(v8 + 20) = *--v7; // 将RC4后的值填入蛇
v6 = (v8 + 24);
}
while ( *v6 );
if ( v2[6] )
{
v9 = (v2 + 6);
do
{
v2 = *v9;
v5 = *(*v9 + 24) == 0;
v9 = *v9 + 24;
}
while ( !v5 );
}
}
new_tail = malloc(0x1Cu);
v11 = key; // 吃到食物后增加尾巴
*new_tail = 0x2A;
new_tail[1] = v2[1];
new_tail[2] = v2[2];
new_tail[3] = new_tail[1];
new_tail[4] = new_tail[2];
new_tail[5] = v11;
v12 = v2[5] - 1;
new_tail[6] = 0;
v2[6] = new_tail;
key = (v11 - 1) ^ v12; // 新的key由 当前要添加的key 和 前一个key生成
}
}
return socre / 300;
}

需要注意的点

image-20230611222135338

0x02 Get Flag

那么既然清楚了数据序列的生成,dump出种子即可生成正确的数据序列

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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
#include <iostream>
#include <string.h>
#include "defs.h"

unsigned char map[] =
{
0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23,
0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23,
0x23, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23,
0x23, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23,
0x23, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23,
0x23, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23,
0x23, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23,
0x23, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23,
0x23, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23,
0x23, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23,
0x23, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23,
0x23, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23,
0x23, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23,
0x23, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23,
0x23, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23,
0x23, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23,
0x23, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23,
0x23, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23,
0x23, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23,
0x23, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23,
0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23,
0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23
};

unsigned char aAbcdefghijklmn[] =
{
0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A,
0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54,
0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x61, 0x62, 0x63, 0x64,
0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E,
0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
0x79, 0x7A, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x00
};

unsigned int get_location(unsigned int seed)
{
unsigned int v8;
unsigned int v9;

srand(seed);
do
{
v8 = rand() % 20;
v9 = rand() % 20;
} while (map[v8 * 20 + v9] != 32);

return (v8 << 8) | v9;
}


int RC4(int len, unsigned int Seed, unsigned char * data )
{

int v8; // ebx
int i; // ecx
int v10 = 0; // esi
int j; // edx
int v12; // ecx
int result; // eax
int v14; // esi
int v15; // edx
int v18; // ecx
unsigned char s[256] = { 0 };
unsigned char k[256] = { 0 };
unsigned char rand_key[256] = { 0 };

for (i = 0; i < 256; i++)
s[i] = i;
srand(Seed);
v8 = (int)((double)rand() / 32767.0 * 256.0);

for (i = 0; i < v8; i++)
{
rand_key[i] = aAbcdefghijklmn[(int)((double)rand() / 32767.0 * 63.0)];
// printf("%c, ", rand_key[i]);
}
for (i = 0; i < 256; ++i)
k[i] = rand_key[i % v8];
for (j = 0; j < 256; ++j)
{
v12 = s[j];
v10 = (v12 + k[j] + v10) % 256;
result = s[v10];
s[j] = result;
s[v10] = v12;
}
v14 = 0;
v15 = 0;
for (i = 0; i < len; i++)
{
v15 = (v15 + 1) % 256;
v18 = s[v15];
v14 = (v18 + v14) % 256;
s[v15] = s[v14];
s[v14] = v18;
data[i] ^= s[(v18 + s[v15]) % 256];
}
return 0;
}

void Reverse(unsigned char* data, int len)
{
int i;
unsigned char tmp[1000] = {0};

for (i = 0; i < len; i++)
tmp[i] = data[i];
for (i = 0; i < len; i++)
data[i] = tmp[len - 1 - i];

}


int main(void)
{
unsigned int seed[] = { 0x0000243E, 0x00004F55, 0x000068BE, 0x00000725, 0x00007BF7, 0x00003D9F, 0x000027C0, 0x00006DC2, 0x0000197C, 0x00003C44, 0x0000447A, 0x000072DC, 0x00000897, 0x000042F1, 0x000046B3, 0x000072AE, 0x000019EE, 0x00006FC9, 0x000063D6, 0x00005D86, 0x00000AE2, 0x00001FB5, 0x000005F5, 0x000032BE, 0x000064B8, 0x000060FB, 0x0000440E, 0x000027EE, 0x000056F6, 0x00007413, 0x00002F8D, 0x00005060, 0x00001110, 0x00004EB6, 0x00001B13, 0x000058C4, 0x00005F44, 0x00005537, 0x00003E76, 0x00002B25, 0x00000EC3, 0x00003E16, 0x00005C09, 0x00000F1C, 0x00005D11, 0x000053D3, 0x00004B1D, 0x00001A44, 0x000076AE, 0x00000900, 0x00000BC7, 0x000004ED, 0x000048F6, 0x0000129A, 0x000047E4, 0x00003715, 0x00002B46, 0x00007C99, 0x0000655B, 0x00002194, 0x00002360, 0x00006CC6, 0x00000DA2, 0x00003796, 0x00004911, 0x000007CD, 0x00004E84, 0x00001C4E, 0x00000D11, 0x00002C93, 0x00003821, 0x000058E9, 0x0000672A, 0x000079C9, 0x00001C36, 0x00002EC1, 0x00002F9C, 0x000051C2, 0x0000529E, 0x000059D4, 0x000027C1, 0x00005081, 0x00002719, 0x00005774, 0x000075ED, 0x00006817, 0x0000544D, 0x00000540, 0x00001898, 0x0000172C, 0x0000300A, 0x00002C52, 0x000014BF, 0x00006DDB, 0x00006CD2, 0x00004CBA, 0x00006387, 0x000054C3, 0x00001499, 0x00003D2B, 0x00006324, 0x00004A5A, 0x000020C9, 0x000072F5, 0x00004EF9, 0x00000A85, 0x00005389, 0x00000633, 0x00000300, 0x00005466, 0x0000363F, 0x00004646, 0x00000E6D, 0x00004275, 0x00006153, 0x00007282, 0x0000598E, 0x000068D3, 0x00007137, 0x00006B26, 0x000062F6, 0x00002DDB, 0x00004CA4, 0x00006E92, 0x000057DA, 0x000010F9, 0x00002026, 0x000036B4, 0x00000BBB, 0x000053BF, 0x000032DA, 0x00000AC4, 0x00001345, 0x00003935, 0x00007876, 0x00001931, 0x00000678, 0x00004F71, 0x0000048B, 0x00002DDB, 0x00002E05, 0x00007768, 0x00004307, 0x00001882, 0x00001FFB, 0x00001F04, 0x000019FE, 0x0000577E, 0x00000FA2, 0x00006177, 0x000058AA, 0x00005AB1, 0x000054A7, 0x000001CE, 0x000017B0, 0x000072BB, 0x00006D7A, 0x000073C9, 0x00006EA4, 0x0000406C, 0x000000F5, 0x000066EA, 0x000022D0, 0x0000387F, 0x0000233E, 0x000007CC, 0x00003331, 0x00000F85, 0x000061EE, 0x00006BB6, 0x000065C3, 0x0000221F, 0x00005B73, 0x00005A70, 0x000039FF, 0x00002D70, 0x000065B3, 0x00006A55, 0x000064A1, 0x00006BD2, 0x000007F1, 0x000022AA, 0x000038AE, 0x000069C8, 0x00004BF5, 0x0000182E, 0x000021B6, 0x00002735, 0x00002A67, 0x000037F2, 0x00001356, 0x000058CB, 0x0000167D, 0x0000346B, 0x00001202, 0x00005DC5, 0x00006CD6, 0x000048C6, 0x00003901, 0x00003DD9, 0x000049A5, 0x0000467B, 0x000061B9, 0x00004368, 0x00000A11, 0x00002125, 0x0000502D, 0x000005F9, 0x00007CDC, 0x00006C91, 0x000008C4, 0x000078E5, 0x00000643, 0x00000115, 0x0000334C, 0x00005253, 0x00003B26, 0x00003A23, 0x00002F3E, 0x00005E67, 0x00003769, 0x0000031D, 0x00003D44, 0x000012B7, 0x0000339A, 0x0000266B, 0x000061F8, 0x000075FF, 0x00001DD4, 0x000012CC, 0x000065EF, 0x00003015, 0x000039E3, 0x00000AE9, 0x000016F6, 0x0000561F, 0x00000CA8, 0x00007330, 0x00002E9B, 0x00004703, 0x000016BF, 0x000031DF, 0x000001F0, 0x00002C1F, 0x00002260, 0x0000555F, 0x00005E8B, 0x0000723B, 0x00002883, 0x000074D4, 0x000038D1, 0x00004EBB, 0x00001148, 0x00007EF2, 0x00000F75, 0x00002519, 0x00005395, 0x00006B12, 0x0000283B, 0x00006093, 0x00003801, 0x00000085, 0x00000A02, 0x00001621, 0x000042F1, 0x00002828, 0x00005801, 0x000002AA, 0x00000A00, 0x00007C38, 0x00007251, 0x00003977, 0x000078A5, 0x00000A68, 0x00007FAB, 0x000016E8, 0x00004810, 0x00007C31, 0x00004474, 0x00004B66, 0x00002E54, 0x0000196A, 0x00006AF6, 0x00001298, 0x000008CB, 0x00005918, 0x000020F1, 0x00006ADA, 0x000005B6, 0x00007487, 0x00002E52, 0x000060EB, 0x00001125, 0x0000309A, 0x00006942, 0x000043E5, 0x00000917, 0x0000515F, 0x00002B62, 0x00005573, 0x00007CE1, 0x00006BE6, 0x00002C55, 0x00004A3E, 0x00007BD4, 0x00000A54, 0x00006580, 0x00002EA8, 0x0000371A, 0x00005633, 0x0000630D, 0x000003BD, 0x00007AE1, 0x00003D0C, 0x00002636, 0x00002866, 0x000042BC, 0x00004338, 0x00007CC0, 0x000062E0, 0x00006D45, 0x000078F3, 0x000071C5, 0x00001E6D, 0x00005308, 0x000045B2, 0x00003BB7, 0x0000314A, 0x0000449C, 0x00007DB7, 0x00004BA2, 0x00003EE0, 0x00003413, 0x000075E2, 0x000061B1, 0x00000A3E, 0x00000D95, 0x000009CA, 0x00004AF4, 0x00004CC7, 0x00000347, 0x0000480C, 0x00002C60, 0x00006528, 0x00005071, 0x000038E3, 0x00007F18, 0x0000728E, 0x000037E1, 0x000072F9, 0x000021EB, 0x00003015, 0x0000418A, 0x0000727D, 0x0000241D, 0x00002483, 0x00007B71, 0x00006676, 0x00002D6A, 0x00007A36, 0x000041CA };
unsigned int location_food;
unsigned char data[500] = { 0 };
data[0] = 0x02;
data[1] = 0xBC;
data[2] = 0x02;
int i, j, len, key;

for (i = 0; i < 361; i++)
{
len = i + 3;
location_food = get_location(seed[i]);
printf("\nfood: %X\n", location_food);

RC4(len, location_food, data);
Reverse(data, len);
if (len == 3)
{
data[i + 3] = 0x92;
key = (data[i + 3] - 1) ^ (data[i + 2] - 1);
}
else
{
data[i + 3] = key;
key = (data[i + 3] - 1) ^ (data[i + 2] - 1);
}
for (j = 0; j < len + 1; j++)
printf("%02x, ", data[j]);
printf("\n");

}
printf("\n");
Reverse(data, 364);
for (i = 1; i < 362; i++)
printf("%02x", data[i]);
printf("\n");

return 0;
}
// SYC{528a122ae49dea3505a184b44859fb9f}
DASCTF X SU
🍬
HFCTF2022
🍪

About this Post

This post is written by P.Z, licensed under CC BY-NC 4.0.