A forum for reverse engineering, OS internals and malware analysis 

Forum for discussion about user-mode development.
 #27145  by InUrFace
 Wed Nov 04, 2015 2:31 pm
I just reversed some of the WOW64 Ntdll on Windows 8.1 and it seems, your code has 2 flaws:
In RTL_VERIFIER_PROVIDER_DESCRIPTOR, ProviderDlls must be set as an array of RTL_VERIFIER_DLL_DESCRIPTOR structures for each Dll you target PLUS an empty entry at the end to mark the array end.

The same thing applies to RTL_VERIFIER_DLL_DESCRIPTOR and DllThunks. There also the last entry in the array needs to be an empty structure:

From ntdll:
Code: Select all
int __thiscall AVrfpDllLoadNotificationInternal(void *this)
{
  int v1; // ebx@1
  int result; // eax@2
  LIST_ENTRY *v3; // edi@3
  RTL_VERIFIER_DLL_DESCRIPTOR *v4; // eax@4
  int v5; // edi@5
  RTL_VERIFIER_DLL_DESCRIPTOR *v6; // esi@5
  RTL_VERIFIER_DLL_DESCRIPTOR *v7; // ecx@5
  char v8; // al@10
  RTL_VERIFIER_DLL_DESCRIPTOR *v9; // [sp+Ch] [bp-Ch]@4
  void *v10; // [sp+14h] [bp-4h]@4

  v1 = (int)this;
  if ( AVrfpEnabled )
  {
    v3 = AVrfpVerifierProvidersList.Flink;
    while ( v3 != &AVrfpVerifierProvidersList )
    {
      v4 = (RTL_VERIFIER_DLL_DESCRIPTOR *)v3[2].Blink;
      v3 = v3->Flink;
      v10 = v3;
      v9 = v4;
      if ( v4->DllName )
      {
        v5 = 0;
        v6 = v4;
        v7 = v4;
        do
        {
          if ( !(v6->DllFlags & 1) )
          {
            if ( _wcsicmp(*(const wchar_t **)(v1 + 48), v6->DllName) )
            {
              v7 = v9;
            }
            else
            {
              if ( AVrfpDebug & 4 )
                DbgPrint(
                  "AVRF: pid 0x%X: found dll descriptor for `%ws' with verified exports \n",
                  NtCurrentTeb()->ClientId.UniqueProcess,
                  *(_DWORD *)(v1 + 48));
              v8 = AVrfpDetectVerifiedExports(v6, v1);
              v7 = v9;
              if ( v8 )
                v6->DllFlags |= 1u;
            }
          }
          ++v5;
          v6 = &v7[v5];
        }
        while ( v6->DllName );
        v3 = (LIST_ENTRY *)v10;
      }
    }
    result = AVrfpSnapDllImports(v1);
  }
  else
  {
    result = 0;
  }
  return result;
}

char __fastcall AVrfpDetectVerifiedExports(RTL_VERIFIER_DLL_DESCRIPTOR *a1, int a2)
{
  RTL_VERIFIER_THUNK_DESCRIPTOR *pCurrentThunk; // edi@1
  char v3; // bl@1
  RTL_VERIFIER_THUNK_DESCRIPTOR *pNextThunk; // esi@2
  int EntryIndex; // esi@10
  STRING DestinationString; // [sp+Ch] [bp-14h]@4
  void *v8; // [sp+14h] [bp-Ch]@4
  int EntryIndex_; // [sp+18h] [bp-8h]@1
  int v10; // [sp+1Ch] [bp-4h]@1
  void *retaddr; // [sp+24h] [bp+4h]@4

  EntryIndex_ = 0;
  pCurrentThunk = a1->DllThunks;
  v3 = 0;
  v10 = a2;
  if ( pCurrentThunk->ThunkName )
  {
    pNextThunk = pCurrentThunk;
    do
    {
      if ( !pNextThunk->ThunkOldAddress )
      {
        RtlInitAnsiString(&DestinationString, pNextThunk->ThunkName);
        if ( LdrGetProcedureAddressForCaller(*(_DWORD *)(v10 + 24), &DestinationString, 0, &v8, 1, retaddr) >= 0 )
        {
          pNextThunk->ThunkOldAddress = v8;
          if ( AVrfpDebug & 2 )
            DbgPrint("AVRF: (%ws) %s export found. \n", *(_DWORD *)(v10 + 48), pNextThunk->ThunkName);
          v3 = 1;
        }
        else if ( AVrfpDebug & 2 )
        {
          DbgPrint("AVRF: warning: did not find `%s' export in %ws . \n", pNextThunk->ThunkName, *(_DWORD *)(v10 + 48));
        }
      }
      EntryIndex = EntryIndex_ + 1;
      EntryIndex_ = EntryIndex;
      pNextThunk = &pCurrentThunk[EntryIndex];
    }
    while ( pNextThunk->ThunkName ); //Check if ThunkName in next entry != NULL
  }
  return v3;
}
 #27153  by EP_X0FF
 Wed Nov 04, 2015 6:01 pm
Do you mean avrfDlls and avrfThunks? Edit. Oh I see billbudsocket post :) Ok I will edit original post to include fix.
Last edited by EP_X0FF on Wed Nov 04, 2015 6:27 pm, edited 1 time in total. Reason: edit
 #27154  by billbudsocket
 Wed Nov 04, 2015 6:13 pm
^--- This is correct. The code in the OP is not right, the hooks and thunks arrays need an empty entry, like so:

RTL_VERIFIER_THUNK_DESCRIPTOR VfProviderNtdllThunks [] = {
{"RtlAllocateHeap", NULL, VfHookRtlAllocateHeap },
{"RtlFreeHeap", NULL, VfHookRtlFreeHeap },
{NULL,NULL,NULL}
};

RTL_VERIFIER_DLL_DESCRIPTOR VfProviderHooks[] = {
{L"ntdll.dll", 0, NULL, VfProviderNtdllThunks},
{ NULL, 0, NULL, NULL}
};