zoukankan      html  css  js  c++  java
  • LuckyStar hctf2018

    LuckyStar hctf2018

    程序注册有TLS回调函数

    char __stdcall TlsCallback_0(int a1, int a2, int a3)
    {
      char result; // al
      HMODULE v4; // eax
      HMODULE v5; // eax
      HMODULE v6; // eax
      int (__usercall *ptr_main)@<eax>(int@<ebp>); // esi
      signed int v8; // edi
      HANDLE v9; // eax
    
      result = a2;
      if ( a2 == 1 )
      {
        v4 = GetModuleHandleA("ntdll.dll");
        dword_407378 = sub_401360(v4, "a7d7bcc95a86a6df3b0a1ccb3c69d440");//此处应该是获取库中的某个函数,我们动态调试的时候看一下
        v5 = GetModuleHandleA("ntdll.dll");
        dword_407380 = (int (__stdcall *)(_DWORD, _DWORD, _DWORD, _DWORD))sub_401360(v5, "8eb35a28209979fe6a9983cff0d23c5a");
        v6 = GetModuleHandleA("kernel32.dll");
        dword_407374 = sub_401360(v6, "05577e1568efa10b8166728bfb414c59");
        srand(0x61616161u);//设置随机数的种子(影响后面main函数中的rand)
        ptr_main = main_401780;//main函数,IDA载入发现已经加密,无法正常解析。
        v8 = 440;
        do
        {
          ptr_main = (int (__usercall *)@<eax>(int@<ebp>))((char *)ptr_main + 1);
          result = byte_417000[rand() % 8216];
          *((_BYTE *)ptr_main - 1) ^= result;//对main进行异或解密
          --v8;
        }
        while ( v8 );
      }
      else if ( a2 == 3 )
      {
        v9 = GetCurrentThread();
        result = dword_407380(v9, 17, 0, 0);
      }
      return result;
    }

    我们动态调试,查看前面要用到库中的哪些函数,并且在main函数解密完成后dump文件,以备后面IDA分析。

     发现前面获取的库函数与反调试相关。

    重命名后的TLS

    char __stdcall TlsCallback_0(int a1, int a2, int a3)
    {
      char result; // al
      HMODULE v4; // eax
      HMODULE v5; // eax
      HMODULE v6; // eax
      int (__usercall *ptr_main)@<eax>(int@<ebp>); // esi
      signed int v8; // edi
      HANDLE v9; // eax
    
      result = a2;
      if ( a2 == 1 )
      {
        v4 = GetModuleHandleA("ntdll.dll");
        NtQuerySystemInformation = sub_401360((int)v4, "a7d7bcc95a86a6df3b0a1ccb3c69d440");
        v5 = GetModuleHandleA("ntdll.dll");
        NtSetInformationThread = (int (__stdcall *)(_DWORD, _DWORD, _DWORD, _DWORD))sub_401360(
                                                                                      (int)v5,
                                                                                      "8eb35a28209979fe6a9983cff0d23c5a");
        v6 = GetModuleHandleA("kernel32.dll");
        *(_DWORD *)CheckRemoteDebuggerPresent = sub_401360((int)v6, "05577e1568efa10b8166728bfb414c59");
        srand(0x61616161u);
        ptr_main = main_401780;
        v8 = 440;
        do
        {
          ptr_main = (int (__usercall *)@<eax>(int@<ebp>))((char *)ptr_main + 1);
          result = byte_417000[rand() % 8216];
          *((_BYTE *)ptr_main - 1) ^= result;
          --v8;
        }
        while ( v8 );
      }
      else if ( a2 == 3 )
      {
        v9 = GetCurrentThread();
        result = NtSetInformationThread(v9, 17, 0, 0);
      }
      return result;
    }
    View Code

    IDA分析mian解密完成时dump的文件

    int __usercall sub_401780@<eax>(int a1@<ebp>, int a2@<edi>, int a3@<esi>)
    {
      signed int v3; // esi
      int v4; // ST08_4
      int v5; // ST0C_4
      int v6; // ST10_4
      int v7; // ST14_4
      int v8; // ST18_4
      int v9; // ST1C_4
      int v10; // ST20_4
      int v11; // ST24_4
      int v12; // ST28_4
      int v13; // ST2C_4
      int v14; // ecx
      const char *v15; // eax
      int v17; // [esp-CCh] [ebp-D8h]
      int v18; // [esp-C8h] [ebp-D4h]
      int v19; // [esp-C4h] [ebp-D0h]
      int v20; // [esp-C0h] [ebp-CCh]
      int v21; // [esp-BCh] [ebp-C8h]
      int v22; // [esp-B8h] [ebp-C4h]
      int v23; // [esp-B4h] [ebp-C0h]
      int v24; // [esp-B0h] [ebp-BCh]
      int v25; // [esp-ACh] [ebp-B8h]
      int v26; // [esp-A8h] [ebp-B4h]
      int v27; // [esp-A4h] [ebp-B0h]
      int v28; // [esp-A0h] [ebp-ACh]
      int v29; // [esp-9Ch] [ebp-A8h]
      int v30; // [esp-98h] [ebp-A4h]
      int v31; // [esp-94h] [ebp-A0h]
      int v32; // [esp-90h] [ebp-9Ch]
      int v33; // [esp-8Ch] [ebp-98h]
      int v34; // [esp-88h] [ebp-94h]
      int v35; // [esp-84h] [ebp-90h]
      int v36; // [esp-80h] [ebp-8Ch]
      int v37; // [esp-7Ch] [ebp-88h]
      int v38; // [esp-78h] [ebp-84h]
      int v39; // [esp-74h] [ebp-80h]
      int v40; // [esp-70h] [ebp-7Ch]
      int v41; // [esp-6Ch] [ebp-78h]
      int v42; // [esp-68h] [ebp-74h]
      int v43; // [esp-64h] [ebp-70h]
      int v44; // [esp-60h] [ebp-6Ch]
      int v45; // [esp-5Ch] [ebp-68h]
      int v46; // [esp-58h] [ebp-64h]
      int v47; // [esp-54h] [ebp-60h]
      int v48; // [esp-50h] [ebp-5Ch]
      int v49; // [esp-4Ch] [ebp-58h]
      int v50; // [esp-48h] [ebp-54h]
      int v51; // [esp-44h] [ebp-50h]
      int v52; // [esp-40h] [ebp-4Ch]
      int v53; // [esp-3Ch] [ebp-48h]
      int v54; // [esp-38h] [ebp-44h]
      int v55; // [esp-34h] [ebp-40h]
      __int128 v56; // [esp-30h] [ebp-3Ch]
      __int64 v57; // [esp-20h] [ebp-2Ch]
      int v58; // [esp-18h] [ebp-24h]
      __int16 v59; // [esp-14h] [ebp-20h]
      unsigned int v60; // [esp-4h] [ebp-10h]
      int v61; // [esp+0h] [ebp-Ch]
      int v62; // [esp+4h] [ebp-8h]
      int retaddr; // [esp+Ch] [ebp+0h]
    
      v61 = a1;
      v62 = retaddr;
      v60 = (unsigned int)&v61 ^ __security_cookie;
      v17 = a3;
      CreateThread(0, 0, StartAddress, 0, 0, 0);    // 播放歌曲,
      printf_401020("%s
    ", (unsigned int)aMmmmmmmmmmmmmm);
      while ( !song_final_sign_40737C )
      {
        Sleep(0x7D0u);
        printf_401020(">");
      }
      printf_401020("
    ");
      v3 = 0;
      do
        *((_BYTE *)&loc_4015E0 + v3++) ^= byte_417000[rand() % 8216];// main中解密输入的加密处理函数
      while ( v3 < 383 );
      printf_401020("Shining!
    ", a2, v17);
      system("cls");
      v58 = 0;
      v56 = 0i64;
      v57 = 0i64;
      v59 = 0;
      memset(&v38, 0, 0x46u);
      printf_401020("My Darling Darling Please!
    input your key!
    ");
      scanf_401050("%29s", &v56);
      ((void (__stdcall *)(__int128 *, int *, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, _DWORD))loc_4015E0)(
        &v56,
        &v38,
        v4,
        v5,
        v6,
        v7,
        v8,
        v9,
        v10,
        v11,
        v12,
        v13,
        v18,
        v19,
        v20,
        v21,
        v22,
        v23,
        v24,
        v25,
        v26,
        v27,
        v28,
        v29,
        v30,
        v31,
        v32,
        v33,
        v34,
        v35,
        v36,
        v37,
        v38,
        v39,
        v40,
        v41,
        v42,
        v43,
        v44,
        v45,
        v46,
        v47,
        v48,
        v49,
        v50,
        v51,
        v52,
        v53,
        v54,
        v55,
        v56);
      *(_OWORD *)&v20 = xmmword_403520;             // 0DEF0A07232EEBC954C11473ABD57E649
      *(_OWORD *)&v24 = xmmword_403530;             // 5CCC8CA3C67C5A6A96E49835683F2AC
      v36 = 0;
      LOWORD(v37) = 0;
      *(_OWORD *)&v28 = 0i64;
      *(_OWORD *)&v32 = 0i64;
      v14 = strcmp((const char *)&v38, (const char *)&v20);
      if ( v14 )
        v14 = -(v14 < 0) | 1;
      v15 = "Maybe next year";
      if ( !v14 )
        v15 = "Nice Job~";
      printf_401020(v15);
      system("pause");
      return 0;
    }

    发现main中对loc_4015E0函数进行了解密,后面用他来加密输入。动态调试,解密后dump

    loc_4015E0函数

    char __cdecl encode_4015E0(const char *myinput, const char *en_temp)
    {
      int v2; // esi
      unsigned int size; // kr00_4
      signed int v4; // edi
      int v5; // ecx
      const char *v6; // eax
      int v7; // eax
      char v8; // al
      int v9; // ecx
      int v10; // ecx
      unsigned int v11; // ecx
      int v12; // eax
      char v13; // al
      signed int v14; // edi
      char result; // al
      signed int v16; // esi
      char v17; // al
      char v18; // cl
      signed int v19; // [esp+Ch] [ebp-8h]
      signed int v20; // [esp+10h] [ebp-4h]
    
      v2 = 0;
      size = strlen(myinput);
      v4 = 0;
      v20 = 4 * size / 3;
      if ( v20 > 0 )
      {
        do
        {
          v5 = v4 & 3;
          if ( v4 & 3 )
          {
            v8 = myinput[v2 - 1];
            if ( v5 == 1 )
            {
              v9 = myinput[v2++];
              v7 = (v9 >> 4) | 16 * (v8 & 3);
            }
            else if ( v5 == 2 )
            {
              v10 = myinput[v2++];
              v7 = (v10 >> 6) | 4 * (v8 & 0xF);
            }
            else
            {
              v7 = v8 & 0x3F;
            }
          }
          else
          {
            v6 = &myinput[v2++];
            v7 = *v6 >> 2;
          }
          en_temp[v4++] = base64_table_4033C8[v7];  // abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/
        }                          
        while ( v4 < v20 );
      }
      if ( strlen(myinput) % 3 == 1 )
      {
        v11 = 4 * size / 3;
        v12 = 16 * (myinput[v2 - 1] & 3);
        *(_WORD *)&en_temp[v20 + 1] = '==';
        v13 = base64_table_4033C8[v12];            //魔改base64,编码表将大写字母与小写字母替换了位置。
      }
      else
      {
        if ( strlen(myinput) % 3 != 2 )
          goto LABEL_15;
        v11 = 4 * size / 3;
        v13 = base64_table_4033C8[4 * (myinput[v2 - 1] & 0xF)];
        en_temp[v20 + 1] = 61;
      }
      en_temp[v11] = v13;
    LABEL_15:
      en_temp[strlen(en_temp)] = 0;
      v14 = 0;
      v19 = strlen(en_temp);
      if ( v19 > 0 )
      {
        do
        {
          v16 = 6;
          do
          {
            v17 = rand() % 4;
            v18 = v16;
            v16 -= 2;
            result = v17 << v18;
            en_temp[v14] ^= result;                 // 获取伪随机序列,输入进行魔改base64编码后与伪随机序列进行了异或操作。
          }
          while ( v16 > -2 );
          ++v14;
        }
        while ( v14 < v19 );
      }
      return result;
    }

    最终main函数

    int __usercall sub_401780@<eax>(int a1@<ebp>)
    {
      signed int v1; // esi
      int v2; // ecx
      const char *v3; // eax
      __int128 tg; // [esp-C0h] [ebp-CCh]
      __int128 v6; // [esp-B0h] [ebp-BCh]
      __int128 v7; // [esp-A0h] [ebp-ACh]
      __int128 v8; // [esp-90h] [ebp-9Ch]
      int v9; // [esp-80h] [ebp-8Ch]
      __int16 v10; // [esp-7Ch] [ebp-88h]
      int temp_str; // [esp-78h] [ebp-84h]
      __int128 myinput; // [esp-30h] [ebp-3Ch]
      __int64 v13; // [esp-20h] [ebp-2Ch]
      int v14; // [esp-18h] [ebp-24h]
      __int16 v15; // [esp-14h] [ebp-20h]
      unsigned int v16; // [esp-4h] [ebp-10h]
      int v17; // [esp+0h] [ebp-Ch]
      int v18; // [esp+4h] [ebp-8h]
      int retaddr; // [esp+Ch] [ebp+0h]
    
      v17 = a1;
      v18 = retaddr;
      v16 = (unsigned int)&v17 ^ __security_cookie;
      printf_401020("%s
    ", aMmmmmmmmmmmmmm);
      printf_401020("
    ");
      v1 = 0;
      do
        *((_BYTE *)encode_4015E0 + v1++) ^= byte_417000[rand() % 8216];
      while ( v1 < 383 );
      printf_401020("Shining!
    ");
      system("cls");
      v14 = 0;
      myinput = 0i64;
      v13 = 0i64;
      v15 = 0;
      memset(&temp_str, 0, 0x46u);
      printf_401020("My Darling Darling Please!
    input your key!
    ");
      scanf_401050("%29s", &myinput);
      encode_4015E0((const char *)&myinput, (const char *)&temp_str);// 魔改base64编码 +异或伪随机序列
      tg = xmmword_403520;                          // 0DEF0A07232EEBC954C11473ABD57E649
      v6 = xmmword_403530;                          // 5CCC8CA3C67C5A6A96E49835683F2AC
      v9 = 0;
      v10 = 0;
      v7 = 0i64;
      v8 = 0i64;
      v2 = strcmp((const char *)&temp_str, (const char *)&tg);// {
                                                    // 0x49, 0xE6, 0x57, 0xBD, 0x3A, 0x47, 0x11, 0x4C, 0x95, 0xBC, 0xEE, 0x32, 0x72, 0xA0, 0xF0, 0xDE,
                                                    // 0xAC, 0xF2, 0x83, 0x56, 0x83, 0x49, 0x6E, 0xA9, 0xA6, 0xC5, 0x67, 0x3C, 0xCA, 0xC8, 0xCC, 0x05
                                                    // };
      if ( v2 )
        v2 = -(v2 < 0) | 1;
      v3 = "Maybe next year";
      if ( !v2 )
        v3 = "Nice Job~";
      printf_401020(v3);
      system("pause");
      return nullsub_2((unsigned int)&v17 ^ v16);
    }

    魔改base64与标准base64编码只存在字母大小写的不同,好解决,关键在于后面与伪随机序列的获取。

    方案1、动态调试,在base64编码后,进行异或操作时,编写脚本,将每一位异或数据记录下来。

    方案2、先获取魔改base64编码后的结果,然后在函数结束后获得异或加密结果,将二者进行异或,便可得到得到伪随机序列

    程序最后将输入的加密结果进行比较,动态调试时dump比较数据。

    wp:

    import base64
    tg=[0x49, 0xE6, 0x57, 0xBD, 0x3A, 0x47, 0x11, 0x4C, 0x95, 0xBC, 0xEE, 0x32, 0x72, 0xA0, 0xF0, 0xDE,
    0xAC, 0xF2, 0x83, 0x56, 0x83, 0x49, 0x6E, 0xA9, 0xA6, 0xC5, 0x67, 0x3C, 0xCA, 0xC8, 0xCC, 0x05]
    order=[0x08,0x81,0x39,0x8d,0x40,0x09,0x42,0x14,0xd0,0xf2,0x98,0x66,0x33,0xd6,0xc9,0xb2,0xc1,0x95,0xb6,0x1e,0xc7,0x2d,0x1c,0xef,0xd2,0xb2,0x5f,0x66,0x8c,0xb9,0xf1,0x38,0x14,0x08,0x8f,0xce,0xe9,0x7f,0x0d,0x05,]
    
    b64=''
    for i in range(len(tg)):
        b64+=chr(order[i]^tg[i])
    print(b64)
    t=''
    for c in b64:
        n=ord(c)
        if n>=ord('A') and n<=ord('Z'):
            t+=chr(n|0x20)
        elif n>=ord('a') and n<=ord('z'):
            t+=chr(n&0xdf)
        else:
            t+=c
    print(t)
    flag=base64.b64decode(t.encode()).decode()
    print(flag)

    hctf{1zumi_K0nat4_Mo3}

    攻防世界里提交失败 0.0 Orz

  • 相关阅读:
    LeetCode算法题-Find Pivot Index(Java实现)
    LeetCode算法题-Longest Word in Dictionary(Java实现)
    LeetCode算法题-1-bit and 2-bit Characters(Java实现)
    2016-8-4学习正则表达式
    doT 这个模板 是怎么实现的?
    manually Invoking Model Binding / Model Binding /Pro asp.net mvc 5
    隐隐约约 听 RazorEngine 在 那里 据说 生成代码 很 美。
    web api 的 安全 认证问题 , 对外开放 的 时候 需要考虑到安全的问题
    鼠标滑过显示图片
    页面加载中效果实现
  • 原文地址:https://www.cnblogs.com/DirWang/p/12289016.html
Copyright © 2011-2022 走看看