首页
社区
课程
招聘
[原创]kctf 2021 第四题
2021-5-15 01:30 5536

[原创]kctf 2021 第四题

2021-5-15 01:30
5536

大概算法:

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
int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v3; // kr00_4
  int v4; // ecx
  char *v5; // esi
  int v6; // edi
  void (*v8)(void); // [esp+Ch] [ebp-2CCh]
  int v9[22]; // [esp+10h] [ebp-2C8h] BYREF
  int v10[128]; // [esp+68h] [ebp-270h] BYREF
  __int128 v11; // [esp+268h] [ebp-70h] BYREF
  char flag[92]; // [esp+278h] [ebp-60h] BYREF
 
  printf("\t\t\t看雪CTF大赛\r\n");
  printf("\t\t祝愿看雪CTF大赛越办越好\r\n");
  printf("Serial: ");
  scanf_s("%s", flag);
  v3 = strlen(flag);
  if ( v3 <= 64 && trans_input(v3, flag, v10) == 1 && check_sudoku((int)v10, v3 - 9) == 1 )// 数独
  {
    v11 = 0i64;
    memset(v9, 0, sizeof(v9));
    v9[5] = 0;
    v9[4] = 0;
    v9[0] = 0x67452301;                         // md5_init
    v9[1] = 0xEFCDAB89;
    v9[2] = 0x98BADCFE;
    v9[3] = 0x10325476;
    mde_update((int)flag, (int)v9, v3);
    md5_final((int)&v11, (int)v9);
    aes_init(v4, (unsigned __int8 *)&v11);
    v8 = (void (*)(void))VirtualAlloc(0, 0x620u, 0x1000u, 0x40u);
    v5 = (char *)v8;
    v6 = 'b';
    do
    {
      *(__m128i *)v5 = _mm_loadu_si128((const __m128i *)&v5[&byte_4181A0 - (_UNKNOWN *)v8]);
      aes_dec((int)v10, v5);
      v5 += 16;
      --v6;
    }
    while ( v6 );
    v8();
  }
  return 0;
}

trans_input把输入转换为数字,然后验证数独,数独比较简单,直接就能解出来:

 

图片描述

 

但是前面那个转换输入的函数我疑惑了好久,首先转换的规则是将输入查一个81大小的table,然后把查到的索引%9+1作为填入数独的数字,但是这样一来一个数字对应的输入就有9种可能,那56个数字就有9^56种可能,最后还会多9个字符,那可能性可就太多了,感觉有限时间内爆破不完。

 

知道后来,我又仔细审了一下tran_input函数,发现末尾有点奇怪的逻辑:
图片描述
当输入是数字时会有一个判断,而每次判断就会把查表的起始索引+9,我突然想到会不会是每一行数字填完之后要输入一个数字把索引+9,而对于的输入就只在起始索引+9的范围内查找,而多的9个数字又正好把多的9个输入覆盖了。试了一下,果然如此:

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
s_table=[[5,6,1,9,2,3,8],
[1,8,3,4,5],
[7,6,2,1,9],
[7,8,4,6,9,2,5],
[4,5,3,9,7,8,6],
[6,9,2,8,7,1,3],
[2,8,5,6,3],
[6,1,7,2,8],
[1,7,9,3,4,5,2]] #+ [1] * 9
 
index_table=[0x24,0x42,0x50,0x56,0x3A,0x75,0x62,0x66,
0x59,0x70,0x7D,0x5D,0x44,0x74,0x4E,0x3E,0x61,0x54,0x5E,0x4D,0x47,0x6D,0x4A,0x51,
0x23,0x2A,0x48,0x72,0x60,0x4F,0x27,0x77,0x6A,0x69,0x63,0x30,0x21,0x68,0x64,0x79,
0x7B,0x6F,0x5A,0x7A,0x2D,0x40,0x6E,0x2B,0x3F,0x26,0x25,0x73,0x5F,0x2F,0x67,0x3C,
0x65,0x5B,0x57,0x29,0x58,0x55,0x78,0x52,0x46,0x53,0x4C,0x52,0x41,0x3B,0x2E,0x6C,
0x3D,0x43,0x45,0x6B,0x76,0x4B,0x2D,0x28,0x71]
 
res = ''
f = 0
for fi in s_table:
    for i in fi:
        res += chr(index_table[i-1+f*9])
    res += str(9-len(fi))
    f += 1
print(len(res),res)

一开始还以为是爆破题,没想到最后是脑洞题,学到了很多,谢谢出题人。


[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

收藏
点赞1
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回