首页
社区
课程
招聘
[原创]KCTF 2023 第三题 秘密计划 解题过程
发表于: 2023-9-6 14:00 8692

[原创]KCTF 2023 第三题 秘密计划 解题过程

xym 活跃值
4
2023-9-6 14:00
8692
下载后发现exe文件本身还挺大的,除了一个txt说明文件外还带了一个code.dat数据文件。首先查看exe文件本身的构成,在资源节发现一个zip包,dump下来后发现里面是一堆xml和image图片,是程序的主界面相关资源。里面没有代码之类的感兴趣的东西。
直接运行发现需要输入32位字符串才有验证的提示,而且输入无法多于32位,因此随意输入一组字符串进行测试。
ida打开后发现字符串没有加密,里面可以搜索到code.dat,并定位到sub_40DA90这个函数。加载调试后发现会报异常,根据报异常的线程反溯到sub_405F10函数。该函数调用CreateTimerQueueTimer启动反调试,而调用该函数前需要判断是否成功调用CreateTimerQueue函数,因此修改CreateTimerQueue的返回值就可以实现去掉反调试。
去掉反调试后继续跟踪sub_40DA90,发现调用该函数的代码下方启动了虚拟机并运行了一段arm代码。
下载后发现exe文件本身还挺大的,除了一个txt说明文件外还带了一个code.dat数据文件。首先查看exe文件本身的构成,在资源节发现一个zip包,dump下来后发现里面是一堆xml和image图片,是程序的主界面相关资源。里面没有代码之类的感兴趣的东西。
直接运行发现需要输入32位字符串才有验证的提示,而且输入无法多于32位,因此随意输入一组字符串进行测试。
ida打开后发现字符串没有加密,里面可以搜索到code.dat,并定位到sub_40DA90这个函数。加载调试后发现会报异常,根据报异常的线程反溯到sub_405F10函数。该函数调用CreateTimerQueueTimer启动反调试,而调用该函数前需要判断是否成功调用CreateTimerQueue函数,因此修改CreateTimerQueue的返回值就可以实现去掉反调试。
去掉反调试后继续跟踪sub_40DA90,发现调用该函数的代码下方启动了虚拟机并运行了一段arm代码。
uc_mem_map((int)uc, 0, 0, (int)sub_A00000, 7, (int)lpAddress);
            v21 = v41;
            uc_mem_write((int)uc, 0x43000i64, (int)v40, v41);
            v22 = Src;
            if ( v56 >= 0x10 )
              v22 = (void **)Src[0];
            uc_mem_write((int)uc, 0x4033i64, (int)v22, v55);
            if ( uc_emu_start(a1, v17, (int)uc, 0x43000, 0, v21 + 0x43000, 0, 0i64, 0) )
            {
              v9 = v47;
              v23 = (void (__stdcall *)(HWND, UINT, WPARAM, LPARAM))SendMessageW;
            }
            else
            {
              memset(wParam, 0, sizeof(wParam));
              uc_mem_read((int)uc, 0x14390u, 0, (LPBYTE)wParam, 0x20u);
              v9 = v47;
              v23 = (void (__stdcall *)(HWND, UINT, WPARAM, LPARAM))SendMessageW;
              v48 = 1;                          // 虚拟机执行成功
              SendMessageW((HWND)v47[7], 0x47Eu, (WPARAM)wParam, 0);// 保存结果
            }
            sub_44E300((int)uc, 0, 0, (int)sub_A00000);
            uc_close((char *)uc);
uc_mem_map((int)uc, 0, 0, (int)sub_A00000, 7, (int)lpAddress);
            v21 = v41;
            uc_mem_write((int)uc, 0x43000i64, (int)v40, v41);
            v22 = Src;
            if ( v56 >= 0x10 )
              v22 = (void **)Src[0];
            uc_mem_write((int)uc, 0x4033i64, (int)v22, v55);
            if ( uc_emu_start(a1, v17, (int)uc, 0x43000, 0, v21 + 0x43000, 0, 0i64, 0) )
            {
              v9 = v47;
              v23 = (void (__stdcall *)(HWND, UINT, WPARAM, LPARAM))SendMessageW;
            }
            else
            {
              memset(wParam, 0, sizeof(wParam));
              uc_mem_read((int)uc, 0x14390u, 0, (LPBYTE)wParam, 0x20u);
              v9 = v47;
              v23 = (void (__stdcall *)(HWND, UINT, WPARAM, LPARAM))SendMessageW;
              v48 = 1;                          // 虚拟机执行成功
              SendMessageW((HWND)v47[7], 0x47Eu, (WPARAM)wParam, 0);// 保存结果
            }
            sub_44E300((int)uc, 0, 0, (int)sub_A00000);
            uc_close((char *)uc);
该虚拟机内存分为3段,其中0x43000地址处为代码,保持不变,0x4033地址处为输入,和界面上的输入相关,而且变化很大,0x14390地址处为输出,运行后读出0x20字节大小并通过0x47E消息发送给主程序。继续分析虚拟机的代码。
该虚拟机内存分为3段,其中0x43000地址处为代码,保持不变,0x4033地址处为输入,和界面上的输入相关,而且变化很大,0x14390地址处为输出,运行后读出0x20字节大小并通过0x47E消息发送给主程序。继续分析虚拟机的代码。
void __noreturn sub_4363C()
{
  int v0; // r1
  char *v1; // r0
  const char *v2; // r2
  int v3; // r5
  int v4; // r3
  int v5; // r4
 
  v0 = 12;
  while ( 1 )
  {
    v1 = "e1b85b27d6bcb05846c18e6a48f118e89f0c0587140de9fb3359f8370d0dba08";
    v2 = "4fc82b26aecb47d2868c4efbe3581732a3e7cbcc6c2efb32062c08170a05eeb8";
    v3 = 0;
    --v0;
    do
    {
      v4 = *(_DWORD *)v1;
      v5 = *(_DWORD *)v2;
      if ( ++v3 >= 16 )
      {
        if ( "4fc82b26aecb47d2868c4efbe3581732a3e7cbcc6c2efb32062c08170a05eeb8" == "6749dae311865d64db83d5ae75bac3c9e36b3aa6f24caba655d9682f7f071023" )
        {
          dword_14390 = 1;
          dword_143A8 = 1;
        }
LABEL_9:
        JUMPOUT(0x43754);
      }
      v1 += 4;
      v2 += 4;
    }
    while ( v4 == v5 );
    if ( !v0 )
      goto LABEL_9;
  }
}
void __noreturn sub_4363C()
{
  int v0; // r1
  char *v1; // r0
  const char *v2; // r2
  int v3; // r5
  int v4; // r3
  int v5; // r4
 
  v0 = 12;
  while ( 1 )
  {
    v1 = "e1b85b27d6bcb05846c18e6a48f118e89f0c0587140de9fb3359f8370d0dba08";
    v2 = "4fc82b26aecb47d2868c4efbe3581732a3e7cbcc6c2efb32062c08170a05eeb8";
    v3 = 0;
    --v0;
    do
    {
      v4 = *(_DWORD *)v1;
      v5 = *(_DWORD *)v2;
      if ( ++v3 >= 16 )
      {
        if ( "4fc82b26aecb47d2868c4efbe3581732a3e7cbcc6c2efb32062c08170a05eeb8" == "6749dae311865d64db83d5ae75bac3c9e36b3aa6f24caba655d9682f7f071023" )
        {

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2023-9-7 12:20 被kanxue编辑 ,原因:
收藏
免费 1
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//