Module Hiding

On domingo, 5 de septiembre de 2010 0 comentarios

Since VAC scans all files in running memory, we need to some how fake it.
This is used by showing VAC that our dll was NEVER injected into process!!!
The deception is possible in ring 3 since the kernel maintains a list of
each loaded DLL for a given process inside its memory space, in userland.
Therefore a process may affect himself and overwrite parts of its memory
in order to hide one of its module. These data structures are of course
undocumented but can be recovered by using the Process Environment Block
(PEB), located at FS:0x30 inside each process. The function below returns
the address of the PEB for the current process.

DWORD GetPEB()
{
DWORD* dwPebBase = NULL;
/* Return PEB address for current process
address is located at FS:0x30 */
__asm
{
push eax
mov eax, FS:[0x30]
mov [dwPebBase], eax
pop eax
}
return (DWORD)dwPebBase;
}


The role of the PEB is to gather frequently accessed information for a
process as follows. At address FS:0x30 (or 0x7FFDF000) stands the
following members of the [PEB].

/* located at 0x7FFDF000 */
typedef struct _PEB
{
BOOLEAN InheritedAddressSpace;
BOOLEAN ReadImageFileExecOptions;
BOOLEAN BeingDebugged;
BOOLEAN Spare;
HANDLE Mutant;
PVOID ImageBaseAddress;
PPEB_LDR_DATA LoaderData;
PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
[...]
ULONG SessionId;
} PEB, *PPEB;



The interesting member in our case is PPEB_LDR_DATA LoaderData that
contains information filled by the loader at startup, and then when
happens a DLL load/unload.

typedef struct _PEB_LDR_DATA
{
ULONG Length;
BOOLEAN Initialized;
PVOID SsHandle;
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
} PEB_LDR_DATA, *PPEB_LDR_DATA;


The PEB_LDR_DATA structure contains three LIST_ENTRY that are part of doubly
linked lists gathering information on loaded DLL in the current process.
InLoadOrderModuleList sorts modules in load order, InMemoryOrderModuleList
in memory order, and InInitializationOrderModuleList keeps track of their
load order since process start.

These doubly linked list contains pointers to LDR_MODULE inside the parent
structure for next and previous module.

typedef struct _LDR_MODULE {

LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
PVOID BaseAddress;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
ULONG Flags;
SHORT LoadCount;
SHORT TlsIndex;
LIST_ENTRY HashTableEntry;
ULONG TimeDateStamp;

} LDR_MODULE, *PLDR_MODULE;


The following code demonstrates how to walk one of the lists and throw
a module away according to its name (szDllToStrip).

/* Walks one of the three modules double linked lists referenced by the
PEB (error check stripped)
ModuleListType is an internal flag to determine on which list to operate :
LOAD_ORDER_TYPE <---> InLoadOrderModuleList
MEM_ORDER_TYPE <---> InMemoryOrderModuleList
INIT_ORDER_TYPE <---> InInitializationOrderModuleList
*/
int WalkModuleList(char ModuleListType, char *szDllToStrip)
{
int i; /* internal counter */
DWORD PebBaseAddr, dwOffset=0;

/* Module list head and iterating pointer */
PLIST_ENTRY pUserModuleListHead, pUserModuleListPtr;

/* PEB->PEB_LDR_DATA*/
PPEB_LDR_DATA pLdrData;
/* Module(s) name in UNICODE/AINSI*/
PUNICODE_STRING pImageName;
char szImageName[BUFMAXLEN];

/* First, get Process Environment Block */
PebBaseAddr = GetPEB(0);

/* Compute PEB->PEB_LDR_DATA */
pLdrData=(PPEB_LDR_DATA)(DWORD *)(*(DWORD *)(PebBaseAddr +
PEB_LDR_DATA_OFFSET));

/* Init linked list head and offset in LDR_MODULE structure */
if(ModuleListType == LOAD_ORDER_TYPE)
{
/* InLoadOrderModuleList */
pUserModuleListHead = pUserModuleListPtr =
(PLIST_ENTRY)(&(pLdrData->ModuleListLoadOrder));
dwOffset = 0x0;
} else if(ModuleListType == MEM_ORDER_TYPE)
{
/* InMemoryOrderModuleList */
pUserModuleListHead = pUserModuleListPtr =
(PLIST_ENTRY)(&(pLdrData->ModuleListMemoryOrder));
dwOffset = 0x08;
} else if(ModuleListType == INIT_ORDER_TYPE)
{
/* InInitializationOrderModuleList */
pUserModuleListHead = pUserModuleListPtr =
(PLIST_ENTRY)(&(pLdrData->ModuleListInitOrder));
dwOffset = 0x10;
}

/* Now walk the selected list */
do
{
/* Jump to next LDR_MODULE structure */
pUserModuleListPtr = pUserModuleListPtr->Flink;
pImageName = (PUNICODE_STRING)(
((DWORD)(pUserModuleListPtr)) +
(LDR_DATA_PATHFILENAME_OFFSET-dwOffset));

/* Decode unicode string to lower case on the fly */
for(i=0; i < (pImageName->Length)/2 && iBuffer)+(i) ));
/* Null terminated string */
szImageName[i] = '\0';

/* Check if it's target DLL */
if( strstr((char*)szImageName, szDllToStrip) != 0 )
{
/* Hide this dll : throw this module away (out of
the double linked list)
(pUserModuleListPtr->Blink)->Flink =
(pUserModuleListPtr->Flink);
(pUserModuleListPtr->Flink)->Blink =
(pUserModuleListPtr->Blink);
/* Here we may also overwrite memory to prevent
recovering (paranoid only ;p) */
}
} while(pUserModuleListPtr->Flink != pUserModuleListHead);

return FUNC_SUCCESS;
}


To process the three linked lists, the cheat calls the HideDll function
below.

int HideDll(char *szDllName)
{
return ( WalkModuleList(LOAD_ORDER_TYPE, szDllName)
&& WalkModuleList(MEM_ORDER_TYPE, szDllName)
&& WalkModuleList(INIT_ORDER_TYPE, szDllName) );
}


http://forum.gamedeception.net/threads/5012-Module-Hiding

0 comentarios:

Publicar un comentario