日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

Win64 驱动内核编程-8.内核里的其他常用

發(fā)布時(shí)間:2025/6/17 58 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Win64 驱动内核编程-8.内核里的其他常用 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

內(nèi)核里的其他常用

1.遍歷鏈表。內(nèi)核里有很多數(shù)據(jù)結(jié)構(gòu),但它們并不是孤立的,內(nèi)核使用雙向鏈表把它們像糖

葫蘆一樣給串了起來。所以遍歷雙向鏈表能獲得很多重要的內(nèi)核數(shù)據(jù)。舉個(gè)簡(jiǎn)單的例子,驅(qū)

動(dòng)對(duì)象?DriverObject?就是使用雙向鏈表給串起來的,遍歷這個(gè)鏈表就可以枚舉內(nèi)核里所有的驅(qū)動(dòng)。示例代碼如下

//傳入驅(qū)動(dòng)自身的 DriverObject VOID EnumDriver(PDRIVER_OBJECT pDriverObject) { PKLDR_DATA_TABLE_ENTRY entry = (PKLDR_DATA_TABLE_ENTRY)pDriverObject->DriverSection; PKLDR_DATA_TABLE_ENTRY firstentry; ULONG64 pDrvBase = 0; KIRQL OldIrql; firstentry = entry; //當(dāng)發(fā)現(xiàn)又找到自己時(shí)跳出循環(huán),否則成了死循環(huán)。 while ((PKLDR_DATA_TABLE_ENTRY)entry->InLoadOrderLinks.Flink != firstentry) { DbgPrint("BASE=%p\tPATH=%wZ", entry->DllBase, entry->FullDllName); entry = (PKLDR_DATA_TABLE_ENTRY)entry->InLoadOrderLinks.Flink; } }

2.等待。這個(gè)等于?RING3?的?Sleep?函數(shù)了。

#define DELAY_ONE_MICROSECOND (-10) #define DELAY_ONE_MILLISECOND (DELAY_ONE_MICROSECOND*1000) VOID MySleep(LONG msec) { LARGE_INTEGER my_interval; my_interval.QuadPart = DELAY_ONE_MILLISECOND; my_interval.QuadPart *= msec; KeDelayExecutionThread(KernelMode, 0, &my_interval); }

3.同步。這個(gè)可以理解成是“條件等待”。常用的是?KeWaitForSingleObject、KeInitializeEvent、

KeSetEvent?這幾個(gè)函數(shù)。為了方便講解,這個(gè)的示例代碼與“內(nèi)核線程”放在一起。先把這

幾個(gè)函數(shù)的原型貼出來。

NTSTATUS KeWaitForSingleObject ( _In_ PVOID Object, _In_ KWAIT_REASON WaitReason, _In_ KPROCESSOR_MODE WaitMode, _In_ BOOLEAN Alertable, _In_opt_ PLARGE_INTEGER Timeout ); VOID KeInitializeEvent ( _Out_ PRKEVENT Event, _In_ EVENT_TYPE Type, _In_ BOOLEAN State ); LONG KeSetEvent ( _Inout_ PRKEVENT Event, _In_ KPRIORITY Increment, _In_ BOOLEAN Wait );

4.獲得系統(tǒng)版本號(hào)。內(nèi)核編程難免使用硬編碼,以及使用一些高版本系統(tǒng)才出現(xiàn)的函數(shù)。為

了使得驅(qū)動(dòng)能在低版本的系統(tǒng)上正常運(yùn)行,就需要根據(jù)不同系統(tǒng)做不同處理了。

VOID GetVersion() { ULONG NtBuildNumber; RTL_OSVERSIONINFOW osi; osi.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOW); RtlFillMemory(&osi, sizeof(RTL_OSVERSIONINFOW), 0); RtlGetVersion(&osi); NtBuildNumber = osi.dwBuildNumber; DbgPrint("NtBuildNumber: %ld\n", NtBuildNumber); return NtBuildNumber; }

5.獲得系統(tǒng)時(shí)間。在內(nèi)核里獲得系統(tǒng)時(shí)間的是標(biāo)準(zhǔn)時(shí)間(GMT+0),轉(zhuǎn)換成本地時(shí)間還需要進(jìn)

行轉(zhuǎn)換。此功能在發(fā)布測(cè)試版軟件的時(shí)候特別有用,限制人們只能在指定時(shí)間之前使用。

VOID MyGetCurrentTime() { LARGE_INTEGER CurrentTime; LARGE_INTEGER LocalTime; TIME_FIELDS TimeFiled; // 這里得到的其實(shí)是格林威治時(shí)間 KeQuerySystemTime(&CurrentTime); // 轉(zhuǎn)換成本地時(shí)間 ExSystemTimeToLocalTime(&CurrentTime, &LocalTime); // 把時(shí)間轉(zhuǎn)換為容易理解的形式 RtlTimeToTimeFields(&LocalTime, &TimeFiled); DbgPrint("[TimeTest] NowTime : %4d-%2d-%2d %2d:%2d:%2d", TimeFiled.Year, TimeFiled.Month, TimeFiled.Day, TimeFiled.Hour, TimeFiled.Minute, TimeFiled.Second); }

6.內(nèi)核線程。內(nèi)核線程就是名義上屬于?SYSTEM?進(jìn)程的線程。比如說你要做壞事,卻讓?SYSTEM

進(jìn)程背黑鍋,是一件很爽的事情。內(nèi)核線程還有幾個(gè)特點(diǎn):1.?PreviousMode?是?KernelMode,

可以直接調(diào)用?Nt?開頭的內(nèi)核函數(shù)(Nt?開頭的內(nèi)核函數(shù)會(huì)檢查?PreviousMode,如果

PreviousMode?不是?KernelMode,就會(huì)拒絕服務(wù)。有些人喜歡直接修改?ETHREAD?里的這個(gè)值,

但我個(gè)人覺得這么改不妥當(dāng))。2.內(nèi)核線程不會(huì)自己結(jié)束,必須調(diào)用?PsTerminateSystemThread

才能被動(dòng)結(jié)束。以下是例子,?同時(shí)演示了?等待?、同步和內(nèi)核線程的使用。

KEVENT kEvent; //事件//線程函數(shù) VOID MyThreadFunc(IN PVOID context) { PUNICODE_STRING str = (PUNICODE_STRING)context; DbgPrint("Kernel thread running: %wZ\n", str); DbgPrint("Wait 3s!\n"); MySleep(3000); DbgPrint("Kernel thread exit!\n"); KeSetEvent(&kEvent, 0, TRUE); PsTerminateSystemThread(STATUS_SUCCESS); } //創(chuàng)建線程的函數(shù) VOID CreateThreadTest() { HANDLE hThread; UNICODE_STRING ustrTest = RTL_CONSTANT_STRING(L"This is a string for test!"); NTSTATUS status; // 初始化事件 KeInitializeEvent(&kEvent, SynchronizationEvent, FALSE); status = PsCreateSystemThread(&hThread, 0, NULL, NULL, NULL, MyThreadFunc, (PVOID)&ustrTest); if (!NT_SUCCESS(status)) { DbgPrint("PsCreateSystemThread failed!"); return; } ZwClose(hThread); // 等待事件 KeWaitForSingleObject(&kEvent, Executive, KernelMode, FALSE, NULL); DbgPrint("CreateThreadTest OVER!\n"); }

7.強(qiáng)制重啟計(jì)算機(jī)。在內(nèi)核里直接使用?OUT?指令就能強(qiáng)制重啟計(jì)算機(jī)而不可能被任何鉤子

攔截。此代碼可以用在反調(diào)試?yán)铩?/span>

VOID ForceReboot() { typedef void(__fastcall *FCRB)(void); /* mov al, 0FEh out 64h, al ret */ FCRB fcrb = NULL; UCHAR shellcode[6] = "\xB0\xFE\xE6\x64\xC3"; fcrb = ExAllocatePool(NonPagedPool, 5); memcpy(fcrb, shellcode, 5); fcrb(); }

8.強(qiáng)制關(guān)閉計(jì)算機(jī)。在內(nèi)核里直接使用?OUT?指令就能強(qiáng)制關(guān)閉計(jì)算機(jī)而不可能被任何鉤子

攔截。此代碼可以用在反調(diào)試?yán)铩?/span>

VOID ForceShutdown() { typedef void(__fastcall *FCRB)(void); /* mov ax,2001h mov dx,1004h out dx,ax ret */ FCRB fcrb = NULL; UCHAR shellcode[12] = "\x66\xB8\x01\x20\x66\xBA\x04\x10\x66\xEF\xC3"; fcrb = ExAllocatePool(NonPagedPool, 11); memcpy(fcrb, shellcode, 11); fcrb(); }

總結(jié)

以上是生活随笔為你收集整理的Win64 驱动内核编程-8.内核里的其他常用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。