首页
社区
课程
招聘
[原创] 看雪 2025 KCTF 第二题 初窥门径
发表于: 2025-8-16 17:46 5209

[原创] 看雪 2025 KCTF 第二题 初窥门径

2025-8-16 17:46
5209

_main(0x7014C0)函数获取输入字符串,长度不超过 112
从 sub_701280 进入,有两处跳转

到达 0x70129F ,是主要逻辑所在。

创建一个函数反编译:

(以下结合AI辅助分析)

中间的while循环将输入的字符v15转换为0-35的整数v12("0123456789abcdefghijklmnopqrstuvwxyz"的索引),按照 0-11, 12-23, 24-35 分别对应 z 的值 0, 1, 2;偶数索引的值 % 12 作为 y 坐标,奇数索引的值 % 12 作为 x 坐标;每两个输入字符在奇数索引处进行合法性检查(dword_703020 数组在坐标位置的值满足 sub_7011C0 的要求)。

sub_701000 是牛顿法计算平方根,sub_701170 是质数检验,sub_7011C0 前半部分内联了 sub_701170 ,整体作用是尝试把参数拆分为两个质数相乘。

dword_703020 全局常量变量是 3 * 10 * 10 的表,对应 x, y, z 坐标,并且可以离线按照 sub_7011C0 的逻辑找到所有满足条件的位置。
符合条件的位置有 56 个,为 [0, 1, 11, 35, 45, 53, 55, 56, 57, 63, 67, 71, 72, 73, 101, 102, 103, 107, 108, 113, 117, 121, 122, 123, 125, 126, 127, 131, 141, 142, 143, 154, 155, 156, 157, 160, 161, 170, 198, 208, 209, 219, 229, 238, 239, 244, 248, 254, 258, 260, 261, 262, 263, 264, 268, 269] (注意输入长度限制为112,恰好是56的两倍,大致能对应两个输入值做一次检测)

sub_70129F 需要转换后的输入坐标位于符合条件的位置,且相邻坐标的距离等于1,且固定首位的位置。将56个位置转换到坐标并重新排列后得到 [(0, 0, 0), (1, 0, 0), (1, 1, 0), (1, 1, 1), (2, 1, 1), (3, 1, 1), (3, 2, 1), (3, 3, 1), (2, 3, 1), (1, 3, 1), (1, 4, 1), (1, 5, 1), (2, 5, 1), (3, 5, 1), (3, 5, 0), (3, 6, 0), (3, 7, 0), (2, 7, 0), (1, 7, 0), (1, 7, 1), (0, 7, 1), (0, 8, 1), (0, 8, 2), (1, 8, 2), (2, 8, 2), (3, 8, 2), (4, 8, 2), (4, 7, 2), (4, 6, 2), (4, 6, 1), (5, 6, 1), (6, 6, 1), (7, 6, 1), (7, 6, 0), (7, 5, 0), (6, 5, 0), (5, 5, 0), (5, 4, 0), (5, 3, 0), (5, 3, 1), (6, 3, 1), (7, 3, 1), (7, 2, 1), (7, 1, 1), (8, 1, 1), (8, 1, 2), (8, 2, 2), (9, 2, 2), (9, 3, 2), (9, 4, 2), (9, 5, 2), (8, 5, 2), (8, 6, 2), (8, 7, 2), (8, 8, 2), (9, 8, 2)]

最后反向转换回输入的格式,验证通过。

一个正确的输入: 0001111d1e1f2f3f3e3d4d5d5e5f53637372717d7c8c8o8p8q8r8s7s6s6g6h6i6j6757565545353h3i3j2j1j1k1w2w2x3x4x5x5w6w7w8w8x

多解:y 坐标的转换很松散,只检查了 % 12 却没有限制 // 12 ,所以输入序列的每个偶数位置都有两到三个合法的取值。例如 c001111d1e1f2f3f3e3d4d5d5e5f53637372717d7c8c8o8p8q8r8s7s6s6g6h6i6j6757565545353h3i3j2j1j1k1w2w2x3x4x5x5w6w7w8w8x。另外,x 坐标转换时 % 的是 12 ,而 dword_703020 的横坐标范围是 10 ,也可能造成影响。

.text:007011B6 ; void sub_7011B6()
.text:007011B6 sub_7011B6      proc near               ; CODE XREF: sub_701280+14↓p
.text:007011B6
.text:007011B6 arg_0           = dword ptr  4
.text:007011B6
.text:007011B6                 mov     [esp+arg_0], offset sub_701EEB
.text:007011BE                 retn
.text:007011BE sub_7011B6      endp
.text:007011B6 ; void sub_7011B6()
.text:007011B6 sub_7011B6      proc near               ; CODE XREF: sub_701280+14↓p
.text:007011B6
.text:007011B6 arg_0           = dword ptr  4
.text:007011B6
.text:007011B6                 mov     [esp+arg_0], offset sub_701EEB
.text:007011BE                 retn
.text:007011BE sub_7011B6      endp
.text:00701B25 sub_701B25      proc near               ; CODE XREF: sub_701EEB+B↓p
.text:00701B25
.text:00701B25 arg_0           = dword ptr  4
.text:00701B25
.text:00701B25                 mov     [esp+arg_0], offset loc_70129F
.text:00701B2D                 retn
.text:00701B2D sub_701B25      endp
.text:00701B25 sub_701B25      proc near               ; CODE XREF: sub_701EEB+B↓p
.text:00701B25
.text:00701B25 arg_0           = dword ptr  4
.text:00701B25
.text:00701B25                 mov     [esp+arg_0], offset loc_70129F
.text:00701B2D                 retn
.text:00701B2D sub_701B25      endp
// positive sp value has been detected, the output may be wrong!
char __usercall sub_70129F@<al>(
        int a1@<eax>,
        int a2@<edx>,
        int a3@<ebp>,
        const char *a4@<esi>,
        int a5,
        int a6,
        int a7,
        int a8,
        int a9,
        int a10,
        int a11)
{
  int v11; // edi
  int v12; // ecx
  char *index; // edx
  int y; // ebx
  char v15; // al
  int z; // esi
  char *v18; // ecx
  int v19; // edx
  int x; // edi
  char *v21; // ecx
  char *retaddr; // [esp+0h] [ebp+0h]
  int input_length; // [esp+4h] [ebp+4h]
  int v24; // [esp+8h] [ebp+8h]
  int lastx; // [esp+Ch] [ebp+Ch]
  int lasty; // [esp+10h] [ebp+10h]
  int lastz; // [esp+14h] [ebp+14h]
 
  if ( a1 != a2 )
  {
    v11 = strlen(a4);
    v12 = 0;
    index = 0;
    y = 0;
    input_length = v11;
    lastz = 0;
    lasty = 0;
    lastx = 0;
    v24 = 0;
    retaddr = 0;
    if ( v11 > 0 )
    {
      while ( 1 )
      {
        v15 = a4[(_DWORD)index];
        while ( a0123456789abcd[v12] != v15 )
        {
          if ( a0123456789abcd[v12 + 1] == v15 )
          {
            ++v12;
            break;
          }
          if ( a0123456789abcd[v12 + 2] == v15 )
          {
            v12 += 2;
            break;
          }
          if ( a0123456789abcd[v12 + 3] == v15 )
          {
            v12 += 3;
            break;
          }
          if ( a0123456789abcd[v12 + 4] == v15 )
          {
            v12 += 4;
            break;
          }
          if ( a0123456789abcd[v12 + 5] == v15 )
          {
            v12 += 5;
            break;
          }
          v12 += 6;
          if ( v12 >= 36 )
            return 0;
        }
        if ( v12 >= 36 )
          break;
        if ( v12 >= 12 )
          z = (v12 >= 24) + 1;
        else
          z = 0;
        if ( ((unsigned __int8)index & 1) != 0 )
        {
          v19 = v24 + 1;
          x = v12 % 12;
          v24 = v19;
          if ( v19 == 1 && dword_703020[80 * z + 10 * z + 10 * y + x] != 0x2C0E )
            return 0;
          v18 = retaddr;
          if ( retaddr == (char *)(input_length - 1) && dword_703020[80 * z + 10 * z + 10 * y + x] != 0x1FB2 )
            return 0;
          if ( v19 > 1 )
          {
            if ( (int)retaddr < input_length
              && (!sub_7011C0(dword_703020[80 * z + 10 * z + 10 * y + x], &a10, &a11) || a10 < 2
                                                                                      || a11 < 2
                                                                                      || a10 == a11)
              || abs32(x - lastx) + abs32(y - lasty) + abs32(z - lastz) != 1 )
            {
              return 0;
            }
            v18 = retaddr;
          }
          lastx = x;
          lasty = y;
          lastz = z;
          if ( v18 == (char *)(input_length - 1) && dword_703020[80 * z + 10 * z + 10 * y + x] == 8114 )
            return 1;
          v11 = input_length;
        }
        else
        {
          y = v12 % 12;
          v18 = retaddr;
        }
        v21 = v18 + 1;
        retaddr = v21;
        if ( (int)v21 >= v11 )
          return 0;
        a4 = *(const char **)(a3 + 8);
        index = v21;
        v12 = 0;
      }
    }
  }
  return 0;
}
// positive sp value has been detected, the output may be wrong!
char __usercall sub_70129F@<al>(
        int a1@<eax>,
        int a2@<edx>,
        int a3@<ebp>,
        const char *a4@<esi>,
        int a5,
        int a6,
        int a7,
        int a8,
        int a9,
        int a10,
        int a11)
{
  int v11; // edi
  int v12; // ecx
  char *index; // edx
  int y; // ebx
  char v15; // al
  int z; // esi
  char *v18; // ecx
  int v19; // edx
  int x; // edi
  char *v21; // ecx
  char *retaddr; // [esp+0h] [ebp+0h]
  int input_length; // [esp+4h] [ebp+4h]
  int v24; // [esp+8h] [ebp+8h]
  int lastx; // [esp+Ch] [ebp+Ch]
  int lasty; // [esp+10h] [ebp+10h]
  int lastz; // [esp+14h] [ebp+14h]
 
  if ( a1 != a2 )
  {
    v11 = strlen(a4);
    v12 = 0;
    index = 0;
    y = 0;
    input_length = v11;
    lastz = 0;
    lasty = 0;
    lastx = 0;
    v24 = 0;
    retaddr = 0;
    if ( v11 > 0 )
    {
      while ( 1 )
      {
        v15 = a4[(_DWORD)index];
        while ( a0123456789abcd[v12] != v15 )
        {
          if ( a0123456789abcd[v12 + 1] == v15 )
          {
            ++v12;
            break;
          }
          if ( a0123456789abcd[v12 + 2] == v15 )
          {
            v12 += 2;
            break;
          }
          if ( a0123456789abcd[v12 + 3] == v15 )
          {
            v12 += 3;
            break;
          }
          if ( a0123456789abcd[v12 + 4] == v15 )
          {
            v12 += 4;
            break;
          }
          if ( a0123456789abcd[v12 + 5] == v15 )
          {
            v12 += 5;
            break;
          }
          v12 += 6;
          if ( v12 >= 36 )
            return 0;
        }
        if ( v12 >= 36 )
          break;
        if ( v12 >= 12 )
          z = (v12 >= 24) + 1;
        else
          z = 0;
        if ( ((unsigned __int8)index & 1) != 0 )
        {
          v19 = v24 + 1;
          x = v12 % 12;
          v24 = v19;
          if ( v19 == 1 && dword_703020[80 * z + 10 * z + 10 * y + x] != 0x2C0E )
            return 0;
          v18 = retaddr;
          if ( retaddr == (char *)(input_length - 1) && dword_703020[80 * z + 10 * z + 10 * y + x] != 0x1FB2 )
            return 0;
          if ( v19 > 1 )
          {
            if ( (int)retaddr < input_length
              && (!sub_7011C0(dword_703020[80 * z + 10 * z + 10 * y + x], &a10, &a11) || a10 < 2
                                                                                      || a11 < 2
                                                                                      || a10 == a11)
              || abs32(x - lastx) + abs32(y - lasty) + abs32(z - lastz) != 1 )
            {
              return 0;
            }
            v18 = retaddr;
          }
          lastx = x;
          lasty = y;
          lastz = z;
          if ( v18 == (char *)(input_length - 1) && dword_703020[80 * z + 10 * z + 10 * y + x] == 8114 )
            return 1;
          v11 = input_length;
        }
        else
        {
          y = v12 % 12;
          v18 = retaddr;
        }
        v21 = v18 + 1;
        retaddr = v21;
        if ( (int)v21 >= v11 )
          return 0;
        a4 = *(const char **)(a3 + 8);
        index = v21;
        v12 = 0;
      }
    }
  }
  return 0;
}
char __cdecl sub_7011C0(int a1, int *a2, int *a3)
{
  int v4; // edi
  int v5; // ecx
  int v6; // esi
  int v7; // ecx
  int v9; // [esp+1Ch] [ebp-4h]
  int v10; // [esp+24h] [ebp+4h]
 
  if ( a1 < 4 )
    return 0;
  v4 = 2;
  v9 = 2;
  v5 = (int)isqrt((double)a1);  // sub_701000
  v10 = v5;
  if ( v5 < 2 )
    return 0;
  while ( 1 )
  {
    if ( a1 % v4 || v4 < 2 )
      goto LABEL_10;
    v6 = 2;
    v7 = (int)isqrt((double)v9);  // sub_701000
    if ( v7 >= 2 )
    {
      while ( v4 % v6 )
      {
        if ( ++v6 > v7 )
          goto LABEL_8;
      }
      goto LABEL_9;
    }
LABEL_8:
    if ( is_prime(a1 / v4) )  // sub_701170
      break;
LABEL_9:
    v5 = v10;
LABEL_10:
    v9 = ++v4;
    if ( v4 > v5 )
      return 0;
  }
  if ( a2 )
    *a2 = v4;
  if ( a3 )
    *a3 = a1 / v4;
  return 1;
}
char __cdecl sub_7011C0(int a1, int *a2, int *a3)
{
  int v4; // edi
  int v5; // ecx
  int v6; // esi
  int v7; // ecx
  int v9; // [esp+1Ch] [ebp-4h]
  int v10; // [esp+24h] [ebp+4h]
 
  if ( a1 < 4 )
    return 0;
  v4 = 2;
  v9 = 2;
  v5 = (int)isqrt((double)a1);  // sub_701000
  v10 = v5;
  if ( v5 < 2 )

[培训]Windows内核深度攻防:从Hook技术到Rootkit实战!

最后于 2025-8-16 17:49 被mb_mgodlfyn编辑 ,原因:
收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回