Super Brain

点击此处获得更好的阅读体验


WriteUp来源

https://mp.weixin.qq.com/s/AzUrC5JD-bVb8mDL0JB4bQ

题目描述

We are performing a rapid chain reaction on S32R274. 附件下载 提取码(GAME)

题目考点

  • PPC逆向

  • CAN Bus分析

  • S32R294芯片驱动分析

解题思路

官方WP

本题是汽车常用架构Power PC芯片的逆向题,其中还包含CAN通讯流量分析以及一个趣味谜题。

因此主要考察S32R294芯片的驱动理解,流量分析能力以及游戏谜题逆向能力。

趣味谜题

本题中使用了最强大脑第七季节目中的多米诺效应的谜题,视频第35分钟有动画介绍

https://m.iqiyi.com/v_19rzjtl830.html

7 * 7的棋盘中部署着上下左右四种指针,奇数行的棋格倍触发指针顺时针旋转,偶数行则逆时针旋转。

用户从最左排的七个棋格中选择一个触发,当指针旋转后将触发被指向的棋格,直到触发到边界,如果最终触发在右边界则为成功。

gmmap.py用于生产一系列唯一解的题目,gmmap.exe可以可视化的玩一下这个谜题。

逆向部分

Power PC参赛选手考虑到接触比较少,为了降低难度本题提供elf进行过渡

逆向时从main函数入手,程序流程并不复杂

对IO和时钟以及CAN初始化后,会依次调用receiveGame,receiveAnswer和checkAnswer

逆向的难点主要有两个:

一是要根据提示,下载S32R274的Reference Manual来明白关于CAN模块的收发操作,好在真正收发CAN的操作代码很简短

https://www.nxp.com/webapp/Download?colCode=S32R274RM&location=null NXP官网注册账号后下载

二是对于后续需要知道一些有初始值的全局变量,要通过读startup,来知道存放在.data位置,从而得知初始值

对数据敏感的参赛者可以不分析,直接感知出变量和静态初始值的偏移

receiveGame用于接收36道谜题,CAN ID为0x100

这个谜题是有7 * 7的棋盘组成,由许多个CAN报文中的前7个字节拼成,一共35 * 7个报文,代码如下

receiveAnswer用于接收36道题的题解,通过接收5个0x100的报文来获得解,每个题的题解应该是0~6

36道题的题正确解是4 6 4 6 6 4 3 3 6 2 2 2 4 1 0 5 1 1 2 6 1 2 3 6 6 6 3 1 4 4 5 1 6 1 6 3

checkAnswer来检查36道题全部解答正确

runGame来运行多米诺效应游戏

最终如果36个解答都是正确的,则会输出答案

CAN通讯部分

题目给出的CAN通讯流量ASC文件,已经将36个解和FLAG抹去

由逆向部分可知,先要从流量中36 * 7个报文里提取出36个谜题棋盘的布置如下

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
[[1, 0, 0, 0, 0, 0, 0], [3, 0, 2, 2, 3, 1, 3], [1, 3, 2, 1, 2, 2, 1], [3, 2, 3, 1, 0, 1, 0], [3, 3, 0, 1, 2, 1, 0], [0, 3, 2, 2, 2, 1, 3], [2, 2, 2, 2, 1, 2, 3]]
[[0, 0, 0, 0, 0, 1, 0], [0, 2, 2, 2, 1, 1, 1], [0, 2, 3, 2, 2, 0, 1], [0, 3, 1, 0, 2, 0, 1], [0, 0, 2, 1, 3, 1, 1], [3, 0, 1, 2, 2, 0, 2], [3, 3, 3, 0, 2, 3, 3]]
[[0, 2, 2, 0, 0, 2, 1], [1, 3, 0, 3, 1, 0, 2], [0, 1, 1, 0, 2, 3, 3], [3, 1, 0, 0, 2, 0, 2], [3, 3, 3, 3, 3, 2, 1], [3, 3, 0, 0, 3, 2, 2], [0, 2, 3, 1, 2, 1, 0]]
[[3, 2, 1, 3, 0, 1, 1], [1, 0, 2, 0, 1, 1, 1], [1, 0, 0, 3, 2, 2, 0], [1, 3, 2, 2, 1, 2, 1], [0, 1, 3, 3, 1, 3, 1], [2, 3, 2, 0, 2, 1, 3], [3, 2, 0, 3, 3, 2, 1]]
[[1, 0, 0, 0, 2, 2, 2], [1, 3, 0, 3, 3, 0, 1], [3, 3, 3, 1, 0, 3, 1], [2, 1, 0, 1, 0, 0, 2], [3, 0, 0, 2, 2, 3, 1], [3, 3, 0, 1, 2, 1, 1], [3, 3, 3, 0, 0, 3, 0]]
[[1, 2, 1, 0, 1, 1, 0], [2, 3, 3, 3, 0, 1, 0], [3, 3, 2, 1, 3, 3, 2], [1, 2, 0, 0, 1, 3, 3], [0, 3, 1, 1, 0, 3, 3], [0, 2, 3, 1, 2, 2, 3], [0, 0, 2, 0, 3, 2, 3]]
[[1, 2, 0, 2, 0, 0, 3], [3, 2, 3, 3, 3, 0, 2], [2, 0, 1, 2, 1, 0, 1], [2, 3, 2, 1, 2, 3, 3], [2, 0, 2, 3, 2, 0, 2], [3, 3, 1, 1, 2, 1, 2], [0, 0, 3, 3, 3, 1, 2]]
[[1, 2, 2, 2, 3, 1, 1], [0, 2, 0, 2, 2, 3, 2], [3, 3, 3, 2, 3, 2, 3], [3, 0, 2, 0, 2, 2, 3], [0, 2, 2, 2, 1, 2, 1], [2, 3, 2, 1, 2, 0, 0], [0, 0, 3, 3, 0, 3, 3]]
[[0, 0, 0, 1, 3, 3, 3], [2, 3, 1, 0, 0, 1, 2], [0, 0, 0, 2, 2, 0, 1], [2, 2, 2, 2, 0, 0, 3], [0, 3, 3, 0, 0, 1, 3], [0, 1, 3, 1, 2, 0, 1], [0, 3, 2, 2, 2, 2, 2]]
[[0, 0, 0, 0, 2, 3, 0], [2, 1, 0, 0, 3, 3, 1], [3, 1, 3, 1, 1, 2, 1], [0, 2, 2, 3, 3, 1, 2], [3, 0, 2, 0, 2, 1, 2], [1, 2, 2, 1, 3, 1, 3], [1, 2, 3, 3, 1, 2, 1]]
[[3, 1, 3, 1, 0, 1, 1], [0, 3, 3, 3, 0, 3, 2], [0, 1, 3, 3, 0, 1, 3], [3, 3, 2, 0, 2, 0, 1], [0, 0, 0, 1, 3, 2, 1], [3, 3, 0, 2, 3, 0, 3], [0, 2, 3, 3, 2, 3, 1]]
[[3, 2, 1, 0, 0, 1, 1], [1, 3, 3, 1, 0, 3, 3], [0, 0, 0, 0, 2, 3, 2], [3, 2, 3, 3, 2, 2, 0], [0, 0, 1, 0, 0, 3, 2], [2, 1, 2, 3, 2, 1, 2], [0, 3, 2, 3, 2, 3, 0]]
[[0, 2, 0, 1, 2, 2, 3], [0, 2, 2, 1, 3, 1, 3], [2, 0, 3, 2, 3, 1, 2], [2, 3, 0, 2, 0, 0, 2], [3, 0, 1, 0, 1, 3, 2], [0, 1, 2, 2, 1, 1, 2], [3, 0, 3, 1, 3, 3, 2]]
[[2, 0, 3, 0, 1, 0, 0], [3, 3, 2, 3, 0, 2, 0], [3, 0, 0, 2, 0, 2, 1], [0, 3, 0, 3, 2, 3, 0], [0, 1, 2, 2, 3, 2, 0], [2, 2, 1, 0, 2, 3, 1], [1, 2, 3, 1, 3, 2, 3]]
[[0, 0, 0, 0, 0, 2, 2], [0, 1, 3, 1, 0, 2, 0], [1, 1, 0, 1, 3, 0, 3], [3, 3, 1, 3, 1, 1, 2], [3, 0, 1, 0, 1, 2, 3], [2, 3, 2, 3, 1, 3, 1], [3, 2, 0, 2, 1, 1, 0]]
[[1, 0, 1, 0, 1, 0, 2], [3, 2, 3, 1, 3, 2, 0], [0, 1, 0, 2, 1, 2, 1], [2, 2, 0, 2, 3, 3, 0], [2, 0, 2, 3, 2, 0, 2], [3, 2, 2, 1, 2, 0, 0], [3, 2, 2, 3, 3, 2, 0]]
[[2, 2, 1, 3, 0, 0, 0], [3, 0, 1, 0, 2, 2, 0], [0, 2, 3, 0, 0, 1, 2], [3, 3, 1, 0, 0, 3, 0], [3, 1, 2, 2, 0, 3, 3], [0, 2, 0, 2, 3, 0, 1], [3, 2, 3, 1, 0, 1, 2]]
[[2, 2, 2, 1, 2, 2, 3], [3, 3, 0, 2, 2, 3, 1], [3, 1, 3, 1, 1, 0, 2], [0, 3, 2, 0, 0, 2, 0], [0, 0, 1, 1, 3, 3, 2], [1, 2, 3, 0, 2, 2, 1], [2, 2, 3, 2, 1, 0, 3]]
[[1, 1, 0, 1, 2, 3, 3], [2, 3, 3, 0, 3, 2, 0], [3, 3, 0, 1, 0, 0, 0], [1, 0, 1, 3, 3, 1, 1], [2, 3, 2, 0, 2, 0, 2], [2, 1, 1, 0, 1, 0, 3], [0, 3, 2, 3, 0, 3, 3]]
[[0, 0, 0, 3, 2, 0, 0], [1, 3, 0, 0, 3, 3, 1], [0, 1, 2, 1, 1, 1, 3], [3, 1, 1, 1, 2, 3, 3], [3, 2, 1, 2, 1, 2, 0], [1, 2, 2, 3, 3, 1, 0], [0, 3, 0, 3, 2, 3, 3]]
[[3, 1, 0, 0, 1, 0, 1], [3, 3, 3, 1, 2, 1, 0], [3, 1, 0, 2, 3, 0, 2], [0, 2, 2, 2, 1, 0, 0], [0, 0, 0, 1, 1, 2, 0], [1, 2, 2, 1, 0, 2, 2], [0, 3, 0, 2, 0, 0, 3]]
[[3, 0, 3, 1, 3, 2, 0], [3, 0, 0, 3, 3, 2, 2], [3, 0, 3, 3, 1, 2, 1], [3, 2, 3, 3, 3, 3, 0], [0, 0, 0, 3, 0, 1, 1], [2, 0, 3, 1, 3, 2, 0], [1, 0, 2, 2, 2, 1, 1]]
[[2, 2, 0, 3, 1, 0, 1], [1, 3, 1, 2, 3, 1, 1], [2, 0, 1, 3, 3, 2, 2], [3, 3, 3, 3, 3, 1, 0], [3, 0, 3, 3, 0, 0, 3], [0, 2, 0, 1, 1, 2, 1], [1, 3, 3, 0, 0, 2, 0]]
[[0, 2, 0, 1, 2, 2, 0], [3, 3, 2, 0, 1, 3, 3], [2, 2, 2, 1, 2, 1, 3], [0, 3, 3, 2, 0, 1, 2], [0, 3, 2, 0, 0, 2, 1], [3, 2, 1, 1, 2, 3, 1], [3, 3, 3, 3, 3, 3, 0]]
[[1, 0, 2, 1, 0, 0, 2], [1, 3, 3, 0, 0, 1, 0], [0, 0, 2, 1, 0, 2, 3], [3, 2, 3, 0, 1, 1, 0], [3, 3, 2, 3, 0, 3, 0], [3, 2, 0, 2, 1, 2, 1], [3, 3, 0, 3, 0, 0, 2]]
[[3, 1, 2, 3, 3, 0, 1], [3, 2, 2, 0, 3, 0, 2], [0, 3, 1, 1, 2, 0, 2], [2, 3, 2, 1, 0, 0, 2], [1, 1, 2, 0, 0, 1, 2], [2, 2, 1, 2, 0, 2, 1], [0, 0, 0, 0, 3, 3, 0]]
[[0, 1, 0, 2, 3, 2, 0], [2, 3, 0, 3, 1, 3, 1], [1, 2, 2, 2, 1, 0, 3], [3, 1, 2, 1, 1, 0, 1], [0, 2, 0, 3, 3, 2, 0], [3, 3, 2, 1, 2, 0, 3], [3, 0, 0, 3, 0, 0, 3]]
[[2, 0, 0, 2, 1, 1, 0], [3, 3, 0, 2, 3, 0, 3], [3, 2, 0, 1, 1, 1, 1], [0, 2, 3, 1, 0, 3, 1], [0, 3, 1, 3, 1, 0, 3], [3, 1, 2, 2, 0, 3, 0], [1, 3, 0, 0, 3, 2, 2]]
[[2, 3, 3, 1, 0, 3, 2], [2, 3, 0, 2, 0, 1, 3], [0, 2, 2, 3, 0, 2, 2], [2, 2, 0, 1, 1, 1, 3], [0, 3, 1, 2, 3, 1, 0], [3, 2, 2, 1, 1, 2, 1], [1, 1, 1, 2, 0, 0, 0]]
[[0, 0, 2, 3, 1, 0, 1], [2, 0, 3, 0, 1, 0, 2], [3, 2, 0, 3, 3, 1, 0], [1, 3, 0, 0, 1, 0, 3], [3, 0, 3, 2, 1, 3, 1], [3, 1, 1, 1, 1, 0, 2], [1, 0, 3, 2, 0, 3, 0]]
[[2, 2, 2, 1, 0, 1, 1], [3, 0, 0, 3, 1, 2, 1], [3, 3, 3, 1, 3, 1, 1], [0, 2, 2, 1, 1, 0, 0], [2, 2, 3, 3, 3, 0, 1], [2, 2, 1, 3, 2, 2, 0], [2, 0, 3, 0, 0, 3, 3]]
[[3, 2, 0, 1, 1, 0, 1], [3, 0, 0, 3, 2, 2, 1], [0, 1, 3, 3, 3, 1, 1], [3, 2, 2, 3, 3, 0, 1], [3, 1, 3, 0, 1, 0, 3], [2, 1, 0, 1, 1, 1, 2], [1, 1, 2, 3, 2, 1, 0]]
[[1, 1, 2, 0, 3, 2, 1], [3, 1, 3, 0, 0, 3, 1], [3, 0, 1, 2, 0, 0, 3], [2, 2, 3, 2, 3, 1, 3], [2, 2, 3, 3, 3, 1, 2], [3, 2, 3, 3, 0, 1, 0], [3, 3, 2, 2, 0, 3, 3]]
[[2, 1, 3, 0, 2, 2, 0], [3, 1, 3, 2, 0, 0, 3], [0, 2, 3, 3, 3, 2, 0], [2, 3, 0, 1, 3, 1, 2], [0, 1, 1, 2, 2, 1, 2], [0, 3, 1, 2, 1, 3, 2], [0, 3, 2, 3, 1, 0, 1]]
[[3, 3, 1, 3, 3, 0, 2], [1, 2, 1, 3, 0, 2, 3], [0, 1, 2, 3, 1, 1, 2], [2, 1, 0, 3, 0, 2, 1], [3, 3, 0, 2, 3, 1, 2], [2, 2, 3, 3, 2, 3, 1], [3, 2, 2, 3, 0, 2, 3]]
[[1, 0, 2, 0, 2, 3, 0], [2, 1, 3, 0, 0, 3, 0], [2, 3, 0, 0, 1, 2, 0], [3, 3, 0, 2, 0, 1, 1], [3, 0, 3, 2, 1, 2, 0], [0, 3, 2, 1, 0, 2, 2], [2, 3, 2, 2, 2, 0, 1]]

其中0为上,1为右,2为下,3为左

然后每题都以0~6分别代入,来得到36个正确解

在根据printFlag中的逻辑,将正确解计算出来

大佬WP by 魔法少女雪殇

ida打开,ppc架构,网上搜索提示串S32R274,得到是个雷达固件,网上找到datasheet,主函数反编译

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
Port_Init(&PortConfigSet);
Mcu_Init(&McuModuleConfiguration);
Mcu_InitClock(0);
while ( Mcu_GetPllStatus() != MCU_PLL_LOCKED )
;
Mcu_SetMode(0);
Mcu_DistributePllClock();
can_init();
receiveGame();
receiveAnswer();
if ( checkAnswer() )
printFlag();
while ( 1 )
;
}

如果checkAnswer()返回非0,则printFlag()

进入checkAnswer()

1
2
3
4
5
6
7
8
9
10
11
12
bool checkAnswer()
{
char v0; // r28
int i; // r29
v0 = 0;
for ( i = 0; i < 36; i = (unsigned __int8)(i + 1) )
{
if ( runGame(Gamemaps[i], Answer[i]) )
++v0;
}
return v0 == 36;
}

对Answer按byte检验,如果都通过则返回1

那么gamemaps和Answer应该是ReceiveGame和receiveAnswer函数接收的receiveGame

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
void receiveGame()
{
int i; // r7
int v1; // r8
uint8_t *v2; // r6
for ( i = 0; i < 36; i = (unsigned __int8)(i + 1) )
{
v1 = 0;
do
{
while ( (MEMORY[0xFFEC0030] & 1) == 0 )
;
if ( ((MEMORY[0xFFEC0084] >> 18) & 0x7FF) == 256 )
{
v2 = Gamemaps[i][v1];
*v2 = MEMORY[0xFFEC0088];
v2[1] = MEMORY[0xFFEC0089];
v2[2] = MEMORY[0xFFEC008A];
v2[3] = MEMORY[0xFFEC008B];
v2[4] = MEMORY[0xFFEC008C];
v2[5] = MEMORY[0xFFEC008D];
v2[6] = MEMORY[0xFFEC008E];
v1 = (unsigned __int8)(v1 + 1);
}
MEMORY[0xFFEC0030] = 1;
}
while ( v1 < 7 );
}
}

出现了没有识别的内存位置,由于这是个雷达固件,猜测这些内存位置保存着某个端口接收后的数据。

还可以看到,gamemaps是36(77)的char数组

同理可以查看receiveAnswer

查看printFlag

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
void printFlag()
{
int i; // r8
int j; // r6
uint8_t *v2; // r7
for ( i = 0; i < 36; i = (unsigned __int8)(i + 1) )
Flag[i + 5] = CharDict[(OfsBas[i] + Answer[i]) % 17];
for ( j = 0; j < 6; j = (unsigned __int8)(j + 1) )
{
MEMORY[0xFFEC0090] = MEMORY[0xFFEC0090] & 0xF0FFFFFF | 0x8000000;
MEMORY[0xFFEC0094] = MEMORY[0xFFEC0094] & 0xE003FFFF | 0x4040000;
v2 = &Flag[8 * j];
MEMORY[0xFFEC0098] = *v2;
MEMORY[0xFFEC0099] = v2[1];
MEMORY[0xFFEC009A] = v2[2];
MEMORY[0xFFEC009B] = v2[3];
MEMORY[0xFFEC009C] = v2[4];
MEMORY[0xFFEC009D] = v2[5];
MEMORY[0xFFEC009E] = v2[6];
MEMORY[0xFFEC009F] = v2[7];
MEMORY[0xFFEC0090] = MEMORY[0xFFEC0090] & 0xFFF0FFFF | 0x80000;
MEMORY[0xFFEC0090] &= 0xFFBFFFFF;
MEMORY[0xFFEC0090] &= 0xFFDFFFFF;
MEMORY[0xFFEC0090] = MEMORY[0xFFEC0090] & 0xF0FFFFFF | 0xC000000;
while ( (HIBYTE(MEMORY[0xFFEC0090]) & 0xF) != 8 )
;
}
}

需要Answer,charDict,ofsBas,查看字符串,发现一个flag{xxx...xxx}

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
.data:00FA0990 a0123456789abcd:.string "0123456789abcdef-"
.data:00FA0990 # DATA XREF:
data_copy2+14↑o
.data:00FA0990 # data_copy_loop3↑r
.data:00FA0990 .byte 0
.data:00FA09A2 .align 2
.data:00FA09A4 .byte 0x17
.data:00FA09A5 .byte 6
.data:00FA09A6 .byte 0xA
.data:00FA09A7 .byte 0x20
.data:00FA09A8 .byte 0x2D # -
.data:00FA09A9 .byte 0xB
.data:00FA09AA .byte 0x39 # 9
.data:00FA09AB .byte 1
.data:00FA09AC .byte 0xA
.data:00FA09AD .byte 0x10
.data:00FA09AE .byte 0x5E # ^
.data:00FA09AF .byte 1
.data:00FA09B0 .byte 0x1A
.data:00FA09B1 .byte 0xF
.data:00FA09B2 .byte 0x51 # Q
.data:00FA09B3 .byte 0x59 # Y
.data:00FA09B4 .byte 6
.data:00FA09B5 .byte 0x1F
.data:00FA09B6 .byte 0xE
.data:00FA09B7 .byte 9
.data:00FA09B8 .byte 0x23 # #
.data:00FA09B9 .byte 0x47 # G
.data:00FA09BA .byte 3
.data:00FA09BB .byte 0xA
.data:00FA09BC .byte 0x38 # 8
.data:00FA09BD .byte 5
.data:00FA09BE .byte 0x48 # H
.data:00FA09BF .byte 0x23 # #
.data:00FA09C0 .byte 2
.data:00FA09C1 .byte 0xA
.data:00FA09C2 .byte 0x12
.data:00FA09C3 .byte 0x33 # 3
.data:00FA09C4 .byte 0x1D
.data:00FA09C5 .byte 0x1F
.data:00FA09C6 .byte 0x48 # H
.data:00FA09C7 .byte 0x15
.data:00FA09C8 aFlagXxxxxxxxxx:.string
"flag{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}"

00FA0990处的数据看起来像字符串,交叉引用发现初始化了charDict,下面那一系列未知的byte正好36个,结合printFlag,猜测这些数据初始化了ofsBas

现在就差Answer和Gamemap,查看CANLog.asc

拖到组后,发现一系列未知值

1
2
3
4
5
6
5.145359 1 101 Rx d 8 66 6C 61 67 7B XX XX XX Length = 215910 BitCount = 112 ID = 257
5.145592 1 101 Rx d 8 XX XX XX XX XX XX XX XX Length = 221910 BitCount = 115 ID = 257
5.145820 1 101 Rx d 8 XX XX XX XX XX XX XX XX Length = 217910 BitCount = 113 ID = 257
5.146046 1 101 Rx d 8 XX XX XX XX XX XX XX XX Length = 215910 BitCount = 112 ID = 257
5.146276 1 101 Rx d 8 XX XX XX XX XX XX XX XX Length = 219910 BitCount = 114 ID = 257
5.146524 1 101 Rx d 8 XX 7D 00 00 00 00 00 00 Length = 237910 BitCount = 123 ID = 257

恰好是flag{xxxx...xxx}

Rx显然是接收端口的意思,可以得知这是使用另一台设备和雷达交互时得到的log,中间那些是数据。

那结合之前的receiveGame和receiveAnswer,上面还是Tx,那上面一定是gamemap和answer。answer还是未知值,36个。

去掉所有未知值和其它信息,应该是gamemap,一共3678个byte,发现每一行最后一个字节都是00,所以这个00应该是无用的,直接删掉。

因为是按byte比较,可以直接复制checkAnswer()进行穷举。

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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>
#include <math.h>
#include "defs.h"
// #include <setimp.h>
uint8_t map[36][7][7] = {
01,00,00,00,00,00,00,03,00,02,02,03,01,03,01,03,02,01,02,02,01,03,02,03,01,00,01,00,03,03,00,01,02,01,00,00,03,02,02,02,01,03,02,02,02,02,01,02,03,
00,00,00,00,00,01,00,00,02,02,02,01,01,01,00,02,03,02,02,00,01,00,03,01,00,02,00,01,00,00,02,01,03,01,01,03,00,01,02,02,00,02,03,03,03,00,02,03,03,
00,02,02,00,00,02,01,01,03,00,03,01,00,02,00,01,01,00,02,03,03,03,01,00,00,02,00,02,03,03,03,03,03,02,01,03,03,00,00,03,02,02,00,02,03,01,02,01,00,
03,02,01,03,00,01,01,01,00,02,00,01,01,01,01,00,00,03,02,02,00,01,03,02,02,01,02,01,00,01,03,03,01,03,01,02,03,02,00,02,01,03,03,02,00,03,03,02,01,
01,00,00,00,02,02,02,01,03,00,03,03,00,01,03,03,03,01,00,03,01,02,01,00,01,00,00,02,03,00,00,02,02,03,01,03,03,00,01,02,01,01,03,03,03,00,00,03,00,
01,02,01,00,01,01,00,02,03,03,03,00,01,00,03,03,02,01,03,03,02,01,02,00,00,01,03,03,00,03,01,01,00,03,03,00,02,03,01,02,02,03,00,00,02,00,03,02,03,
01,02,00,02,00,00,03,03,02,03,03,03,00,02,02,00,01,02,01,00,01,02,03,02,01,02,03,03,02,00,02,03,02,00,02,03,03,01,01,02,01,02,00,00,03,03,03,01,02,
01,02,02,02,03,01,01,00,02,00,02,02,03,02,03,03,03,02,03,02,03,03,00,02,00,02,02,03,00,02,02,02,01,02,01,02,03,02,01,02,00,00,00,00,03,03,00,03,03,
00,00,00,01,03,03,03,02,03,01,00,00,01,02,00,00,00,02,02,00,01,02,02,02,02,00,00,03,00,03,03,00,00,01,03,00,01,03,01,02,00,01,00,03,02,02,02,02,02,
00,00,00,00,02,03,00,02,01,00,00,03,03,01,03,01,03,01,01,02,01,00,02,02,03,03,01,02,03,00,02,00,02,01,02,01,02,02,01,03,01,03,01,02,03,03,01,02,01,
03,01,03,01,00,01,01,00,03,03,03,00,03,02,00,01,03,03,00,01,03,03,03,02,00,02,00,01,00,00,00,01,03,02,01,03,03,00,02,03,00,03,00,02,03,03,02,03,01,
03,02,01,00,00,01,01,01,03,03,01,00,03,03,00,00,00,00,02,03,02,03,02,03,03,02,02,00,00,00,01,00,00,03,02,02,01,02,03,02,01,02,00,03,02,03,02,03,00,
00,02,00,01,02,02,03,00,02,02,01,03,01,03,02,00,03,02,03,01,02,02,03,00,02,00,00,02,03,00,01,00,01,03,02,00,01,02,02,01,01,02,03,00,03,01,03,03,02,
02,00,03,00,01,00,00,03,03,02,03,00,02,00,03,00,00,02,00,02,01,00,03,00,03,02,03,00,00,01,02,02,03,02,00,02,02,01,00,02,03,01,01,02,03,01,03,02,03,
00,00,00,00,00,02,02,00,01,03,01,00,02,00,01,01,00,01,03,00,03,03,03,01,03,01,01,02,03,00,01,00,01,02,03,02,03,02,03,01,03,01,03,02,00,02,01,01,00,
01,00,01,00,01,00,02,03,02,03,01,03,02,00,00,01,00,02,01,02,01,02,02,00,02,03,03,00,02,00,02,03,02,00,02,03,02,02,01,02,00,00,03,02,02,03,03,02,00,
02,02,01,03,00,00,00,03,00,01,00,02,02,00,00,02,03,00,00,01,02,03,03,01,00,00,03,00,03,01,02,02,00,03,03,00,02,00,02,03,00,01,03,02,03,01,00,01,02,
02,02,02,01,02,02,03,03,03,00,02,02,03,01,03,01,03,01,01,00,02,00,03,02,00,00,02,00,00,00,01,01,03,03,02,01,02,03,00,02,02,01,02,02,03,02,01,00,03,
01,01,00,01,02,03,03,02,03,03,00,03,02,00,03,03,00,01,00,00,00,01,00,01,03,03,01,01,02,03,02,00,02,00,02,02,01,01,00,01,00,03,00,03,02,03,00,03,03,
00,00,00,03,02,00,00,01,03,00,00,03,03,01,00,01,02,01,01,01,03,03,01,01,01,02,03,03,03,02,01,02,01,02,00,01,02,02,03,03,01,00,00,03,00,03,02,03,03,
03,01,00,00,01,00,01,03,03,03,01,02,01,00,03,01,00,02,03,00,02,00,02,02,02,01,00,00,00,00,00,01,01,02,00,01,02,02,01,00,02,02,00,03,00,02,00,00,03,
03,00,03,01,03,02,00,03,00,00,03,03,02,02,03,00,03,03,01,02,01,03,02,03,03,03,03,00,00,00,00,03,00,01,01,02,00,03,01,03,02,00,01,00,02,02,02,01,01,
02,02,00,03,01,00,01,01,03,01,02,03,01,01,02,00,01,03,03,02,02,03,03,03,03,03,01,00,03,00,03,03,00,00,03,00,02,00,01,01,02,01,01,03,03,00,00,02,00,
00,02,00,01,02,02,00,03,03,02,00,01,03,03,02,02,02,01,02,01,03,00,03,03,02,00,01,02,00,03,02,00,00,02,01,03,02,01,01,02,03,01,03,03,03,03,03,03,00,
01,00,02,01,00,00,02,01,03,03,00,00,01,00,00,00,02,01,00,02,03,03,02,03,00,01,01,00,03,03,02,03,00,03,00,03,02,00,02,01,02,01,03,03,00,03,00,00,02,
03,01,02,03,03,00,01,03,02,02,00,03,00,02,00,03,01,01,02,00,02,02,03,02,01,00,00,02,01,01,02,00,00,01,02,02,02,01,02,00,02,01,00,00,00,00,03,03,00,
00,01,00,02,03,02,00,02,03,00,03,01,03,01,01,02,02,02,01,00,03,03,01,02,01,01,00,01,00,02,00,03,03,02,00,03,03,02,01,02,00,03,03,00,00,03,00,00,03,
02,00,00,02,01,01,00,03,03,00,02,03,00,03,03,02,00,01,01,01,01,00,02,03,01,00,03,01,00,03,01,03,01,00,03,03,01,02,02,00,03,00,01,03,00,00,03,02,02,
02,03,03,01,00,03,02,02,03,00,02,00,01,03,00,02,02,03,00,02,02,02,02,00,01,01,01,03,00,03,01,02,03,01,00,03,02,02,01,01,02,01,01,01,01,02,00,00,00,
00,00,02,03,01,00,01,02,00,03,00,01,00,02,03,02,00,03,03,01,00,01,03,00,00,01,00,03,03,00,03,02,01,03,01,03,01,01,01,01,00,02,01,00,03,02,00,03,00,
02,02,02,01,00,01,01,03,00,00,03,01,02,01,03,03,03,01,03,01,01,00,02,02,01,01,00,00,02,02,03,03,03,00,01,02,02,01,03,02,02,00,02,00,03,00,00,03,03,
03,02,00,01,01,00,01,03,00,00,03,02,02,01,00,01,03,03,03,01,01,03,02,02,03,03,00,01,03,01,03,00,01,00,03,02,01,00,01,01,01,02,01,01,02,03,02,01,00,
01,01,02,00,03,02,01,03,01,03,00,00,03,01,03,00,01,02,00,00,03,02,02,03,02,03,01,03,02,02,03,03,03,01,02,03,02,03,03,00,01,00,03,03,02,02,00,03,03,
02,01,03,00,02,02,00,03,01,03,02,00,00,03,00,02,03,03,03,02,00,02,03,00,01,03,01,02,00,01,01,02,02,01,02,00,03,01,02,01,03,02,00,03,02,03,01,00,01,
03,03,01,03,03,00,02,01,02,01,03,00,02,03,00,01,02,03,01,01,02,02,01,00,03,00,02,01,03,03,00,02,03,01,02,02,02,03,03,02,03,01,03,02,02,03,00,02,03,
01,00,02,00,02,03,00,02,01,03,00,00,03,00,02,03,00,00,01,02,00,03,03,00,02,00,01,01,03,00,03,02,01,02,00,00,03,02,01,00,02,02,02,03,02,02,02,00,01};
void printArray(const char *name,uint8_t *v,size_t len){
printf("========%s=========\n",name);
for(size_t i=0;i<len;i++){
printf("0x%02X,",v[i]);
}
printf("\n=================\n");
}
uint8_t loc_F98664[]=
{0xe8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x18,0x21,0x6,0xa0,0x19,0xc1,0x9,0x18,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
0xe8,0x0,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
0x7c,0x0,0x2,0x78,0x7c,0x21,0xa,0x78,0x7c,0x42,0x12,0x78,0x7c,0x63,0x1a,0x78,0x7c,
0x84,0x22,0x78,0x7c,0xa5,0x2a,0x78,0x7c,0xc6,0x32,0x78,0x7c,0xe7,0x3a,0x78,0x7d
,0x8,0x42,0x78,0x7d,0x29,0x4a,0x78,0x7d,0x4a,0x52,0x78,0x7d,0x6b,0x5a,0x78,0x7d,
0x8c,0x62,0x78,0x7d,0xad,0x6a,0x78,0x7d,0xce,0x72,0x78,0x7d,0xef,0x7a,0x78,0x7e,
0x10,0x82,0x78,0x7e,0x31,0x8a,0x78,0x7e,0x52,0x92,0x78,0x7e,0x73,0x9a,0x78,0x7e,
0x94,0xa2,0x78,0x7e,0xb5,0xaa,0x78,0x7e,0xd6,0xb2,0x78,0x7e,0xf7,0xba,0x78,0x7f,
0x18,0xc2,0x78,0x7f,0x39,0xca,0x78,0x7f,0x5a,0xd2,0x78};
uint8_t runGame(uint8_t (*gamemap)[7], uint8_t startPoint)
{
int startPoint_1; // r18
char *v3; // r7
char *v4; // r6
int v5; // ctr
char v6; // r4
char v7; // r5
int v8; // r17
int v9; // r6
int v10; // r19
char *v11; // r5
uint8_t *v12; // r4
uint8_t *v13; // r4
uint8_t *v14; // r5
char *v15; // r20
char *v16; // r3
int v17; // r6
char v19[61]; // [sp+7h] [-79h] BYREF

LOBYTE(startPoint_1) = startPoint;
v3 = (char *)loc_F98664 + 1;
v4 = v19;
v5 = 24;
do
{
v6 = v3[1];
v3 += 2;
v7 = *v3;
v4[1] = v6;
v4 += 2;
*v4 = v7;
--v5;
}
while ( v5 );
v4[1] = v3[1];
v8 = -1;
v9 = 0;
v10 = 0;
do
{
v11 = &v19[7 * v9];
v12 = &(*gamemap)[7 * v9 - 1];
do
{
*++v11 = *++v12;
++v10;
}
while ( ((v10 - 7) & 1) != 0 );
for ( ; v10 < 7; v10 += 2 )
{
v13 = v12 + 1;
v14 = v11 + 1;
*v14 = *v13;
v12 = v13 + 1;
v11 = v14 + 1;
*v11 = *v12;
}
++v9;
v10 = 0;
}
while ( v9 < 7 );
startPoint_1 = (char)startPoint_1;
LABEL_10:
v15 = &v19[7 * startPoint_1 + 1];
while ( v10 < 7 && startPoint_1 >= 0 && startPoint_1 < 7 )
{
v16 = &v15[v10];
v17 = v15[v10];
if ( startPoint_1 % 2 )
{
if ( v15[v10] )
{
if ( v17 == 1 )
{
*v16 = 0;
v8 = 0;
--startPoint_1;
goto LABEL_10;
}
if ( v17 != 2 )
{
if ( v17 != 3 )
return v8 == 1;
*v16 = 2;
v8 = 2;
++startPoint_1;
goto LABEL_10;
}
*v16 = 1;
v8 = 1;
if ( ++v10 >= 0 )
goto LABEL_10;
}
else
{
*v16 = 3;
v8 = 3;
if ( --v10 >= 0 )
goto LABEL_10;
}
return v8 == 1;
}
if ( v15[v10] )
{
if ( v17 == 1 )
{
*v16 = 2;
v8 = 2;
++startPoint_1;
goto LABEL_10;
}
if ( v17 != 2 )
{
if ( v17 != 3 )
return v8 == 1;
*v16 = 0;
v8 = 0;
--startPoint_1;
goto LABEL_10;
}
*v16 = 3;
v8 = 3;
if ( --v10 >= 0 )
goto LABEL_10;
return v8 == 1;
}
*v16 = 1;
v8 = 1;
if ( ++v10 < 0 )
return v8 == 1;
}
return v8 == 1;
}

int main(){
uint8_t flag[37]={0};
for(int i=0;i<36;i++){
for(int j=0;j<0x7f;j++){
if(runGame(map[i],j)){
flag[i]=j;
break;
}
}
}
printArray("flag",flag,36);
return 0;
}

得到输出之后求解flag

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
charDict = '0123456789abcdef-'
ofsBas = [
0x17, 0x06, 0x0a, 0x20, 0x2d, 0x0b,
0x39, 0x01, 0x0a, 0x10, 0x5e, 0x01,
0x1a, 0x0f, 0x51, 0x59, 0x06, 0x1f,
0x0e, 0x09, 0x23, 0x47, 0x03, 0x0a,
0x38, 0x05, 0x48, 0x23, 0x02, 0x0a,
0x12, 0x33, 0x1d, 0x1f, 0x48, 0x15
]
f = [
0x04, 0x06, 0x04, 0x06, 0x06, 0x04,
0x03, 0x03, 0x06, 0x02, 0x02, 0x02,
0x04, 0x01, 0x00, 0x05, 0x01, 0x01,
0x02, 0x06, 0x01, 0x02, 0x03, 0x06,
0x06, 0x06, 0x03, 0x01, 0x04, 0x04,
0x05, 0x01, 0x06, 0x01, 0x06, 0x03
]
r = 'flag{'

for i in range(36):
r += charDict[(f[i] + ofsBas[i]) % 17]

r += '}'
print(r)

Flag

1
flag{ace40f94-1b3d-d97f-f256-bb726e611fa7}