[ 西湖论剑2023 Quals ] Reverse WriteUp(1)

  • 去年西湖论剑没打,今年要打了,补下之前的题。

一. BabyRe

  • main函数中只有一句

  • int __cdecl main(int argc, const char **argv, const char **envp)
    {
      __CheckForDebuggerJustMyCode(&unk_4090A2);
      GetLastError();
      return 0;
    }
    
  • 查看字符串,并交叉引用

  • 找到几个函数:

  • int sub_401000()
    {
      __CheckForDebuggerJustMyCode(&unk_4090A2);
      sub_401170(&unk_4085C6);
      return atexit(sub_405770);
    }
    
  • int sub_401050()
    {
      __CheckForDebuggerJustMyCode(&unk_4090A2);
      sub_401230(&unk_4085C4);
      return atexit(sub_4057B0);
    }
    
  • int sub_4010A0()
    {
      __CheckForDebuggerJustMyCode(&unk_4090A2);
      sub_4012B0(&unk_4085C5);
      return atexit(sub_4057F0);
    }
    
  • 发现了atexit函数,这个函数为登记函数,是在正常程序退出时调用的函数,⼀个进程可以登记若⼲个(具体⾃⼰验证⼀下)个函数,这些函数由exit⾃动调⽤,这些函数被称为终⽌处理函数, atexit函数可以登记这些函数。 exit调⽤终⽌处理函数的顺序和atexit登记的顺序相反

  • 再通过打断点动调,即可找到函数调用顺序

  • 401170
    401230
    4012B0
    main
    atexit 4014E0
    atexit 4015C0
    atexit 401670
    
  • 分别分析函数作用如下:

  • void *__thiscall sub_401170(void *this)//输入函数
    {
      char v2; // [esp+0h] [ebp-E4h]
      size_t i; // [esp+D0h] [ebp-14h]
    
      __CheckForDebuggerJustMyCode(&unk_4090A2);
      sub_4025A0("Input:", v2);
      sub_402620("%99s", (char)Str);
      for ( i = 0; i < strlen(Str); ++i )
      {
        if ( Str[i] < 48 || Str[i] > 57 )
          ExitProcess(0);
      }
      return this;
    }
    
  • void *__thiscall sub_401230(void *this)//按位取反,得到01234567的table
    {
      int i; // [esp+D0h] [ebp-14h]
    
      __CheckForDebuggerJustMyCode(&unk_4090A2);
      for ( i = 0; i < 8; ++i )
        byte_408104[i] = ~byte_408104[i];
      return this;
    }
    
  • int __thiscall sub_4012B0(void *this)//遍历输入表进行hook
    {
      int i; // [esp+DCh] [ebp-9Ch]
      char *v3; // [esp+E8h] [ebp-90h]
      char *v4; // [esp+F4h] [ebp-84h]
      const CHAR *lpModuleName; // [esp+10Ch] [ebp-6Ch]
      _DWORD *v6; // [esp+118h] [ebp-60h]
      DWORD flOldProtect[9]; // [esp+124h] [ebp-54h] BYREF
      int v8; // [esp+148h] [ebp-30h]
      HMODULE v9; // [esp+154h] [ebp-24h]
      HMODULE ModuleHandleA; // [esp+160h] [ebp-18h]
      void *v11; // [esp+16Ch] [ebp-Ch]
    
      v11 = this;
      __CheckForDebuggerJustMyCode(&unk_4090A2);
      ModuleHandleA = GetModuleHandleA(0);
      v9 = ModuleHandleA;
      v8 = (int)ModuleHandleA + *((_DWORD *)ModuleHandleA + 15) + 4;
      flOldProtect[6] = v8 + 20;
      flOldProtect[3] = v8 + 116;
      v6 = (_DWORD *)((char *)ModuleHandleA + *(_DWORD *)(v8 + 124));
      while ( v6[3] )
      {
        lpModuleName = (char *)ModuleHandleA + v6[3];
        if ( GetModuleHandleA(lpModuleName) || LoadLibraryA(lpModuleName) )
        {
          v4 = (char *)ModuleHandleA + *v6;
          v3 = (char *)ModuleHandleA + v6[4];
          for ( i = 0; *(_DWORD *)&v4[4 * i]; ++i )
          {
            if ( *(int *)&v4[4 * i] >= 0 && !strcmp((const char *)ModuleHandleA + *(_DWORD *)&v4[4 * i] + 2, "GetLastError") )
            {
              dword_4085C0 = *(_DWORD *)&v3[4 * i];
              VirtualProtect(&v3[4 * i], 4u, 4u, flOldProtect);
              *(_DWORD *)&v3[4 * i] = sub_4019D0;//将GetLastError函数改为4019D0
              break;
            }
          }
          v6 += 5;
        }
        else
        {
          v6 += 5;
        }
      }
      return (int)v11;
    }
    
  • int sub_401670()
    {
      int result; // eax
    
      __CheckForDebuggerJustMyCode(&unk_4090A2);
      sub_401720(&Str, (int)&unk_4081C0);//base8加密
      result = memcmp(&unk_4081D0, a16230465152334, 0x60u);//赋值
      if ( result )
        ExitProcess(0);
      return result;
    }
    
  • int sub_4015C0()
    {
      int result; // eax
    
      __CheckForDebuggerJustMyCode(&unk_4090A2);
      sub_401CC0((int)&unk_4081C0, 112, 0, Buffer);//sha-1
      result = memcmp(Buffer, a67339fc92b4875, 0x28u);
      if ( result )
        ExitProcess(0);
      return result;
    }
    
  • int __cdecl sub_4014E0()//检验
    {
      char v1; // [esp+0h] [ebp-E8h]
    
      __CheckForDebuggerJustMyCode(&unk_4090A2);
      memcpy(&unk_4084C0, &unk_4081C0, 0x70u);//赋值,前16位未知,后面96位已知
      sub_401B60(&unk_4083C0, &unk_408182, 6);//RC4_init,6位密钥为输入的后六位
      sub_401A40(&unk_4083C0, &unk_4084C0, 112);//RC4
      if ( memcmp(&unk_4084C0, &unk_408090, 0x70u) )//比较函数
        ExitProcess(0);
      return sub_4025A0("Good, flag is DASCTF{your input}", v1);
    }
    
  • void *__cdecl sub_401CC0(int a1, __int64 a2, char *Buffer)//换了常数的SHA-1加密
    {
      void *result; // eax
      int v4; // [esp+Ch] [ebp-4D4h]
      int v5; // [esp+10h] [ebp-4D0h]
      int v6; // [esp+14h] [ebp-4CCh]
      int v7; // [esp+18h] [ebp-4C8h]
      int v8; // [esp+1A0h] [ebp-340h]
      int v9; // [esp+1ACh] [ebp-334h]
      int v10; // [esp+1B8h] [ebp-328h]
      int v11; // [esp+1C4h] [ebp-31Ch]
      int v12; // [esp+1D0h] [ebp-310h]
      int v13; // [esp+1DCh] [ebp-304h]
      int v14; // [esp+1E4h] [ebp-2FCh]
      int v15; // [esp+1E8h] [ebp-2F8h]
      int v16[2]; // [esp+1ECh] [ebp-2F4h]
      int v17; // [esp+1F4h] [ebp-2ECh]
      int v18; // [esp+200h] [ebp-2E0h]
      int v19[2]; // [esp+204h] [ebp-2DCh]
      int v20; // [esp+20Ch] [ebp-2D4h]
      int v21[167]; // [esp+218h] [ebp-2C8h]
      int i; // [esp+4B4h] [ebp-2Ch]
      size_t Size; // [esp+4C0h] [ebp-20h]
      unsigned int v24; // [esp+4CCh] [ebp-14h]
      unsigned int v25; // [esp+4D8h] [ebp-8h]
    
      __CheckForDebuggerJustMyCode(&unk_4090A2);
      v12 = 271733878;
      v11 = -1984242434;
      v10 = -271733879;
      v9 = 1732588033;
      v8 = 253635900;
      for ( i = 0; i < 20; ++i )
        v21[i + 85] = dword_408148[0];
      for ( i = 20; i < 40; ++i )
        v21[i + 85] = dword_408148[1];
      for ( i = 40; i < 60; ++i )
        v21[i + 85] = dword_408148[2];
      for ( i = 60; i < 80; ++i )
        v21[i + 85] = dword_408148[3];
      if ( a2 % 64 <= 56 )
        v4 = 64 - a2 % 64;
      else
        v4 = 128 - a2 % 64;
      Size = v4 + a2;
      result = malloc(v4 + a2);
      v25 = (unsigned int)result;
      if ( result )
      {
        for ( i = 0; i < a2; ++i )
          *(_BYTE *)(v25 + i + 3 - 2 * (i % 4)) = *(_BYTE *)(i + a1);
        *(_BYTE *)(v25 + i + 3 - 2 * (i % 4)) = 0x80;
        ++i;
        while ( i < (int)Size )
        {
          *(_BYTE *)(v25 + i + 3 - 2 * (i % 4)) = 0;
          ++i;
        }
        *(_DWORD *)(Size + v25 - 4) = 8 * a2;
        *(_DWORD *)(Size + v25 - 8) = a2 >> 29;
        v24 = Size + v25;
        while ( v25 < v24 )
        {
          for ( i = 0; i < 16; ++i )
            v21[i + 3] = *(_DWORD *)(v25 + 4 * i);
          for ( i = 16; i < 80; ++i )
          {
            dword_4081BC = *(&v14 + i) ^ v16[i] ^ v19[i] ^ v21[i];
            v21[i + 3] = (2 * dword_4081BC) | (dword_4081BC >> 31) & 1;
          }
          v20 = v12;
          v18 = v11;
          v17 = v10;
          v15 = v9;
          v13 = v8;
          for ( i = 0; i < 80; ++i )
          {
            dword_4081BC = v20;
            if ( i >= 40 )
            {
              if ( i >= 60 )
                v5 = v15 ^ v17 ^ v18;
              else
                v5 = v15 & v17 | v15 & v18 | v17 & v18;
              v6 = v5;
            }
            else
            {
              if ( i >= 20 )
                v7 = v15 ^ v17 ^ v18;
              else
                v7 = v15 & ~v18 | v17 & v18;
              v6 = v7;
            }
            v21[0] = v21[i + 85] + v21[i + 3] + v13 + v6 + ((32 * dword_4081BC) | (dword_4081BC >> 27) & 0x1F);
            v13 = v15;
            v15 = v17;
            dword_4081BC = v18;
            v17 = (v18 << 30) | (v18 >> 2) & 0x3FFFFFFF;
            v18 = v20;
            v20 = v21[0];
          }
          v12 += v20;
          v11 += v18;
          v10 += v17;
          v9 += v15;
          v8 += v13;
          v25 += 64;
        }
        free((void *)(v25 - Size));
        return (void *)sub_4026A0(Buffer, "%08x%08x%08x%08x%08x", v12);
      }
      return result;
    }
    
  • 六位密钥,可以先进行爆破

  • c=[0x3F, 0x95, 0xBB, 0xF2, 0x57, 0xF1, 0x7A, 0x5A, 0x22, 0x61,
      0x51, 0x43, 0xA2, 0xFA, 0x9B, 0x6F, 0x44, 0x63, 0xC0, 0x08,
      0x12, 0x65, 0x5C, 0x8A, 0x8C, 0x4C, 0xED, 0x5E, 0xCA, 0x76,
      0xB9, 0x85, 0xAF, 0x05, 0x38, 0xED, 0x42, 0x3E, 0x42, 0xDF,
      0x5D, 0xBE, 0x05, 0x8B, 0x35, 0x6D, 0xF3, 0x1C, 0xCF, 0xF8,
      0x6A, 0x73, 0x25, 0xE4, 0xB7, 0xB9, 0x36, 0xFB, 0x02, 0x11,
      0xA0, 0xF0, 0x57, 0xAB, 0x21, 0xC6, 0xC7, 0x46, 0x99, 0xBD,
      0x1E, 0x61, 0x5E, 0xEE, 0x55, 0x18, 0xEE, 0x03, 0x29, 0x84,
      0x7F, 0x94, 0x5F, 0xB4, 0x6A, 0x29, 0xD8, 0x6C, 0xE4, 0xC0,
      0x9D, 0x6B, 0xCC, 0xD5, 0x94, 0x5C, 0xDD, 0xCC, 0xD5, 0x3D,
      0xC0, 0xEF, 0x0C, 0x29, 0xE5, 0xB0, 0x93, 0xF1, 0xB3, 0xDE,
      0xB0, 0x70]
    x=[0]*16+[0x31, 0x36, 0x32, 0x33, 0x30, 0x34, 0x36, 0x35, 0x31, 0x35,
      0x32, 0x33, 0x33, 0x34, 0x36, 0x32, 0x31, 0x34, 0x34, 0x33,
      0x31, 0x34, 0x37, 0x31, 0x31, 0x35, 0x30, 0x33, 0x31, 0x30,
      0x37, 0x30, 0x31, 0x35, 0x30, 0x33, 0x32, 0x30, 0x37, 0x31,
      0x31, 0x36, 0x30, 0x33, 0x32, 0x30, 0x36, 0x33, 0x31, 0x34,
      0x30, 0x33, 0x33, 0x34, 0x36, 0x36, 0x31, 0x35, 0x34, 0x33,
      0x34, 0x34, 0x36, 0x31, 0x31, 0x34, 0x34, 0x33, 0x34, 0x30,
      0x36, 0x36, 0x31, 0x34, 0x32, 0x33, 0x30, 0x34, 0x36, 0x36,
      0x31, 0x35, 0x36, 0x33, 0x34, 0x34, 0x36, 0x36, 0x31, 0x35,
      0x34, 0x33, 0x30, 0x34, 0x36, 0x34]
    a1=[0]*256
    v5=[0]*256
    for i1 in range(48,58):
        for i2 in range(48, 58):
            for i3 in range(48, 58):
                for i4 in range(48, 58):
                    for i5 in range(48, 58):
                        for i6 in range(48, 58):
                            key=[i1,i2,i3,i4,i5,i6]
                            v6=0
                            for i in range(256):
                                a1[i]=i
                                v5[i]=key[i%6]
                            for i in range(256):
                                v6=(v5[i]+v6+a1[i])%256
                                v4=a1[i]
                                a1[i]=a1[v6]
                                a1[v6]=v4
                            flag=1
                            v6=0
                            v7=0
                            for i in range(112):
                                v7=(v7+1)%256
                                v6=(v6+a1[v7])%256
                                v4=a1[v7]
                                a1[v7]=a1[v6]
                                a1[v6]=v4
                                if i<16:
                                    continue
                                else:
                                    if c[i]^a1[(a1[v6]+a1[v7])%256]!=x[i]:
                                        flag=0
                                        break
                            if flag==1:
                                print(i1,i2,i3,i4,i5,i6)
                                exit(0)
    
  • 然后直接对密文先进行RC4解密,再进行base8解密即可

  • def base8decode(c):
        flag=''
        for i in c:
            flag+=bin(int(chr(i)))[2:].rjust(3,'0')
        return [int(flag[i:i+8],2) for i in range(0,len(flag),8)]
    key=[56 ,48 ,55 ,51 ,57, 49]
    v6=0
    a1=[0]*256
    v5=[0]*256
    for i in range(256):
        a1[i]=i
        v5[i]=key[i%6]
    for i in range(256):
        v6=(v5[i]+v6+a1[i])%256
        a1[i],a1[v6]=a1[v6],a1[i]
    v6=0
    v7=0
    for i in range(112):
        v7=(v7+1)%256
        v6=(v6+a1[v7])%256
        a1[v7],a1[v6]=a1[v6],a1[v7]
        c[i]^=a1[(a1[v6]+a1[v7])%256]
    flag=bytes(base8decode(c)+key)
    print(flag)
    
  • DASCTF{561516915572239428449843076691286116796614807391}

二. Dual personality

  • 本题打开就是一片红,发现是依据Window的WoW机制进行实现的天堂之门,那么本题主要思路就是一段一段dump分析即可

  • main第一段:

  • .text:004013A0
    .text:004013A0                               ; int __cdecl main(int argc, const char **argv, const char **envp)
    .text:004013A0                               _main:                                  ; CODE XREF: invoke_main(void)+2E↓p
    .text:004013A0 55                            push    ebp
    .text:004013A1 8B EC                         mov     ebp, esp
    .text:004013A3 81 EC 34 01 00 00             sub     esp, 134h
    .text:004013A9 53                            push    ebx
    .text:004013AA 56                            push    esi
    .text:004013AB 57                            push    edi
    .text:004013AC 8D 7D 8C                      lea     edi, [ebp-74h]
    .text:004013AF B9 1D 00 00 00                mov     ecx, 1Dh
    .text:004013B4 B8 CC CC CC CC                mov     eax, 0CCCCCCCCh
    .text:004013B9 F3 AB                         rep stosd
    .text:004013BB A1 24 70 40 00                mov     eax, ___security_cookie
    .text:004013C0 33 C5                         xor     eax, ebp
    .text:004013C2 89 45 FC                      mov     [ebp-4], eax
    .text:004013C5 E8 36 FC FF FF                call    sub_401000
    .text:004013C5
    .text:004013CA 68 60 70 40 00                push    offset unk_407060
    .text:004013CF 68 70 51 40 00                push    offset a99s                     ; "%99s"
    .text:004013D4 E8 47 02 00 00                call    sub_401620
    .text:004013D4
    .text:004013D9 83 C4 08                      add     esp, 8
    .text:004013DC 68 D0 11 40 00                push    offset dword_4011D0
    .text:004013E1 6A 07                         push    7
    .text:004013E3 E8 38 FD FF FF                call    sub_401120
    .text:004013E3
    .text:004013E8 83 C4 08                      add     esp, 8
    .text:004013EB 85 C0                         test    eax, eax
    .text:004013ED 74 05                         jz      short loc_4013F4
    .text:004013ED
    .text:004013EF A1 58 70 40 00                mov     eax, dword_407058
    .text:004013EF
    
  • 主要分析401120函数

  • 两个参数,一个是长度,一个是地址

  • int __cdecl sub_401120(size_t Size, int a2)
    {
      char *v2; // ebx
      char *retaddr; // [esp+D0h] [ebp+4h]
    
      dword_407050 = VirtualAlloc(0, Size + 6, 0x3000u, 0x40u);
      dword_407000 = (int)dword_407050;
      memcpy(dword_407050, retaddr, Size);
      v2 = (char *)dword_407050 + Size;
      *v2 = -23;
      *(_DWORD *)(v2 + 1) = &retaddr[Size] - v2 - 5;
      v2[5] = -52;
      *retaddr = -22;
      *(_DWORD *)(retaddr + 1) = a2;
      *(_WORD *)(retaddr + 5) = 51;
      return 0;
    }
    
  • 该函数首先创建新空间,将未修改前的指令拷贝至新申请的内存中,将调用函数的后长度个字修改为0xEA地址0x33 ,还有一个跳转回原地址的指令

  • 修改后的指令实现一个远跳,同时修改cs与ip的地址,并切换成64位模式

  • 下面将对应地址数据进行dump

  • seg000:0000000000000000                               sub_0 proc near
    seg000:0000000000000000 65 48 8B 04 25 60 00 00 00    mov     rax, qword ptr gs:loc_5F+1
    seg000:0000000000000009 8A 40 02                      mov     al, [rax+2]
    seg000:000000000000000C 88 04 25 5C 70 40 00          mov     ds:40705Ch, al
    seg000:0000000000000013 84 C0                         test    al, al
    seg000:0000000000000015 75 0E                         jnz     short loc_25
    seg000:0000000000000015
    seg000:0000000000000017 41 BC AE 66 F9 5D             mov     r12d, 5DF966AEh
    seg000:000000000000001D 44 89 24 25 58 70 40 00       mov     ds:407058h, r12d
    seg000:000000000000001D
    seg000:0000000000000025
    seg000:0000000000000025                               loc_25:                                 ; CODE XREF: sub_0+15↑j
    seg000:0000000000000025 44 B8 00 70 40 00             mov     eax, 407000h
    seg000:000000000000002B 48 FF 28                      jmp     qword ptr [rax]
    seg000:000000000000002B
    seg000:000000000000002B                               sub_0 endp
    
  • 其中很明显的使用了Beingdebugged反调试技巧

  • 并将407058的值进行修改

  • 最终跳回407000中所存的地址处(就是原地址)

  • 继续向下分析主函数

  • .text:004013F4                               loc_4013F4:                             ; CODE XREF: .text:004013ED↑j
    .text:004013F4 2D 11 41 52 21                sub     eax, 21524111h
    .text:004013F9 A3 58 70 40 00                mov     dword_407058, eax
    .text:004013FE C7 45 F4 60 70 40 00          mov     dword ptr [ebp-0Ch], offset unk_407060
    .text:00401405 C7 45 E8 00 00 00 00          mov     dword ptr [ebp-18h], 0
    .text:0040140C EB 09                         jmp     short loc_401417
    .text:0040140C
    .text:0040140E                               ; ---------------------------------------------------------------------------
    .text:0040140E
    .text:0040140E                               loc_40140E:                             ; CODE XREF: .text:0040144A↓j
    .text:0040140E 8B 45 E8                      mov     eax, [ebp-18h]
    .text:00401411 83 C0 01                      add     eax, 1
    .text:00401414 89 45 E8                      mov     [ebp-18h], eax
    .text:00401414
    .text:00401417
    .text:00401417                               loc_401417:                             ; CODE XREF: .text:0040140C↑j
    .text:00401417 83 7D E8 08                   cmp     dword ptr [ebp-18h], 8
    .text:0040141B 7D 2F                         jge     short loc_40144C
    .text:0040141B
    .text:0040141D 8B 45 E8                      mov     eax, [ebp-18h]
    .text:00401420 8B 4D F4                      mov     ecx, [ebp-0Ch]
    .text:00401423 8B 14 81                      mov     edx, [ecx+eax*4]
    .text:00401426 03 15 58 70 40 00             add     edx, dword_407058
    .text:0040142C 8B 45 E8                      mov     eax, [ebp-18h]
    .text:0040142F 8B 4D F4                      mov     ecx, [ebp-0Ch]
    .text:00401432 89 14 81                      mov     [ecx+eax*4], edx
    .text:00401435 8B 45 E8                      mov     eax, [ebp-18h]
    .text:00401438 8B 4D F4                      mov     ecx, [ebp-0Ch]
    .text:0040143B 8B 15 58 70 40 00             mov     edx, dword_407058
    .text:00401441 33 14 81                      xor     edx, [ecx+eax*4]
    .text:00401444 89 15 58 70 40 00             mov     dword_407058, edx
    .text:0040144A EB C2                         jmp     short loc_40140E
    .text:0040144A
    
  • 很明显的一段加密,循环

  • 第一次加密后继续跳转

  • .text:0040144C                               loc_40144C:                             ; CODE XREF: .text:0040141B↑j
    .text:0040144C 6A 00                         push    0
    .text:0040144E 8D 05 60 70 40 00             lea     eax, unk_407060
    .text:00401454 50                            push    eax
    .text:00401455 FF 1D 0C 70 40 00             call    fword ptr byte_40700C
    
  • 这里的call实现第二次向64位的切换,

  • .data:0040700C byte_40700C db 0, 12h, 40h, 0, 33h, 0  
    
  • 将401200处数据dump下来

  • dump脚本如下:

  • static main(void)
    {
      auto fp, begin, end, dexbyte;
      fp = fopen("D:\dump1", "wb");
      begin = 0x401200;
      end = 0x401288;
      for ( dexbyte = begin; dexbyte < end; dexbyte ++ )
          fputc(Byte(dexbyte), fp);
    }
    
  • void sub_0()
    {
      _QWORD *v0; // [rsp+10h] [rbp+10h]
    
      if ( MEMORY[0x40705C] )
      {
        *v0 = __ROL8__(*v0, 32);
        v0[1] = __ROL8__(v0[1], 32);
        v0[2] = __ROL8__(v0[2], 32);
        v0[3] = __ROL8__(v0[3], 32);
        JUMPOUT(0x7Ci64);
      }
      *v0 = __ROL8__(*v0, 12);
      v0[1] = __ROL8__(v0[1], 34);
      v0[2] = __ROL8__(v0[2], 56);
      v0[3] = __ROL8__(v0[3], 14);
      JUMPOUT(0x77i64);
    }
    
  • 如果调试中,则错误加密,否则正确加密

  • 结束后

    .text:0040127C mov     ebx, 0
    .text:00401281 dec     eax
    .text:00401282 xor     eax, eax
    .text:00401284 dec     eax
    .text:00401285 mov     esp, ebp
    .text:00401287 pop     ebp
    .text:00401288 retf    8
    
  • 重新切换到32位模式(retf跳回原位置)

  • 继续分析main

  • text:0040145B push    offset dword_401290
    .text:00401460 push    7
    .text:00401462 call    sub_401120
    .text:00401462
    .text:00401467 add     esp, 8
    .text:0040146A test    eax, eax
    .text:0040146C jnz     short near ptr loc_40146F+4
    .text:0040146C
    .text:0040146E dec     eax
    
  • 又是一个401120函数,第三次切换成64位模式

  • 继续dump分析

  • __int64 sub_0()
    {
      MEMORY[0x407000] = 4199621;
      MEMORY[0x407014] &= MEMORY[0x407018];
      MEMORY[0x407018] |= MEMORY[0x40701C];
      MEMORY[0x40701C] ^= MEMORY[0x407020];
      MEMORY[0x407020] = ~MEMORY[0x407020];
      return MEMORY[0x407050]();
    }
    
  • 这里直接返回未修改前保存的指令,并未切换为32位

  • 导致下面的指令无法被IDA32分析,故继续dump

  • seg000:0000000000000000                               sub_0 proc near                         ; CODE XREF: sub_0+4C↓j
    seg000:0000000000000000 48 8B 04 25 C8 70 40 00       mov     rax, ds:4070C8h
    seg000:0000000000000008 48 83 F8 20                   cmp     rax, 20h ; ' '
    seg000:000000000000000C 74 40                         jz      short loc_4E
    seg000:000000000000000C
    seg000:000000000000000E 48 33 D2                      xor     rdx, rdx
    seg000:0000000000000011 48 B9 04 00 00 00 00 00 00 00 mov     rcx, 4
    seg000:000000000000001B 48 F7 F1                      div     rcx
    seg000:000000000000001E 48 8D 1C 25 14 70 40 00       lea     rbx, ds:407014h
    seg000:0000000000000026 8A 14 93                      mov     dl, [rbx+rdx*4]
    seg000:0000000000000029 48 8B 04 25 C8 70 40 00       mov     rax, ds:4070C8h
    seg000:0000000000000031 48 8D 1C 25 60 70 40 00       lea     rbx, ds:407060h
    seg000:0000000000000039 8A 0C 03                      mov     cl, [rbx+rax]
    seg000:000000000000003C 32 CA                         xor     cl, dl
    seg000:000000000000003E 88 0C 03                      mov     [rbx+rax], cl
    seg000:0000000000000041 48 FF C0                      inc     rax
    seg000:0000000000000044 48 89 04 25 C8 70 40 00       mov     ds:4070C8h, rax
    seg000:000000000000004C EB B2                         jmp     short sub_0
    seg000:000000000000004C
    seg000:000000000000004E                               ; ---------------------------------------------------------------------------
    seg000:000000000000004E
    seg000:000000000000004E                               loc_4E:                                 ; CODE XREF: sub_0+C↑j
    seg000:000000000000004E 44 B8 00 70 40 00             mov     eax, 407000h
    seg000:0000000000000054 48 FF 28                      jmp     qword ptr [rax]
    seg000:0000000000000054
    seg000:0000000000000057                               ; ---------------------------------------------------------------------------
    seg000:0000000000000057 33 C0                         xor     eax, eax
    seg000:0000000000000059 89 45 BC                      mov     [rbp-44h], eax
    seg000:000000000000005C 89 45 C0                      mov     [rbp-40h], eax
    seg000:000000000000005F 89 45 C4                      mov     [rbp-3Ch], eax
    seg000:0000000000000062 89 45 C8                      mov     [rbp-38h], eax
    seg000:0000000000000065 89 45 CC                      mov     [rbp-34h], eax
    seg000:0000000000000068 89 45 D0                      mov     [rbp-30h], eax
    seg000:000000000000006B 89 45 D4                      mov     [rbp-2Ch], eax
    seg000:000000000000006E 89 45 D8                      mov     [rbp-28h], eax
    seg000:0000000000000071 88 45 DC                      mov     [rbp-24h], al
    seg000:0000000000000074 C6 45 90 AA                   mov     byte ptr [rbp-70h], 0AAh
    seg000:0000000000000078 C6 45 91 4F                   mov     byte ptr [rbp-6Fh], 4Fh ; 'O'
    seg000:000000000000007C C6 45 92 0F                   mov     byte ptr [rbp-6Eh], 0Fh
    seg000:0000000000000080 C6 45 93 E2                   mov     byte ptr [rbp-6Dh], 0E2h
    seg000:0000000000000084 C6 45 94 E4                   mov     byte ptr [rbp-6Ch], 0E4h
    seg000:0000000000000088 C6 45 95 41                   mov     byte ptr [rbp-6Bh], 41h ; 'A'
    seg000:000000000000008C C6 45 96 99                   mov     byte ptr [rbp-6Ah], 99h
    seg000:0000000000000090 C6 45 97 54                   mov     byte ptr [rbp-69h], 54h ; 'T'
    seg000:0000000000000094 C6 45 98 2C                   mov     byte ptr [rbp-68h], 2Ch ; ','
    seg000:0000000000000098 C6 45 99 2B                   mov     byte ptr [rbp-67h], 2Bh ; '+'
    seg000:000000000000009C C6 45 9A 84                   mov     byte ptr [rbp-66h], 84h
    seg000:00000000000000A0 C6 45 9B 7E                   mov     byte ptr [rbp-65h], 7Eh ; '~'
    seg000:00000000000000A4 C6 45 9C BC                   mov     byte ptr [rbp-64h], 0BCh
    seg000:00000000000000A8 C6 45 9D 8F                   mov     byte ptr [rbp-63h], 8Fh
    seg000:00000000000000AC C6 45 9E 8B                   mov     byte ptr [rbp-62h], 8Bh
    seg000:00000000000000B0 C6 45 9F 78                   mov     byte ptr [rbp-61h], 78h ; 'x'
    seg000:00000000000000B4 C6 45 A0 D3                   mov     byte ptr [rbp-60h], 0D3h
    seg000:00000000000000B8 C6 45 A1 73                   mov     byte ptr [rbp-5Fh], 73h ; 's'
    seg000:00000000000000BC C6 45 A2 88                   mov     byte ptr [rbp-5Eh], 88h
    seg000:00000000000000C0 C6 45 A3 5E                   mov     byte ptr [rbp-5Dh], 5Eh ; '^'
    seg000:00000000000000C4 C6 45 A4 AE                   mov     byte ptr [rbp-5Ch], 0AEh
    seg000:00000000000000C8 C6 45 A5 47                   mov     byte ptr [rbp-5Bh], 47h ; 'G'
    seg000:00000000000000CC C6 45 A6 85                   mov     byte ptr [rbp-5Ah], 85h
    seg000:00000000000000D0 C6 45 A7 70                   mov     byte ptr [rbp-59h], 70h ; 'p'
    seg000:00000000000000D4 C6 45 A8 31                   mov     byte ptr [rbp-58h], 31h ; '1'
    seg000:00000000000000D8 C6 45 A9 B3                   mov     byte ptr [rbp-57h], 0B3h
    seg000:00000000000000DC C6 45 AA 09                   mov     byte ptr [rbp-56h], 9
    seg000:00000000000000E0 C6 45 AB CE                   mov     byte ptr [rbp-55h], 0CEh
    seg000:00000000000000E4 C6 45 AC 13                   mov     byte ptr [rbp-54h], 13h
    seg000:00000000000000E8 C6 45 AD F5                   mov     byte ptr [rbp-53h], 0F5h
    seg000:00000000000000EC C6 45 AE 0D                   mov     byte ptr [rbp-52h], 0Dh
    seg000:00000000000000F0 C6 45 AF CA                   mov     byte ptr [rbp-51h], 0CAh
    seg000:00000000000000F4 33 C0                         xor     eax, eax
    seg000:00000000000000F6 88 45 B0                      mov     [rbp-50h], al
    seg000:00000000000000F9 6A 20                         push    20h ; ' '
    seg000:00000000000000FB 8D 45 90                      lea     eax, [rbp-70h]
    seg000:00000000000000FE 50                            push    rax
    seg000:00000000000000FF 68 60 70 40 00                push    407060h
    seg000:0000000000000104 E8 AD 2C 00 00                call    near ptr 2DB6h
    seg000:0000000000000104
    seg000:0000000000000109 83 C4 0C                      add     esp, 0Ch
    seg000:000000000000010C 85 C0                         test    eax, eax
    seg000:000000000000010E 75 28                         jnz     short loc_138
    seg000:000000000000010E
    seg000:0000000000000110 8B F4                         mov     esi, esp
    seg000:0000000000000112 68 78 51 40 00                push    405178h
    seg000:0000000000000117 FF 15 F8 50 40 00             call    qword ptr cs:405215h
    seg000:0000000000000117
    seg000:000000000000011D 83 C4 04                      add     esp, 4
    seg000:0000000000000120 3B F4                         cmp     esi, esp
    seg000:0000000000000122 E8 9B 02 00 00                call    near ptr 3C2h
    seg000:0000000000000122
    seg000:0000000000000127 8B F4                         mov     esi, esp
    seg000:0000000000000129 6A 00                         push    0
    seg000:000000000000012B FF 15 F0 50 40 00             call    qword ptr cs:405221h
    seg000:000000000000012B
    seg000:0000000000000131 3B F4                         cmp     esi, esp
    seg000:0000000000000133 E8 8A 02 00 00                call    near ptr 3C2h
    seg000:0000000000000133
    seg000:0000000000000138
    seg000:0000000000000138                               loc_138:                                ; CODE XREF: sub_0+10E↑j
    seg000:0000000000000138 8B F4                         mov     esi, esp
    seg000:000000000000013A 68 9C 51 40 00                push    40519Ch
    seg000:000000000000013F FF 15 F8 50 40 00             call    qword ptr cs:40523Dh
    seg000:000000000000013F
    seg000:0000000000000145 83 C4 04                      add     esp, 4
    seg000:0000000000000148 3B F4                         cmp     esi, esp
    seg000:000000000000014A E8 73 02 00 00                call    near ptr 3C2h
    seg000:000000000000014A
    seg000:000000000000014F 33 C0                         xor     eax, eax
    seg000:0000000000000151 52                            push    rdx
    seg000:0000000000000152 8B CD                         mov     ecx, ebp
    seg000:0000000000000154 50                            push    rax
    seg000:0000000000000155 8D 15 F0 15 40 00             lea     edx, cs:40174Bh
    seg000:000000000000015B E8 02 02 00 00                call    near ptr 362h
    seg000:000000000000015B
    seg000:0000000000000160 58                            pop     rax
    seg000:0000000000000161 5A                            pop     rdx
    seg000:0000000000000162 5F                            pop     rdi
    seg000:0000000000000163 5E                            pop     rsi
    seg000:0000000000000164 5B                            pop     rbx
    seg000:0000000000000165 8B 4D FC                      mov     ecx, [rbp-4]
    seg000:0000000000000168 33 CD                         xor     ecx, ebp
    seg000:000000000000016A E8 C3 02 00 00                call    near ptr 432h
    seg000:000000000000016A
    seg000:000000000000016F 81 C4 34 01 00 00             add     esp, 134h
    seg000:0000000000000175 3B EC                         cmp     ebp, esp
    seg000:0000000000000177 E8 46 02 00 00                call    near ptr 3C2h
    seg000:0000000000000177
    seg000:000000000000017C 8B E5                         mov     esp, ebp
    seg000:000000000000017E 5D                            pop     rbp
    seg000:000000000000017E
    seg000:000000000000017E                               sub_0 endp ; sp-analysis failed
    
  • 主要操作即为 : ^key[i%4]

  • 再回到主函数,后面就没有天堂之门了

  • 按顺序写一下解密函数

  • int main()
    {
        DWORD key[] = { 4 ,119 ,130 ,-182 };
        DWORD delta = 0x5df966ae;
        unsigned char flag[]={0xAA, 0x4F, 0x0F, 0xE2, 0xE4, 0x41, 0x99, 0x54, 0x2C, 0x2B, 0x84, 0x7E, 0xBC, 0x8F, 0x8B, 0x78, 0xD3, 0x73, 0x88, 0x5E, 0xAE, 0x47, 0x85, 0x70, 0x31, 0xB3, 0x09, 0xCE, 0x13, 0xF5, 0x0D, 0xCA};
        DWORD* pDwordFlag = (DWORD*)flag;
        unsigned long long* pQwordFlag = (unsigned long long*)flag;
        for (int i = 0; i < 32; i++)
        {
            flag[i] ^= key[i % 4];
        }
    
        pQwordFlag = (unsigned long long*)flag;
        *(pQwordFlag + 0) = (*(pQwordFlag + 0) >> 12) | (*(pQwordFlag + 0) << (64 - 12));
        *(pQwordFlag + 1) = (*(pQwordFlag + 1) >> 34) | (*(pQwordFlag + 1) << (64 - 34));
        *(pQwordFlag + 2) = (*(pQwordFlag + 2) >> 56) | (*(pQwordFlag + 2) << (64 - 56));
        *(pQwordFlag + 3) = (*(pQwordFlag + 3) >> 14) | (*(pQwordFlag + 3) << (64 - 14));
    
        delta = 0x5df966ae;
    
        delta += 0xdeadbeef;  //0x3CA7259D
    
        for (int i = 0; i < 8; i++)
        {
            DWORD tmp = pDwordFlag[i] ^ delta;
            pDwordFlag[i] -= delta;
            delta = tmp;
        }
    
        printf("flag:DASCTF{%s}", flag);
    
        return 0;
    }
    
  • DASCTF{6cc1e44811647d38a15017e389b3f704}