吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4036|回复: 7
收起左侧

[CTF] BUUCTF 刮开有奖1题解

[复制链接]
NodeSans 发表于 2021-1-18 22:35

这个题目是我目前为止做过的最难的逆向题目了,相当的恶心。不过适应了也还好。不说了,拿到程序后丢进ida,发现是一个 32 位程序,先进WinMain函数,然后F5反汇编。最终我们拿到了这样的一个程序:

int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
  DialogBoxParamA(hInstance, (LPCSTR)0x67, 0, DialogFunc, 0);
  return 0;
}

其中DialogFunc就是这个窗口的内部程序的程序过程。所以双击函数名进入。然后大致浏览,可以得到这个是该程序的主要逻辑部分。

可以发现,函数sub_4010F0对一个数组进行了预处理,同时还有一个函数sub_401000对输入进行了加密。

通过判断条件

if ( String == v7 + 34
        && v19 == v11
        && 4 * v20 - 141 == 3 * v9
        && v21 / 4 == 2 * (v14 / 9)
        && !strcmp(v4, "ak1w")
        && !strcmp(v5, "V1Ax") )
      {
        MessageBoxA(hDlg, "U g3t 1T!", "@_@", 0);
      }

我们可以知道输入的字符串前半部分对部分预处理结果进行对比判断,然后将输入的后半部分编码和几个已知的字符串进行对比判断。
所以接下来我们的重点是看看这两个函数究竟干了什么。

函数 sub_4010F0

这个函数由于是预处理,我们可以直接将这段伪代码转换成能执行的 C 语言代码,运行求解即可。转换后的代码:

int sub_4010F0(int a1, int a2, int a3)
{
  int result; // eax
  int i;      // esi
  int v5;     // ecx
  int v6;     // edx

  result = a3;
  for (i = a2; i <= a3; a2 = i)
  {
    v5 = 4 * i;
    v6 = *(int *)(4 * i + a1);
    if (a2 < result && i < result)
    {
      do
      {
        if (v6 > *(int *)(a1 + 4 * result))
        {
          if (i >= result)
            break;
          ++i;
          *(int *)(v5 + a1) = *(int *)(a1 + 4 * result);
          if (i >= result)
            break;
          while (*(int *)(a1 + 4 * i) <= v6)
          {
            if (++i >= result)
              goto LABEL_13;
          }
          if (i >= result)
            break;
          v5 = 4 * i;
          *(int *)(a1 + 4 * result) = *(int *)(4 * i + a1);
        }
        --result;
      } while (i < result);
    }
  LABEL_13:
    *(int *)(a1 + 4 * result) = v6;
    sub_4010F0(a1, a2, i - 1);
    result = a3;
    ++i;
  }
  return result;
}

至于转换得到方法,其实也很简单,就是将一些不属于 C 的变量类型换掉就可以了,这个网上有不少博客都有总结,可以自行百度。

这个程序因为是 32 位程序,所以这个函数只能在32位环境下才能正常运行,要不然会因为64位指针类型和32位指针类型占用的空间大小不一样,可能导致运行出错或是无法编译。

64位系统要如何编译32位程序可以看下面这个博客
https://blog.csdn.net/x356982611/article/details/79056089

运行后用 debug 查看结果如下:
IuvoYNyViszgkwS
然后根据判断条件,就得到了开头的几个输入。

没准这个函数就是排序函数呢,不过这么大串代码不会真的有人去读吧

函数 sub_401000

接下来我们就来分析这个函数。这个函数因为是对输入加密,所以比较复杂,但是这个函数的代码也是相当复杂,如果我们对这个函数的程序一行一行去读,估计也是读不出来什么的。所以我们按照上面所说的,将函数的伪代码转换成能运行的C代码。

char *sub_401000(int a1, int a2)
{
  int v2;         // eax
  int v3;         // esi
  size_t v4;      // ebx
  char *v5;       // eax
  char *v6;       // edi
  int v7;         // eax
  char *v8;       // ebx
  int v9;         // edi
  signed int v10; // edx
  int v11;        // edi
  signed int v12; // eax
  signed int v13; // esi
  char *result;   // eax
  char *v15;      // [esp+Ch] [ebp-10h]
  char *v16;      // [esp+10h] [ebp-Ch]
  int v17;        // [esp+14h] [ebp-8h]
  int v18;        // [esp+18h] [ebp-4h]

  v2 = a2 / 3;
  v3 = 0;
  if (a2 % 3 > 0)
    ++v2;
  v4 = 4 * v2 + 1;
  v5 = (char *)malloc(v4);
  v6 = v5;
  v15 = v5;
  if (!v5)
    exit(0);
  memset(v5, 0, v4);
  v7 = a2;
  v8 = v6;
  v16 = v6;
  if (a2 > 0)
  {
    while (1)
    {
      v9 = 0;
      v10 = 0;
      v18 = 0;
      do
      {
        if (v3 >= v7)
          break;
        ++v10;
        v9 = *(unsigned char *)(v3++ + a1) | (v9 << 8);
      } while (v10 < 3);
      v11 = v9 << 8 * (3 - v10);
      v12 = 0;
      v17 = v3;
      v13 = 18;
      do
      {
        if (v10 >= v12)
        {
          *((char *)&v18 + v12) = (v11 >> v13) & 0x3F;
          v8 = v16;
        }
        else
        {
          *((char *)&v18 + v12) = 64;
        }
        *v8++ = byte_407830[*((char *)&v18 + v12)];
        v13 -= 6;
        ++v12;
        v16 = v8;
      } while (v13 > -6);
      v3 = v17;
      if (v17 >= a2)
        break;
      v7 = a2;
    }
    v6 = v15;
  }
  result = v6;
  *v8 = 0;
  return result;
}

然后我们将部分数据代入这个函数,然后得到输出,然后丢到一些自动判断加密算法的程序,看看是不是一些已知的加密或者编码算法。比如说这个网站就可以

https://www.cmd5.com

PEsoWNeOuZkxMrX

然后我们知道这个加密算法是 base64 编码算法。接下来的步骤就简单了,因为base64可逆,只需要将伪代码中的"ak1w","V1Ax"字符串解码就可以得到了剩下的几个输入了。

话说为啥这个题目我死活找不到输入在哪里啊,是我 win API 编程还不太熟悉吗?希望有大佬能在评论区指出来该怎么输入这个逆向出来的密码啊

免费评分

参与人数 1威望 +1 吾爱币 +20 热心值 +1 收起 理由
Hmily + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

dabaigege 发表于 2021-1-20 14:45
没有回复呢   我看不懂
lifz888 发表于 2021-1-20 16:58
 楼主| NodeSans 发表于 2021-1-20 17:55
CCCDD 发表于 2021-7-28 11:09
本帖最后由 CCCDD 于 2021-7-28 16:56 编辑

同没有找到输入,最后得到零散的字母和base64解密后的结果不知道怎么拼接
0xK4ws 发表于 2021-8-14 06:17
我也想知道如何定位到输入位置
Songhi 发表于 2022-11-12 12:04
为什么我找到这个函数F5直接不能用,然后我直接看这个函数偏移位置也没办法跳转。为啥捏,哭了。
keaidexiaoyu 发表于 2022-11-13 14:17

如何定位到输入位置啊请问
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-5-11 10:40

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表