Skip to content

Instantly share code, notes, and snippets.

@Inndy
Last active August 29, 2015 13:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Inndy/d9d1d37221a3a99a3c71 to your computer and use it in GitHub Desktop.
Save Inndy/d9d1d37221a3a99a3c71 to your computer and use it in GitHub Desktop.
Proceess Module Enumerating and Hiding
#include <Windows.h>
// #include <ntstatus.h>
#include <Winternl.h>
#include <stdio.h>
#include <locale.h>
// #define FAST_GET_PEB
#ifndef STATUS_SUCCESS
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
#endif
typedef struct _W7_X86_PEB_LDR_DATA // 9 elements, 0x30 bytes (sizeof)
{
ULONG32 Length; /*0x00*/
UINT8 Initialized; /*0x04*/
UINT8 _PADDING0_[0x3]; /*0x05*/
VOID* SsHandle; /*0x08*/
struct _LIST_ENTRY InLoadOrderModuleList; /*0x0C*/ // 2 elements, 0x08 bytes (sizeof)
struct _LIST_ENTRY InMemoryOrderModuleList; /*0x14*/ // 2 elements, 0x08 bytes (sizeof)
struct _LIST_ENTRY InInitializationOrderModuleList; /*0x1C*/ // 2 elements, 0x08 bytes (sizeof)
VOID* EntryInProgress; /*0x24*/
UINT8 ShutdownInProgress; /*0x28*/
UINT8 _PADDING1_[0x3]; /*0x29*/
VOID* ShutdownThreadId; /*0x2C*/
} W7_X86_PEB_LDR_DATA, *W7_X86_PPEB_LDR_DATA;
typedef struct _W7_X86_LDR_DATA_TABLE_ENTRY // 24 elements, 0x78 bytes (sizeof)
{
struct _LIST_ENTRY InLoadOrderLinks; /*0x000*/ // 2 elements, 0x8 bytes (sizeof)
struct _LIST_ENTRY InMemoryOrderLinks; /*0x008*/ // 2 elements, 0x8 bytes (sizeof)
struct _LIST_ENTRY InInitializationOrderLinks; /*0x010*/ // 2 elements, 0x8 bytes (sizeof)
VOID* DllBase; /*0x018*/
VOID* EntryPoint; /*0x01C*/
ULONG32 SizeOfImage; /*0x020*/
struct _UNICODE_STRING FullDllName; /*0x024*/ // 3 elements, 0x8 bytes (sizeof)
struct _UNICODE_STRING BaseDllName; /*0x02C*/ // 3 elements, 0x8 bytes (sizeof)
ULONG32 Flags; /*0x034*/
UINT16 LoadCount; /*0x038*/
UINT16 TlsIndex; /*0x03A*/
union // 2 elements, 0x8 bytes (sizeof)
{
struct _LIST_ENTRY HashLinks; /*0x03C*/ // 2 elements, 0x8 bytes (sizeof)
struct // 2 elements, 0x8 bytes (sizeof)
{
VOID* SectionPointer; /*0x03C*/
ULONG32 CheckSum; /*0x040*/
};
};
union // 2 elements, 0x4 bytes (sizeof)
{
ULONG32 TimeDateStamp; /*0x044*/
VOID* LoadedImports; /*0x044*/
};
struct _ACTIVATION_CONTEXT* EntryPointActivationContext; /*0x048*/
VOID* PatchInformation; /*0x04C*/
struct _LIST_ENTRY ForwarderLinks; /*0x050*/ // 2 elements, 0x8 bytes (sizeof)
struct _LIST_ENTRY ServiceTagLinks; /*0x058*/ // 2 elements, 0x8 bytes (sizeof)
struct _LIST_ENTRY StaticLinks; /*0x060*/ // 2 elements, 0x8 bytes (sizeof)
VOID* ContextInformation; /*0x068*/
ULONG32 OriginalBase; /*0x06C*/
union _LARGE_INTEGER LoadTime; /*0x070*/ // 4 elements, 0x8 bytes (sizeof)
} W7_X86_LDR_DATA_TABLE_ENTRY, *W7_X86_PLDR_DATA_TABLE_ENTRY;
PPEB __stdcall GetPEB() {
#ifdef FAST_GET_PEB
DWORD peb = 0;
__asm {
mov eax, fs:[0x30];
mov [peb], eax;
}
return (PPEB)peb;
#else
typedef NTSTATUS (WINAPI *pNtQueryInformationProcess) (
HANDLE ProcessHandle,
PROCESSINFOCLASS ProcessInformationClass,
PVOID ProcessInformation,
ULONG ProcessInformationLength,
PULONG ReturnLength
);
HMODULE hNTDLL = LoadLibrary("ntdll");
if (hNTDLL == NULL) {
printf("[-] LoadLibrary(\"ntdll\") Failed\n");
return NULL;
}
pNtQueryInformationProcess theNtQueryInformationProcess =
(pNtQueryInformationProcess)GetProcAddress(hNTDLL, "NtQueryInformationProcess");
if (theNtQueryInformationProcess == NULL) {
printf("[-] GetProcAddress(hNTDLL, \"NtQueryInformationProcess\") Failed\n");
return NULL;
}
PROCESS_BASIC_INFORMATION PBI = { 0 };
DWORD RetLength = 0;
NTSTATUS ret = theNtQueryInformationProcess(GetCurrentProcess(), ProcessBasicInformation,
&PBI, sizeof(PBI), &RetLength);
if (ret != STATUS_SUCCESS) {
printf("[-] NtQueryInformationProcess(...) Failed\n");
return NULL;
}
if (RetLength < 8) {
printf("[-] NtQueryInformationProcess(...) Failed (not enough returned length)\n");
return NULL;
}
return PBI.PebBaseAddress;
#endif
}
wchar_t * ReadUnicodeString (PUNICODE_STRING str, wchar_t buffer[], int buff_size) {
int i, length;
if (str == NULL)
return NULL;
buff_size = (buff_size - 1) / sizeof(wchar_t);
length = str->Length;
if (length > buff_size)
length = buff_size;
CopyMemory(buffer, str->Buffer, length * sizeof(wchar_t));
buffer[length] = 0;
return buffer;
}
BOOL ModuleExists(HMODULE module) {
PPEB peb = GetPEB();
if (peb == NULL)
return FALSE;
PLIST_ENTRY modlist = &peb->Ldr->InMemoryOrderModuleList;
PLIST_ENTRY p = modlist->Flink;
do {
W7_X86_PLDR_DATA_TABLE_ENTRY data = (W7_X86_PLDR_DATA_TABLE_ENTRY)(p - 1);
if (data->DllBase == module)
return TRUE;
p = p->Flink;
} while (p != modlist);
return FALSE;
}
void EraseUnicodeString(PUNICODE_STRING str) {
str->Length = 0;
SecureZeroMemory(str->Buffer, str->Length * sizeof(wchar_t));
}
void BreakLink(PLIST_ENTRY link) {
link->Blink->Flink = link->Flink;
link->Flink->Blink = link->Blink;
}
BOOL EraseModule(HMODULE module) {
if (module == NULL || ModuleExists(module) == FALSE)
return FALSE;
PPEB peb = GetPEB();
if (peb == NULL)
return FALSE;
// Find the link structure
PLIST_ENTRY modlist = &peb->Ldr->InMemoryOrderModuleList;
PLIST_ENTRY p = modlist->Flink;
W7_X86_PLDR_DATA_TABLE_ENTRY data;
do {
data = (W7_X86_PLDR_DATA_TABLE_ENTRY)(p - 1);
if (data->DllBase == module)
break;
p = p->Flink;
} while (p != modlist);
// Break Link
BreakLink(&data->InLoadOrderLinks);
BreakLink(&data->InMemoryOrderLinks);
BreakLink(&data->InInitializationOrderLinks);
// Erase DLL Name and DLL Path
EraseUnicodeString(&data->BaseDllName);
EraseUnicodeString(&data->FullDllName);
// Erase PE header
PIMAGE_DOS_HEADER dos_header = (PIMAGE_DOS_HEADER)data->DllBase;
PIMAGE_NT_HEADERS nt_header = (PIMAGE_NT_HEADERS)(((char *)dos_header) + dos_header->e_lfanew);
DWORD OldProtection;
VirtualProtect(dos_header, 0x1000, PAGE_EXECUTE_READWRITE, &OldProtection);
SecureZeroMemory(dos_header, sizeof(PIMAGE_DOS_HEADER));
SecureZeroMemory(nt_header, sizeof(IMAGE_NT_HEADERS));
VirtualProtect(dos_header, 0x1000, OldProtection, &OldProtection);
// Erase entire information block
/*** Notice: If you do this, "GetModuleHandle" will make your application crash
ntdll.dll+0x57D7B:
772D7D7B 8D47 2C lea eax,dword ptr ds:[edi+0x2C]
772D7D7E 50 push eax ; Eax is invalid address
772D7D7F FF75 08 push dword ptr ss:[ebp+0x8] ; The dll that we search for
772D7D82 E8 7ED9FFFF call ntdll.RtlEqualUnicodeString ; And... Crash :(
772D7D87 84C0 test al,al
772D7D89 0F84 280D0000 je ntdll.772D8AB7
772D7D8F F747 34 00000010 test dword ptr ds:[edi+0x34],0x10000000
772D7D96 0F85 1B0D0000 jnz ntdll.772D8AB7
772D7D9C 8B45 10 mov eax,dword ptr ss:[ebp+0x10]
772D7D9F 8938 mov dword ptr ds:[eax],edi
772D7DA1 E9 86FEFFFF jmp ntdll.772D7C2C
*/
//SecureZeroMemory(data, sizeof(W7_X86_LDR_DATA_TABLE_ENTRY));
// Clean strucuture
data->DllBase = NULL;
data->EntryPoint = NULL;
data->SizeOfImage = 0;
data->LoadCount = 0;
return TRUE;
}
void EnumerateModule(PLIST_ENTRY list, const char * description, int offset) {
if (description != NULL)
printf("[+] Enumerating Modules (%s)\n", description);
else
printf("[+] Enumerating Modules\n");
int count = 0;
PLIST_ENTRY p = list->Flink;
do {
count++;
printf("[*] Node: %.8X -> %.8X", p, p->Flink);
W7_X86_PLDR_DATA_TABLE_ENTRY data = (W7_X86_PLDR_DATA_TABLE_ENTRY)(p - offset);
printf(" .... Structure At %.8X, DllBase = %.8X\n", data, data->DllBase);
wchar_t buffer[512];
wprintf(L" DllName: %s\n", ReadUnicodeString(&data->BaseDllName, buffer, sizeof(buffer)));
wprintf(L" FullPath: %s\n", ReadUnicodeString(&data->FullDllName, buffer, sizeof(buffer)));
printf("\n");
p = p->Flink;
} while (p != list);
printf("[*] --> Module Count = %d\n", count);
}
int main () {
// to print chinese widechar
setlocale(LC_CTYPE, "");
#ifdef FAST_GET_PEB
const char * __fast_get_peb = "Enabled";
#else
const char * __fast_get_peb = "Disabled";
#endif
PPEB peb = GetPEB();
if (peb == NULL) {
printf("[-] GetPEB() Failed\n");
return -1;
}
printf("\x5B\x2B\x5D\x20\x50\x72\x6F\x63\x65\x65\x73\x73\x20\x4D\x6F\x64");
printf("\x75\x6C\x65\x20\x45\x6E\x75\x6D\x65\x72\x61\x74\x69\x6E\x67\x20");
printf("\x61\x6E\x64\x20\x45\x72\x61\x73\x69\x6E\x67\x0A\x20\x20\x20\x20");
printf("\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20");
printf("\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20");
printf("\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x42\x79\x20\x49\x6E\x6E");
printf("\x64\x79\x0A");
printf("[*] FAST_GET_PEB: %s\n", __fast_get_peb);
printf("[+] PEB = %.8X\n", peb);
PPEB_LDR_DATA pebldr = peb->Ldr;
printf("[+] PEB_LDR_DATA = %.8X\n", pebldr);
W7_X86_PPEB_LDR_DATA w7ldr = (W7_X86_PPEB_LDR_DATA)pebldr;
printf("[+] InLoadOrderModuleList = %.8X\n"
"[+] InMemoryOrderModuleList = %.8X\n"
"[+] InInitializationOrderModuleList = %.8X\n",
w7ldr->InLoadOrderModuleList,
w7ldr->InMemoryOrderModuleList,
w7ldr->InInitializationOrderModuleList);
// EnumerateModule(&w7ldr->InLoadOrderModuleList, "InLoadOrderModuleList", 0);
EnumerateModule(&w7ldr->InMemoryOrderModuleList, "InMemoryOrderModuleList", 1);
// EnumerateModule(&w7ldr->InInitializationOrderModuleList, "InInitializationOrderModuleList", 2);
HMODULE hNTDLL = GetModuleHandle("ntdll");
printf("[+] Erase Module... ntdll.dll (%.8X)\n", hNTDLL);
EraseModule(hNTDLL);
printf("[+] Enumerate DLL again...\n");
EnumerateModule(&w7ldr->InLoadOrderModuleList, "InLoadOrderModuleList", 0);
EnumerateModule(&w7ldr->InMemoryOrderModuleList, "InMemoryOrderModuleList", 1);
EnumerateModule(&w7ldr->InInitializationOrderModuleList, "InInitializationOrderModuleList", 2);
printf("[*] GetModuleHandle(\"ntdll\") says... %.8X\n", GetModuleHandle("ntdll"));
printf("[!] Press Ctrl - C to Exit\n");
while (1) ;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment