首页
社区
课程
招聘
[讨论]25KCTF-初窥门径
发表于: 2025-8-18 05:48 3995

[讨论]25KCTF-初窥门径

2025-8-18 05:48
3995

25KCTF-初窥门径

IDA反编译main函数,可以看到第一个条件,要求输入长度>0x70(112)

 

1

Dbg跟进到sub_0070129E,这个就是验证函数,但由于程序是通过Shellcode的方式间接调用到验证函数,IDA识别不出该函数有关的调用,所以会出现如 3所示的未定义情况。解决方案是在0070129E的位置上按下P键,创建函数定义。此时IDA便可进行F5反编译函数,效果如 4所示。

 

2

 

3

 

4

先梳理一下验证流程,首先是要求输入长度>0x70,其次是要求sub_0070129E的返回值为1

根据返回值回溯第一个条件,通过动态调试确定符号信息,v19是某个indexv24-1是输入字符串的最后一个indexdword_703020是张映射表,映射关系是80 * v18 + 10 * v18 + 10 * v15 + v21,关系涉及到三个变量,分别为v18v15v21。映射值为8114时即走向验证成功。

if ( v19 == v24 - 1 && dword_703020[80 * v18 + 10 * v18 + 10 * v15 + v21] == 8114 )

  return 1;

第二个条件如下表所示,v23是某个indexv24是输入字符串的长度;与dword_703020相关的映射关系和第一个条件是相同的;a11为栈ESPa11为栈ESP+4

经验之谈,一般ESP寄存器值的bit4位是0001,地址与19FE 2000相像。所以a11<2a12<2a11 == a12是假条件,永不成立。最终我们需要关注的是v23 < v24 && (!sub_7011C0(dword_703020[80 * v18 + 10 * v18 + 10 * v15 + v21], &a11, &a12)abs32(v21 - v26) + abs32(v15 - v27) + abs32(v18 - v28) != 1 )

if ( v23 < v24

  && (!sub_7011C0(dword_703020[80 * v18 + 10 * v18 + 10 * v15 + v21], &a11, &a12)

    || a11 < 2

    || a12 < 2

    || a11 == a12)

  || abs32(v21 - v26) + abs32(v15 - v27) + abs32(v18 - v28) != 1 )

{

  return 0;

}

由于v23是某个indexv24是输入字符串的长度,猜测v23一直小于24,即在条件当中恒为1

这就要求!sub_7011C0的值为0,即sub_7011C0的返回值为1,使得1 && !sub_7011C0的结果为0。这样就不会走向return 0。其次是abs32(v21 - v26) + abs32(v15 - v27) + abs32(v18 - v28) != 1 ),要求表达式的值为1,这样不会走向return 0,涉及到六个变量,分别为v18v15v21v28v27v26。我们要做的,就是搞清楚俩组变量之间的关系。

第三个条件如下表所示,v20 是某个 index,要求dword_703020的映射值为11278,否则走向验证失败。

if ( v20 == 1 && dword_703020[80 * v18 + 10 * v18 + 10 * v15 + v21] != 11278 )

    return 0;

第四个条件如下表所示,v23为某个indexv24-1为输入字符串的最后一个index,要求其为最后一个index同时dword_703020的映射值为8114,否则走向验证失败。

if ( v23 == v24 - 1 && dword_703020[80 * v18 + 10 * v18 + 10 * v15 + v21] != 8114 )

  return 0;

V14为当前的indexv14 & 1 != 0,取当前index的最低位与1做与运算,即每当v14位偶数时触发验证。同时也意味着输入字符串2字节为一组。

if ( (v14 & 1) != 0 )

{

  // 开始条件验证

}

接下来是6个变量的关系,可以发现后一组的三个变量保存着上一次index的值。前一组变量都根据v13计算,而v13的值根据byte_7020F9表和input[index]映射出。

if ( (v14 & 1) != 0 )

{        

  v21 = v13 % 12;

  if ( v13 >= 12 )

            v18 = (v13 >= 24) + 1;

          else

            v18 = 0;

}

else{

  v15 = v13 % 12;

}

 

// 验证后

v26 = v21;

v27 = v15;

v28 = v18;

v13 根据表byte_7020F9input[index]映射出

输入条件根据80 * v18 + 10 * v18 + 10 * v15 + v21推出变量的范围,最终通过打表的方式得到一张完整的合法输入表(input_unit)。

v21 = v13 % 12; (v12恒小于12)

v15 = v13 % 12; (v15恒小于12)

v18恒小于2,根据dword_703020[index] == 8114index得出,index269,当v17>3时,80 * 3 + 10 * 3 = 270,必然走向验证失败

// 由于idb丢了,所以实际算法与理论存在符号偏差

for (size_t v17 = 0; v17 <= 2; v17++)

{

  for (size_t v14 = 0; v14 < 12; v14++)

  {

    for (size_t v20 = 0; v20 < 12; v20++)

    {

      int f = sub_7011C0(dword_703020[table_offset], &a10, &a11);

      if (f == 1)

      {

 

        char left = str_table[v14];

        char right = str_table[v17 * 12 + v20];

        Unit unit;

        unit.v17 = v17;

        unit.v14 = v14;

        unit.v20 = v20;

        unit.left = left;

        unit.right = right;

        input_unit.push_back(unit);

      }


传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2025-8-18 14:23 被zZhouQing编辑 ,原因:
上传的附件:
收藏
免费 1
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回