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

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

2021-5-14 21:06
5801

IDA

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

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

导出数独初始值

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

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

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 )
  {
    //...
  }
//...
}
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 )
  {
    //...
  }
//...
}
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;
}
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;                                   // 属于第几列的 记录下来

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

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