Last active
August 29, 2015 13:56
-
-
Save Inndy/d9d1d37221a3a99a3c71 to your computer and use it in GitHub Desktop.
Proceess Module Enumerating and Hiding
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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