2

I have decompiled a DLL and IDA Pro came up with the following code:

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;
}

Where EnumFirstValidChild is defined as:

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

I modified the code above to call the userpurge function as follows:

int *v12 = &v11;

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

The problem I am having is that the call to this function is causing a stack a Run-Time Check Failure #2 - Stack around v11 variable.

v11 is 4 bytes long and I see that more than 16 bytes are wtitten to that pointer.

What could it be wrong?

Thanks!

EDIT:

Disassembled code listing of 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 ; ---------------------------------------------------------------------------

Disassembled code listing of 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 ; ---------------------------------------------------------------------------

Decompiled code of 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;
}

Decompiled code of 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;
}
3
  • In your code, sub_10029800 takes 2 arguments but in your prototypes it takes 3. I'm not sure, but I guess that sub_10029800 is following the __thiscall calling convention, and the decompiler misinterprets its prototype.
    – Spl3en
    Jun 19, 2015 at 19:52
  • Could you give us the disassembly code for 10029900 and 10029800 so we can figure out what's going on precisely ?
    – Spl3en
    Jun 19, 2015 at 20:22
  • Spl3en thanks, I modified above 10029800 to EnumFirstValidChild, and copy pasted both functions
    – fred26
    Jun 19, 2015 at 21:34

1 Answer 1

3

Let's start from the beginning:

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

Your EnumFirstValidChild prototype takes eax as the first argument, but if you look at eax in this function, it gets immediately erased by Teb->NtTib->ExceptionList (aka fs:[0]) at .text:1000B718.

Thus, the first argument isn't valid. Let's fix that as a first step:

int __cdecl EnumFirstValidChild (int a1, int a2);

I think you have already found that out, but better make sure everything is clear.

Now, more precisely about your question:

v11 is 4 bytes long and I see that more than 16 bytes are written to that pointer. What could it be wrong?

As you may know, Hex-Rays doesn't produce compilable C code, but pseudo C-like code. You have to give hints to the decompiler if you want it to decompile a correct C code.

About your issue, you were right. v11 is not 4 bytes long, but actually at least 32 bytes long: at the end of the function EnumFirstValidChild, it writes 32 bytes at the address of the second argument:

*(_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;

Furthermore, the decompiler gives you a quick way to notice this: In sub_10029900, there's nothing on the stack except:

int v11; // [bp-20h]

As you can see, there's some space between bp and bp-20h. There is just enough space for your 32 bytes array, so we can conclude that your structure size is indeed 32 bytes long.

If you wish, you can fix the output of Hex-Rays following this procedure:

Enter image description here

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.