首页
论坛
课程
招聘
[原创]2021 KCTF 春季赛 第二题 南冥神功 wp
2021-5-11 15:58 2751

[原创]2021 KCTF 春季赛 第二题 南冥神功 wp

2021-5-11 15:58
2751

初步分析

windows32位程序.
定位到main函数, 004B3CC0.
观察后看出是个走迷宫游戏.

分析游戏逻辑

整理main函数的代码

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
char g_szHex[] = "012345"
                 "6789AB"
                 "CDEFGH"
                 "IJKLMN"
                 "OPQRST"
                 "UVWXYZ";
DWORD g_nHexTableSize = 0x24; //sizeof(g_szHex)
 
#define ROW 10
char g_szMaze[][ROW] = {
    {'S', 0, 1, 0, 0, 1, 0, 0, 1, 1 },
    1, 1, 0, 0, 1, 0, 0, 1, 0, 0 },
    0, 0, 1, 0, 1, 1, 1, 1, 1, 0 },
    0, 1, 1, 0, 1, 0, 0, 1, 0, 0 },
    0, 0, 1, 0, 0, 1, 0, 0, 1, 1 },
    1, 1, 0, 1, 1, 1, 0, 1, 0, 1 },
    0, 0, 1, 1, 1, 1, 0, 1, 0, 1 },
    0, 1, 1, 0, 0, 1, 0, 1, 0, 1 },
    0, 0, 0, 1, 0, 0, 1, 1, 0, 0 },
};
 
 
int main(int argc, const char** argv, const char** envp)
{
    char ch;
    int nInputIdx;
    int nHexIdx;
    unsigned int nX;
    unsigned int nY;
    int nStep1;
    int nStep2;
    int flag;   
    int nCount0;
    char* pNow;  
    char* pNextRow;  
    char szInput[76] = { 0 };
 
    printf("Input your code: ");
    scanf("%48s", szInput);
    if (strlen(szInput) <= 0x30)
    {
        nX = 0;
        nY = 0;
        nInputIdx = 0;
        ch = szInput[nInputIdx];
 
        if (ch != 0)
        {
            do
            {
                if (g_nHexTableSize > 0)
                {
                    //get nHexIdx
                    nHexIdx = 0;
                    do {
                        if (g_szHex[nHexIdx] == ch)
                            break;
                    } while (g_nHexTableSize != ++nHexIdx);
 
                    nStep1 = 5 - (nHexIdx + nInputIdx) % 6;
                    nStep2 = (nInputIdx + nHexIdx / 6) % 6;
 
                    switch (nStep1)
                    {
                    case 1:
                        //x++
                        ++nX;
                        break;
                    case 2:
                        //if y==red  x++ ,y++
                        flag = (nY++ & 1) == 0;
                        nX += flag;
                        break;
                    case 3:
                        //if y==green   x-- ,y++
                        flag = (nY++ & 1) != 0;
                        nX -= flag;
                        break;
                    case 4:
                        //x--
                        --nX;
                        break;
                    case 5:
                        //if y==green   x-- ,y--
                        flag = (nY-- & 1) != 0;
                        nX -= flag;
                        break;
                    default:
                        //if y==red  x++ ,y--
                        flag = (nY-- & 1) == 0;
                        nX += flag;
                        break;
                    }
                    //检查越界
                    if (nX > 9)
                        goto LABEL_F;
                    if (nY > 8)
                        goto LABEL_F;
                    if (g_szMaze[nY][nX] == 1)
                        goto LABEL_F;
                    g_szMaze[nY][nX] = 1;
 
                    switch (nStep2)
                    {
                    case 1:
                        //x++
                        ++nX;
                        break;
                    case 2:
                        //if y==red  x++ ,y++
                        flag = (nY++ & 1) == 0;
                        nX += flag;
                        break;
                    case 3:
                        //if y==green   x-- ,y++
                        flag = (nY++ & 1) != 0;
                        nX -= flag;
                        break;
                    case 4:
                        //x--
                        --nX;
                        break;
                    case 5:
                        //if y==green   x-- ,y--
                        flag = (nY-- & 1) != 0;
                        nX -= flag;
                        break;
                    default:
                        //if y==red  x++ ,y--
                        flag = (nY-- & 1) == 0;
                        nX += flag;
                        break;
                    }
                    //检查越界
                    if (nX > 9)
                        goto LABEL_F;
                    if (nY > 8)
                        goto LABEL_F;
                    if (g_szMaze[nY][nX] == 1)
                        goto LABEL_F;
                    g_szMaze[nY][nX] = 1;
                }
            } while (0 != (ch = szInput[++nInputIdx]));
        }
 
        //检查迷宫, 迷宫全部为1则验证通过
        pNow = (char*)g_szMaze;
        nCount0 = 0;
        do
        {
            pNextRow = pNow+ ROW;
            do
                nCount0 += *pNow++ == 0;
            while (pNextRow != pNow);
        } while (&g_szMaze[0][0] + sizeof(g_szMaze) != (char*)pNextRow);
 
        if (nCount0 == 0)
        {
            printf("Good job!");
            return 0;
        }
    }
 
LABEL_F:
    printf("Try again...");
    return 0;
}

迷宫如下:

迷宫中总共有6中走法(指令0~5).
在红色格子和绿色格子上每个指令表示的走法不同, 见下表格:

 

迷宫走法:

根据上面走法的表格得出通关指令为:

1
1234321234321101210050543450501210121234322321

转换输入的字符串

输入的字符串, 每一个字符对应迷宫中走两步.

1
2
3
4
5
nStep1 = 5 - (nHexIdx + nInputIdx) % 6;
nStep2 = (nInputIdx + nHexIdx / 6) % 6;
//推出:
InputIdx_X = (nStep1 - nHexIdx) % 6;
InputIdx_Y = (nStep2 - nHexIdx) % 6;

把通关指令每2个分一组, 算出InputIdx_X和InputIdx_Y,查下表得出要输入的字符串.

1
GJ0V4LA4VKEVQZSVCNGJ00N

看雪2022 KCTF 秋季赛 防守篇规则,征题截止日期11月12日!(iPhone 14等你拿!)

最后于 2021-5-12 00:08 被KuCha128编辑 ,原因:
上传的附件:
收藏
点赞0
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回