Introduction
When studying Matt Pietrek's excellent article "A Crash Course on the Depths of Win32 Structured Exception Handling" (MSJ, Jan 1997), I found a new routine was called in _except_handler3
in Windows XP SP2. It's _ValidateEH3RN
. Microsoft doesn't supply the source code of this function. I searched for it in Google, but couldn't find any useful information.
With the help of the Visual Studio .NET 2003 debugger, I spent a day and night to finish it, and named the file _ValidateEH3RN.c, although I know its original name in the CRT source is eh3valid.c. I compiled it using the command line "CL /c /Ob1 /Z7 /Zl _ValidateEH3RN.c" and then disassembled the generated obj file and the Microsoft supplied obj file (eh3valid.obj in the crt\src\intel\xst_lib directory) using DUMPBIN. When I compared them with Beyond Compare, I found the first 217 lines are the same exactly, and the remainder is similar (in fact, they are only different in their register usage). Because of the difference, my code is 2 bytes longer than eh3valid.obj. Although I spent a lot of time on the compiler documents and the debugger, I couldn't address the problem.
The following is the _ValidateEH3RN.c file:
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define TRYLEVEL_NONE -1 // For convenient
typedef struct _SCOPETABLE_ENTRY {
DWORD EnclosingLevel;
PVOID FilterFunc;
PVOID HandlerFunc;
} SCOPETABLE_ENTRY, *PSCOPETABLE_ENTRY;
typedef struct _EH3_EXCEPTION_REGISTRATION {
struct _EH3_EXCEPTION_REGISTRATION *Next;
PVOID ExceptionHandler;
PSCOPETABLE_ENTRY ScopeTable;
DWORD TryLevel;
} EH3_EXCEPTION_REGISTRATION, *PEH3_EXCEPTION_REGISTRATION;
#define PcTeb 0x18
__inline struct _TEB * NtCurrentTeb( void ) { __asm mov eax, fs:[PcTeb] }
INT nValidPages=0;
PVOID rgValidPages[0x10]={NULL};
BOOL lModifying=FALSE;
int __cdecl _ValidateEH3RN(
PEH3_EXCEPTION_REGISTRATION pRN)
{
MEMORY_BASIC_INFORMATION mbi;
PIMAGE_SECTION_HEADER pSection;
PVOID pScopePage;
INT iValid;
UINT iSection;
INT iValid2;
PNT_TIB pTIB;
PSCOPETABLE_ENTRY pScopeTable;
INT nFilters;
PVOID pTmp;
PIMAGE_NT_HEADERS pNTHeader;
PIMAGE_DOS_HEADER pDOSHeader;
PIMAGE_OPTIONAL_HEADER pOptHeader;
DWORD level;
DWORD rvaScopeTable;
pScopeTable = pRN->ScopeTable;
if ((DWORD)pScopeTable & 0x3)
{
return 0;
}
pTIB = (PNT_TIB)NtCurrentTeb();
if ((PVOID)pScopeTable >= (PVOID)pTIB->StackLimit
&& (PVOID)pScopeTable < (PVOID)pTIB->StackBase)
{
return 0;
}
if (pRN->TryLevel == TRYLEVEL_NONE)
{
return 1;
}
for (nFilters=0, level=0; level<=pRN->TryLevel; level++)
{
DWORD enclosing = pScopeTable[level].EnclosingLevel;
if (enclosing != TRYLEVEL_NONE && enclosing >= level)
{
return 0;
}
if (pScopeTable[level].FilterFunc != NULL)
nFilters++;
}
if (nFilters
&& ((PVOID)*(PDWORD)((PBYTE)pRN-8) < pTIB->StackLimit || (PVOID)*(PDWORD)((PBYTE)pRN-8) >= (PVOID)pRN))
{
return 0;
}
pScopePage = (PVOID)((DWORD)pScopeTable & 0xFFFFF000);
for (iValid=0; iValid<nValidPages; iValid++)
{
if (rgValidPages[iValid] == pScopePage)
{
if (iValid>0 && !InterlockedExchange(&lModifying, 1))
{
if (rgValidPages[iValid] != pScopePage)
{
for (iValid=nValidPages-1; iValid>=0; iValid--)
{
if (rgValidPages[iValid] == pScopePage)
break;
}
if (iValid < 0)
{
if (nValidPages < 0x10)
nValidPages++;
iValid = nValidPages - 1;
}
else
{
if (iValid == 0)
{
InterlockedExchange(&lModifying, 0);
return 1;
}
}
}
for (iValid2=0; iValid2<=iValid; iValid2++)
{
pTmp = rgValidPages[iValid2];
rgValidPages[iValid2] = pScopePage;
pScopePage = pTmp;
}
InterlockedExchange(&lModifying, 0);
}
return 1;
}
}
if (!VirtualQuery((LPCVOID)pScopeTable, &mbi, sizeof(mbi))
|| mbi.Type != MEM_IMAGE)
{
return -1;
}
if (!(mbi.Protect & (PAGE_READWRITE | PAGE_WRITECOPY |
PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY)))
{
goto exit_success;
}
pDOSHeader = (PIMAGE_DOS_HEADER)mbi.AllocationBase;
if (pDOSHeader->e_magic != IMAGE_DOS_SIGNATURE)
{
return -1;
}
pNTHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDOSHeader + pDOSHeader->e_lfanew);
if (pNTHeader->Signature != IMAGE_NT_SIGNATURE)
{
return -1;
}
pOptHeader = (PIMAGE_OPTIONAL_HEADER)&pNTHeader->OptionalHeader;
if (pOptHeader->Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC)
{
return -1;
}
rvaScopeTable = (PBYTE)pScopeTable - (PBYTE)pDOSHeader;
iSection = 0;
pSection = IMAGE_FIRST_SECTION(pNTHeader); if (iSection < (UINT)pNTHeader->FileHeader.NumberOfSections)
{
if (rvaScopeTable >= pSection->VirtualAddress
&& rvaScopeTable < pSection->VirtualAddress +
pSection->Misc.VirtualSize
&& pSection->Characteristics & IMAGE_SCN_MEM_WRITE)
{
return 0;
}
}
else
{
return -1;
}
exit_success:
if (InterlockedExchange(&lModifying, 1))
{
return 1;
}
for (iValid=nValidPages; iValid>0; iValid--)
{
if (rgValidPages[iValid-1] == pScopePage)
break;
}
if (!iValid)
{
for (iValid=(nValidPages>0xF)?0xF:nValidPages, iValid2=0;
iValid2<=iValid; iValid2++)
{
pTmp = rgValidPages[iValid2];
rgValidPages[iValid2] = pScopePage;
pScopePage = pTmp;
}
if (nValidPages < 0x10)
nValidPages++;
}
InterlockedExchange(&lModifying, 0);
return 1;
}
The following is the output of DUMPBIN with the _ValidateEH3RN.obj file:
Microsoft (R) COFF/PE Dumper Version 7.10.3077
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file _ValidateEH3RN.obj
File Type: COFF OBJECT
__ValidateEH3RN:
00000000: 55 push ebp
00000001: 8B EC mov ebp,esp
00000003: 83 EC 5C sub esp,5Ch
00000006: 8B 45 08 mov eax,dword ptr [ebp+8]
00000009: 8B 48 08 mov ecx,dword ptr [eax+8]
0000000C: 89 4D E0 mov dword ptr [ebp-20h],ecx
0000000F: 8B 55 E0 mov edx,dword ptr [ebp-20h]
00000012: 83 E2 03 and edx,3
00000015: 74 07 je 0000001E
00000017: 33 C0 xor eax,eax
00000019: E9 C8 03 00 00 jmp 000003E6
0000001E: 64 A1 18 00 00 00 mov eax,dword ptr fs:[00000018h]
00000024: 89 45 DC mov dword ptr [ebp-24h],eax
00000027: 8B 45 DC mov eax,dword ptr [ebp-24h]
0000002A: 8B 4D E0 mov ecx,dword ptr [ebp-20h]
0000002D: 3B 48 08 cmp ecx,dword ptr [eax+8]
00000030: 72 12 jb 00000044
00000032: 8B 55 DC mov edx,dword ptr [ebp-24h]
00000035: 8B 45 E0 mov eax,dword ptr [ebp-20h]
00000038: 3B 42 04 cmp eax,dword ptr [edx+4]
0000003B: 73 07 jae 00000044
0000003D: 33 C0 xor eax,eax
0000003F: E9 A2 03 00 00 jmp 000003E6
00000044: 8B 4D 08 mov ecx,dword ptr [ebp+8]
00000047: 83 79 0C FF cmp dword ptr [ecx+0Ch],0FFFFFFFFh
0000004B: 75 0A jne 00000057
0000004D: B8 01 00 00 00 mov eax,1
00000052: E9 8F 03 00 00 jmp 000003E6
00000057: C7 45 E4 00 00 00 mov dword ptr [ebp-1Ch],0
00
0000005E: C7 45 F8 00 00 00 mov dword ptr [ebp-8],0
00
00000065: EB 09 jmp 00000070
00000067: 8B 55 F8 mov edx,dword ptr [ebp-8]
0000006A: 83 C2 01 add edx,1
0000006D: 89 55 F8 mov dword ptr [ebp-8],edx
00000070: 8B 45 08 mov eax,dword ptr [ebp+8]
00000073: 8B 4D F8 mov ecx,dword ptr [ebp-8]
00000076: 3B 48 0C cmp ecx,dword ptr [eax+0Ch]
00000079: 77 3F ja 000000BA
0000007B: 8B 55 F8 mov edx,dword ptr [ebp-8]
0000007E: 6B D2 0C imul edx,edx,0Ch
00000081: 8B 45 E0 mov eax,dword ptr [ebp-20h]
00000084: 8B 0C 10 mov ecx,dword ptr [eax+edx]
00000087: 89 4D A8 mov dword ptr [ebp-58h],ecx
0000008A: 83 7D A8 FF cmp dword ptr [ebp-58h],0FFFFFFFFh
0000008E: 74 0F je 0000009F
00000090: 8B 55 A8 mov edx,dword ptr [ebp-58h]
00000093: 3B 55 F8 cmp edx,dword ptr [ebp-8]
00000096: 72 07 jb 0000009F
00000098: 33 C0 xor eax,eax
0000009A: E9 47 03 00 00 jmp 000003E6
0000009F: 8B 45 F8 mov eax,dword ptr [ebp-8]
000000A2: 6B C0 0C imul eax,eax,0Ch
000000A5: 8B 4D E0 mov ecx,dword ptr [ebp-20h]
000000A8: 83 7C 01 04 00 cmp dword ptr [ecx+eax+4],0
000000AD: 74 09 je 000000B8
000000AF: 8B 55 E4 mov edx,dword ptr [ebp-1Ch]
000000B2: 83 C2 01 add edx,1
000000B5: 89 55 E4 mov dword ptr [ebp-1Ch],edx
000000B8: EB AD jmp 00000067
000000BA: 83 7D E4 00 cmp dword ptr [ebp-1Ch],0
000000BE: 74 20 je 000000E0
000000C0: 8B 45 08 mov eax,dword ptr [ebp+8]
000000C3: 8B 4D DC mov ecx,dword ptr [ebp-24h]
000000C6: 8B 50 F8 mov edx,dword ptr [eax-8]
000000C9: 3B 51 08 cmp edx,dword ptr [ecx+8]
000000CC: 72 0B jb 000000D9
000000CE: 8B 45 08 mov eax,dword ptr [ebp+8]
000000D1: 8B 48 F8 mov ecx,dword ptr [eax-8]
000000D4: 3B 4D 08 cmp ecx,dword ptr [ebp+8]
000000D7: 72 07 jb 000000E0
000000D9: 33 C0 xor eax,eax
000000DB: E9 06 03 00 00 jmp 000003E6
000000E0: 8B 55 E0 mov edx,dword ptr [ebp-20h]
000000E3: 81 E2 00 F0 FF FF and edx,0FFFFF000h
000000E9: 89 55 CC mov dword ptr [ebp-34h],edx
000000EC: C7 45 D0 00 00 00 mov dword ptr [ebp-30h],0
00
000000F3: EB 09 jmp 000000FE
000000F5: 8B 45 D0 mov eax,dword ptr [ebp-30h]
000000F8: 83 C0 01 add eax,1
000000FB: 89 45 D0 mov dword ptr [ebp-30h],eax
000000FE: 8B 4D D0 mov ecx,dword ptr [ebp-30h]
00000101: 3B 0D 00 00 00 00 cmp ecx,dword ptr [_nValidPages]
00000107: 0F 8D 11 01 00 00 jge 0000021E
0000010D: 8B 55 D0 mov edx,dword ptr [ebp-30h]
00000110: 8B 04 95 00 00 00 mov eax,dword ptr [edx*4]
00
00000117: 3B 45 CC cmp eax,dword ptr [ebp-34h]
0000011A: 0F 85 F9 00 00 00 jne 00000219
00000120: 83 7D D0 00 cmp dword ptr [ebp-30h],0
00000124: 0F 8E E5 00 00 00 jle 0000020F
0000012A: 6A 01 push 1
0000012C: 68 00 00 00 00 push offset _lModifying
00000131: FF 15 00 00 00 00 call dword ptr [__imp__InterlockedExchange@8]
00000137: 85 C0 test eax,eax
00000139: 0F 85 D0 00 00 00 jne 0000020F
0000013F: 8B 4D D0 mov ecx,dword ptr [ebp-30h]
00000142: 8B 14 8D 00 00 00 mov edx,dword ptr [ecx*4]
00
00000149: 3B 55 CC cmp edx,dword ptr [ebp-34h]
0000014C: 74 78 je 000001C6
0000014E: A1 00 00 00 00 mov eax,dword ptr [_nValidPages]
00000153: 83 E8 01 sub eax,1
00000156: 89 45 D0 mov dword ptr [ebp-30h],eax
00000159: EB 09 jmp 00000164
0000015B: 8B 4D D0 mov ecx,dword ptr [ebp-30h]
0000015E: 83 E9 01 sub ecx,1
00000161: 89 4D D0 mov dword ptr [ebp-30h],ecx
00000164: 83 7D D0 00 cmp dword ptr [ebp-30h],0
00000168: 7C 13 jl 0000017D
0000016A: 8B 55 D0 mov edx,dword ptr [ebp-30h]
0000016D: 8B 04 95 00 00 00 mov eax,dword ptr [edx*4]
00
00000174: 3B 45 CC cmp eax,dword ptr [ebp-34h]
00000177: 75 02 jne 0000017B
00000179: EB 02 jmp 0000017D
0000017B: EB DE jmp 0000015B
0000017D: 83 7D D0 00 cmp dword ptr [ebp-30h],0
00000181: 7D 26 jge 000001A9
00000183: 83 3D 00 00 00 00 cmp dword ptr [_nValidPages],10h
10
0000018A: 7D 0F jge 0000019B
0000018C: 8B 0D 00 00 00 00 mov ecx,dword ptr [_nValidPages]
00000192: 83 C1 01 add ecx,1
00000195: 89 0D 00 00 00 00 mov dword ptr [_nValidPages],ecx
0000019B: 8B 15 00 00 00 00 mov edx,dword ptr [_nValidPages]
000001A1: 83 EA 01 sub edx,1
000001A4: 89 55 D0 mov dword ptr [ebp-30h],edx
000001A7: EB 1D jmp 000001C6
000001A9: 83 7D D0 00 cmp dword ptr [ebp-30h],0
000001AD: 75 17 jne 000001C6
000001AF: 6A 00 push 0
000001B1: 68 00 00 00 00 push offset _lModifying
000001B6: FF 15 00 00 00 00 call dword ptr [__imp__InterlockedExchange@8]
000001BC: B8 01 00 00 00 mov eax,1
000001C1: E9 20 02 00 00 jmp 000003E6
000001C6: C7 45 D8 00 00 00 mov dword ptr [ebp-28h],0
00
000001CD: EB 09 jmp 000001D8
000001CF: 8B 45 D8 mov eax,dword ptr [ebp-28h]
000001D2: 83 C0 01 add eax,1
000001D5: 89 45 D8 mov dword ptr [ebp-28h],eax
000001D8: 8B 4D D8 mov ecx,dword ptr [ebp-28h]
000001DB: 3B 4D D0 cmp ecx,dword ptr [ebp-30h]
000001DE: 7F 22 jg 00000202
000001E0: 8B 55 D8 mov edx,dword ptr [ebp-28h]
000001E3: 8B 04 95 00 00 00 mov eax,dword ptr [edx*4]
00
000001EA: 89 45 E8 mov dword ptr [ebp-18h],eax
000001ED: 8B 4D D8 mov ecx,dword ptr [ebp-28h]
000001F0: 8B 55 CC mov edx,dword ptr [ebp-34h]
000001F3: 89 14 8D 00 00 00 mov dword ptr [ecx*4],edx
00
000001FA: 8B 45 E8 mov eax,dword ptr [ebp-18h]
000001FD: 89 45 CC mov dword ptr [ebp-34h],eax
00000200: EB CD jmp 000001CF
00000202: 6A 00 push 0
00000204: 68 00 00 00 00 push offset _lModifying
00000209: FF 15 00 00 00 00 call dword ptr [__imp__InterlockedExchange@8]
0000020F: B8 01 00 00 00 mov eax,1
00000214: E9 CD 01 00 00 jmp 000003E6
00000219: E9 D7 FE FF FF jmp 000000F5
0000021E: 6A 1C push 1Ch
00000220: 8D 4D AC lea ecx,[ebp-54h]
00000223: 51 push ecx
00000224: 8B 55 E0 mov edx,dword ptr [ebp-20h]
00000227: 52 push edx
00000228: FF 15 00 00 00 00 call dword ptr [__imp__VirtualQuery@12]
0000022E: 85 C0 test eax,eax
00000230: 74 09 je 0000023B
00000232: 81 7D C4 00 00 00 cmp dword ptr [ebp-3Ch],1000000h
01
00000239: 74 08 je 00000243
0000023B: 83 C8 FF or eax,0FFFFFFFFh
0000023E: E9 A3 01 00 00 jmp 000003E6
00000243: 8B 45 C0 mov eax,dword ptr [ebp-40h]
00000246: 25 CC 00 00 00 and eax,0CCh
0000024B: 75 05 jne 00000252
0000024D: E9 C0 00 00 00 jmp $exit_success$19845
00000252: 8B 4D B0 mov ecx,dword ptr [ebp-50h]
00000255: 89 4D F0 mov dword ptr [ebp-10h],ecx
00000258: 8B 55 F0 mov edx,dword ptr [ebp-10h]
0000025B: 0F B7 02 movzx eax,word ptr [edx]
0000025E: 3D 4D 5A 00 00 cmp eax,5A4Dh
00000263: 74 08 je 0000026D
00000265: 83 C8 FF or eax,0FFFFFFFFh
00000268: E9 79 01 00 00 jmp 000003E6
0000026D: 8B 4D F0 mov ecx,dword ptr [ebp-10h]
00000270: 8B 55 F0 mov edx,dword ptr [ebp-10h]
00000273: 03 51 3C add edx,dword ptr [ecx+3Ch]
00000276: 89 55 EC mov dword ptr [ebp-14h],edx
00000279: 8B 45 EC mov eax,dword ptr [ebp-14h]
0000027C: 81 38 50 45 00 00 cmp dword ptr [eax],4550h
00000282: 74 08 je 0000028C
00000284: 83 C8 FF or eax,0FFFFFFFFh
00000287: E9 5A 01 00 00 jmp 000003E6
0000028C: 8B 4D EC mov ecx,dword ptr [ebp-14h]
0000028F: 83 C1 18 add ecx,18h
00000292: 89 4D F4 mov dword ptr [ebp-0Ch],ecx
00000295: 8B 55 F4 mov edx,dword ptr [ebp-0Ch]
00000298: 0F B7 02 movzx eax,word ptr [edx]
0000029B: 3D 0B 01 00 00 cmp eax,10Bh
000002A0: 74 08 je 000002AA
000002A2: 83 C8 FF or eax,0FFFFFFFFh
000002A5: E9 3C 01 00 00 jmp 000003E6
000002AA: 8B 4D E0 mov ecx,dword ptr [ebp-20h]
000002AD: 2B 4D F0 sub ecx,dword ptr [ebp-10h]
000002B0: 89 4D FC mov dword ptr [ebp-4],ecx
000002B3: C7 45 D4 00 00 00 mov dword ptr [ebp-2Ch],0
00
000002BA: 8B 55 EC mov edx,dword ptr [ebp-14h]
000002BD: 0F B7 42 14 movzx eax,word ptr [edx+14h]
000002C1: 8B 4D EC mov ecx,dword ptr [ebp-14h]
000002C4: 8D 54 01 18 lea edx,[ecx+eax+18h]
000002C8: 89 55 C8 mov dword ptr [ebp-38h],edx
000002CB: 8B 45 EC mov eax,dword ptr [ebp-14h]
000002CE: 0F B7 48 06 movzx ecx,word ptr [eax+6]
000002D2: 39 4D D4 cmp dword ptr [ebp-2Ch],ecx
000002D5: 73 33 jae 0000030A
000002D7: 8B 55 C8 mov edx,dword ptr [ebp-38h]
000002DA: 8B 45 FC mov eax,dword ptr [ebp-4]
000002DD: 3B 42 0C cmp eax,dword ptr [edx+0Ch]
000002E0: 72 26 jb 00000308
000002E2: 8B 4D C8 mov ecx,dword ptr [ebp-38h]
000002E5: 8B 51 0C mov edx,dword ptr [ecx+0Ch]
000002E8: 8B 45 C8 mov eax,dword ptr [ebp-38h]
000002EB: 03 50 08 add edx,dword ptr [eax+8]
000002EE: 39 55 FC cmp dword ptr [ebp-4],edx
000002F1: 73 15 jae 00000308
000002F3: 8B 4D C8 mov ecx,dword ptr [ebp-38h]
000002F6: 8B 51 24 mov edx,dword ptr [ecx+24h]
000002F9: 81 E2 00 00 00 80 and edx,80000000h
000002FF: 74 07 je 00000308
00000301: 33 C0 xor eax,eax
00000303: E9 DE 00 00 00 jmp 000003E6
00000308: EB 08 jmp $exit_success$19845
0000030A: 83 C8 FF or eax,0FFFFFFFFh
0000030D: E9 D4 00 00 00 jmp 000003E6
$exit_success$19845:
00000312: 6A 01 push 1
00000314: 68 00 00 00 00 push offset _lModifying
00000319: FF 15 00 00 00 00 call dword ptr [__imp__InterlockedExchange@8]
0000031F: 85 C0 test eax,eax
00000321: 74 0A je 0000032D
00000323: B8 01 00 00 00 mov eax,1
00000328: E9 B9 00 00 00 jmp 000003E6
0000032D: A1 00 00 00 00 mov eax,dword ptr [_nValidPages]
00000332: 89 45 D0 mov dword ptr [ebp-30h],eax
00000335: EB 09 jmp 00000340
00000337: 8B 4D D0 mov ecx,dword ptr [ebp-30h]
0000033A: 83 E9 01 sub ecx,1
0000033D: 89 4D D0 mov dword ptr [ebp-30h],ecx
00000340: 83 7D D0 00 cmp dword ptr [ebp-30h],0
00000344: 7E 13 jle 00000359
00000346: 8B 55 D0 mov edx,dword ptr [ebp-30h]
00000349: 8B 04 95 FC FF FF mov eax,dword ptr [edx*4-4]
FF
00000350: 3B 45 CC cmp eax,dword ptr [ebp-34h]
00000353: 75 02 jne 00000357
00000355: EB 02 jmp 00000359
00000357: EB DE jmp 00000337
00000359: 83 7D D0 00 cmp dword ptr [ebp-30h],0
0000035D: 75 75 jne 000003D4
0000035F: 83 3D 00 00 00 00 cmp dword ptr [_nValidPages],0Fh
0F
00000366: 7E 09 jle 00000371
00000368: C7 45 A4 0F 00 00 mov dword ptr [ebp-5Ch],0Fh
00
0000036F: EB 09 jmp 0000037A
00000371: 8B 0D 00 00 00 00 mov ecx,dword ptr [_nValidPages]
00000377: 89 4D A4 mov dword ptr [ebp-5Ch],ecx
0000037A: 8B 55 A4 mov edx,dword ptr [ebp-5Ch]
0000037D: 89 55 D0 mov dword ptr [ebp-30h],edx
00000380: C7 45 D8 00 00 00 mov dword ptr [ebp-28h],0
00
00000387: EB 09 jmp 00000392
00000389: 8B 45 D8 mov eax,dword ptr [ebp-28h]
0000038C: 83 C0 01 add eax,1
0000038F: 89 45 D8 mov dword ptr [ebp-28h],eax
00000392: 8B 4D D8 mov ecx,dword ptr [ebp-28h]
00000395: 3B 4D D0 cmp ecx,dword ptr [ebp-30h]
00000398: 7F 22 jg 000003BC
0000039A: 8B 55 D8 mov edx,dword ptr [ebp-28h]
0000039D: 8B 04 95 00 00 00 mov eax,dword ptr [edx*4]
00
000003A4: 89 45 E8 mov dword ptr [ebp-18h],eax
000003A7: 8B 4D D8 mov ecx,dword ptr [ebp-28h]
000003AA: 8B 55 CC mov edx,dword ptr [ebp-34h]
000003AD: 89 14 8D 00 00 00 mov dword ptr [ecx*4],edx
00
000003B4: 8B 45 E8 mov eax,dword ptr [ebp-18h]
000003B7: 89 45 CC mov dword ptr [ebp-34h],eax
000003BA: EB CD jmp 00000389
000003BC: 83 3D 00 00 00 00 cmp dword ptr [_nValidPages],10h
10
000003C3: 7D 0F jge 000003D4
000003C5: 8B 0D 00 00 00 00 mov ecx,dword ptr [_nValidPages]
000003CB: 83 C1 01 add ecx,1
000003CE: 89 0D 00 00 00 00 mov dword ptr [_nValidPages],ecx
000003D4: 6A 00 push 0
000003D6: 68 00 00 00 00 push offset _lModifying
000003DB: FF 15 00 00 00 00 call dword ptr [__imp__InterlockedExchange@8]
000003E1: B8 01 00 00 00 mov eax,1
000003E6: 8B E5 mov esp,ebp
000003E8: 5D pop ebp
000003E9: C3 ret
Summary
4C .bss
6B5 .debug$S
11A4 .debug$T
3EA .text
The following is the output of DUMPBIN with the eh3valid.obj file:
Microsoft (R) COFF/PE Dumper Version 7.10.3077
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file eh3valid.obj
File Type: COFF OBJECT
__ValidateEH3RN:
00000000: 55 push ebp
00000001: 8B EC mov ebp,esp
00000003: 83 EC 5C sub esp,5Ch
00000006: 8B 45 08 mov eax,dword ptr [ebp+8]
00000009: 8B 48 08 mov ecx,dword ptr [eax+8]
0000000C: 89 4D E0 mov dword ptr [ebp-20h],ecx
0000000F: 8B 55 E0 mov edx,dword ptr [ebp-20h]
00000012: 83 E2 03 and edx,3
00000015: 74 07 je 0000001E
00000017: 33 C0 xor eax,eax
00000019: E9 C6 03 00 00 jmp 000003E4
0000001E: 64 A1 18 00 00 00 mov eax,dword ptr fs:[00000018h]
00000024: 89 45 DC mov dword ptr [ebp-24h],eax
00000027: 8B 45 DC mov eax,dword ptr [ebp-24h]
0000002A: 8B 4D E0 mov ecx,dword ptr [ebp-20h]
0000002D: 3B 48 08 cmp ecx,dword ptr [eax+8]
00000030: 72 12 jb 00000044
00000032: 8B 55 DC mov edx,dword ptr [ebp-24h]
00000035: 8B 45 E0 mov eax,dword ptr [ebp-20h]
00000038: 3B 42 04 cmp eax,dword ptr [edx+4]
0000003B: 73 07 jae 00000044
0000003D: 33 C0 xor eax,eax
0000003F: E9 A0 03 00 00 jmp 000003E4
00000044: 8B 4D 08 mov ecx,dword ptr [ebp+8]
00000047: 83 79 0C FF cmp dword ptr [ecx+0Ch],0FFFFFFFFh
0000004B: 75 0A jne 00000057
0000004D: B8 01 00 00 00 mov eax,1
00000052: E9 8D 03 00 00 jmp 000003E4
00000057: C7 45 E4 00 00 00 mov dword ptr [ebp-1Ch],0
00
0000005E: C7 45 F8 00 00 00 mov dword ptr [ebp-8],0
00
00000065: EB 09 jmp 00000070
00000067: 8B 55 F8 mov edx,dword ptr [ebp-8]
0000006A: 83 C2 01 add edx,1
0000006D: 89 55 F8 mov dword ptr [ebp-8],edx
00000070: 8B 45 08 mov eax,dword ptr [ebp+8]
00000073: 8B 4D F8 mov ecx,dword ptr [ebp-8]
00000076: 3B 48 0C cmp ecx,dword ptr [eax+0Ch]
00000079: 77 3F ja 000000BA
0000007B: 8B 55 F8 mov edx,dword ptr [ebp-8]
0000007E: 6B D2 0C imul edx,edx,0Ch
00000081: 8B 45 E0 mov eax,dword ptr [ebp-20h]
00000084: 8B 0C 10 mov ecx,dword ptr [eax+edx]
00000087: 89 4D A8 mov dword ptr [ebp-58h],ecx
0000008A: 83 7D A8 FF cmp dword ptr [ebp-58h],0FFFFFFFFh
0000008E: 74 0F je 0000009F
00000090: 8B 55 A8 mov edx,dword ptr [ebp-58h]
00000093: 3B 55 F8 cmp edx,dword ptr [ebp-8]
00000096: 72 07 jb 0000009F
00000098: 33 C0 xor eax,eax
0000009A: E9 45 03 00 00 jmp 000003E4
0000009F: 8B 45 F8 mov eax,dword ptr [ebp-8]
000000A2: 6B C0 0C imul eax,eax,0Ch
000000A5: 8B 4D E0 mov ecx,dword ptr [ebp-20h]
000000A8: 83 7C 01 04 00 cmp dword ptr [ecx+eax+4],0
000000AD: 74 09 je 000000B8
000000AF: 8B 55 E4 mov edx,dword ptr [ebp-1Ch]
000000B2: 83 C2 01 add edx,1
000000B5: 89 55 E4 mov dword ptr [ebp-1Ch],edx
000000B8: EB AD jmp 00000067
000000BA: 83 7D E4 00 cmp dword ptr [ebp-1Ch],0
000000BE: 74 20 je 000000E0
000000C0: 8B 45 08 mov eax,dword ptr [ebp+8]
000000C3: 8B 4D DC mov ecx,dword ptr [ebp-24h]
000000C6: 8B 50 F8 mov edx,dword ptr [eax-8]
000000C9: 3B 51 08 cmp edx,dword ptr [ecx+8]
000000CC: 72 0B jb 000000D9
000000CE: 8B 45 08 mov eax,dword ptr [ebp+8]
000000D1: 8B 48 F8 mov ecx,dword ptr [eax-8]
000000D4: 3B 4D 08 cmp ecx,dword ptr [ebp+8]
000000D7: 72 07 jb 000000E0
000000D9: 33 C0 xor eax,eax
000000DB: E9 04 03 00 00 jmp 000003E4
000000E0: 8B 55 E0 mov edx,dword ptr [ebp-20h]
000000E3: 81 E2 00 F0 FF FF and edx,0FFFFF000h
000000E9: 89 55 CC mov dword ptr [ebp-34h],edx
000000EC: C7 45 D0 00 00 00 mov dword ptr [ebp-30h],0
00
000000F3: EB 09 jmp 000000FE
000000F5: 8B 45 D0 mov eax,dword ptr [ebp-30h]
000000F8: 83 C0 01 add eax,1
000000FB: 89 45 D0 mov dword ptr [ebp-30h],eax
000000FE: 8B 4D D0 mov ecx,dword ptr [ebp-30h]
00000101: 3B 0D 00 00 00 00 cmp ecx,dword ptr [_nValidPages]
00000107: 0F 8D 11 01 00 00 jge 0000021E
0000010D: 8B 55 D0 mov edx,dword ptr [ebp-30h]
00000110: 8B 04 95 00 00 00 mov eax,dword ptr [edx*4]
00
00000117: 3B 45 CC cmp eax,dword ptr [ebp-34h]
0000011A: 0F 85 F9 00 00 00 jne 00000219
00000120: 83 7D D0 00 cmp dword ptr [ebp-30h],0
00000124: 0F 8E E5 00 00 00 jle 0000020F
0000012A: 6A 01 push 1
0000012C: 68 00 00 00 00 push offset _lModifying
00000131: FF 15 00 00 00 00 call dword ptr [__imp__InterlockedExchange@8]
00000137: 85 C0 test eax,eax
00000139: 0F 85 D0 00 00 00 jne 0000020F
0000013F: 8B 4D D0 mov ecx,dword ptr [ebp-30h]
00000142: 8B 14 8D 00 00 00 mov edx,dword ptr [ecx*4]
00
00000149: 3B 55 CC cmp edx,dword ptr [ebp-34h]
0000014C: 74 78 je 000001C6
0000014E: A1 00 00 00 00 mov eax,dword ptr [_nValidPages]
00000153: 83 E8 01 sub eax,1
00000156: 89 45 D0 mov dword ptr [ebp-30h],eax
00000159: EB 09 jmp 00000164
0000015B: 8B 4D D0 mov ecx,dword ptr [ebp-30h]
0000015E: 83 E9 01 sub ecx,1
00000161: 89 4D D0 mov dword ptr [ebp-30h],ecx
00000164: 83 7D D0 00 cmp dword ptr [ebp-30h],0
00000168: 7C 13 jl 0000017D
0000016A: 8B 55 D0 mov edx,dword ptr [ebp-30h]
0000016D: 8B 04 95 00 00 00 mov eax,dword ptr [edx*4]
00
00000174: 3B 45 CC cmp eax,dword ptr [ebp-34h]
00000177: 75 02 jne 0000017B
00000179: EB 02 jmp 0000017D
0000017B: EB DE jmp 0000015B
0000017D: 83 7D D0 00 cmp dword ptr [ebp-30h],0
00000181: 7D 26 jge 000001A9
00000183: 83 3D 00 00 00 00 cmp dword ptr [_nValidPages],10h
10
0000018A: 7D 0F jge 0000019B
0000018C: 8B 0D 00 00 00 00 mov ecx,dword ptr [_nValidPages]
00000192: 83 C1 01 add ecx,1
00000195: 89 0D 00 00 00 00 mov dword ptr [_nValidPages],ecx
0000019B: 8B 15 00 00 00 00 mov edx,dword ptr [_nValidPages]
000001A1: 83 EA 01 sub edx,1
000001A4: 89 55 D0 mov dword ptr [ebp-30h],edx
000001A7: EB 1D jmp 000001C6
000001A9: 83 7D D0 00 cmp dword ptr [ebp-30h],0
000001AD: 75 17 jne 000001C6
000001AF: 6A 00 push 0
000001B1: 68 00 00 00 00 push offset _lModifying
000001B6: FF 15 00 00 00 00 call dword ptr [__imp__InterlockedExchange@8]
000001BC: B8 01 00 00 00 mov eax,1
000001C1: E9 1E 02 00 00 jmp 000003E4
000001C6: C7 45 D8 00 00 00 mov dword ptr [ebp-28h],0
00
000001CD: EB 09 jmp 000001D8
000001CF: 8B 45 D8 mov eax,dword ptr [ebp-28h]
000001D2: 83 C0 01 add eax,1
000001D5: 89 45 D8 mov dword ptr [ebp-28h],eax
000001D8: 8B 4D D8 mov ecx,dword ptr [ebp-28h]
000001DB: 3B 4D D0 cmp ecx,dword ptr [ebp-30h]
000001DE: 7F 22 jg 00000202
000001E0: 8B 55 D8 mov edx,dword ptr [ebp-28h]
000001E3: 8B 04 95 00 00 00 mov eax,dword ptr [edx*4]
00
000001EA: 89 45 E8 mov dword ptr [ebp-18h],eax
000001ED: 8B 4D D8 mov ecx,dword ptr [ebp-28h]
000001F0: 8B 55 CC mov edx,dword ptr [ebp-34h]
000001F3: 89 14 8D 00 00 00 mov dword ptr [ecx*4],edx
00
000001FA: 8B 45 E8 mov eax,dword ptr [ebp-18h]
000001FD: 89 45 CC mov dword ptr [ebp-34h],eax
00000200: EB CD jmp 000001CF
00000202: 6A 00 push 0
00000204: 68 00 00 00 00 push offset _lModifying
00000209: FF 15 00 00 00 00 call dword ptr [__imp__InterlockedExchange@8]
0000020F: B8 01 00 00 00 mov eax,1
00000214: E9 CB 01 00 00 jmp 000003E4
00000219: E9 D7 FE FF FF jmp 000000F5
0000021E: 6A 1C push 1Ch
00000220: 8D 4D AC lea ecx,[ebp-54h]
00000223: 51 push ecx
00000224: 8B 55 E0 mov edx,dword ptr [ebp-20h]
00000227: 52 push edx
00000228: FF 15 00 00 00 00 call dword ptr [__imp__VirtualQuery@12]
0000022E: 85 C0 test eax,eax
00000230: 74 09 je 0000023B
00000232: 81 7D C4 00 00 00 cmp dword ptr [ebp-3Ch],1000000h
01
00000239: 74 08 je 00000243
0000023B: 83 C8 FF or eax,0FFFFFFFFh
0000023E: E9 A1 01 00 00 jmp 000003E4
00000243: 8B 45 C0 mov eax,dword ptr [ebp-40h]
00000246: 25 CC 00 00 00 and eax,0CCh
0000024B: 75 05 jne 00000252
0000024D: E9 C0 00 00 00 jmp $exit_success$19252
00000252: 8B 4D B0 mov ecx,dword ptr [ebp-50h]
00000255: 89 4D F0 mov dword ptr [ebp-10h],ecx
00000258: 8B 55 F0 mov edx,dword ptr [ebp-10h]
0000025B: 0F B7 02 movzx eax,word ptr [edx]
0000025E: 3D 4D 5A 00 00 cmp eax,5A4Dh
00000263: 74 08 je 0000026D
00000265: 83 C8 FF or eax,0FFFFFFFFh
00000268: E9 77 01 00 00 jmp 000003E4
0000026D: 8B 4D F0 mov ecx,dword ptr [ebp-10h]
00000270: 8B 55 F0 mov edx,dword ptr [ebp-10h]
00000273: 03 51 3C add edx,dword ptr [ecx+3Ch]
00000276: 89 55 EC mov dword ptr [ebp-14h],edx
00000279: 8B 45 EC mov eax,dword ptr [ebp-14h]
0000027C: 81 38 50 45 00 00 cmp dword ptr [eax],4550h
00000282: 74 08 je 0000028C
00000284: 83 C8 FF or eax,0FFFFFFFFh
00000287: E9 58 01 00 00 jmp 000003E4
0000028C: 8B 4D EC mov ecx,dword ptr [ebp-14h]
0000028F: 83 C1 18 add ecx,18h
00000292: 89 4D F4 mov dword ptr [ebp-0Ch],ecx
00000295: 8B 55 F4 mov edx,dword ptr [ebp-0Ch]
00000298: 0F B7 02 movzx eax,word ptr [edx]
0000029B: 3D 0B 01 00 00 cmp eax,10Bh
000002A0: 74 08 je 000002AA
000002A2: 83 C8 FF or eax,0FFFFFFFFh
000002A5: E9 3A 01 00 00 jmp 000003E4
000002AA: 8B 4D E0 mov ecx,dword ptr [ebp-20h]
000002AD: 2B 4D F0 sub ecx,dword ptr [ebp-10h]
000002B0: 89 4D FC mov dword ptr [ebp-4],ecx
000002B3: C7 45 D4 00 00 00 mov dword ptr [ebp-2Ch],0
00
000002BA: 8B 55 EC mov edx,dword ptr [ebp-14h]
000002BD: 0F B7 42 14 movzx eax,word ptr [edx+14h]
000002C1: 8B 4D EC mov ecx,dword ptr [ebp-14h]
000002C4: 8D 54 01 18 lea edx,[ecx+eax+18h]
000002C8: 89 55 C8 mov dword ptr [ebp-38h],edx
000002CB: 8B 55 EC mov edx,dword ptr [ebp-14h]
000002CE: 0F B7 42 06 movzx eax,word ptr [edx+6]
000002D2: 39 45 D4 cmp dword ptr [ebp-2Ch],eax
000002D5: 73 33 jae 0000030A
000002D7: 8B 4D C8 mov ecx,dword ptr [ebp-38h]
000002DA: 8B 55 FC mov edx,dword ptr [ebp-4]
000002DD: 3B 51 0C cmp edx,dword ptr [ecx+0Ch]
000002E0: 72 26 jb 00000308
000002E2: 8B 45 C8 mov eax,dword ptr [ebp-38h]
000002E5: 8B 48 0C mov ecx,dword ptr [eax+0Ch]
000002E8: 8B 55 C8 mov edx,dword ptr [ebp-38h]
000002EB: 03 4A 08 add ecx,dword ptr [edx+8]
000002EE: 39 4D FC cmp dword ptr [ebp-4],ecx
000002F1: 73 15 jae 00000308
000002F3: 8B 45 C8 mov eax,dword ptr [ebp-38h]
000002F6: 8B 48 24 mov ecx,dword ptr [eax+24h]
000002F9: 81 E1 00 00 00 80 and ecx,80000000h
000002FF: 74 07 je 00000308
00000301: 33 C0 xor eax,eax
00000303: E9 DC 00 00 00 jmp 000003E4
00000308: EB 08 jmp $exit_success$19252
0000030A: 83 C8 FF or eax,0FFFFFFFFh
0000030D: E9 D2 00 00 00 jmp 000003E4
$exit_success$19252:
00000312: 6A 01 push 1
00000314: 68 00 00 00 00 push offset _lModifying
00000319: FF 15 00 00 00 00 call dword ptr [__imp__InterlockedExchange@8]
0000031F: 85 C0 test eax,eax
00000321: 74 0A je 0000032D
00000323: B8 01 00 00 00 mov eax,1
00000328: E9 B7 00 00 00 jmp 000003E4
0000032D: 8B 15 00 00 00 00 mov edx,dword ptr [_nValidPages]
00000333: 89 55 D0 mov dword ptr [ebp-30h],edx
00000336: EB 09 jmp 00000341
00000338: 8B 45 D0 mov eax,dword ptr [ebp-30h]
0000033B: 83 E8 01 sub eax,1
0000033E: 89 45 D0 mov dword ptr [ebp-30h],eax
00000341: 83 7D D0 00 cmp dword ptr [ebp-30h],0
00000345: 7E 13 jle 0000035A
00000347: 8B 4D D0 mov ecx,dword ptr [ebp-30h]
0000034A: 8B 14 8D FC FF FF mov edx,dword ptr [ecx*4-4]
FF
00000351: 3B 55 CC cmp edx,dword ptr [ebp-34h]
00000354: 75 02 jne 00000358
00000356: EB 02 jmp 0000035A
00000358: EB DE jmp 00000338
0000035A: 83 7D D0 00 cmp dword ptr [ebp-30h],0
0000035E: 75 72 jne 000003D2
00000360: 83 3D 00 00 00 00 cmp dword ptr [_nValidPages],0Fh
0F
00000367: 7E 09 jle 00000372
00000369: C7 45 A4 0F 00 00 mov dword ptr [ebp-5Ch],0Fh
00
00000370: EB 08 jmp 0000037A
00000372: A1 00 00 00 00 mov eax,dword ptr [_nValidPages]
00000377: 89 45 A4 mov dword ptr [ebp-5Ch],eax
0000037A: 8B 4D A4 mov ecx,dword ptr [ebp-5Ch]
0000037D: 89 4D D0 mov dword ptr [ebp-30h],ecx
00000380: C7 45 D8 00 00 00 mov dword ptr [ebp-28h],0
00
00000387: EB 09 jmp 00000392
00000389: 8B 55 D8 mov edx,dword ptr [ebp-28h]
0000038C: 83 C2 01 add edx,1
0000038F: 89 55 D8 mov dword ptr [ebp-28h],edx
00000392: 8B 45 D8 mov eax,dword ptr [ebp-28h]
00000395: 3B 45 D0 cmp eax,dword ptr [ebp-30h]
00000398: 7F 22 jg 000003BC
0000039A: 8B 4D D8 mov ecx,dword ptr [ebp-28h]
0000039D: 8B 14 8D 00 00 00 mov edx,dword ptr [ecx*4]
00
000003A4: 89 55 E8 mov dword ptr [ebp-18h],edx
000003A7: 8B 45 D8 mov eax,dword ptr [ebp-28h]
000003AA: 8B 4D CC mov ecx,dword ptr [ebp-34h]
000003AD: 89 0C 85 00 00 00 mov dword ptr [eax*4],ecx
00
000003B4: 8B 55 E8 mov edx,dword ptr [ebp-18h]
000003B7: 89 55 CC mov dword ptr [ebp-34h],edx
000003BA: EB CD jmp 00000389
000003BC: 83 3D 00 00 00 00 cmp dword ptr [_nValidPages],10h
10
000003C3: 7D 0D jge 000003D2
000003C5: A1 00 00 00 00 mov eax,dword ptr [_nValidPages]
000003CA: 83 C0 01 add eax,1
000003CD: A3 00 00 00 00 mov dword ptr [_nValidPages],eax
000003D2: 6A 00 push 0
000003D4: 68 00 00 00 00 push offset _lModifying
000003D9: FF 15 00 00 00 00 call dword ptr [__imp__InterlockedExchange@8]
000003DF: B8 01 00 00 00 mov eax,1
000003E4: 8B E5 mov esp,ebp
000003E6: 5D pop ebp
000003E7: C3 ret
Summary
4C .bss
6BE .debug$S
1164 .debug$T
3E8 .text
When I posted this question to OpenRCE, RolfRolles gave me the following answer:
Nice job on the decompilation.
My experience diff-ing patches (noticing that sometimes the only difference between two functions seem to be register/stack allocation) makes me suspect that MSVC uses a non-deterministic register allocator. I may be wrong, and would be interested to hear the correct answer if so. Register allocation is often formulated as a graph-coloring problem, which is in NP, and therefore there can exist no algorithm to solve it optimally in polynomial time (assuming P != NP). Consequently, approximation algorithms are often used to "solve" problems such as this, and these algorithms often employ the use of random variables.
Therefore, in general, there is no guarantee that two successive compilations of the same source code (or a conforming decompilation/recompilation) will see the same variables assigned to the same registers at the same program points. If the only differences between your recompilation and the original binary are register assignments / stack spills, you should consider it a job well-done; I would, anyway.
I have compiled _ValidateEH3RN.c several times, but they seemed to be always the same. Can't we really solve this problem?
I ardently anticipate the answer.