日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Win64 驱动内核编程-2.基本框架(安装.通讯.HelloWorld)

發(fā)布時(shí)間:2025/6/17 编程问答 61 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Win64 驱动内核编程-2.基本框架(安装.通讯.HelloWorld) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

驅(qū)動(dòng)安裝,通訊,Hello?World

開發(fā)驅(qū)動(dòng)的簡單流程是這樣,開發(fā)驅(qū)動(dòng)安裝程序,開發(fā)驅(qū)動(dòng)程序,然后安裝程序(或者其他程序)通過通訊給驅(qū)動(dòng)傳命令,驅(qū)動(dòng)接到之后進(jìn)行解析并且執(zhí)行,然后把執(zhí)行結(jié)果返回。

驅(qū)動(dòng)程序Hello?World

之前總結(jié)了驅(qū)動(dòng)環(huán)境的搭建,這里就直接繼續(xù)之前搭建好的環(huán)境創(chuàng)建項(xiàng)目,打開vs2015創(chuàng)建一個(gè)驅(qū)動(dòng)項(xiàng)目:



寫代碼之前先配置下編譯選項(xiàng):


然后添加一個(gè)項(xiàng)目文件main.c(注意后綴是.c,前面名字無所謂可以不叫main),里面的內(nèi)容如下(下面模板代碼來源于網(wǎng)絡(luò),作者:胡文亮,我是在看他的資料學(xué)習(xí),感謝這位前輩。)

/* WIN64驅(qū)動(dòng)開發(fā)模板 作者:Tesla.Angela *///【0】包含的頭文件,可以加入系統(tǒng)或自己定義的頭文件 #include <ntddk.h> #include <windef.h> #include <stdlib.h>//【1】定義符號鏈接,一般來說修改為驅(qū)動(dòng)的名字即可 #define DEVICE_NAME L"\\Device\\KrnlHW64" #define LINK_NAME L"\\DosDevices\\KrnlHW64" #define LINK_GLOBAL_NAME L"\\DosDevices\\Global\\KrnlHW64"//【2】定義驅(qū)動(dòng)功能號和名字,提供接口給應(yīng)用程序調(diào)用 #define IOCTL_IO_TEST CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_SAY_HELLO CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)//【3】驅(qū)動(dòng)卸載的處理例程 VOID DriverUnload(PDRIVER_OBJECT pDriverObj) { UNICODE_STRING strLink; DbgPrint("[KrnlHW64]DriverUnload\n"); //刪除符號連接和設(shè)備 RtlInitUnicodeString(&strLink, LINK_NAME); IoDeleteSymbolicLink(&strLink); IoDeleteDevice(pDriverObj->DeviceObject); }//【4】IRP_MJ_CREATE對應(yīng)的處理例程,一般不用管它 NTSTATUS DispatchCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp) { DbgPrint("[KrnlHW64]DispatchCreate\n"); pIrp->IoStatus.Status = STATUS_SUCCESS; pIrp->IoStatus.Information = 0; IoCompleteRequest(pIrp, IO_NO_INCREMENT); return STATUS_SUCCESS; }//【5】IRP_MJ_CLOSE對應(yīng)的處理例程,一般不用管它 NTSTATUS DispatchClose(PDEVICE_OBJECT pDevObj, PIRP pIrp) { DbgPrint("[KrnlHW64]DispatchClose\n"); pIrp->IoStatus.Status = STATUS_SUCCESS; pIrp->IoStatus.Information = 0; IoCompleteRequest(pIrp, IO_NO_INCREMENT); return STATUS_SUCCESS; }//【6】IRP_MJ_DEVICE_CONTROL對應(yīng)的處理例程,驅(qū)動(dòng)最重要的函數(shù)之一,一般走正常途徑調(diào)用驅(qū)動(dòng)功能的程序,都會(huì)經(jīng)過這個(gè)函數(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; DbgPrint("[KrnlHW64]DispatchIoctl\n"); //獲得IRP里的關(guān)鍵數(shù)據(jù) pIrpStack = IoGetCurrentIrpStackLocation(pIrp); //這個(gè)就是傳說中的控制碼 uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode; //輸入和輸出的緩沖區(qū)(DeviceIoControl的InBuffer和OutBuffer都是它) pIoBuffer = pIrp->AssociatedIrp.SystemBuffer; //EXE發(fā)送傳入數(shù)據(jù)的BUFFER長度(DeviceIoControl的nInBufferSize) uInSize = pIrpStack->Parameters.DeviceIoControl.InputBufferLength; //EXE接收傳出數(shù)據(jù)的BUFFER長度(DeviceIoControl的nOutBufferSize) uOutSize = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength; switch(uIoControlCode) { //在這里加入接口 case IOCTL_IO_TEST: { DWORD dw=0; //輸入 memcpy(&dw,pIoBuffer,sizeof(DWORD)); //使用 dw++; //輸出 memcpy(pIoBuffer,&dw,sizeof(DWORD)); //返回通信狀態(tài) status = STATUS_SUCCESS; break; } case IOCTL_SAY_HELLO: { DbgPrint("[KrnlHW64]IOCTL_SAY_HELLO\n"); status = STATUS_SUCCESS; break; } } //這里設(shè)定DeviceIoControl的*lpBytesReturned的值(如果通信失敗則返回0長度) if(status == STATUS_SUCCESS) pIrp->IoStatus.Information = uOutSize; else pIrp->IoStatus.Information = 0; //這里設(shè)定DeviceIoControl的返回值是成功還是失敗 pIrp->IoStatus.Status = status; IoCompleteRequest(pIrp, IO_NO_INCREMENT); return status; }//【7】驅(qū)動(dòng)加載的處理例程,里面進(jìn)行了驅(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è)置分發(fā)函數(shù)和卸載例程 pDriverObj->MajorFunction[IRP_MJ_CREATE] = DispatchCreate; pDriverObj->MajorFunction[IRP_MJ_CLOSE] = DispatchClose; pDriverObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctl; pDriverObj->DriverUnload = DriverUnload; //創(chuàng)建一個(gè)設(shè)備 RtlInitUnicodeString(&ustrDevName, DEVICE_NAME); status = IoCreateDevice(pDriverObj, 0, &ustrDevName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDevObj); if(!NT_SUCCESS(status)) return status; //判斷支持的WDM版本,其實(shí)這個(gè)已經(jīng)不需要了,純屬WIN9X和WINNT并存時(shí)代的殘留物 if(IoIsWdmVersionAvailable(1, 0x10)) RtlInitUnicodeString(&ustrLinkName, LINK_GLOBAL_NAME); else RtlInitUnicodeString(&ustrLinkName, LINK_NAME); //創(chuàng)建符號連接 status = IoCreateSymbolicLink(&ustrLinkName, &ustrDevName); if(!NT_SUCCESS(status)) { IoDeleteDevice(pDevObj); return status; } DbgPrint("[KrnlHW64]DriverEntry\n"); //返回加載驅(qū)動(dòng)的狀態(tài)(如果返回失敗,驅(qū)動(dòng)講被清除出內(nèi)核空間) return STATUS_SUCCESS; }

然后右鍵編譯工程,會(huì)出現(xiàn)這個(gè)錯(cuò)誤提示:


然后把這個(gè)文件刪除:


繼續(xù)編譯,還是不會(huì)過:繼續(xù)改另一個(gè)配置文件選項(xiàng):


然后就可以了:


然后是驅(qū)動(dòng)安裝程序:

目前如果沒有仔細(xì)看上面的那個(gè)基本模板代碼,需要回去仔細(xì)看下。大體了解細(xì)節(jié),尤其是里面的注釋。

看完代碼了,接下來是驅(qū)動(dòng)安裝。

驅(qū)動(dòng)安裝和服務(wù)安裝,如果之前寫過安裝服務(wù)的代碼看驅(qū)動(dòng)安裝代碼會(huì)很熟悉,都是采用SCM安裝。具體流程是:


然后這個(gè)函數(shù)要仔細(xì)看定義:


更詳細(xì)的細(xì)節(jié)之前看MSDN吧。

然后還是把資料上的模板代碼直接拿過來,注意目前先用這個(gè)模板,因?yàn)檫@個(gè)安裝模板是和上面的那個(gè)Hello?World對應(yīng)的,等看懂之后了,在自己定義相關(guān)驅(qū)動(dòng)安裝和驅(qū)動(dòng)程序的代碼,也可以自己寫個(gè)模板,這里先不自己隨便定義,可能會(huì)導(dǎo)致鏈接名字,驅(qū)動(dòng)名字,還有驅(qū)動(dòng)通訊的那個(gè)地方的細(xì)節(jié)自己弄亂了。這個(gè)博客看完了再回頭定義自己的就行。

創(chuàng)建C++工程,然后直接添加安裝代碼和安裝測試代碼:

功能代碼:

/*============================ Drvier Control Class (SCM way) ============================*/#pragma comment(lib,"advapi32.lib")class cDrvCtrl { public: cDrvCtrl() { m_pSysPath = NULL; m_pServiceName = NULL; m_pDisplayName = NULL; m_hSCManager = NULL; m_hService = NULL; m_hDriver = INVALID_HANDLE_VALUE; } ~cDrvCtrl() { CloseServiceHandle(m_hService); CloseServiceHandle(m_hSCManager); CloseHandle(m_hDriver); } public: DWORD m_dwLastError; PCHAR m_pSysPath; PCHAR m_pServiceName; PCHAR m_pDisplayName; HANDLE m_hDriver; SC_HANDLE m_hSCManager; SC_HANDLE m_hService; public: BOOL Install(PCHAR pSysPath,PCHAR pServiceName,PCHAR pDisplayName); BOOL Start(); BOOL Stop(); BOOL Remove(); BOOL Open(PCHAR pLinkName); BOOL IoControl(DWORD dwIoCode, PVOID InBuff, DWORD InBuffLen, PVOID OutBuff, DWORD OutBuffLen, DWORD *RealRetBytes); private: BOOL GetSvcHandle(PCHAR pServiceName); DWORD CTL_CODE_GEN(DWORD lngFunction); protected: //null };BOOL cDrvCtrl::GetSvcHandle(PCHAR pServiceName) { m_pServiceName = pServiceName; m_hSCManager = OpenSCManagerA(NULL,NULL,SC_MANAGER_ALL_ACCESS); if (NULL == m_hSCManager) { m_dwLastError = GetLastError(); return FALSE; } m_hService = OpenServiceA(m_hSCManager,m_pServiceName,SERVICE_ALL_ACCESS); if (NULL == m_hService) { CloseServiceHandle(m_hSCManager); return FALSE; } else { return TRUE; } }BOOL cDrvCtrl::Install(PCHAR pSysPath,PCHAR pServiceName,PCHAR pDisplayName) { m_pSysPath = pSysPath; m_pServiceName = pServiceName; m_pDisplayName = pDisplayName; m_hSCManager = OpenSCManagerA(NULL,NULL,SC_MANAGER_ALL_ACCESS); if (NULL == m_hSCManager) { m_dwLastError = GetLastError(); return FALSE; } m_hService = CreateServiceA(m_hSCManager,m_pServiceName,m_pDisplayName,SERVICE_ALL_ACCESS,SERVICE_KERNEL_DRIVER,SERVICE_DEMAND_START,SERVICE_ERROR_NORMAL,m_pSysPath,NULL,NULL,NULL,NULL,NULL); if (NULL == m_hService) { m_dwLastError = GetLastError(); if (ERROR_SERVICE_EXISTS == m_dwLastError) { m_hService = OpenServiceA(m_hSCManager,m_pServiceName,SERVICE_ALL_ACCESS); if (NULL == m_hService) { CloseServiceHandle(m_hSCManager); return FALSE; } } else { CloseServiceHandle(m_hSCManager); return FALSE; } } return TRUE; }BOOL cDrvCtrl::Start() { if (!StartServiceA(m_hService,NULL,NULL)) { m_dwLastError = GetLastError(); return FALSE; } return TRUE; }BOOL cDrvCtrl::Stop() { SERVICE_STATUS ss; GetSvcHandle(m_pServiceName); if (!ControlService(m_hService,SERVICE_CONTROL_STOP,&ss)) { m_dwLastError = GetLastError(); return FALSE; } return TRUE;}BOOL cDrvCtrl::Remove() { GetSvcHandle(m_pServiceName); if (!DeleteService(m_hService)) { m_dwLastError = GetLastError(); return FALSE; } return TRUE; }BOOL cDrvCtrl::Open(PCHAR pLinkName)//example: \\\\.\\xxoo { if (m_hDriver != INVALID_HANDLE_VALUE) return TRUE; m_hDriver = CreateFileA(pLinkName, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if(m_hDriver != INVALID_HANDLE_VALUE) return TRUE; else return FALSE; }BOOL cDrvCtrl::IoControl(DWORD dwIoCode, PVOID InBuff, DWORD InBuffLen, PVOID OutBuff, DWORD OutBuffLen, DWORD *RealRetBytes) { DWORD dw; BOOL b=DeviceIoControl(m_hDriver,CTL_CODE_GEN(dwIoCode),InBuff,InBuffLen,OutBuff,OutBuffLen,&dw,NULL); if(RealRetBytes) *RealRetBytes=dw; return b; }DWORD cDrvCtrl::CTL_CODE_GEN(DWORD lngFunction) { return (FILE_DEVICE_UNKNOWN * 65536) | (FILE_ANY_ACCESS * 16384) | (lngFunction * 4) | METHOD_BUFFERED; }
測試代碼:

// DriverInstall.cpp : 定義控制臺應(yīng)用程序的入口點(diǎn)。 //#include "stdafx.h" #include <string> #include <windows.h> #include "ScmDrvCtrl.h"#pragma warning(disable:4996)#pragma comment(lib,"user32.lib")using namespace std;void GetAppPath(char *szCurFile) //最后帶斜杠 { GetModuleFileNameA(0, szCurFile, MAX_PATH); for (SIZE_T i = strlen(szCurFile) - 1; i >= 0; i--) { if (szCurFile[i] == '\\') { szCurFile[i + 1] = '\0'; break; } } }int main() { BOOL b; cDrvCtrl dc; //設(shè)置驅(qū)動(dòng)名稱 char szSysFile[MAX_PATH] = { 0 }; char szSvcLnkName[] = "KrnlHW64";; GetAppPath(szSysFile); strcat(szSysFile, "KrnlHW64.sys"); //安裝并啟動(dòng)驅(qū)動(dòng) b = dc.Install(szSysFile, szSvcLnkName, szSvcLnkName); b = dc.Start(); printf("LoadDriver=%d\n", b); //“打開”驅(qū)動(dòng)的符號鏈接 dc.Open("\\\\.\\KrnlHW64"); //使用控制碼控制驅(qū)動(dòng)(0x800:傳入一個(gè)數(shù)字并返回一個(gè)數(shù)字) DWORD x = 100, y = 0, z = 0; dc.IoControl(0x800, &x, sizeof(x), &y, sizeof(y), &z); printf("INPUT=%ld\nOUTPUT=%ld\nReturnBytesLength=%ld\n", x, y, z); //使用控制碼控制驅(qū)動(dòng)(0x801:在DBGVIEW里顯示HELLOWORLD) dc.IoControl(0x801, 0, 0, 0, 0, 0); //關(guān)閉符號鏈接句柄 CloseHandle(dc.m_hDriver); //停止并卸載驅(qū)動(dòng) b = dc.Stop(); b = dc.Remove(); printf("UnloadDriver=%d\n", b); getchar(); return 0; }

然后就直接本地嘗試調(diào)試安裝一次,結(jié)果先是這個(gè):


不用管它,點(diǎn)擊全部允許,但是還是會(huì)發(fā)現(xiàn)

?

還是裝不上,其實(shí)是肯定裝不上的。原因是64位機(jī)器需要的強(qiáng)制簽名加載驅(qū)動(dòng):


注意最后面那句,各種系統(tǒng)的防護(hù)已經(jīng)被攻克,他沒有說win10,不過目前已經(jīng)親測win10也已經(jīng)攻克,之后有機(jī)會(huì)再說這些東西,這里只討論正常安裝。想在win64上安裝無簽名驅(qū)動(dòng)也可以,如果是win7,直接cmd?輸入??bcdedit?/set?testsigning?on?,然后重啟電腦(win7是這樣,win10貌似是前面要多輸入一條命令,如果是要win10的話自己搜下吧,同時(shí)還有其他改設(shè)置關(guān)掉無簽名驅(qū)動(dòng)提示等的設(shè)置,加載測試驅(qū)動(dòng)程序,需要的也可以找找,網(wǎng)上很多)。設(shè)置后上面的配置之后,重啟電腦:

?

有的時(shí)候會(huì)有測試模式水印,有的時(shí)候沒有,可能提示不是正版的話會(huì)沒這個(gè)水印,不過這不重要,只要相面的那個(gè)cmd命令執(zhí)行成功,重啟電腦就可以加載無簽名64位驅(qū)動(dòng)了。

接下來測試下我們上面的那一套代碼(所有程序都右鍵管理員啟動(dòng)):

先打開dbgview全都選上:


然后啟動(dòng)安裝程序:


OK驅(qū)動(dòng)加載成功,并且通訊測試成功。這里基本模板就算完事了,之后就是一些常用的驅(qū)動(dòng)開發(fā),后續(xù)再整理。

總結(jié)

以上是生活随笔為你收集整理的Win64 驱动内核编程-2.基本框架(安装.通讯.HelloWorld)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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