国产精品久久99,51久久成人国产精品麻豆,亚洲欧洲免费三级网站,最近中文字幕mv,重口老太大和小伙乱

首頁(yè)>影視 > 正文

資訊:驅(qū)動(dòng)開(kāi)發(fā):摘除InlineHook內(nèi)核鉤子

2023-06-24 13:56:26來(lái)源:博客園


(相關(guān)資料圖)

在筆者上一篇文章《驅(qū)動(dòng)開(kāi)發(fā):內(nèi)核層InlineHook掛鉤函數(shù)》中介紹了通過(guò)替換函數(shù)頭部代碼的方式實(shí)現(xiàn)Hook掛鉤,對(duì)于ARK工具來(lái)說(shuō)實(shí)現(xiàn)掃描與摘除InlineHook鉤子也是最基本的功能,此類(lèi)功能的實(shí)現(xiàn)一般可在應(yīng)用層進(jìn)行,而驅(qū)動(dòng)層只需要保留一個(gè)讀寫(xiě)字節(jié)的函數(shù)即可,將復(fù)雜的流程放在應(yīng)用層實(shí)現(xiàn)是一個(gè)非常明智的選擇,與《驅(qū)動(dòng)開(kāi)發(fā):內(nèi)核實(shí)現(xiàn)進(jìn)程反匯編》中所使用的讀寫(xiě)驅(qū)動(dòng)基本一致,本篇文章中的驅(qū)動(dòng)只保留兩個(gè)功能,控制信號(hào)IOCTL_GET_CUR_CODE用于讀取函數(shù)的前16個(gè)字節(jié)的內(nèi)存,信號(hào)IOCTL_SET_ORI_CODE則用于設(shè)置前16個(gè)字節(jié)的內(nèi)存。

之所以是前16個(gè)字節(jié)是因?yàn)橐话愕?code>內(nèi)聯(lián)Hook只需要使用兩條指令就可實(shí)現(xiàn)劫持,如下是通用ARK工具掃描到的被掛鉤函數(shù)的樣子。

首先將內(nèi)核驅(qū)動(dòng)程序代碼放到如下,內(nèi)核驅(qū)動(dòng)程序沒(méi)有任何特別的,僅僅只是一個(gè)通用驅(qū)動(dòng)模板,在其基礎(chǔ)上使用CR3讀寫(xiě),如果不理解CR3讀寫(xiě)的原理您可以去看《驅(qū)動(dòng)開(kāi)發(fā):內(nèi)核CR3切換讀寫(xiě)內(nèi)存》這一篇中的詳細(xì)介紹。

// 署名權(quán)// right to sign one"s name on a piece of work// PowerBy: LyShark// Email: me@lyshark.com#include #include #include #defineDEVICE_NAMEL"\\Device\\WinDDK"#define LINK_NAMEL"\\DosDevices\\WinDDK"#define LINK_GLOBAL_NAMEL"\\DosDevices\\Global\\WinDDK"http:// 控制信號(hào) IOCTL_GET_CUR_CODE 用于讀 | IOCTL_SET_ORI_CODE 用于寫(xiě)#define IOCTL_GET_CUR_CODECTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)#define IOCTL_SET_ORI_CODECTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)// 引用__readcr0等函數(shù)必須增加#pragma intrinsic(_disable)#pragma intrinsic(_enable)// 定義讀寫(xiě)結(jié)構(gòu)體typedef struct{PVOID Address;ULONG64 Length;UCHAR data[256];} KF_DATA, *PKF_DATA;KIRQL g_irql;// 關(guān)閉寫(xiě)保護(hù)void WPOFFx64(){ULONG64 cr0;g_irql = KeRaiseIrqlToDpcLevel();cr0 = __readcr0();cr0 &= 0xfffffffffffeffff;__writecr0(cr0);_disable();}// 開(kāi)啟寫(xiě)保護(hù)void WPONx64(){ULONG64 cr0;cr0 = __readcr0();cr0 |= 0x10000;_enable();__writecr0(cr0);KeLowerIrql(g_irql);}// 設(shè)備創(chuàng)建時(shí)觸發(fā)NTSTATUS DispatchCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp){pIrp->IoStatus.Status = STATUS_SUCCESS;pIrp->IoStatus.Information = 0;DbgPrint("[LyShark] 設(shè)備已創(chuàng)建 \n");IoCompleteRequest(pIrp, IO_NO_INCREMENT);return STATUS_SUCCESS;}// 設(shè)備關(guān)閉時(shí)觸發(fā)NTSTATUS DispatchClose(PDEVICE_OBJECT pDevObj, PIRP pIrp){pIrp->IoStatus.Status = STATUS_SUCCESS;pIrp->IoStatus.Information = 0;DbgPrint("[LyShark] 設(shè)備已關(guān)閉 \n");IoCompleteRequest(pIrp, IO_NO_INCREMENT);return STATUS_SUCCESS;}// 主派遣函數(shù)NTSTATUS DispatchIoctl(PDEVICE_OBJECT pDevObj, PIRP pIrp){NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;PIO_STACK_LOCATION pIrpStack;ULONG uIoControlCode;PVOID pIoBuffer;ULONG uInSize;ULONG uOutSize;// 獲取當(dāng)前設(shè)備棧pIrpStack = IoGetCurrentIrpStackLocation(pIrp);uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;// 獲取緩沖區(qū)pIoBuffer = pIrp->AssociatedIrp.SystemBuffer;// 獲取緩沖區(qū)長(zhǎng)度uInSize = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;// 輸出緩沖區(qū)長(zhǎng)度uOutSize = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;switch (uIoControlCode){// 讀內(nèi)存case IOCTL_GET_CUR_CODE:{KF_DATA dat = { 0 };// 將緩沖區(qū)格式化為KF_DATA結(jié)構(gòu)體RtlCopyMemory(&dat, pIoBuffer, 16);WPOFFx64();// 將數(shù)據(jù)寫(xiě)回到緩沖區(qū)RtlCopyMemory(pIoBuffer, dat.Address, dat.Length);WPONx64();status = STATUS_SUCCESS;break;}// 寫(xiě)內(nèi)存case IOCTL_SET_ORI_CODE:{KF_DATA dat = { 0 };// 將緩沖區(qū)格式化為KF_DATA結(jié)構(gòu)體RtlCopyMemory(&dat, pIoBuffer, sizeof(KF_DATA));WPOFFx64();// 將數(shù)據(jù)寫(xiě)回到緩沖區(qū)RtlCopyMemory(dat.Address, dat.data, dat.Length);WPONx64();status = STATUS_SUCCESS;break;}}if (status == STATUS_SUCCESS)pIrp->IoStatus.Information = uOutSize;elsepIrp->IoStatus.Information = 0;pIrp->IoStatus.Status = status;IoCompleteRequest(pIrp, IO_NO_INCREMENT);return status;}// 驅(qū)動(dòng)卸載VOID DriverUnload(PDRIVER_OBJECT pDriverObj){UNICODE_STRING strLink;// 刪除符號(hào)鏈接卸載設(shè)備RtlInitUnicodeString(&strLink, LINK_NAME);IoDeleteSymbolicLink(&strLink);IoDeleteDevice(pDriverObj->DeviceObject);}// 驅(qū)動(dòng)程序入口NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegistryString){NTSTATUS status = STATUS_SUCCESS;UNICODE_STRING ustrLinkName;UNICODE_STRING ustrDevName;PDEVICE_OBJECT pDevObj;// 初始化派遣函數(shù)pDriverObj->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;pDriverObj->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;pDriverObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctl;DbgPrint("hello lysahrk.com \n");// 初始化設(shè)備名RtlInitUnicodeString(&ustrDevName, DEVICE_NAME);// 創(chuàng)建設(shè)備status = IoCreateDevice(pDriverObj, 0, &ustrDevName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDevObj);if (!NT_SUCCESS(status)){return status;}// 創(chuàng)建符號(hào)鏈接RtlInitUnicodeString(&ustrLinkName, LINK_NAME);status = IoCreateSymbolicLink(&ustrLinkName, &ustrDevName);if (!NT_SUCCESS(status)){IoDeleteDevice(pDevObj);return status;}pDriverObj->DriverUnload = DriverUnload;return STATUS_SUCCESS;}

接著來(lái)分析下應(yīng)用層做了什么,首先GetKernelBase64函數(shù)的作用,該函數(shù)內(nèi)部通過(guò)GetProcAddress()函數(shù)動(dòng)態(tài)尋找到ZwQuerySystemInformation()函數(shù)的內(nèi)存地址(此函數(shù)未被到處所以只能動(dòng)態(tài)找到),找到后調(diào)用ZwQuerySystemInformation()直接拿到系統(tǒng)中的所有模塊信息,通過(guò)pSystemModuleInformation->Module[0].Base得到系統(tǒng)中第一個(gè)模塊的基地址,此模塊就是ntoskrnl.exe,該模塊也是系統(tǒng)運(yùn)行后的第一個(gè)啟動(dòng)的,此時(shí)我們即可拿到KernelBase也就是系統(tǒng)內(nèi)存中的基地址。

此時(shí)通過(guò)LoadLibraryExA()函數(shù)動(dòng)態(tài)加載,此時(shí)加載的是磁盤(pán)中的被Hook函數(shù)的所屬模塊,獲得映射地址后將此地址裝入hKernel變量?jī)?nèi),此時(shí)我們擁有了內(nèi)存中的KernelBase以及磁盤(pán)中加載的hKernel,接著調(diào)用RepairRelocationTable()讓兩者的重定位表保持一致。

此時(shí)當(dāng)用戶(hù)調(diào)用GetSystemRoutineAddress()則執(zhí)行如下流程,想要獲取當(dāng)前內(nèi)存地址,則需要使用當(dāng)前內(nèi)存中的KernelBase模塊基址加上通過(guò)GetProcAddress()動(dòng)態(tài)獲取到的磁盤(pán)基址中的函數(shù)地址減去磁盤(pán)中的基地址,將內(nèi)存中的KernelBase加上磁盤(pán)中的相對(duì)偏移就得到了當(dāng)前內(nèi)存中加載函數(shù)的實(shí)際地址。

address1 = KernelBase + (ULONG64)GetProcAddress(hKernel, "NtWriteFile") - (ULONG64)hKerneladdress2 = KernelBase - (ULONG64)hKernel + (ULONG64)GetProcAddress(hKernel, "NtWriteFile")

調(diào)用GetOriginalMachineCode()則用于獲取相對(duì)偏移地址,該地址的獲取方式如下,用戶(hù)傳入一個(gè)Address當(dāng)前地址,該地址減去KernelBase內(nèi)存中的基址,然后再加上hKernel磁盤(pán)加載的基址來(lái)獲取到相對(duì)偏移。

OffsetAddress = Address - KernelBase + hKernel

有了這兩條信息那么功能也就實(shí)現(xiàn)了,通過(guò)GetOriginalMachineCode()得到指定內(nèi)存地址處原始機(jī)器碼,通過(guò)GetCurrentMachineCode()得到當(dāng)前內(nèi)存機(jī)器碼,兩者通過(guò)memcmp()函數(shù)比對(duì)即可知道是否被掛鉤了,如果被掛鉤則可以通過(guò)CR3切換將原始機(jī)器碼覆蓋到特定位置替換即可,這段程序的完整代碼如下;

// 署名權(quán)// right to sign one"s name on a piece of work// PowerBy: LyShark// Email: me@lyshark.com#include #include #pragma comment(lib,"user32.lib")#pragma comment(lib,"Advapi32.lib")#ifndef NT_SUCCESS#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)#endif#define BYTE_ARRAY_LENGTH 16#define SystemModuleInformation 11#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)typedef long(__stdcall *ZWQUERYSYSTEMINFORMATION)(IN ULONG SystemInformationClass,IN PVOID SystemInformation,IN ULONG SystemInformationLength,IN PULONG ReturnLength OPTIONAL);typedef struct{ULONG Unknow1;ULONG Unknow2;ULONG Unknow3;ULONG Unknow4;PVOID Base;ULONG Size;ULONG Flags;USHORT Index;USHORT NameLength;USHORT LoadCount;USHORT ModuleNameOffset;char ImageName[256];} SYSTEM_MODULE_INFORMATION_ENTRY, *PSYSTEM_MODULE_INFORMATION_ENTRY;typedef struct{ULONG Count;SYSTEM_MODULE_INFORMATION_ENTRY Module[1];} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;typedef struct{PVOID Address;ULONG64 Length;UCHAR data[256];} KF_DATA, *PKF_DATA;HANDLE hDriver = 0;HMODULEhKernel = 0;ULONG64KernelBase = 0;CHAR NtosFullName[260] = { 0 };// 生成控制信號(hào)DWORD CTL_CODE_GEN(DWORD lngFunction){return (FILE_DEVICE_UNKNOWN * 65536) | (FILE_ANY_ACCESS * 16384) | (lngFunction * 4) | METHOD_BUFFERED;}// 發(fā)送控制信號(hào)的函數(shù)BOOL IoControl(HANDLE hDrvHandle, DWORD dwIoControlCode, PVOID lpInBuffer, DWORD nInBufferSize, PVOID lpOutBuffer, DWORD nOutBufferSize){DWORD lDrvRetSize;return DeviceIoControl(hDrvHandle, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, &lDrvRetSize, 0);}// 動(dòng)態(tài)獲取ntdll.dll模塊的基地址ULONG64 GetKernelBase64(PCHAR NtosName){ZWQUERYSYSTEMINFORMATION ZwQuerySystemInformation;PSYSTEM_MODULE_INFORMATION pSystemModuleInformation;ULONG NeedSize, BufferSize = 0x5000;PVOID pBuffer = NULL;NTSTATUS Result;// 該函數(shù)只能通過(guò)動(dòng)態(tài)方式得到地址ZwQuerySystemInformation = (ZWQUERYSYSTEMINFORMATION)GetProcAddress(GetModuleHandleA("ntdll.dll"), "ZwQuerySystemInformation");do{pBuffer = malloc(BufferSize);if (pBuffer == NULL) return 0;// 查詢(xún)系統(tǒng)中的所有模塊信息Result = ZwQuerySystemInformation(SystemModuleInformation, pBuffer, BufferSize, &NeedSize);if (Result == STATUS_INFO_LENGTH_MISMATCH){free(pBuffer);BufferSize *= 2;}else if (!NT_SUCCESS(Result)){free(pBuffer);return 0;}} while (Result == STATUS_INFO_LENGTH_MISMATCH);// 取模塊信息結(jié)構(gòu)pSystemModuleInformation = (PSYSTEM_MODULE_INFORMATION)pBuffer;// 得到模塊基地址ULONG64 ret = (ULONG64)(pSystemModuleInformation->Module[0].Base);// 拷貝模塊名if (NtosName != NULL){strcpy(NtosName, pSystemModuleInformation->Module[0].ImageName + pSystemModuleInformation->Module[0].ModuleNameOffset);}free(pBuffer);return ret;}// 判斷并修復(fù)重定位表BOOL RepairRelocationTable(ULONG64 HandleInFile, ULONG64 BaseInKernel){PIMAGE_DOS_HEADERpDosHeader;PIMAGE_NT_HEADERS64pNtHeader;PIMAGE_BASE_RELOCATIONpRelocTable;ULONG i, dwOldProtect;// 得到DOS頭并判斷是否符合DOS規(guī)范pDosHeader = (PIMAGE_DOS_HEADER)HandleInFile;if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE){return FALSE;}// 得到Nt頭pNtHeader = (PIMAGE_NT_HEADERS64)((ULONG64)HandleInFile + pDosHeader->e_lfanew);// 是否存在重定位表if (pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size){// 獲取到重定位表基地址pRelocTable = (PIMAGE_BASE_RELOCATION)((ULONG64)HandleInFile + pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);do{// 得到重定位號(hào)ULONGnumofReloc = (pRelocTable->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / 2;SHORTminioffset = 0;// 得到重定位數(shù)據(jù)PUSHORT pRelocData = (PUSHORT)((ULONG64)pRelocTable + sizeof(IMAGE_BASE_RELOCATION));// 循環(huán)或直接判斷*pRelocData是否為0也可以作為結(jié)束標(biāo)記for (i = 0; i> 12) == IMAGE_REL_BASED_DIR64){// 計(jì)算需要進(jìn)行重定位的地址// 重定位數(shù)據(jù)的低12位再加上本重定位塊頭的RVA即真正需要重定位的數(shù)據(jù)的RVAminioffset = (*pRelocData) & 0xFFF; // 小偏移// 模塊基址+重定位基址+每個(gè)數(shù)據(jù)表示的小偏移量RelocAddress = (PULONG64)(HandleInFile + pRelocTable->VirtualAddress + minioffset);// 直接在RING3修改: 原始數(shù)據(jù)+基址-IMAGE_OPTINAL_HEADER中的基址VirtualProtect((PVOID)RelocAddress, 4, PAGE_EXECUTE_READWRITE, &dwOldProtect);// 因?yàn)槭荝3直接LOAD的所以要修改一下內(nèi)存權(quán)限*RelocAddress = *RelocAddress + BaseInKernel - pNtHeader->OptionalHeader.ImageBase;VirtualProtect((PVOID)RelocAddress, 4, dwOldProtect, NULL);}// 下一個(gè)重定位數(shù)據(jù)pRelocData++;}// 下一個(gè)重定位塊pRelocTable = (PIMAGE_BASE_RELOCATION)((ULONG64)pRelocTable + pRelocTable->SizeOfBlock);} while (pRelocTable->VirtualAddress);return TRUE;}return FALSE;}// 初始化BOOL InitEngine(BOOL IsClear){if (IsClear == TRUE){// 動(dòng)態(tài)獲取ntdll.dll模塊的基地址KernelBase = GetKernelBase64(NtosFullName);printf("模塊基址: %llx | 模塊名: %s \n", KernelBase, NtosFullName);if (!KernelBase){return FALSE;}// 動(dòng)態(tài)加載模塊到內(nèi)存,并獲取到模塊句柄hKernel = LoadLibraryExA(NtosFullName, 0, DONT_RESOLVE_DLL_REFERENCES);if (!hKernel){return FALSE;}// 判斷并修復(fù)重定位表if (!RepairRelocationTable((ULONG64)hKernel, KernelBase)){return FALSE;}return TRUE;}else{FreeLibrary(hKernel);return TRUE;}}// 獲取原始函數(shù)機(jī)器碼VOID GetOriginalMachineCode(ULONG64 Address, PUCHAR ba, SIZE_T Length){ULONG64 OffsetAddress = Address - KernelBase + (ULONG64)hKernel;RtlCopyMemory(ba, (PVOID)OffsetAddress, Length);}// 獲取傳入函數(shù)的內(nèi)存地址ULONG64 GetSystemRoutineAddress(PCHAR FuncName){return KernelBase + (ULONG64)GetProcAddress(hKernel, FuncName) - (ULONG64)hKernel;}// 獲取當(dāng)前函數(shù)機(jī)器碼VOID GetCurrentMachineCode(ULONG64 Address, PUCHAR ba, SIZE_T Length){ULONG64 dat[2] = { 0 };dat[0] = Address;dat[1] = Length;IoControl(hDriver, CTL_CODE_GEN(0x800), dat, 16, ba, Length);}// 清除特定位置的機(jī)器碼VOID ClearInlineHook(ULONG64 Address, PUCHAR ba, SIZE_T Length){KF_DATA dat = { 0 };dat.Address = (PVOID)Address;dat.Length = Length;// 直接調(diào)用寫(xiě)出控制碼RtlCopyMemory(dat.data, ba, Length);IoControl(hDriver, CTL_CODE_GEN(0x801), &dat, sizeof(KF_DATA), 0, 0);}// 打印數(shù)據(jù)VOID PrintBytes(PCHAR DescriptionString, PUCHAR ba, UINT Length){printf("%s", DescriptionString);for (UINT i = 0; i

首先編譯驅(qū)動(dòng)程序WinDDK.sys并通過(guò)KmdManager將驅(qū)動(dòng)程序拉起來(lái),運(yùn)行客戶(hù)端lyshark.exe程序會(huì)輸出當(dāng)前FunctionList列表中,指定的4個(gè)函數(shù)的掛鉤情況。

參考文獻(xiàn)

WIN64內(nèi)核編程基礎(chǔ) 胡文亮

關(guān)鍵詞:

責(zé)任編輯:

免責(zé)聲明

頭條新聞

精彩推送

新聞推送