首页
社区
课程
招聘
[原创]KCTF2021 第四题 英雄救美 writeup
2021-5-14 21:06 5138

[原创]KCTF2021 第四题 英雄救美 writeup

2021-5-14 21:06
5138

KCTF2021 第四题 英雄救美 writeup

IDA

main

1
2
3
4
5
6
7
8
9
10
11
main(){
//...
  printf("Serial: ");
  scanf_s("%s", v12);
  v3 = strlen(v12);
  if ( v3 <= 64 && sub_691240(v3, (int)v12, v10) == 1 && sub_691000(v10, v3 - 9) == 1 )
  {
    //...
  }
//...
}

sub_691240

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
int __usercall sub_691240@<eax>(int a1@<edx>, int a2@<ecx>, int *a3)
{
  //...
  __int128 v13[5]; // [esp+Ch] [ebp-58h] 9*9 初始化表
  char v14; // [esp+5Ch] [ebp-8h]
 
  v13[0] = (__int128)_mm_load_si128(&stru_6A6280);
  v3 = 0;
  v13[1] = (__int128)_mm_load_si128(stru_6A62A0);
  v4 = 0;
  v11 = a1;
  v10 = a2;
  v14 = 'q';
  v13[2] = (__int128)_mm_load_si128(&stru_6A6270);
  v13[3] = (__int128)_mm_load_si128(&stru_6A6290);
  v13[4] = (__int128)_mm_load_si128(&stru_6A6260);
  if ( a1 <= 0 )
    return 1;
  v5 = 0;
  while ( 1 )
  {
    v6 = *(_BYTE *)(v4 + a2);
    if ( v6 > '0' && v6 <= '9' )
      break;
    v7 = v5;
    if ( v5 >= 81 )                             // 数字不可以超过9
      return 0;
    while ( v6 != *((_BYTE *)v13 + v7) )        // 从数字的个数*9的位置开始检索 就是第n行开始
    {
      if ( (unsigned int)++v7 >= 81 )
        return 0;
    }
    v9 = v7 % 9 + 1;
    if ( v9 == -1 )
      return 0;
    *a3 = v9;                                   // 属于第几列的 记录下来
    a2 = v10;
    ++v3;
    ++a3;
    a1 = v11;
LABEL_13:
    if ( ++v4 >= a1 )
      return 1;
  }
  if ( v3 + v6 == '9' )                         // 数字在字符串后为(9-字符长度)
  {
    v3 = 0;
    v5 += 9;
    goto LABEL_13;
  }
  return -1;
}

sub_691240 通过输入的字符串生成一个数组仅包含数字1-9。
在9*9的初始化表中匹配字符,每出现数字就从下一行开始匹配,将匹配到的第几列存下来。按数字分割字符串,数字=9-数字前字符串的长度。
通过main中sub_691000(v10, v3 - 9)的调用可以知道数字会出现9次。
导出初始化表

1
"$BPV:ubfYp}]DtN>aT^MGmJQ#*Hr`O'wjic0!hdy{oZz-@n+?&%s_/g<e[W)XUxRFSLRA;.l=CEkvK-(q"

sub_691000

sub_691000(arr, arr_len) 是个数独的判断。
首先将arr顺序填充到006A87C0非零的值上,9行9列,其中0值有55个,则要输入64(55+9)个字符。
接下来就是判断每行每列每个9宫格不能有重复数字。

 

导出数独初始值

1
2
3
4
5
6
7
8
9
0 4 0 7 0 0 0 0 0
9 2 0 0 0 0 6 0 7
8 3 0 0 0 5 4 0 0
0 1 0 0 0 3 0 0 0
0 0 0 2 0 1 0 0 0
0 0 0 5 0 0 0 4 0
0 0 4 9 0 0 0 7 1
3 0 5 0 0 0 0 9 4
0 0 0 0 0 8 0 6 0

求出数独
图片描述
得到arr值5619238183457621978469254539786692871328563617281793452
然而并不知道如何分割为9份。
感谢出题人手下留情,按照数独分行即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <string>
using namespace std;
 
int main()
{
    string ar[] = { "5619238","18345","76219","7846925","4539786","6928713","28563","61728","1793452" };
    string key = "$BPV:ubfYp}]DtN>aT^MGmJQ#*Hr`O'wjic0!hdy{oZz-@n+?&%s_/g<e[W)XUxRFSLRA;.l=CEkvK-(q";
    for (int i = 0; i < 9; i++)
    {
        string s = ar[i];
        for (char c : s)
        {
            int d = c - '1';
            printf("%c", key[i * 9 + d]);
        }
        printf("%d", 9 - s.length());
    }
    return 0;
}

:u$YBPf2pa]Dt4#QM^H4ic'j0`w2y{d-Zzo2%/n_s@+2<UW)e4AR;F.4=-qEkvC2


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

最后于 2021-5-14 21:17 被Wblank编辑 ,原因:
收藏
点赞1
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回