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 83. Remove Duplicates from Sorted List (从有序链表中去除重复项)
    LeetCode 21. Merge Two Sorted Lists (合并两个有序链表)
    LeetCode 720. Longest Word in Dictionary (字典里最长的单词)
    LeetCode 690. Employee Importance (职员的重要值)
    LeetCode 645. Set Mismatch (集合不匹配)
    LeetCode 500. Keyboard Row (键盘行)
    LeetCode 463. Island Perimeter (岛的周长)
    115.Distinct Subsequences
    55.Jump Game
    124.Binary Tree Maximum Path Sum
  • 原文地址:https://www.cnblogs.com/DirWang/p/12289016.html
Copyright © 2011-2022 走看看