IDA Pro 代码问题

逆向工程 艾达
2021-06-29 17:41:05

我反编译了一个 DLL,IDA Pro 提出了以下代码:

signed int __thiscall sub_10029900(void *a1, int a2) 
{    
int v2; // esi@1
int v3; // ebx@1
int v4; // eax@1
int v5; // edx@3
int v6; // eax@5
signed int v7; // esi@5
bool v8; // cf@7
signed int v9; // eax@8
int v11; // [sp+10h] [bp-20h]@1

v2 = 0;
v3 = EnumFirstValidChild(a1, &v11);

..........

return v2;
}

其中EnumFirstValidChild定义为:

int __userpurge EnumFirstValidChild<eax>(int a1<eax>, int a2, int a3);

我修改了上面的代码来调用 userpurge 函数如下:

int *v12 = &v11;

__asm 
{ 
  push v12
  push a1
  call sub_10029800
  mov v3, eax
}

我遇到的问题是对该函数的调用导致堆栈出现运行时检查失败 #2 - 围绕v11变量的堆栈

v11 是 4 个字节长,我看到超过 16 个字节指向该指针。

可能有什么问题?

谢谢!

编辑:

反汇编代码清单 sub_10029900

.text:10029900 ; =============== S U B R O U T I N E ===========
.text:10029900
.text:10029900 ; Attributes: bp-based frame
.text:10029900
.text:10029900 sub_10029900    proc near               ; CODE XREF: sub_1000F400+F1p
.text:10029900                                         ; sub_10010870+135p ...
.text:10029900
.text:10029900 var_20          = dword ptr -20h
.text:10029900 arg_0           = dword ptr  8
.text:10029900
.text:10029900                 mov     edi, edi
.text:10029902                 push    ebp
.text:10029903                 mov     ebp, esp
.text:10029905                 and     esp, 0FFFFFFF8h
.text:10029908                 sub     esp, 24h
.text:1002990B                 lea     eax, [esp+24h+var_20]
.text:1002990F                 push    ebx
.text:10029910                 push    esi
.text:10029911                 push    edi
.text:10029912                 push    eax
.text:10029913                 push    ecx
.text:10029914                 xor     esi, esi
.text:10029916                 call    ds:EnumFirstValidChild
.text:1002991C                 mov     ebx, eax
.text:1002991E                 lea     eax, [esi+1]
.text:10029921                 test    ebx, ebx
.text:10029923                 jz      short loc_10029985
.text:10029925                 mov     edi, [ebp+arg_0]
.text:10029928
.text:10029928 loc_10029928:                           ; CODE XREF: sub_10029900+6Aj
.text:10029928                 test    eax, eax
.text:1002992A                 jz      short loc_10029983
.text:1002992C                 mov     edx, [esp+30h+var_20]
.text:10029930                 test    edx, edx
.text:10029932                 jz      short loc_1002995E
.text:10029934                 test    edi, edi
.text:10029936                 jz      short loc_1002995E
.text:10029938                 mov     eax, edi
.text:1002993A                 mov     esi, 0Ch
.text:1002993F                 nop
.text:10029940
.text:10029940 loc_10029940:                           ; CODE XREF: sub_10029900+4Fj
.text:10029940                 mov     ecx, [edx]
.text:10029942                 cmp     ecx, [eax]
.text:10029944                 jnz     short loc_10029958
.text:10029946                 add     edx, 4
.text:10029949                 add     eax, 4
.text:1002994C                 sub     esi, 4
.text:1002994F                 jnb     short loc_10029940
.text:10029951                 mov     eax, 1
.text:10029956                 jmp     short loc_1002995A
.text:10029958 ; ---------------------------------------------------------------------------
.text:10029958
.text:10029958 loc_10029958:                           ; CODE XREF: sub_10029900+44j
.text:10029958                 xor     eax, eax
.text:1002995A
.text:1002995A loc_1002995A:                           ; CODE XREF: sub_10029900+56j
.text:1002995A                 test    eax, eax
.text:1002995C                 jnz     short loc_1002996C
.text:1002995E
.text:1002995E loc_1002995E:                           ; CODE XREF: sub_10029900+32j
.text:1002995E                                         ; sub_10029900+36j
.text:1002995E                 lea     eax, [esp+30h+var_20]
.text:10029962                 push    eax
.text:10029963                 push    ebx
.text:10029964                 call    ds:EnumNextValidChild
.text:1002996A                 jmp     short loc_10029928
.text:1002996C ; ---------------------------------------------------------------------------
.text:1002996C
.text:1002996C loc_1002996C:                           ; CODE XREF: sub_10029900+5Cj
.text:1002996C                 push    ebx
.text:1002996D                 mov     esi, 1
.text:10029972                 call    ds:EndEnumValidChild
.text:10029978                 mov     eax, esi
.text:1002997A                 pop     edi
.text:1002997B                 pop     esi
.text:1002997C                 pop     ebx
.text:1002997D                 mov     esp, ebp
.text:1002997F                 pop     ebp
.text:10029980                 retn    4
.text:10029983 ; ---------------------------------------------------------------------------

的反汇编代码清单EnumFirstValidChild

.text:1000B710 ; Exported entry   4. EnumFirstValidChild
.text:1000B710
.text:1000B710 ; =============== S U B R O U T I N E ==============
.text:1000B710
.text:1000B710 ; Attributes: bp-based frame
.text:1000B710
.text:1000B710                 public EnumFirstValidChild
.text:1000B710 EnumFirstValidChild proc near ; DATA XREF: .text:off_10027368o
.text:1000B710
.text:1000B710 var_28          = dword ptr -28h
.text:1000B710 var_24          = dword ptr -24h
.text:1000B710 var_20          = dword ptr -20h
.text:1000B710 var_1C          = dword ptr -1Ch
.text:1000B710 var_18          = byte ptr -18h
.text:1000B710 var_C           = dword ptr -0Ch
.text:1000B710 var_4           = dword ptr -4
.text:1000B710 arg_0           = dword ptr  8
.text:1000B710 arg_4           = dword ptr  0Ch
.text:1000B710
.text:1000B710                 mov     edi, edi
.text:1000B712                 push    ebp
.text:1000B713                 mov     ebp, esp
.text:1000B715                 and     esp, 0FFFFFFF8h
.text:1000B718                 mov     eax, large fs:0
.text:1000B71E                 push    0FFFFFFFFh
.text:1000B720                 push    offset SEH_1001DAD0
.text:1000B725                 push    eax
.text:1000B726                 mov     large fs:0, esp
.text:1000B72D                 sub     esp, 20h
.text:1000B730                 mov     ecx, dword_1002ACE8
.text:1000B736                 push    ebx
.text:1000B737                 push    esi
.text:1000B738                 push    edi
.text:1000B739                 xor     edi, edi
.text:1000B73B                 test    ecx, ecx
.text:1000B73D                 jnz     short loc_1000B77D
.text:1000B73F                 push    dword_1002ACE4
.text:1000B745                 lea     eax, [esp+3Ch+var_28]
.text:1000B749                 push    eax
.text:1000B74A                 push    7Ch
.text:1000B74C                 push    1
.text:1000B74E                 call    ds:api_func_107
.text:1000B754                 mov     ecx, [esp+38h+var_28]
.text:1000B758                 mov     [esp+38h+var_24], ecx
.text:1000B75C                 mov     [esp+38h+var_4], edi
.text:1000B760                 test    ecx, ecx
.text:1000B762                 jz      short loc_1000B76D
.text:1000B764                 call    sub_10005440
.text:1000B769                 mov     ecx, eax
.text:1000B76B                 jmp     short loc_1000B76F
.text:1000B76D ; ---------------------------------------------------------------------------
.text:1000B76D
.text:1000B76D loc_1000B76D:                           ; CODE XREF: EnumFirstValidChild+52j
.text:1000B76D                 xor     ecx, ecx
.text:1000B76F
.text:1000B76F loc_1000B76F:                           ; CODE XREF: EnumFirstValidChild+5Bj
.text:1000B76F                 mov     [esp+38h+var_4], 0FFFFFFFFh
.text:1000B777                 mov     dword_1002ACE8, ecx
.text:1000B77D
.text:1000B77D loc_1000B77D:                           ; CODE XREF: EnumFirstValidChild+2Dj
.text:1000B77D                 mov     eax, [ebp+arg_0]
.text:1000B780                 lea     esi, [ecx+34h]
.text:1000B783                 mov     [esp+38h+var_24], eax
.text:1000B787                 mov     ecx, esi
.text:1000B789                 lea     eax, [esp+38h+var_24]
.text:1000B78D                 push    eax
.text:1000B78E                 lea     eax, [esp+3Ch+var_18]
.text:1000B792                 push    eax
.text:1000B793                 call    sub_10008330
.text:1000B798                 mov     ecx, [eax]
.text:1000B79A                 mov     ebx, [eax+4]
.text:1000B79D                 mov     eax, [esi+4]
.text:1000B7A0                 mov     [esp+38h+var_20], ecx
.text:1000B7A4                 mov     [esp+38h+var_1C], ebx
.text:1000B7A8                 mov     [esp+38h+var_24], eax
.text:1000B7AC                 test    ecx, ecx
.text:1000B7AE                 jz      short loc_1000B7B4
.text:1000B7B0                 cmp     ecx, esi
.text:1000B7B2                 jz      short loc_1000B7BE
.text:1000B7B4
.text:1000B7B4 loc_1000B7B4:                           ; CODE XREF: EnumFirstValidChild+9Ej
.text:1000B7B4                 call    ds:_invalid_parameter_noinfo
.text:1000B7BA                 mov     eax, [esp+38h+var_24]
.text:1000B7BE
.text:1000B7BE loc_1000B7BE:                           ; CODE XREF: EnumFirstValidChild+A2j
.text:1000B7BE                 mov     esi, [ebp+arg_4]
.text:1000B7C1                 cmp     ebx, eax
.text:1000B7C3                 jz      short loc_1000B80B
.text:1000B7C5                 lea     ecx, [esp+38h+var_20]
.text:1000B7C9                 call    sub_10008390
.text:1000B7CE                 mov     ebx, [eax+4]
.text:1000B7D1                 test    ebx, ebx
.text:1000B7D3                 jz      short loc_1000B80B
.text:1000B7D5                 push    esi
.text:1000B7D6                 push    0
.text:1000B7D8                 mov     ecx, ebx
.text:1000B7DA                 call    sub_1001D620
.text:1000B7DF                 test    eax, eax
.text:1000B7E1                 jz      short loc_1000B80B
.text:1000B7E3                 push    dword_1002ACE4
.text:1000B7E9                 lea     eax, [esp+3Ch+var_24]
.text:1000B7ED                 push    eax
.text:1000B7EE                 push    8
.text:1000B7F0                 push    1
.text:1000B7F2                 call    ds:api_func_107
.text:1000B7F8                 mov     edi, [esp+38h+var_24]
.text:1000B7FC                 test    edi, edi
.text:1000B7FE                 jz      short loc_1000B80B
.text:1000B800                 mov     [edi], ebx
.text:1000B802                 mov     dword ptr [edi+4], 0
.text:1000B809                 jmp     short loc_1000B824
.text:1000B80B ; ---------------------------------------------------------------------------
.text:1000B80B
.text:1000B80B loc_1000B80B:                           ; CODE XREF: EnumFirstValidChild+B3j
.text:1000B80B                                         ; EnumFirstValidChild+C3j ...
.text:1000B80B                 xor     eax, eax
.text:1000B80D                 mov     [esi], eax
.text:1000B80F                 mov     [esi+4], eax
.text:1000B812                 mov     [esi+8], eax
.text:1000B815                 mov     [esi+0Ch], eax
.text:1000B818                 mov     [esi+10h], eax
.text:1000B81B                 mov     [esi+14h], eax
.text:1000B81E                 mov     [esi+18h], eax
.text:1000B821                 mov     [esi+1Ch], eax
.text:1000B824
.text:1000B824 loc_1000B824:                           ; CODE XREF: EnumFirstValidChild+F9j
.text:1000B824                 mov     ecx, [esp+38h+var_C]
.text:1000B828                 mov     eax, edi
.text:1000B82A                 pop     edi
.text:1000B82B                 pop     esi
.text:1000B82C                 mov     large fs:0, ecx
.text:1000B833                 pop     ebx
.text:1000B834                 mov     esp, ebp
.text:1000B836                 pop     ebp
.text:1000B837                 retn    8
.text:1000B837 EnumFirstValidChild endp
.text:1000B837
.text:1000B837 ; ---------------------------------------------------------------------------

的反编译代码sub_10029900

signed int __thiscall sub_10029900(void *this, int a2) //note that I changed *this to *a1
{
  int v2; // esi@1
  int v3; // ebx@1
  int v4; // eax@1
  int v5; // edx@3
  int v6; // eax@5
  signed int v7; // esi@5
  bool v8; // cf@7
  signed int v9; // eax@8
  int v11; // [sp+10h] [bp-20h]@1

  v2 = 0;
  v3 = EnumFirstValidChild(this, &v11);
  v4 = 1;
  if ( v3 )
  {
    while ( v4 )
    {
     v5 = v11;
      if ( v11 && a2 )
      {
        v6 = a2;
        v7 = 12;
        while ( *(_DWORD *)v5 == *(_DWORD *)v6 )
        {
          v5 += 4;
          v6 += 4;
          v8 = (unsigned int)v7 < 4;
          v7 -= 4;
          if ( v8 )
          {
            v9 = 1;
            goto LABEL_10;
          }
        }
        v9 = 0;
LABEL_10:
        if ( v9 )
        {
          EndEnumValidChild(v3);
          return 1;
       }
      }
      v4 = EnumNextValidChild(v3, &v11);
    }
    v2 = 0;
  }
  EndEnumValidChild(v3);
  return v2;
}

的反编译代码EnumFirstValidChild

int __userpurge EnumFirstValidChild<eax>(int a1<eax>, int a2, int a3)
{
  int v3; // ecx@1
  int v4; // edi@1
  int v5; // esi@6
  int v6; // eax@6
  int v7; // ecx@6
  int v8; // ebx@6
  int v9; // eax@6
  int v10; // ebx@10
  int v12; // [sp+1Ch] [bp-28h]@2
  int v13; // [sp+20h] [bp-24h]@2
  int v14; // [sp+24h] [bp-20h]@6
  int v15; // [sp+28h] [bp-1Ch]@6
  char v16; // [sp+2Ch] [bp-18h]@6
  int v17; // [sp+38h] [bp-Ch]@1
  int (__cdecl *v18)(); // [sp+3Ch] [bp-8h]@1
  int v19; // [sp+40h] [bp-4h]@1

  v19 = -1;
  v18 = SEH_1001DAD0;
  v17 = a1;
  v3 = dword_1002ACE8;
  v4 = 0;
  if ( !dword_1002ACE8 )
  {
    api_func_107(1, 124, &v12, dword_1002ACE4);
    v13 = v12;
    v19 = 0;
    if ( v12 )
      v3 = sub_10005440(v12);
    else
      v3 = 0;
    v19 = -1;
    dword_1002ACE8 = v3;
  }
  v5 = v3 + 52;
  v13 = a2;
  v6 = sub_10008330(v3 + 52, (int)&v16, (int)&v13);
  v7 = *(_DWORD *)v6;
  v8 = *(_DWORD *)(v6 + 4);
  v9 = *(_DWORD *)(v5 + 4);
  v14 = v7;
  v15 = v8;
  v13 = v9;
  if ( !v7 || v7 != v5 )
  {
    invalid_parameter_noinfo(v7);
    v9 = v13;
  }
  if ( v8 != v9
    && (v10 = *(_DWORD *)(sub_10008390(&v14) + 4)) != 0
    && sub_1001D620(v10, 0, a3)
    && (api_func_107(1, 8, &v13, dword_1002ACE4), (v4 = v13) != 0) )
  {
    *(_DWORD *)v13 = v10;
    *(_DWORD *)(v4 + 4) = 0;
  }
  else
  {
    *(_DWORD *)a3 = 0;
    *(_DWORD *)(a3 + 4) = 0;
    *(_DWORD *)(a3 + 8) = 0;
    *(_DWORD *)(a3 + 12) = 0;
    *(_DWORD *)(a3 + 16) = 0;
    *(_DWORD *)(a3 + 20) = 0;
    *(_DWORD *)(a3 + 24) = 0;
    *(_DWORD *)(a3 + 28) = 0;
  }
  return v4;
}
1个回答

让我们从头开始:

int __userpurge EnumFirstValidChild<eax>(int a1<eax>, int a2, int a3);

您的EnumFirstValidChild原型将eax作为第一个参数,但是如果您查看eax此函数,它会立即被Teb->NtTib->ExceptionList(aka fs:[0]) at擦除.text:1000B718

因此,第一个参数无效,让我们作为第一步修复它:

int __cdecl EnumFirstValidChild (int a1, int a2);

我想你已经发现了,但最好确保一切都清楚。

现在,更准确地说你的问题:

v11 有 4 个字节长,我看到超过 16 个字节被写入该指针。可能有什么问题?

您可能知道,Hexrays 不会生成可编译的 C 代码,而是生成类似于 C 的伪代码。如果您希望反编译器反编译正确的 C 代码,则必须向反编译器提供提示。

关于你的问题,你是对的,v11 不是 4 个字节长,但实际上至少 32 个字节长:在函数的末尾EnumFirstValidChild,它在第二个参数的地址处写入 32 个字节:

*(_DWORD *)a3 = 0;
*(_DWORD *)(a3 + 4) = 0;
*(_DWORD *)(a3 + 8) = 0;
*(_DWORD *)(a3 + 12) = 0;
*(_DWORD *)(a3 + 16) = 0;
*(_DWORD )(a3 + 20) = 0;
*(_DWORD *)(a3 + 24) = 0;
*(_DWORD *)(a3 + 28) = 0; 

此外,反编译器为您提供了一种快速注意到这一点的方法:在 中sub_10029900,堆栈中除了:

int v11; // [bp-20h]

如您所见,bp 和 bp-20h 之间有一些空格。您的 32 字节数组有足够的空间,因此我们可以得出结论,您的结构大小确实是 32 字节长。

如果您愿意,可以按照以下步骤修复 Hexray 的输出:

在此处输入图片说明