how to remove your module from the PEB linked list

On domingo, 5 de septiembre de 2010 0 comentarios

This method can be used to remove your module from the module list of a process. The biggest use is to prevent VAC from performing a a checksum scan of your module (though it does not prevent string scanning). I think it can also be useful for PB but I haven't used PB so I don't know

You may need the Windows 2000/XP/Server 2003 DDK installed to compile. Otherwise you will have to just pad the structures out to the right size whenever there is an undefined type, or get someone with the DDK to send you the relevent header files and get the structures yourself. Particularly the CONTAINING_RECORD and other list managedment macros are in the DDK only and not the SDK I believe, although you can also find them in the Wine project source.

You can use the header I already made with the information from http://undocumented.ntinternals.net/. Download it here if you want: http://www.tabris.game-deception.com/VAC/NTundoc.h

All 3 linked lists are essentially the same, but you have to remove your module from all 3 in order to be hidden well. I have only commented the first one.

// IF YOU USE THIS CODE, PLEASE CREDIT WWW.GAME-DECEPTION.COM
// YOU MAY FREELY RELEASE BINARIES CONTAINING THIS CODE AS LONG AS SUCH A CREDIT APPEARS IN THE DOCUMENTATION

void RemoveModuleFromPEB(void)
{
PTEB pTEB;
PPEB_LDR_DATA pLDR;
PLIST_ENTRY pMark, pEntry;
PLDR_MODULE pLM;
char *pSig = "anything can go here this string does not matter in fact you could use a pointer to one of the existing variables I just wanted to make it obvious what was going on ok stop bugging me";

pTEB = GetCurrentTeb(); // get the current Thread Environment Block

pLDR = pTEB->Peb->LoaderData; // get a pointer to the loader data structure within the PEB (process environment block) within the TEB

pMark = &(pLDR->InMemoryOrderModuleList); // the list is circular-linked, so we have to mark the point at which we start traversing it so we know when we've made a full traversal

for(pEntry = pMark->Flink; pEntry != pMark; pEntry = pEntry->Flink)
{
pLM = CONTAINING_RECORD(pEntry, LDR_MODULE, InMemoryOrderModuleList); // CONTAINING_RECORD is in the DDK, it basically just gets a pointer to the actual structure from the linked list element
if((DWORD)pSig > (DWORD)pLM->BaseAddress && (DWORD)pSig < ((DWORD)pLM->BaseAddress + (DWORD)pLM->SizeOfImage)) // check if the "signature" variable is inside this module, if so it is our module
{
pEntry->Blink->Flink = pEntry->Flink; // change the previous element to point to the next element, so that traversing the list in a forward direction no longer yields our module
pEntry->Flink->Blink = pEntry->Blink; // change the next element to point to the previous element, so that traversing the list in a reverse direction no longer yields our module
}
}

pMark = &(pLDR->InLoadOrderModuleList);

for(pEntry = pMark->Flink; pEntry != pMark; pEntry = pEntry->Flink)
{
pLM = CONTAINING_RECORD(pEntry, LDR_MODULE, InLoadOrderModuleList);
if((DWORD)pSig > (DWORD)pLM->BaseAddress && (DWORD)pSig < ((DWORD)pLM->BaseAddress + (DWORD)pLM->SizeOfImage))
{
pEntry->Blink->Flink = pEntry->Flink;
pEntry->Flink->Blink = pEntry->Blink;
}
}

pMark = &(pLDR->InInitializationOrderModuleList);

for(pEntry = pMark->Flink; pEntry != pMark; pEntry = pEntry->Flink)
{
pLM = CONTAINING_RECORD(pEntry, LDR_MODULE, InInitializationOrderModuleList);
if((DWORD)pSig > (DWORD)pLM->BaseAddress && (DWORD)pSig < ((DWORD)pLM->BaseAddress + (DWORD)pLM->SizeOfImage))
{
pEntry->Blink->Flink = pEntry->Flink;
pEntry->Flink->Blink = pEntry->Blink;
}
}
}


If you have done it right, you should be able to load LordPE, OllyDbg, or something similar and list the modules in the process without your module showing in the list at all. It totally prevents the Toolhelp32 functions (Module32First and Module32Next) from seeing your module.

If you are really obsessive about hiding your module, you may be able to blank out the LoaderModule structure after finding and unlinking it, though I have not checked if this works without causing any odd behaviour

Thanks to the good people at undocumented.ntinternals.net for their excellent documentation and to RetarT for giving me the idea

If anyone asks "where do I put this" I will delete their post.

0 comentarios:

Publicar un comentario