首页
论坛
专栏
课程

[原创]2019看雪CTF 第四题:达芬奇密码

2019-6-27 00:50 2985

[原创]2019看雪CTF 第四题:达芬奇密码

2019-6-27 00:50
2985
运行程序,随便输入一串字符,弹出提示框:

将程序拖入IDA,打开Strings窗口搜索 Wrong
emmmm,居然没有搜索到,这表示程序会在运行过程中,动态解密所需字符串。
动态调试,果然在程序内存中发现有Wrong字符串,计算出Wrong字符串偏移是0x1FDE
IDA打开程序,按住Ctrl+S,找出基址为0x400000,Wrong字符串在程序中偏移地址为0x400000+0x1FDE=0x401FDE
按G,输入0x401FDE,跳转到对应位置,按F5反编译成伪代码:
int __thiscall sub_401EA0(CWnd *this)
{
  CWnd *v1; // esi
  int v2; // eax
  WCHAR String; // [esp+Ch] [ebp-310h]
  char v5; // [esp+Eh] [ebp-30Eh]
  char v6; // [esp+20Ch] [ebp-110h]
  char v7; // [esp+20Dh] [ebp-10Fh]
  DWORD v8; // [esp+30Ch] [ebp-10h]
  CWnd *v9; // [esp+310h] [ebp-Ch]
  unsigned int v10; // [esp+314h] [ebp-8h]
  DWORD flOldProtect; // [esp+318h] [ebp-4h]

  v1 = this;
  v9 = this;
  String = 0;
  memset(&v5, 0, 0x1FEu);
  v6 = 0;
  memset(&v7, 0, 0xFFu);
  CWnd::GetDlgItemTextW(v1, 0x3E8, &String, 0x14);
  if ( wcslen(&String) == 0x10 )
  {
    v2 = 0;
    while ( !(*(&String + v2) & 0xFF00) )
    {
      *(&v6 + v2) = *((_BYTE *)&String + 2 * v2);
      if ( ++v2 >= 0x10 )
      {
        v8 = 0x40;
        flOldProtect = 0;
        VirtualProtect(sub_4010E0, 0xD17u, 0x40u, &flOldProtect);
        if ( GetLastError() )
          return CWnd::MessageBoxW(v1, L"Wrong!", 0, 0);
        qmemcpy(sub_4010E0, &byte_5647B8, 0x330u);
        VirtualProtect(sub_4010E0, 0xD17u, flOldProtect, &v8);
        if ( !GetLastError() )
        {
          v10 = 0;
          v10 = sub_4010E0();
          if ( v10 == 1 )
            return CWnd::MessageBoxW(v9, L"Congratulations! You are right!", 0, 0);
        }
        v1 = v9;
        return CWnd::MessageBoxW(v1, L"Wrong!", 0, 0);
      }
    }
  }
  return CWnd::MessageBoxW(v1, L"Wrong!", 0, 0);
}

if ( wcslen(&String) == 0x10 ) //只能输入长度为16的字符

while ( !(*(&String + v2) & 0xFF00) ) // 字符范围是从0001到00FF,即ASCII码

动态解密函数sub_4010E0
VirtualProtect(sub_4010E0, 0xD17u, 0x40u, &flOldProtect);
if ( GetLastError() ) return CWnd::MessageBoxW(v1, L"Wrong!", 0, 0);
qmemcpy(sub_4010E0, &byte_5647B8, 0x330u);
VirtualProtect(sub_4010E0, 0xD17u, flOldProtect, &v8);

qmemcpy引起我的兴趣,其作用为将一段长度为0x330的字符复制到sub_4010E0里面。右击byte_5647B8,查找引用。发现sub_401D80()做了一些操作,它异或了0xAB

只要函数sub_4010E0返回值为1,我们就达到目的

上面已经分析过了,函数sub_4010E0是动态解密的。动态调试程序,等它解密完成(即qmemcpy()运行后),再分析sub_4010E0函数。

因为代码太长了,我就不贴了,万一被认为水字数就不好了。⁄(⁄⁄•⁄ω⁄•⁄⁄)

仔细分析了一下代码,emmmmm,居然是解二元二次方程!!!⁄想起高考前被数学支配的恐惧 ヽ(。>д<)p
解完方程还要异或一下,后面有说明。

方程为x*x-7y*y=8,且1<<56 <= x < 1<<60、1<<56 <= y < 1<<60

手动运算是不可能的,编程也不会,只能靠好心的大佬们的程序才能维持得了生活的样子,咕咕咕。

这里使用wolframalpha算出x = 385044246406735194, y = 145533045678356702
wolframalpha网址:https://www.wolframalpha.com/

//分析sub_4010E0函数得到的
XorTable = [0x16, 0x96, 0x8c, 0xe3, 0x81, 0x98, 0x6e, 0x64,
            0x84, 0x08, 0xdc, 0x81, 0xbe, 0x4d, 0x48, 0x4f]
将x,y转换为十六进制,和XorTable异或一下,颠倒顺序,拼接,转换成字符串,得到密码:L3mZ2k9aZ0a36DMM

忙到半夜,困死了,补觉



[公告]安全服务和外包项目请将项目需求发到看雪企服平台:https://qifu.kanxue.com

最后于 2019-6-27 15:28 被xmhwws编辑 ,原因:
最新回复 (0)
游客
登录 | 注册 方可回帖
返回