(35)3环PEB断链
生活随笔
收集整理的這篇文章主要介紹了
(35)3环PEB断链
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
一、斷鏈原理
3環下PEB斷鏈是一種常見的模塊隱藏技術,原理是修改 _PEB_LDR_DATA 中的三個雙向鏈表,刪除鏈表中的項,讓 CreateToolhelp32Snapshot 之類的API無法通過模塊列表枚舉DLL。
以 InLoadOrderModuleList 鏈表為例,畫個簡單的示意圖:
所謂斷鏈,就是把三個鏈表斷掉,讓3環的API讀不出模塊信息。最簡單的做法就是讓Head的Flink和Blink指向它自己。
二、隱藏所有模塊
// PEB斷鏈.cpp : 定義控制臺應用程序的入口點。 //#include "stdafx.h" #include <Windows.h>// 內核Unicode字符串 typedef struct _UNICODE_STRING {USHORT Length;USHORT MaximumLength;PWSTR Buffer; } UNICODE_STRING, *PUNICODE_STRING;// LDR鏈表頭 typedef struct _PEB_LDR_DATA {DWORD Length;bool Initialized;PVOID SsHandle;// LIST_ENTRY 是雙端鏈表項,指向前后節點LIST_ENTRY InLoadOrderModuleList; // 指向了 InLoadOrderModuleList 鏈表的第一項LIST_ENTRY InMemoryOrderModuleList;LIST_ENTRY InInitializationOrderModuleList; } PEB_LDR_DATA,*PPEB_LDR_DATA;// LDR表項,存儲了模塊信息 typedef struct _LDR_DATA_TABLE_ENTRY {LIST_ENTRY InLoadOrderModuleList;LIST_ENTRY InMemoryOrderModuleList;LIST_ENTRY InInitializationOrderModuleList;void* BaseAddress;void* EntryPoint; ULONG SizeOfImage;UNICODE_STRING FullDllName;UNICODE_STRING BaseDllName;ULONG Flags;SHORT LoadCount;SHORT TlsIndex;HANDLE SectionHandle;ULONG CheckSum;ULONG TimeDateStamp; } LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;void HideModule() { PPEB_LDR_DATA ldr; PLDR_DATA_TABLE_ENTRY ldte;// 獲取LDR__asm{mov eax,fs:[0x30] // PEB mov ecx,[eax + 0x0c] // LDRmov ldr,ecx }PLIST_ENTRY Head; // Head 指向鏈表第一項,第一項不存儲模塊信息// 分別將三個鏈表斷鏈處理Head = &(ldr->InLoadOrderModuleList);Head->Flink = Head->Blink = Head;Head = &(ldr->InMemoryOrderModuleList);Head->Flink = Head->Blink = Head;Head = &(ldr->InInitializationOrderModuleList);Head->Flink = Head->Blink = Head; }int _tmain(int argc, _TCHAR* argv[]) {printf("未斷鏈前狀態(敲任意字符開始斷鏈)\n");getchar();HideModule();printf("斷鏈后狀態.\n");getchar();return 0; }斷鏈前:
斷鏈后:
三、隱藏特定模塊
如果想隱藏某個特定模塊,例如隱藏掉 kernel32.dll,可以這樣做:
// PEB斷鏈.cpp : 定義控制臺應用程序的入口點。 //#include "stdafx.h" #include <Windows.h>// 內核Unicode字符串 typedef struct _UNICODE_STRING {USHORT Length;USHORT MaximumLength;PWSTR Buffer; } UNICODE_STRING, *PUNICODE_STRING;// LDR鏈表頭 typedef struct _PEB_LDR_DATA {DWORD Length;bool Initialized;PVOID SsHandle;// LIST_ENTRY 是雙端鏈表項,指向前后節點LIST_ENTRY InLoadOrderModuleList; // 指向了 InLoadOrderModuleList 鏈表的第一項LIST_ENTRY InMemoryOrderModuleList;LIST_ENTRY InInitializationOrderModuleList; } PEB_LDR_DATA,*PPEB_LDR_DATA;// LDR表項,存儲了模塊信息 typedef struct _LDR_DATA_TABLE_ENTRY {LIST_ENTRY InLoadOrderModuleList;LIST_ENTRY InMemoryOrderModuleList;LIST_ENTRY InInitializationOrderModuleList;void* BaseAddress;void* EntryPoint; ULONG SizeOfImage;UNICODE_STRING FullDllName;UNICODE_STRING BaseDllName;ULONG Flags;SHORT LoadCount;SHORT TlsIndex;HANDLE SectionHandle;ULONG CheckSum;ULONG TimeDateStamp; } LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;void HideModule(HMODULE hModule) { PPEB_LDR_DATA ldr; PLDR_DATA_TABLE_ENTRY ldte;// 獲取LDR__asm{mov eax,fs:[0x30] // PEB mov ecx,[eax + 0x0c] // LDRmov ldr,ecx }PLIST_ENTRY Head, Cur; // Head 指向鏈表第一項,第一項不存儲模塊信息;Cur指向第二項,是第一個存儲了模塊信息的項// 分別將三個鏈表斷鏈處理Head = &(ldr->InLoadOrderModuleList);Cur = Head->Flink;do{// CONTAINING_RECORD宏的作用是傳入一個地址,一個結構體類型和該地址屬于結構體中的哪個屬性,返回結構體基址ldte = CONTAINING_RECORD( Cur, LDR_DATA_TABLE_ENTRY, InLoadOrderModuleList);if (ldte->BaseAddress == hModule){ // 斷鏈ldte->InLoadOrderModuleList.Blink->Flink = ldte->InLoadOrderModuleList.Flink; ldte->InLoadOrderModuleList.Flink->Blink = ldte->InLoadOrderModuleList.Blink; }Cur = Cur->Flink;} while(Head != Cur);Head = &(ldr->InMemoryOrderModuleList);Cur = Head->Flink;do { // CONTAINING_RECORD宏的作用是傳入一個地址,一個結構體類型和該地址屬于結構體中的哪個屬性,返回結構體基址ldte = CONTAINING_RECORD( Cur, LDR_DATA_TABLE_ENTRY, InMemoryOrderModuleList); if (ldte->BaseAddress == hModule){// 斷鏈ldte->InMemoryOrderModuleList.Blink->Flink = ldte->InMemoryOrderModuleList.Flink; ldte->InMemoryOrderModuleList.Flink->Blink = ldte->InMemoryOrderModuleList.Blink; }Cur = Cur->Flink;} while(Head != Cur);Head = &(ldr->InInitializationOrderModuleList);Cur = Head->Flink;do { // CONTAINING_RECORD宏的作用是傳入一個地址,一個結構體類型和該地址屬于結構體中的哪個屬性,返回結構體基址ldte = CONTAINING_RECORD( Cur, LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList); if (ldte->BaseAddress == hModule){// 斷鏈ldte->InInitializationOrderModuleList.Blink->Flink = ldte->InInitializationOrderModuleList.Flink; ldte->InInitializationOrderModuleList.Flink->Blink = ldte->InInitializationOrderModuleList.Blink; }Cur = Cur->Flink;} while(Head != Cur); }int _tmain(int argc, _TCHAR* argv[]) {printf("未斷鏈前狀態(敲任意字符開始斷鏈)\n");getchar();HideModule(GetModuleHandleA("kernel32.dll"));printf("斷鏈后狀態.\n");getchar();return 0; }斷鏈前:
斷鏈后:
總結
以上是生活随笔為你收集整理的(35)3环PEB断链的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (34)内核编程基础
- 下一篇: (36)内核空间与内核模块,遍历内核模块