首页
社区
课程
招聘
[原创]KCTF2022 第二题pizzatqqql队题解
2022-5-12 16:18 13731

[原创]KCTF2022 第二题pizzatqqql队题解

2022-5-12 16:18
13731

KCTF2022 第二题题解

解题

第一部分

输入一段字符串,然后用输入的字符串在下图进行一系列运算后,将运算的结果存入v39之中,然后进行一个sbox的初始化,和输入没有半毛钱关系,每次运行都是相同的数,所以可以动调然后取出。
图片描述

 

接着用sbox和我们的输入进行了一系列运算,将结果存进int类型的v11中。

 

图片描述

 

接下来是一个常规的字符串转数字存入内存的函数,不过这里的ascii大于0x39的字符是减55后存入内存。

 

图片描述

 

然后下图的最下面的if判断需要满足,否则game over。向上看do while,发现和我们的输入有关的只有v39,也就是上面的那个运算的结果

 

图片描述

 

这里通过爆破得出了v17的范围

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
#include <cstring>
#include <iostream>
using namespace std;
int v3; // ebx
int len; // esi
char v5; // cl
int v6; // edi
char* v7; // esi
char v8; // ch
char v9; // cl
char v10; // dl
int v11; // ecx
int i; // edx
int v13; // ecx
int v14; // esi
int v15; // eax
int j; // edx
int v17; // edi
int v18; // esi
int v19; // edi
int v20; // esi
int v21; // eax
int v22; // ecx
int v23; // eax
int v24; // ecx
int v25; // eax
int v26; // edx
int v27; // ecx
char v28; // bl
char v29; // bh
int v30; // ecx
char* v31; // edi
int v33[200]; // [esp+10h] [ebp-368h]
int v34; // [esp+330h] [ebp-48h]
int v35; // [esp+334h] [ebp-44h]
int v36; // [esp+338h] [ebp-40h]
int v37; // [esp+33Ch] [ebp-3Ch]
int v38; // [esp+340h] [ebp-38h]
char v39; // [esp+347h] [ebp-31h]
char input[6]; // [esp+348h] [ebp-30h] BYREF
char v41[38]; // [esp+34Eh] [ebp-2Ah] BYREF
int main()
{
    for (int i = 0; i <= 0xff; i++)
    {
        v13 = i;
        v15 = v13;
        for (j = 1; j < 200; ++j)
        {
            if ((v15 & 1) != 0)                     // 奇数*3+1
                v15 = 3 * v15 + 1;
            else
                v15 >>= 1;                              // 偶数右移1
            v33[j] = v15;
        }
        v17 = v33[198] | v33[197] | v33[196];
        cout << v17 << endl;
    }
}

图片描述

 

只有7,这就好办了。爆破input前三个数就行。这里注意此处的input已经被之前的string_into_memory函数转化过了,爆破固定的范围即可。

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
#include <cstring>
#include <iostream>
using namespace std;
int v3; // ebx
int len; // esi
char v5; // cl
int v6; // edi
char* v7; // esi
char v8; // ch
char v9; // cl
char v10; // dl
int v11; // ecx
int i; // edx
int v13; // ecx
int v14; // esi
int v15; // eax
int j; // edx
int v17; // edi
int v18; // esi
int v19; // edi
int v20; // esi
int v21; // eax
int v22; // ecx
int v23; // eax
int v24; // ecx
int v25; // eax
int v26; // edx
int v27; // ecx
char v28; // bl
char v29; // bh
int v30; // ecx
char* v31; // edi
int v33[200]; // [esp+10h] [ebp-368h]
int v34; // [esp+330h] [ebp-48h]
int v35; // [esp+334h] [ebp-44h]
int v36; // [esp+338h] [ebp-40h]
int v37; // [esp+33Ch] [ebp-3Ch]
int v38; // [esp+340h] [ebp-38h]
char v39; // [esp+347h] [ebp-31h]
char input[6]; // [esp+348h] [ebp-30h] BYREF
char v41[38]; // [esp+34Eh] [ebp-2Ah] BYREF
int main()
{
    for (int j = 0; j < 50; j++)
    {
        for (int z = 0; z < 50; z++)
        {
            for (int w = 0; w < 50; w++)
            {
                if ((j ^ z ^ w) == 7)
                {
                    if (j > 9)
                    {
                        cout << (char)(j + 55);
                    }
                    else
                    {
                        cout << (char)(j + 48);
                    }
                    if (z > 9)
                    {
                        cout << (char)(z + 55);
                    }
                    else
                    {
                        cout << (char)(z + 48);
                    }
                    if (w > 9)
                    {
                        cout << (char)(w + 55);
                    }
                    else
                    {
                        cout << (char)(w + 48);
                    }
                    cout << endl;
                }
            }
        }
    }
}

得出一堆满足的数,随便选一个0AD填进去第一关就过了

 

图片描述

第二部分

图片描述

 

这里相当于告诉你后面几位是多少了,不做赘述,加上后现在已知的flag是0ADKCTF

第三部分

又是一个运算

 

图片描述

 

v19是v17+2,v17就是刚刚爆破出来结果全是7的那个,所以可以得知循环的次数固定是9次。此处进行运算的是我们输入的0ADKCTF的后九位。假设输入为0ADKCTF123456789时,这里的v41[v22]最开始指向的就是1

 

图片描述

 

当v24%v36不等于0时会失败。注意这里循环一次只需要取一次余,不用将前面的余全部取一遍。

 

比如输入123456789,先判断1%1==0,然后判断12%2==0,然后判断123%3==0,依次类推。

 

写了个脚本爆破,但是发现后面还有个限制,这里是从小到大排序我们刚刚输入的九个数

 

图片描述

 

然后这里是比较,必须1到9全部出现。所以刚刚的爆破还要加个限制。

 

图片描述

 

脚本如下

1
2
3
4
5
for i in range(100000000,1000000000):
    if i//10000000 %2 == 0 and i//1000000%3 == 0 and i//100000%4 == 0 and i//10000%5 == 0 and i//1000 %6 == 0 and i//100 % 7 == 0 and i//10 % 8 == 0 and i%9 == 0:
        num_all = str(i)
        if "1" in num_all and "2" in num_all and "3" in num_all and "4" in num_all and "5" in num_all and "6" in num_all and "7" in num_all and "8" in num_all and "9" in num_all :
            print(i)

发现只能爆破出一个数381654729

第四部分

这个函数不知道有啥用,我直接f8发现没事就没看了

 

图片描述

 

最后一关就是要满足这个v34等于这个数,查看v34交叉引用,发现是和很上面的sbox运算有关

 

图片描述

 

我们的前三位爆破出了很多数,我是随便选了一个就过的,看来这里是作为前三位的限制。

 

因为我们只有前三位不是唯一的,只需要爆破前三位就行。脚本如下

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
#include <iostream>
using namespace std;
int v3; // ebx
int len; // esi
char v5; // cl
int v6; // edi
char* v7; // esi
char v8; // ch
char v9; // cl
char v10; // dl
int v11; // ecx
int i; // edx
int v13; // ecx
int v14; // esi
int v15; // eax
int j; // edx
int v17; // edi
int v18; // esi
int v19; // edi
int v20; // esi
int v21; // eax
int v22; // ecx
int v23; // eax
int v24; // ecx
int v25; // eax
int v26; // edx
int v27; // ecx
char v28; // bl
char v29; // bh
int v30; // ecx
char* v31; // edi
int v33[200]; // [esp+10h] [ebp-368h]
int v34; // [esp+330h] [ebp-48h]
int v35; // [esp+334h] [ebp-44h]
int v36; // [esp+338h] [ebp-40h]
int v37; // [esp+33Ch] [ebp-3Ch]
int v38; // [esp+340h] [ebp-38h]
char v39; // [esp+347h] [ebp-31h]
char v41[38]; // [esp+34Eh] [ebp-2Ah] BYREF
unsigned int sbox[] = { 0x00000000, 0x09073096, 0x120E612C, 0x1B0951BA, 0xFF6DC419, 0xF66AF48F, 0xED63A535, 0xE46495A3,
0xFEDB8832, 0xF7DCB8A4, 0xECD5E91E, 0xE5D2D988, 0x01B64C2B, 0x08B17CBD, 0x13B82D07, 0x1ABF1D91,
0xFDB71064, 0xF4B020F2, 0xEFB97148, 0xE6BE41DE, 0x02DAD47D, 0x0BDDE4EB, 0x10D4B551, 0x19D385C7,
0x036C9856, 0x0A6BA8C0, 0x1162F97A, 0x1865C9EC, 0xFC015C4F, 0xF5066CD9, 0xEE0F3D63, 0xE7080DF5,
0xFB6E20C8, 0xF269105E, 0xE96041E4, 0xE0677172, 0x0403E4D1, 0x0D04D447, 0x160D85FD, 0x1F0AB56B,
0x05B5A8FA, 0x0CB2986C, 0x17BBC9D6, 0x1EBCF940, 0xFAD86CE3, 0xF3DF5C75, 0xE8D60DCF, 0xE1D13D59,
0x06D930AC, 0x0FDE003A, 0x14D75180, 0x1DD06116, 0xF9B4F4B5, 0xF0B3C423, 0xEBBA9599, 0xE2BDA50F,
0xF802B89E, 0xF1058808, 0xEA0CD9B2, 0xE30BE924, 0x076F7C87, 0x0E684C11, 0x15611DAB, 0x1C662D3D,
0xF6DC4190, 0xFFDB7106, 0xE4D220BC, 0xEDD5102A, 0x09B18589, 0x00B6B51F, 0x1BBFE4A5, 0x12B8D433,
0x0807C9A2, 0x0100F934, 0x1A09A88E, 0x130E9818, 0xF76A0DBB, 0xFE6D3D2D, 0xE5646C97, 0xEC635C01,
0x0B6B51F4, 0x026C6162, 0x196530D8, 0x1062004E, 0xF40695ED, 0xFD01A57B, 0xE608F4C1, 0xEF0FC457,
0xF5B0D9C6, 0xFCB7E950, 0xE7BEB8EA, 0xEEB9887C, 0x0ADD1DDF, 0x03DA2D49, 0x18D37CF3, 0x11D44C65,
0x0DB26158, 0x04B551CE, 0x1FBC0074, 0x16BB30E2, 0xF2DFA541, 0xFBD895D7, 0xE0D1C46D, 0xE9D6F4FB,
0xF369E96A, 0xFA6ED9FC, 0xE1678846, 0xE860B8D0, 0x0C042D73, 0x05031DE5, 0x1E0A4C5F, 0x170D7CC9,
0xF005713C, 0xF90241AA, 0xE20B1010, 0xEB0C2086, 0x0F68B525, 0x066F85B3, 0x1D66D409, 0x1461E49F,
0x0EDEF90E, 0x07D9C998, 0x1CD09822, 0x15D7A8B4, 0xF1B33D17, 0xF8B40D81, 0xE3BD5C3B, 0xEABA6CAD,
0xEDB88320, 0xE4BFB3B6, 0xFFB6E20C, 0xF6B1D29A, 0x12D54739, 0x1BD277AF, 0x00DB2615, 0x09DC1683,
0x13630B12, 0x1A643B84, 0x016D6A3E, 0x086A5AA8, 0xEC0ECF0B, 0xE509FF9D, 0xFE00AE27, 0xF7079EB1,
0x100F9344, 0x1908A3D2, 0x0201F268, 0x0B06C2FE, 0xEF62575D, 0xE66567CB, 0xFD6C3671, 0xF46B06E7,
0xEED41B76, 0xE7D32BE0, 0xFCDA7A5A, 0xF5DD4ACC, 0x11B9DF6F, 0x18BEEFF9, 0x03B7BE43, 0x0AB08ED5,
0x16D6A3E8, 0x1FD1937E, 0x04D8C2C4, 0x0DDFF252, 0xE9BB67F1, 0xE0BC5767, 0xFBB506DD, 0xF2B2364B,
0xE80D2BDA, 0xE10A1B4C, 0xFA034AF6, 0xF3047A60, 0x1760EFC3, 0x1E67DF55, 0x056E8EEF, 0x0C69BE79,
0xEB61B38C, 0xE266831A, 0xF96FD2A0, 0xF068E236, 0x140C7795, 0x1D0B4703, 0x060216B9, 0x0F05262F,
0x15BA3BBE, 0x1CBD0B28, 0x07B45A92, 0x0EB36A04, 0xEAD7FFA7, 0xE3D0CF31, 0xF8D99E8B, 0xF1DEAE1D,
0x1B64C2B0, 0x1263F226, 0x096AA39C, 0x006D930A, 0xE40906A9, 0xED0E363F, 0xF6076785, 0xFF005713,
0xE5BF4A82, 0xECB87A14, 0xF7B12BAE, 0xFEB61B38, 0x1AD28E9B, 0x13D5BE0D, 0x08DCEFB7, 0x01DBDF21,
0xE6D3D2D4, 0xEFD4E242, 0xF4DDB3F8, 0xFDDA836E, 0x19BE16CD, 0x10B9265B, 0x0BB077E1, 0x02B74777,
0x18085AE6, 0x110F6A70, 0x0A063BCA, 0x03010B5C, 0xE7659EFF, 0xEE62AE69, 0xF56BFFD3, 0xFC6CCF45,
0xE00AE278, 0xE90DD2EE, 0xF2048354, 0xFB03B3C2, 0x1F672661, 0x166016F7, 0x0D69474D, 0x046E77DB,
0x1ED16A4A, 0x17D65ADC, 0x0CDF0B66, 0x05D83BF0, 0xE1BCAE53, 0xE8BB9EC5, 0xF3B2CF7F, 0xFAB5FFE9,
0x1DBDF21C, 0x14BAC28A, 0x0FB39330, 0x06B4A3A6, 0xE2D03605, 0xEBD70693, 0xF0DE5729, 0xF9D967BF,
0xE3667A2E, 0xEA614AB8, 0xF1681B02, 0xF86F2B94, 0x1C0BBE37, 0x150C8EA1, 0x0E05DF1B, 0x0702EF8D };
char input[] = "0ADKCTF381654729";
int main()
{
    int duibi = 0xad1f89a;
    v11 = -1;
    for (int j1 = 0; j1 < 0x7f; j1++)
    {
        for (int j2 = 0; j2 < 0x7f; j2++)
        {
            for (int j3 = 0; j3 < 0x7f; j3++)
            {
                v11 = -1;
                v11 = sbox[(unsigned __int8)(v11 ^ j1)] ^ (v11 >> 8);
                v11 = sbox[(unsigned __int8)(v11 ^ j2)] ^ (v11 >> 8);
                v11 = sbox[(unsigned __int8)(v11 ^ j3)] ^ (v11 >> 8);
                for (i = 3; i < 16; ++i)
                    v11 = sbox[(unsigned __int8)(v11 ^ input[i])] ^ (v11 >> 8);
                if (v11 == duibi)
                    cout << char(j1) << char(j2) << char(j3) << endl;
            }
        }
    }
 
}

得到前三位是421,所以最终的序列号是421KCTF381654729

 

图片描述

感想

题出的很有意思,像闯关游戏一样hhh

 

然后和第一名差了2秒,有点悲伤(


[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界

收藏
点赞3
打赏
分享
最新回复 (2)
雪    币: 3906
活跃值: (5528)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
badboyl 2 2022-6-3 00:33
2
0
楼主0xad1f89a 从哪儿得到得?
雪    币: 887
活跃值: (2147)
能力值: ( LV4,RANK:52 )
在线值:
发帖
回帖
粉丝
夏男人 2022-6-4 10:27
3
0
是那个0xF52E0765的取反的结果
游客
登录 | 注册 方可回帖
返回