說說windows核心中為什麼要隱藏執行緒?(附原始碼)
阿新 • • 發佈:2019-01-08
一、論:
接著上一篇來談談,程序都能隱藏,單獨隱藏程序中的某一個執行緒幹啥?
二、需求:
需求源動力,就是有需求,除了正兒八經熱愛喜歡專研的朋友,無利無名、無食而學日不思,真的讓人很尊敬。
三、打個比方:
當你想要去實現隱藏執行緒的時候你有可能在幹什麼?做一個工具?或者說是學習?通過隱藏執行緒可以更深入理解windows內部原理?程序與執行緒之間的關係?一個正常程序裡面包含惡意執行緒?這是一個很棒的學習方式。也許你會用它來做一些事情,以前想寫過一個類似於ARK的工具,才有了學習的需求及動力。但是還沒有實際的環境去應用隱藏執行緒,沒有需求,但還是把程式碼認真的寫出來,分享一些知識,知識在於分享。
四、還是那些結構體:
有時候我在想,不用winAPI我能做什麼事?也許我還能做很多的事情,因為有足夠的結構體我就不慌、但是,如果沒有了結構體我能做什麼事情?這個還真不好說,其實相對於windows我更為喜歡Linux那種自由。
介紹主人公_ETHREAD與_KTHREAD:
1、_EPROCESS.ThreadListHead ---> _ETHREAD
2、_KPROCESS.ThreadListHead ---> _KTHREAD
執行緒屬於程序,一個程序由多個執行緒、那麼同一個程序的多個執行緒使用的是相同的程序空間,執行緒也叫做輕量級程序。執行緒掛靠技術,也可以本執行緒使用其他程序的空間。
windows下執行緒是最小執行單位,每個程序至少會有一個主執行緒去響應執行。同樣_ETHREAD屬於執行體層,內嵌偏移0是_KTHREAD(微核心層),異曲同工之妙,windows的管理不得不說很優秀,可以用藝術來形容。
_KPROCESS中會有一個成員叫做ThreadListHead欄位是程序所有執行緒的連結串列。指向的位置是_KTHREAD.ThreadListEntry,這個地方當時異或了好久,為啥?為啥這個連結串列指向的就是這個結構體這個位置,其實我現在也很糾結.
_KPROCESS.ThreadListHead指向 -----> _KTHREAD.ThreadListEntry
就是這個情況.核心就是通過這個來遍歷屬於某一個程序空間的所有執行緒。詳細資料還是參考:https://bbs.pediy.com/thread-223858.htm 個人感覺翻譯過來的文章質量五星好評。
五、貼上原始碼
#include "HideThreadHeader.h" VOID UnLoad(PDRIVER_OBJECT pDriverObj) { UNICODE_STRING DeleteSymbolicLinkName; RtlInitUnicodeString(&DeleteSymbolicLinkName, L"\\DosDevices\\SymbolicLinkName"); IoDeleteSymbolicLink(&DeleteSymbolicLinkName); IoDeleteDevice(pDriverObj->DeviceObject); KdPrint(("UnLoad Sucess")); } NTSTATUS DefaultFun(DEVICE_OBJECT* pDeviceObj, IRP* irp) { UNREFERENCED_PARAMETER(pDeviceObj); irp->IoStatus.Information = 0; irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } NTSTATUS onCreate(DEVICE_OBJECT* pDeviceObj, IRP* irp) { UNREFERENCED_PARAMETER(pDeviceObj); irp->IoStatus.Information = 0; irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } NTSTATUS onClose(DEVICE_OBJECT* pDeviceObj, IRP* irp) { UNREFERENCED_PARAMETER(pDeviceObj); irp->IoStatus.Information = 0; irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } // 遍歷屬於某個程序所有執行緒 通過斷鏈實現隱藏執行緒 VOID HideThreadListLink() { CLIENT_ID* ThreadId = NULL; PEPROCESS pkProcess = NULL; PKTHREAD pkThread = NULL; PETHREAD pEthread = NULL; LIST_ENTRY* pEthreadNext = NULL; LIST_ENTRY* pEthreadCurrent = NULL; pkProcess = PsGetCurrentProcess(); // 獲取_KPROCESS->ThreadListHead(_LIST_ENTRY) pEthreadCurrent = (LIST_ENTRY *)((ULONG_PTR)pkProcess + 0x02c); /* 注: 1. _KPROCESS.ThreadListHead->Flink指向的是一個_KTHREAD.ThreadListEntry 2. _KTHREAD.ThreadListEntry - 偏移ThreadListEntry獲取到KTHREAD地址,其實也就是ETHREAD地址. */ KdPrint(("ThreadListHead.Flink = %p\n", pEthreadCurrent->Flink)); KdPrint(("ThreadListHead.blink = %p\n", pEthreadCurrent->Blink)); // 這個 (PETHREAD)(PEPROCESS + 0x2c) pEthreadNext = pEthreadCurrent->Flink; DbgBreakPoint(); while (pEthreadCurrent != pEthreadNext) { pkThread = (PKTHREAD)((ULONG_PTR)pEthreadNext - 0x1e0); // pKthread->Teb 偏移 0x88 // KdPrint(("pKThread->Teb = %p , %s \n", (ULONG_PTR)pkThread + 0x88, (((ULONG_PTR)pKThread + 0x88) == NULL || pkThread->Teb > 0x80000000 ? "System Thread" : "Non System Thread"))); // 轉換成EPROCESS pEthread = (PETHREAD)pkThread; DbgBreakPoint(); // pEthread->Cid 偏移0x22c ThreadId = (CLIENT_ID *)((ULONG_PTR)pEthread + 0x22c); KdPrint(("ThreadId = %d, ProcessId = %d\n\n", ThreadId->UniqueThread, ThreadId->UniqueProcess)); // 這個地方也可以使用斷鏈 虛擬碼 if (ThreadId->UniqueThread == "隱藏的執行緒id") { // 與程序隱藏斷鏈方式一樣 } pEthreadNext = pEthreadNext->Flink; } } // 驅動物件入口點 NTSTATUS DriverEntry(DRIVER_OBJECT* pDriverObj, IRP* irp) { UNREFERENCED_PARAMETER(irp); DbgBreakPoint(); for (int i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; ++i) { pDriverObj->MajorFunction[i] = DefaultFun; } pDriverObj->DriverUnload = UnLoad; pDriverObj->MajorFunction[IRP_MJ_CREATE] = onCreate; pDriverObj->MajorFunction[IRP_MJ_CLOSE] = onClose; UNICODE_STRING DeviceName; UNICODE_STRING SymbolicLinkName; DEVICE_OBJECT* DeviceObj; NTSTATUS nStatus = STATUS_SUCCESS; RtlInitUnicodeString(&DeviceName, L"\\Device\\DeviceName"); RtlInitUnicodeString(&SymbolicLinkName, L"\\DosDevices\\SymbolicLinkName"); nStatus = IoCreateDevice(pDriverObj, 0, &DeviceName, FILE_DEVICE_UNKNOWN, 0, 0, &DeviceObj); if (!NT_SUCCESS(nStatus)) return nStatus; nStatus = IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName); if (!NT_SUCCESS(nStatus)) return nStatus; DbgBreakPoint(); // 沒有使用控制碼等處理 虛擬碼進行測試 HideThreadListLink(); return STATUS_SUCCESS; }