Some more information about this loader.
// Inside of WoW (latest release 11.0.5.57534) (this functions just a bit under the initial VirtualAlloc in the OP
wardenFunctionHolder = 0LL; // This contains information _about_ wow? It also gives warden functions from wows memory that it can call. __int64 __fastcall sub_B80C(char *a1)
sub_143348B30((__int64)&wardenFunctionHolder, v15, v16, v17, *((__int64 *)&wardenFunctionHolder + 1), v37);// warden calls functions defined inside this
Code:
void __fastcall sub_143348B30(__int64 a1, int a2, __int64 a3, __int64 a4, __int64 a5, __int64 a6)
{
*(_WORD *)a1 = 0xBEEF;
*(_WORD *)(a1 + 2) = 1;
*(_QWORD *)(a1 + 0x18) = sub_14334B960;
*(_QWORD *)(a1 + 0x10) = sub_14334BE80;
*(_QWORD *)(a1 + 0x20) = sub_14334BFF0;
*(_QWORD *)(a1 + 0x28) = byte_14334BFA0;
*(_DWORD *)(a1 + 48) = a2;
}
Warden function calls look like this.
Code:
__int64 __fastcall sub_7140(char *a1, __int64 a2, __int64 a3)
{
__int64 v3; // rsi
__int64 v4; // rdx
sub_2200(a1, a2, a3, sub_B7E0);
v3 = (unsigned int)sub_B7E0(a1);
sub_4D10(a1, v3, v4, sub_B7E0);
return (unsigned int)v3;
}
It appears to be that sub_2200 Decrypts sub_b7e0, then it is called, and then sub_4d10 encrypts it again.
Code:
__int64 __fastcall sub_2200(__int64 a1, __int64 a2, __int64 a3, __int64 a4)
{
int v4; // r9d
__int64 v5; // r11
__int64 v6; // r8
__int64 v7; // r10
_BYTE *v8; // rdi
unsigned __int64 v9; // r15
_BYTE *v10; // rsi
__int64 v11; // rbx
__int64 result; // rax
int v13; // r14d
int v14; // esi
__int64 v15; // rdx
__int64 v16; // rdi
__int64 v17; // r11
unsigned __int8 *v18; // rbx
__int64 v19; // rdx
char v20; // r9
unsigned __int8 *v21; // rbx
unsigned __int8 v22; // dl
if ( !a4 )
__halt();
v4 = *(_DWORD *)(a4 + 1);
v5 = *(unsigned int *)(a4 + 15);
v6 = (unsigned int)(v4 - 15);
if ( *(_BYTE *)(a4 + 19) )
{
v7 = a4 + 5;
if ( (_DWORD)v5 )
{
v8 = (_BYTE *)(a4 + v6 + 20);
v9 = v5 + a4 + v6 + 20;
v10 = v8;
do
{
*v10 ^= byte_14390[*(unsigned __int8 *)(v7 + (unsigned __int8)((__int64)(v9 - (_QWORD)v10) % v6) + 15)];
++v10;
}
while ( (unsigned __int64)v10 < v9 );
v11 = v5;
do
{
result = *((unsigned __int8 *)sub_145C0
+ *(unsigned __int8 *)(v7 + (unsigned __int8)((__int64)(v9 - (_QWORD)v8) % v6) + 15));
*v8++ ^= result;
--v11;
}
while ( v11 );
}
v13 = (*(_DWORD *)(a4 + 11) | *(_DWORD *)(a4 + 20)) - (*(_DWORD *)(a4 + 11) & *(_DWORD *)(a4 + 20));
v14 = 732807390;
if ( (_DWORD)v5 )
{
v15 = v5 & 3;
v16 = 0LL;
if ( (unsigned __int64)(v5 - 1) >= 3 )
{
v17 = v5 - v15;
v14 = -2128831035;
v16 = 0LL;
do
{
v14 = 16777619
* ((16777619
* ((16777619
* ((16777619 * (v14 ^ *(unsigned __int8 *)(a4 + v6 + 23 + v16 - 3))) ^ *(unsigned __int8 *)(a4 + v6 + 23 + v16 - 2))) ^ *(unsigned __int8 *)(a4 + v6 + 23 + v16 - 1))) ^ *(unsigned __int8 *)(a4 + v6 + 23 + v16));
v16 += 4LL;
}
while ( v17 != v16 );
}
else
{
v14 = -2128831035;
}
if ( v15 )
{
v18 = (unsigned __int8 *)(a4 + v6 + v16 + 20);
v19 = -v15;
do
{
v14 = 16777619 * (v14 ^ *v18++);
++v19;
}
while ( v19 );
}
}
if ( v14 != v13 )
__halt();
*(_BYTE *)(a4 + 19) = 0;
v20 = *(_BYTE *)(a4 + (unsigned int)(v4 - 16) + 20);
if ( (unsigned int)v6 >= 2 )
{
v21 = (unsigned __int8 *)(a4 + 21);
v22 = *(_BYTE *)(a4 + 20);
do
{
result = *v21;
*v21++ = v22;
v22 = result;
}
while ( (unsigned __int64)v21 < v7 + v6 + 15 );
}
*(_BYTE *)(a4 + 20) = v20;
*(_DWORD *)(a4 + 11) = *(_DWORD *)(a4 + 20) ^ v13;
}
return result;
}
Code:
void __fastcall sub_4D10(__int64 a1, __int64 a2, __int64 a3, __int64 a4)
{
__int64 v4; // r11
__int64 v5; // r8
int v6; // edx
__int64 v7; // rax
__int64 v8; // rdi
unsigned __int8 *v9; // rbx
__int64 v10; // rax
_BYTE *v11; // r9
unsigned __int64 v12; // r10
_BYTE *v13; // rsi
__int64 v14; // rbx
if ( !a4 )
__halt();
v4 = *(unsigned int *)(a4 + 15);
v5 = (unsigned int)(*(_DWORD *)(a4 + 1) - 15);
if ( *(_BYTE *)(a4 + 19) != 1 )
{
v6 = 732807390;
if ( (_DWORD)v4 )
{
v7 = v4 & 3;
v8 = 0LL;
if ( (unsigned __int64)(v4 - 1) >= 3 )
{
v6 = -2128831035;
v8 = 0LL;
do
{
v6 = 16777619
* ((16777619
* ((16777619
* ((16777619 * (v6 ^ *(unsigned __int8 *)(a4 + v5 + 23 + v8 - 3))) ^ *(unsigned __int8 *)(a4 + v5 + 23 + v8 - 2))) ^ *(unsigned __int8 *)(a4 + v5 + 23 + v8 - 1))) ^ *(unsigned __int8 *)(a4 + v5 + 23 + v8));
v8 += 4LL;
}
while ( v4 - v7 != v8 );
}
else
{
v6 = -2128831035;
}
if ( (v4 & 3) != 0 )
{
v9 = (unsigned __int8 *)(a4 + v5 + v8 + 20);
v10 = -v7;
do
{
v6 = 16777619 * (v6 ^ *v9++);
++v10;
}
while ( v10 );
}
}
if ( v6 != (*(_DWORD *)(a4 + 11) ^ *(_DWORD *)(a4 + 20)) )
__halt();
if ( (_DWORD)v4 )
{
v11 = (_BYTE *)(a4 + v5 + 20);
v12 = v4 + a4 + v5 + 20;
v13 = v11;
if ( (_DWORD)v4 != 1 )
{
v14 = (v4 & 1) - v4;
v13 = (_BYTE *)(a4 + v5 + 20);
do
{
*v13 ^= *((_BYTE *)sub_145C0
+ *(unsigned __int8 *)(a4 + (unsigned __int8)((__int64)(v12 - (_QWORD)v13) % v5) + 20));
v13[1] ^= *((_BYTE *)sub_145C0
+ *(unsigned __int8 *)(a4 + (unsigned __int8)((__int64)(v12 - (_QWORD)(v13 + 1)) % v5) + 20));
v13 += 2;
v14 += 2LL;
}
while ( v14 );
}
if ( (v4 & 1) != 0 )
*v13 ^= *((_BYTE *)sub_145C0
+ *(unsigned __int8 *)(a4 + (unsigned __int8)((__int64)(v12 - (_QWORD)v13) % v5) + 20));
do
{
*v11 ^= byte_14390[*(unsigned __int8 *)(a4 + (unsigned __int8)((__int64)(v12 - (_QWORD)v11) % v5) + 20)];
++v11;
}
while ( (unsigned __int64)v11 < v12 );
}
*(_BYTE *)(a4 + 19) = 1;
}
}
This is the function that subsequently calls VirtualAlloc from the WardenLoader buffer _after_ warden is loaded. So this is what I was seeing as 0x10BCA, but this address is not consistent the warden module seems to have some variation.
Code:
__int64 __fastcall sub_125EC(__int64 a1, unsigned __int64 a2, __int64 a3, _DWORD *a4)
{
unsigned int v5; // ecx
unsigned int v6; // eax
__int64 v7; // rdx
_WORD *v8; // r14
unsigned int v9; // eax
unsigned __int64 v10; // r12
unsigned __int64 v11; // rcx
unsigned __int64 v12; // r12
char *v13; // r13
__int64 result; // rax
__int64 v15; // rdx
char *v16; // rax
__int64 v17; // rdx
int v18; // edx
char *v19; // r8
unsigned int v20; // r9d
_DWORD *v21; // rcx
unsigned int v22; // [rsp+2Ch] [rbp-5FCh] BYREF
unsigned int v23; // [rsp+30h] [rbp-5F8h] BYREF
int v24; // [rsp+34h] [rbp-5F4h] BYREF
unsigned __int64 v25; // [rsp+38h] [rbp-5F0h] BYREF
int v26; // [rsp+44h] [rbp-5E4h] BYREF
__int64 v27; // [rsp+48h] [rbp-5E0h]
__int64 v28; // [rsp+50h] [rbp-5D8h]
__int64 v29; // [rsp+58h] [rbp-5D0h]
__int64 v30; // [rsp+60h] [rbp-5C8h]
_DWORD v31[2]; // [rsp+68h] [rbp-5C0h] BYREF
_BYTE v32[32]; // [rsp+70h] [rbp-5B8h] BYREF
_BYTE v33[1024]; // [rsp+90h] [rbp-598h] BYREF
_BYTE v34[160]; // [rsp+490h] [rbp-198h] BYREF
__int64 v35; // [rsp+530h] [rbp-F8h] BYREF
_BYTE v36[32]; // [rsp+538h] [rbp-F0h] BYREF
__int64 v37; // [rsp+558h] [rbp-D0h]
__int64 v38; // [rsp+560h] [rbp-C8h]
__int64 v39; // [rsp+568h] [rbp-C0h]
__int64 v40; // [rsp+570h] [rbp-B8h]
__int64 v41; // [rsp+578h] [rbp-B0h]
__int64 v42; // [rsp+580h] [rbp-A8h]
__int64 v43; // [rsp+588h] [rbp-A0h]
__int64 v44; // [rsp+590h] [rbp-98h]
__int64 v45; // [rsp+598h] [rbp-90h]
__int64 v46; // [rsp+5A0h] [rbp-88h]
__int64 v47; // [rsp+5A8h] [rbp-80h]
__int64 v48; // [rsp+5B0h] [rbp-78h]
__int64 v49; // [rsp+5B8h] [rbp-70h]
__int64 v50; // [rsp+5C0h] [rbp-68h]
__int64 v51; // [rsp+5C8h] [rbp-60h]
__int64 v52; // [rsp+5D0h] [rbp-58h]
__int64 v53; // [rsp+5D8h] [rbp-50h]
__int64 v54; // [rsp+5E0h] [rbp-48h]
__int64 v55; // [rsp+5E8h] [rbp-40h]
v22 = 0;
v25 = 0LL;
v26 = 0;
v5 = a4[4];
v23 = v5;
v6 = a4[2];
v7 = 256LL;
v8 = 0LL;
if ( v6 >= 0x11 )
{
a1 = (unsigned int)a4[5];
v8 = 0LL;
v7 = 257LL;
if ( v6 >= (unsigned int)a1 )
{
a1 = (unsigned int)(a1 + 17);
if ( v6 == (_DWORD)a1 )
{
v9 = sub_71B0(a1, a2, (__int64)&v25, v5, (__int64)&v26);
v7 = v9;
v8 = 0LL;
if ( !v9 )
{
v10 = (unsigned int)(a4[7] + a4[5] + 156);
v8 = (_WORD *)MEMORY[0x27ECA3C6F90](a1, a2, 0LL, v10);
v7 = 128LL;
if ( v8 )
{
memset(v8, 0, v10);
*v8 = 3;
v8[1] = 30;
v11 = (unsigned int)a4[5];
*((_DWORD *)v8 + 37) = v11;
*((_DWORD *)v8 + 26) = a4[6];
v27 = 1LL;
v28 = 0LL;
v29 = 0LL;
v30 = 1LL;
*(_QWORD *)(v8 + 54) = 0x7FF7727FBFA0LL;
*((_DWORD *)v8 + 23) = a4[7];
*((_QWORD *)v8 + 10) = (char *)v8 + v11 + 156;
*((_QWORD *)v8 + 12) = 0LL;
*(_QWORD *)(v8 + 58) = &dword_16250;
*(_QWORD *)(v8 + 66) = 0x27ECA3C6F90LL;
*(_QWORD *)(v8 + 70) = 0x27ECA3C7AF0LL;
*(_QWORD *)(v8 + 62) = 0x27ECA3D6CB0LL;
qmemcpy(v8 + 76, (char *)a4 + 33, v11);
a1 = (__int64)v8 + v11 + 152;
a2 = v25;
v7 = 517LL;
if ( v25 )
{
if ( *(_DWORD *)v25 == 0x8B08EB && *(_WORD *)(v25 + 4) == 1 )
{
v12 = *(unsigned int *)(v25 + 16);
v13 = (char *)VirtualAlloc(a1, v25, v12, 0LL, 0x1000LL, 0x40LL);
v7 = 128LL;
if ( v13 )
{
a2 = (unsigned int)sub_6C50(a1, a2, (_DWORD)v13, a2, (_DWORD)v8, (unsigned int)&v22);
v25 = 0LL;
memset(v13, 0, v12);
a1 = (__int64)&v13[v12];
VirtualFree(&v13[v12], a2, 0LL, v13, 0x8000LL);
if ( !(_WORD)a2 )
{
v16 = (char *)(*((_QWORD *)v8 + 10) - 4LL);
qmemcpy(v16, &v23, 4uLL);
a2 = (unsigned __int64)&v24;
a1 = (__int64)(v16 + 4);
v17 = v22;
if ( v22 == 4 )
{
v18 = a4[4];
v19 = (char *)v31;
qmemcpy(v32, qword_167C8, sizeof(v32));
qmemcpy(v33, qword_167E8, sizeof(v33));
qmemcpy(v36, qword_16270, sizeof(v36));
qmemcpy(v34, qword_16BE8, sizeof(v34));
a2 = (unsigned __int64)&qword_16BE8[20];
a1 = (__int64)&v35;
v31[1] = 0;
v35 = 0LL;
v37 = 0LL;
v31[0] = v18;
v38 = 0LL;
v39 = 0LL;
v40 = 0LL;
v41 = 0LL;
v42 = 0LL;
v43 = 0LL;
v44 = 0LL;
v45 = 0LL;
v46 = 0LL;
v47 = 0LL;
v48 = 0LL;
v49 = 0LL;
v50 = 0LL;
v51 = 0LL;
v52 = 0LL;
v53 = 0LL;
v54 = 0LL;
v55 = 0LL;
v17 = 4LL;
v20 = 1416;
v21 = a4;
}
else
{
v20 = *((_DWORD *)v8 + 22) + 4;
v21 = a4;
v19 = v16;
}
sub_80F0(a1, a2, v17, (__int64)v21, (__int64)v19, v20);
return MEMORY[0x27ECA3C7AF0](a1, a2, v15, v8);
}
v7 = 515LL;
}
}
}
}
}
}
}
}
result = sub_80F0(a1, a2, v7, (__int64)a4, (__int64)&v23, 4u);
if ( v25 )
result = MEMORY[0x27ECA3C7AF0]();
if ( v8 )
return MEMORY[0x27ECA3C7AF0](a1, a2, v15, v8);
return result;
}
[code]
I need to update my module dumper to map IAT addresses properly. But I mapped some of them.