Home > Programming, Reversing, Windows > Erasing the Cached Module Pointer in NTDLL

Erasing the Cached Module Pointer in NTDLL

Darawk first documented this insecurity in his CloakDLL project but never fixed it, Shynd then fixed it in his HideModule class.

Here it is again, but upgraded for x64 and to work with my Cloaker class:

// TODO: Scan more than just the image. Scan the heap.
void Cloaker::Module::EraseCachedPointer()
{
// Exception handling
try
{
// SEH proxy
SehGuard Guard;

// Get handle to NTDLL
HMODULE Handle = GetModuleHandle(_T(”ntdll.dll”));

// Check handle is valid
if (!Handle)
throw std::runtime_error(”Cloaker::Module::EraseCachedPointer: Handle to ntdll.dll is invalid.”);

// Check DOS header is valid
PIMAGE_DOS_HEADER pDosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(Handle);
if (!pDosHeader || pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
throw std::runtime_error(”Cloaker::Module::EraseCachedPointer: DOS PE header is invalid.”);

// Check NT header is valid
PIMAGE_NT_HEADERS pNtHeader = reinterpret_cast<PIMAGE_NT_HEADERS>
((PCHAR)Handle + pDosHeader->e_lfanew);
if (pNtHeader->Signature != IMAGE_NT_SIGNATURE)
throw std::runtime_error(”Cloaker::Module::EraseCachedPointer: NT PE header is invalid.”);

// Get beginning and end of search region (entire region)
// TODO: Scan heap too
DWORD_PTR* Begin = reinterpret_cast<DWORD_PTR*>(pNtHeader->OptionalHeader.ImageBase);
DWORD_PTR* End = reinterpret_cast<DWORD_PTR*>(pNtHeader->OptionalHeader.ImageBase + pNtHeader->OptionalHeader.SizeOfImage);

// Search for cached pointers
DWORD_PTR* Searcher = NULL;
for (Searcher = Begin; Searcher < End; Searcher++)
{
// Check for cached pointer
if (*Searcher != reinterpret_cast<DWORD_PTR>(m_Handle))
continue;

// Get information for page of memory
MEMORY_BASIC_INFORMATION mbi = { 0 };
if (!VirtualQuery(Searcher, &mbi, sizeof(mbi)))
continue;

// Check page flags to verify we can write to it
if ((mbi.Protect & PAGE_READWRITE) == PAGE_READWRITE ||
(mbi.Protect & PAGE_EXECUTE_READWRITE) == PAGE_EXECUTE_READWRITE)
*Searcher = 0;
}
}
// Catch access violations
catch (const SehException& e)
{
e;
TDBGOUT(_T(”SEH Error in Cloaker::EraseCachedPointer: “) << e << std::endl);
}
}

Credits to Darawk for documenting it, and Shynd for his HideModule class which I ripped the base of this function from.

  1. Shynd
    May 6th, 2009 at 06:27 | #1

    I actually have no idea if that even works; never tested the theory behind the code. Let me know if you find that it actually adds any security (I always considered it a ‘better be safe than sorry’ kind of deal).

  2. Cypherjb
    May 6th, 2009 at 19:40 | #2

    Hey. I actually dove into NTDLL and found the cached pointer variable, so yes it is a valid avenue for attack, albeit an unlikely one.

  1. No trackbacks yet.