首页
社区
课程
招聘
[原创]看雪 2022 KCTF 春季赛 第三题 石像病毒
发表于: 2022-5-16 06:16 8034

[原创]看雪 2022 KCTF 春季赛 第三题 石像病毒

2022-5-16 06:16
8034

IDA逆向

主程序:

注意到 MEMORY[0] = v.field_40;,这是第一次引发异常的位置。
引发异常的位置还有若干个;程序利用 SEH(Structured Exception Handling,结构化异常处理) 机制处理异常,在处理过程中对程序进行了一定的修改。

这部分的汇编如下:

IDA 已经标记出了 __try、__except filter 和 __except 块(在反编译的C代码中看不到)。

.rdata 节也有相应的数据结构,例如:

关于SEH机制,在搜索资料的过程中找到了两篇个人认为不错的文章:

对于本题,只需要理解到本题程序发生异常后的控制流都是先运行 __except filter 块再运行 __except 块即可。

在此基础上也可以patch程序让程序的控制流恢复正常。(但对于做题来讲速度就太慢了)

通过程序结构和常量,初步识别出 sub_402DB0 是 md5,sub_402070 是 AES (是否魔改过暂时未知)。

动态调试。异常会被调试器捕获,需要透传给程序,在 x64dbg 调试器中按 shift+F7/F8/F9

md5 过程中在 0x402D1C 触发了一次除零异常,然后进入 __except filter,在 0x402D2B 调用 0x402C60 修改了 md5 常量表的一个值。

对于 AES,

sub_4010BE(AES 的 key expansion) 里,0x401685 处有无效指令异常(可以手动patch成nop,IDA就能正确反编译此函数并识别出 __except 块灯信息了),在 __except filter 0x40168F 处调用到 sub_402330 函数交换了 sbox 0x71 和 0xA3 两项的值。(动态调试发现是每轮都会交换)

实际上,上面的分析全部都不用做,直接等到 sub_4010BE 结束从内存中提取展开后的 11 个 AES 轮密钥。

接下来是 AES 的四种轮操作,自己找一份标准 AES 实现,打印出每步的计算结果与程序做比对,看程序是否有对标准算法做修改:

根据分析结果修改 AES 解密的逻辑

得到flag:

 
int __cdecl main_0(int argc, const char **argv, const char **envp)
{
  void *v3; // esp
  char v7; // [esp-10h] [ebp-1048h]
  struct struc_1 v; // [esp+0h] [ebp-1038h] BYREF
  CPPEH_RECORD ms_exc; // [esp+1020h] [ebp-18h]
 
  v3 = alloca(4128);
  memset(&v, 0xCCu, sizeof(v));
  ms_exc.registration.ScopeTable = (PSCOPETABLE_ENTRY)((int)ms_exc.registration.ScopeTable ^ __security_cookie);
  memset(v.s, 0, sizeof(v.s));
  memset(v.ciphertext, 0, sizeof(v.ciphertext));
  gets_s(v.s, 4000u);
  if ( strlen(v.s) == 32 )
  {
    for ( v.field_40 = 0; v.field_40 < 512; ++v.field_40 )
    {
      v.field_3C = 0;
      MEMORY[0] = v.field_40;
      ms_exc.registration.TryLevel = -2;
    }
    strcpy(v.field_24, "Enj0y_1t_4_fuuuN");
    _DX = '_\0';
    *(_WORD *)&v.field_24[17] = 0;
    v.field_24[19] = 0;
    memset(v.field_8, 0, sizeof(v.field_8));
    for ( v.field_0 = 0; v.field_0 < 512; ++v.field_0 )
    {
      __asm { insb }
      ms_exc.registration.TryLevel = -2;
      _DX = LOWORD(v.field_0) + 1;
    }
    j_md5(v.field_24, 0x10u, v.field_8);
    j_aes(v.field_8, 0x10u, v.s, v.ciphertext, 32);
    if ( !memcmp(v.ciphertext, finalcompare, 0x20u) )
      j_printf("OK\n", v7);
    else
      j_printf("NO\n", v7);
    return 0;
  }
  else
  {
    j_printf("NO\n", v7);
    return 0;
  }
}
int __cdecl main_0(int argc, const char **argv, const char **envp)
{
  void *v3; // esp
  char v7; // [esp-10h] [ebp-1048h]
  struct struc_1 v; // [esp+0h] [ebp-1038h] BYREF
  CPPEH_RECORD ms_exc; // [esp+1020h] [ebp-18h]
 
  v3 = alloca(4128);
  memset(&v, 0xCCu, sizeof(v));
  ms_exc.registration.ScopeTable = (PSCOPETABLE_ENTRY)((int)ms_exc.registration.ScopeTable ^ __security_cookie);
  memset(v.s, 0, sizeof(v.s));
  memset(v.ciphertext, 0, sizeof(v.ciphertext));
  gets_s(v.s, 4000u);
  if ( strlen(v.s) == 32 )
  {
    for ( v.field_40 = 0; v.field_40 < 512; ++v.field_40 )
    {
      v.field_3C = 0;
      MEMORY[0] = v.field_40;
      ms_exc.registration.TryLevel = -2;
    }
    strcpy(v.field_24, "Enj0y_1t_4_fuuuN");
    _DX = '_\0';
    *(_WORD *)&v.field_24[17] = 0;
    v.field_24[19] = 0;
    memset(v.field_8, 0, sizeof(v.field_8));
    for ( v.field_0 = 0; v.field_0 < 512; ++v.field_0 )
    {
      __asm { insb }
      ms_exc.registration.TryLevel = -2;
      _DX = LOWORD(v.field_0) + 1;
    }
    j_md5(v.field_24, 0x10u, v.field_8);
    j_aes(v.field_8, 0x10u, v.s, v.ciphertext, 32);
    if ( !memcmp(v.ciphertext, finalcompare, 0x20u) )
      j_printf("OK\n", v7);
    else
      j_printf("NO\n", v7);
    return 0;
  }
  else
  {
    j_printf("NO\n", v7);
    return 0;
  }
}
 
.text:004028B8 loc_4028B8:                             ; CODE XREF: _main_0:loc_40290B↓j
.text:004028B8                 mov     ecx, [ebp+v.field_40]
.text:004028BE                 add     ecx, 1
.text:004028C1                 mov     [ebp+v.field_40], ecx
.text:004028C7
.text:004028C7 loc_4028C7:                             ; CODE XREF: _main_0+F6↑j
.text:004028C7                 cmp     [ebp+v.field_40], 200h
.text:004028D1                 jge     short loc_40290D
.text:004028D3 ;   __try { // __except at loc_402901
.text:004028D3                 mov     [ebp+ms_exc.registration.TryLevel], 0
.text:004028DA                 mov     [ebp+v.field_3C], 0
.text:004028E4                 mov     edx, [ebp+v.field_3C]
.text:004028EA                 mov     al, byte ptr [ebp+v.field_40]
.text:004028F0                 mov     [edx], al
.text:004028F0 ;   } // starts at 4028D3
.text:004028F2                 mov     [ebp+ms_exc.registration.TryLevel], 0FFFFFFFEh
.text:004028F9                 jmp     short loc_40290B
.text:004028FB ; ---------------------------------------------------------------------------
.text:004028FB
.text:004028FB loc_4028FB:                            ; DATA XREF: .rdata:stru_40A030↓o
.text:004028FB ;   __except filter // owned by 4028D3
.text:004028FB                 mov     eax, 1
.text:00402900                 retn
.text:00402901 ; ---------------------------------------------------------------------------
.text:00402901
.text:00402901 loc_402901:                             ; DATA XREF: .rdata:stru_40A030↓o
.text:00402901 ;   __except(loc_4028FB) // owned by 4028D3
.text:00402901                 mov     esp, [ebp+ms_exc.old_esp]
.text:00402904                 mov     [ebp+ms_exc.registration.TryLevel], 0FFFFFFFEh
.text:0040290B
.text:0040290B loc_40290B:                             ; CODE XREF: _main_0+139↑j
.text:0040290B                 jmp     short loc_4028B8
.text:0040290D ; ---------------------------------------------------------------------------
.text:0040290D
.text:004028B8 loc_4028B8:                             ; CODE XREF: _main_0:loc_40290B↓j
.text:004028B8                 mov     ecx, [ebp+v.field_40]
.text:004028BE                 add     ecx, 1
.text:004028C1                 mov     [ebp+v.field_40], ecx
.text:004028C7
.text:004028C7 loc_4028C7:                             ; CODE XREF: _main_0+F6↑j
.text:004028C7                 cmp     [ebp+v.field_40], 200h
.text:004028D1                 jge     short loc_40290D
.text:004028D3 ;   __try { // __except at loc_402901
.text:004028D3                 mov     [ebp+ms_exc.registration.TryLevel], 0
.text:004028DA                 mov     [ebp+v.field_3C], 0
.text:004028E4                 mov     edx, [ebp+v.field_3C]
.text:004028EA                 mov     al, byte ptr [ebp+v.field_40]
.text:004028F0                 mov     [edx], al
.text:004028F0 ;   } // starts at 4028D3
.text:004028F2                 mov     [ebp+ms_exc.registration.TryLevel], 0FFFFFFFEh
.text:004028F9                 jmp     short loc_40290B
.text:004028FB ; ---------------------------------------------------------------------------
.text:004028FB
.text:004028FB loc_4028FB:                            ; DATA XREF: .rdata:stru_40A030↓o
.text:004028FB ;   __except filter // owned by 4028D3
.text:004028FB                 mov     eax, 1
.text:00402900                 retn
.text:00402901 ; ---------------------------------------------------------------------------
.text:00402901
.text:00402901 loc_402901:                             ; DATA XREF: .rdata:stru_40A030↓o
.text:00402901 ;   __except(loc_4028FB) // owned by 4028D3
.text:00402901                 mov     esp, [ebp+ms_exc.old_esp]
.text:00402904                 mov     [ebp+ms_exc.registration.TryLevel], 0FFFFFFFEh
.text:0040290B
.text:0040290B loc_40290B:                             ; CODE XREF: _main_0+139↑j
.text:0040290B                 jmp     short loc_4028B8
.text:0040290D ; ---------------------------------------------------------------------------
.text:0040290D
 
.rdata:0040A030 stru_40A030     dd 0FFFFFFE4h           ; GSCookieOffset
.rdata:0040A030                                         ; DATA XREF: _main_0+5↑o
.rdata:0040A030                 dd 0                    ; GSCookieXOROffset
.rdata:0040A030                 dd 0FFFFEFB8h           ; EHCookieOffset
.rdata:0040A030                 dd 0                    ; EHCookieXOROffset
.rdata:0040A030                 dd 0FFFFFFFEh           ; ScopeRecord.EnclosingLevel
.rdata:0040A030                 dd offset loc_4028FB    ; ScopeRecord.FilterFunc
.rdata:0040A030                 dd offset loc_402901    ; ScopeRecord.HandlerFunc
.rdata:0040A030                 dd 0FFFFFFFEh           ; ScopeRecord.EnclosingLevel
.rdata:0040A030                 dd offset loc_4029AF    ; ScopeRecord.FilterFunc
.rdata:0040A030                 dd offset loc_4029B5    ; ScopeRecord.HandlerFunc
.rdata:0040A058                 align 10h
.rdata:0040A030 stru_40A030     dd 0FFFFFFE4h           ; GSCookieOffset
.rdata:0040A030                                         ; DATA XREF: _main_0+5↑o
.rdata:0040A030                 dd 0                    ; GSCookieXOROffset
.rdata:0040A030                 dd 0FFFFEFB8h           ; EHCookieOffset
.rdata:0040A030                 dd 0                    ; EHCookieXOROffset
.rdata:0040A030                 dd 0FFFFFFFEh           ; ScopeRecord.EnclosingLevel
.rdata:0040A030                 dd offset loc_4028FB    ; ScopeRecord.FilterFunc
.rdata:0040A030                 dd offset loc_402901    ; ScopeRecord.HandlerFunc
.rdata:0040A030                 dd 0FFFFFFFEh           ; ScopeRecord.EnclosingLevel
.rdata:0040A030                 dd offset loc_4029AF    ; ScopeRecord.FilterFunc
.rdata:0040A030                 dd offset loc_4029B5    ; ScopeRecord.HandlerFunc
.rdata:0040A058                 align 10h
 
 
 
 

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

收藏
免费 3
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//