首页
社区
课程
招聘
[原创] 第二题 南冥神功题解
发表于: 2021-5-11 21:46 4925

[原创] 第二题 南冥神功题解

2021-5-11 21:46
4925

使用ida打开pzcrackme.exe, 跳转到主函数F5, 首先看到输入, 将其重命名为input;

image-1

之后进入循环:

主体逻辑是循环找到a0123456789abcd字符串中输入字符所在的位置keypos之后进入下面的逻辑, 分析见注释:

之后是验证:

所以就是要走迷宫把迷宫走成全是1的.

因为并没有分析它的一系列初始化函数, 怕哪里藏了坑然后静态的数据其实是骗你的, 所以接下来进行动态调试, 也为了绕过可能存在的反ida的调试措施(后来发现并没有) 所以使用frida进行动态调试.

根据分析结果写个frida agent脚本 (使用了typescript):

运行后输出如下:

image-2

起始在左上角, 可以自由向左右上下走, (从0开始算)在偶数行可以向右上或右下走, 在奇数行可以向左上或左下走, 可以手走一遍出结果, 为: convertInput("1234321234321101210050543450501210121234322321")

将其输出出来, 最后flag是GJ0V4LA4VKEVQZSVCNGJ00N

 
 
  if ( strlen(input) <= 0x30 )
  {
    inpc = input[0];
    if ( input[0] )
    {
      ipos = 0;
      y = 0;
      tx = 0;
      length = dword_4B7020;
      keyc = a0123456789abcd[0];
next:
      if ( length > 0 )
      {
        keypos = 0;
        if ( keyc == inpc )
        {
LABEL_11:
        ...(此处暂时省略)
        }
        else
        {
          while ( length != ++keypos )
          {
            if ( a0123456789abcd[keypos] == inpc )
              goto LABEL_11;
          }
        }
      }
    }
  if ( strlen(input) <= 0x30 )
  {
    inpc = input[0];
    if ( input[0] )
    {
      ipos = 0;
      y = 0;
      tx = 0;
      length = dword_4B7020;
      keyc = a0123456789abcd[0];
next:
      if ( length > 0 )
      {
        keypos = 0;
        if ( keyc == inpc )
        {
LABEL_11:
        ...(此处暂时省略)
        }
        else
        {
          while ( length != ++keypos )
          {
            if ( a0123456789abcd[keypos] == inpc )
              goto LABEL_11;
          }
        }
      }
    }
LABEL_11:
    v7 = (ipos + keypos / 6) % 6;
    v8 = keypos + ipos;
    x = tx;
    inp2 = v7;
    inp1 = 5 - v8 % 6; // 将keypos + ipos 按6进制分解为inp1和inp2
    for ( i = 0; ; i = 1 )
    {
    switch ( inp1 ) // 然后走迷宫
    {
        case 1:
            ++x;                            //
            break;
        case 2:
            v17 = (y++ & 1) == 0;           // 偶行 右下 奇行 下
            x += v17;
            break;
        case 3:
            v12 = (y++ & 1) != 0;           // 偶行 下 奇行 左下
            x -= v12;
            break;
        case 4:
            --x;                            //
            break;
        case 5:
            v19 = (y-- & 1) != 0;           // 偶行 上 奇行 左上
            x -= v19;
            break;
        default:                            // 偶行 右上 奇行 上
            v18 = (y-- & 1) == 0;
            x += v18;
            break;
    }
    if ( x > 9 ) // 迷宫有10
        break;
    if ( y > 8 ) // 迷宫有9
        break;
    v13 = &byte_4B7080[10 * y + x]; // 迷宫数据在byte_4B7080
    if ( *v13 )
        break;
    *v13 = 1; // 只能走在数据为0的格子, 走过的位置设为1
    if ( i == 1 )
    {
        ++ipos;
        tx = x;
        inpc = input[ipos];
        if ( inpc )
            goto next;
        goto fin;
    }
    inp1 = inp2;
LABEL_11:
    v7 = (ipos + keypos / 6) % 6;
    v8 = keypos + ipos;
    x = tx;
    inp2 = v7;
    inp1 = 5 - v8 % 6; // 将keypos + ipos 按6进制分解为inp1和inp2
    for ( i = 0; ; i = 1 )
    {
    switch ( inp1 ) // 然后走迷宫
    {
        case 1:
            ++x;                            //
            break;
        case 2:
            v17 = (y++ & 1) == 0;           // 偶行 右下 奇行 下
            x += v17;
            break;
        case 3:
            v12 = (y++ & 1) != 0;           // 偶行 下 奇行 左下
            x -= v12;
            break;
        case 4:
            --x;                            //
            break;
        case 5:
            v19 = (y-- & 1) != 0;           // 偶行 上 奇行 左上
            x -= v19;
            break;
        default:                            // 偶行 右上 奇行 上
            v18 = (y-- & 1) == 0;
            x += v18;
            break;
    }
    if ( x > 9 ) // 迷宫有10
        break;
    if ( y > 8 ) // 迷宫有9
        break;
    v13 = &byte_4B7080[10 * y + x]; // 迷宫数据在byte_4B7080
    if ( *v13 )
        break;
    *v13 = 1; // 只能走在数据为0的格子, 走过的位置设为1
    if ( i == 1 )
    {
        ++ipos;
        tx = x;
        inpc = input[ipos];
        if ( inpc )
            goto next;
        goto fin;
    }
    inp1 = inp2;
v14 = byte_4B7080; // 迷宫数据
v15 = 0;
do
{
    v16 = v14 + 0xA;
    do
        v15 += *v14++ == 0; // 如果迷宫数据中任意位是0 则v15会增加
    while ( v16 != v14 );
} while ( &unk_4B70DA != (_UNKNOWN *)v16 );
if ( !v15 ) // 当v15没有增加时 成功
{
    sub_4ABF30(&dword_4B8860, "Good job!", 9);
    sub_4AD980(&dword_4B8860);
    return 0;
}
v14 = byte_4B7080; // 迷宫数据
v15 = 0;

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

收藏
免费 1
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//