windows內核研究(驅動開發-0環與3環的通信)

驅動開發


0環與3環的通信

設備對象

在之前開發窗口程序時,消息都是被封裝成一個結構體(MSG),在內核開發時,消息被封裝成另外一個結構體:IRP(I/O Request Package)

在窗口程序中,能夠接收消息的只能是窗口對象,在內核中,能夠接收IRP消息的只能是設備對象

創建設備對象

// 創建設備名稱
UNICODE_STRING deviceName;
RtlInitUnicodeString(&deviceName, L"\\Device\\MyDevice");/*
NTSTATUS IoCreateDevice([in]           PDRIVER_OBJECT  DriverObject,			// 驅動對象[in]           ULONG           DeviceExtensionSize,	// 指定要為設備對象的 設備擴展 分配的驅動程序確定字節數[in, optional] PUNICODE_STRING DeviceName,			// 設備名稱[in]           DEVICE_TYPE     DeviceType,			// 設備類型[in]           ULONG           DeviceCharacteristics,	// 設備特征[in]           BOOLEAN         Exclusive,				// 指定設備對象是否表示 獨占設備[out]          PDEVICE_OBJECT  *DeviceObject			// 指向接收指向新創建的 DEVICE_OBJECT 結構的指針的變量的指針
);
*/// 創建設備對象
NTSTATUS ntIoCreate = IoCreateDevice(driverObject, 0, &deviceName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &pDeviceObject);

數據的交互方式

// 設置數據的交互方式
driverObject->Flags |= DO_BUFFERED_IO;
  • 緩存區方式讀寫(DO_BUFFERED_IO):操作系統將應用程序提供緩沖區的數據復制到內核模式下的地址中
  • 直接方式讀寫(DO_DIRECT_IO):操作系統會將用戶模式下的緩沖區鎖住,然后操作系統將這段緩沖區在內核模式地址再次映射一遍,這樣,用戶模式的緩沖區和內核模式的緩沖區指向的是同一區域的物理內存(缺點就是要單獨占用物理頁面)
  • 其他方式讀寫(在調用IoCreateDevice創建設備后對drivceObjcet->Flags既不設置DO_BUFFERED_IO也不設置DO_DIRECT_IO此時就是其它方式):在使用其他方式讀寫設備時,派遣函數直接讀寫應用程序提供的緩沖地址。在驅動程序中,直接操作應用程序的緩沖區是很危險的,只有驅動程序與應用程序運行在相同線程上下文的情況下,才能使用這種方式

IRP的類型

當應用層通過CreateFile,ReadFile,WriteFile,CloseHandle等函數打開,從設備讀取數據,向設備寫入數據,關閉設備的時候,會使操作系統系統產出不同的IRP_CREATE,IPR_MJ_READ,IRP_MJ_WRITE等IRP

其它類型

IRP類型來源
IRP_MJ_DEVICE_CONTROLDeviceControl函數會產生些IRP
IRP_MJ_POWER在操作系統處理電源消息時,產生此IRP
IRP_MJ_SHUTDOWN關閉系統前會產生些IRP

IRP_MJ_DEVICE_CONTROL才是我們Ring3與驅動交互的常規方式

測試代碼

3環應用程序代碼

#include<iostream>
#include<windows.h>#define IN_BUFFER_MAXLENGIT			0x10			// 輸入緩存最大長度
#define OUT_BUFFER_MAXLENGTH		0x10			// 輸出緩存最大長度
// 參數說明:1,設備類型,2,操作碼,3,以什么方式進行訪問,4,訪問權限
#define OPER1 CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) 
#define OPER2 CTL_CODE(FILE_DEVICE_UNKNOWN,0x900,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define SYMBOLICLINK_NAME "\\\\.\\MyTestDriver"HANDLE g_hDriver;BOOL open(const CHAR* pLinkName) {TCHAR szBuffer[10] = { 0 };g_hDriver = CreateFileA(pLinkName,GENERIC_READ|GENERIC_WRITE,0,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);DWORD errorCode = GetLastError();swprintf(szBuffer,sizeof(szBuffer),L"%d:\n",errorCode);if (g_hDriver != INVALID_HANDLE_VALUE)return TRUE;else return FALSE;
}/*
BOOL DeviceIoControl([in]                HANDLE       hDevice,			設備句柄[in]                DWORD        dwIoControlCode,	控制代碼[in, optional]      LPVOID       lpInBuffer,		向0環傳遞的緩沖區的地址[in]                DWORD        nInBufferSize,		緩沖區的大小[out, optional]     LPVOID       lpOutBuffer,		向3還傳遞的緩沖區的地址[in]                DWORD        nOutBufferSize,	緩沖區的大小[out, optional]     LPDWORD      lpBytesReturned,	實際返回的長度(字節數)[in, out, optional] LPOVERLAPPED lpOverlapped		
);
*/BOOL ioControl(DWORD dwIoCode,PVOID InBuffer,DWORD InBuffLen,PVOID OutBuff,DWORD OutBuffLen) { DWORD dw;DeviceIoControl(g_hDriver,dwIoCode,InBuffer,InBuffLen,OutBuff,OutBuffLen,&dw,NULL);return TRUE;
}int main() {DWORD dwInBuffer = 0x11112222;TCHAR szOutBuffer[OUT_BUFFER_MAXLENGTH] = { 0 };// 通過符號鏈接 打開設備if (open(SYMBOLICLINK_NAME)) {printf("open device success\n");}else {printf("open device failed\n");}ioControl(OPER2, &dwInBuffer, IN_BUFFER_MAXLENGIT, szOutBuffer, OUT_BUFFER_MAXLENGTH);CloseHandle(g_hDriver);system("pause");return 0;
} 

0環驅動程序

#include <ntddk.h>#define DEVICE_NAME L"\\Device\\MyDevice"
// Ring3用CreateDevice打開設備時用 \\\\.\\MyTestDriver
#define SYMBOLICLINK_NAME L"\\??\\MyTestDriver"#define OPER1 CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define OPER2 CTL_CODE(FILE_DEVICE_UNKNOWN,0x900,METHOD_BUFFERED,FILE_ANY_ACCESS)// IRP_MJ_CREATE 處理函數
NTSTATUS IrpCreateProc(PDEVICE_OBJECT pDevObj,PIRP pIrp) {DbgPrint("設備創建了...");// 設置返回狀態pIrp->IoStatus.Status = STATUS_SUCCESS;pIrp->IoStatus.Information = 0;IoCompleteRequest(pIrp, IO_NO_INCREMENT);return STATUS_SUCCESS;
}// IRP_MJ_CLOSE 處理函數
NTSTATUS IrpCloseProc(PDEVICE_OBJECT pDevObj, PIRP pIrp) {DbgPrint("設備關閉了...");// 設置返回狀態pIrp->IoStatus.Status = STATUS_SUCCESS;pIrp->IoStatus.Information = 0;IoCompleteRequest(pIrp, IO_NO_INCREMENT);return STATUS_SUCCESS;
}// IRP_MJ_DEVICE_CONTROL 處理函數
NTSTATUS IrpDeviceControlProc(PDEVICE_OBJECT pDevObj, PIRP pIrp) {NTSTATUS stauts = STATUS_INVALID_DEVICE_REQUEST;PIO_STACK_LOCATION pIrpStack;ULONG uIoControlCode;PVOID pIoBuffer;ULONG uInLength;ULONG uOutLength;ULONG uRead;ULONG uWrite;// 設置臨時變量的值uRead = 0;uWrite = 0x12345678;//獲取IRP數據pIrpStack = IoGetCurrentIrpStackLocation(pIrp);//獲取控制碼uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;// 獲取緩沖區地址(輸入和輸出的緩沖區都是一個)pIoBuffer = pIrp->AssociatedIrp.SystemBuffer;// Ring3 發送數據的長度uInLength = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;// Ring0 發送數據的長度uOutLength = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;pIrp->IoStatus.Information = 0;switch (uIoControlCode) {case OPER1:{DbgPrint("調用IRP_MJ_DEVICE_CONTROL —> 1");// 設置返回狀態pIrp->IoStatus.Information = 1;stauts = STATUS_SUCCESS;break;}case OPER2:{DbgPrint("調用IRP_MJ_DEVICE_CONTROL —> 2 接收字節數:%d\n", uInLength);DbgPrint("調用IRP_MJ_DEVICE_CONTROL —> 2 輸出字節數:%d\n", uOutLength);// 讀緩存memcpy(&uRead,pIoBuffer,4);DbgPrint("調用IRP_MJ_DEVICE_CONTROL —> 2 地址:%llx",uRead);// 寫緩存memcpy(pIoBuffer,&uWrite,4);// 設置返回狀態pIrp->IoStatus.Information = 2;stauts = STATUS_SUCCESS;break;}}// 設置返回狀態pIrp->IoStatus.Status = stauts;IoCompleteRequest(pIrp, IO_NO_INCREMENT);return STATUS_SUCCESS;}// 卸載函數
VOID DriverUnload(PDRIVER_OBJECT DriverObject) {DbgPrint("驅動被卸載了\n");
}NTSTATUS DriverEntry(PDRIVER_OBJECT driverObject, PUNICODE_STRING reg_path) {NTSTATUS ntIoCreate = 0;PDEVICE_OBJECT pDeviceObject = NULL;UNICODE_STRING deviceName;UNICODE_STRING symbolicLinkName;// 創建設備名稱RtlInitUnicodeString(&deviceName, L"\\Device\\MyDevice");// 創建設備對象ntIoCreate = IoCreateDevice(driverObject, 0, &deviceName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &pDeviceObject);if (ntIoCreate != STATUS_SUCCESS) {DbgPrint("設備對象創建失敗!\n");return ntIoCreate;}// 設置數據的交互方式driverObject->Flags |= DO_BUFFERED_IO;// 創建符號鏈接名稱(給Ring3訪問)// Ring3用CreateFile打開設備時用 \\\\.\\MyTestDriverRtlInitUnicodeString(&symbolicLinkName, L"\\??\\MyTestDriver");// 創建符號鏈接ntIoCreate = IoCreateSymbolicLink(&symbolicLinkName, &deviceName);if(ntIoCreate != STATUS_SUCCESS) {DbgPrint("符號鏈接創建失敗!\n");	IoDeleteDevice(pDeviceObject);return ntIoCreate;}// 設置派遣函數和卸載函數driverObject->MajorFunction[IRP_MJ_CREATE] = IrpCreateProc;driverObject->MajorFunction[IRP_MJ_CLOSE] = IrpCloseProc;driverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IrpDeviceControlProc;driverObject->DriverUnload = DriverUnload;return STATUS_SUCCESS;
}

演示效果

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/915680.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/915680.shtml
英文地址,請注明出處:http://en.pswp.cn/news/915680.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

ASP.NET Core Web API 內存緩存(IMemoryCache)入門指南

在 Web API 開發中&#xff0c;頻繁訪問數據庫或第三方服務可能會帶來性能瓶頸。為了提升接口響應速度并減輕后端壓力&#xff0c;使用緩存是非常有效的優化手段。本文將帶你快速上手 ASP.NET Core 提供的內存緩存&#xff08;IMemoryCache&#xff09;&#xff0c;無需安裝額外…

Axios Token 設置示例

以下是一個完整的 Axios Token 設置示例&#xff0c;涵蓋全局配置、請求攔截器和單次請求設置三種方式&#xff1a;1. 基礎配置&#xff08;推薦方案&#xff09;javascript復制代碼import axios from axios;// 創建 Axios 實例 const apiClient axios.create({baseURL: https…

Excel數據合并工具:零門檻快速整理

軟件介紹 在數據處理工作中&#xff0c;合并Excel同類數據是一項常見但繁瑣的任務。今天為大家推薦一款專為簡化此類操作設計的工具&#xff0c;它能快速完成工作表內多行同類數據的合并整理&#xff0c;大幅提升數據處理效率。 零門檻操作體驗 相比Excel自帶的數據透視…

深度學習 -- 梯度計算及上下文控制

深度學習 – 梯度計算及上下文控制 文章目錄深度學習 -- 梯度計算及上下文控制一&#xff0c;自動微分1.1 基礎概念1.2 計算梯度1.2.1 計算標量梯度1.2.2 計算向量梯度1.2.3 多標量梯度計算1.2.4 多向量梯度計算二&#xff0c;梯度上下文控制2.1 控制梯度計算2.2 累計梯度2.3 梯…

Redisson RLocalCachedMap 核心參數詳解

&#x1f9d1; 博主簡介&#xff1a;CSDN博客專家&#xff0c;歷代文學網&#xff08;PC端可以訪問&#xff1a;https://literature.sinhy.com/#/?__c1000&#xff0c;移動端可微信小程序搜索“歷代文學”&#xff09;總架構師&#xff0c;15年工作經驗&#xff0c;精通Java編…

【Unity3D實例-功能-移動】角色移動-通過WSAD(Rigidbody方式)

你是否曾夢想在虛擬世界中自由翱翔&#xff0c;像海豚一樣在海洋自由穿梭&#xff0c;或者像宇航員一樣在宇宙中盡情探索&#xff1f;今天&#xff0c;我們就來聊聊如何在Unity中使用Rigidbody來實現角色移動。 廢話不多說&#xff0c;走&#xff0c;讓我們馬上來一探究竟&…

Vue接口平臺學習十一——業務流測試

效果圖及簡單說明 與之前的用例列表相似布局&#xff0c;也分左右&#xff0c;左邊用于顯示測試流程的名稱&#xff0c;右邊用于顯示流程相關信息。 左側點擊添加&#xff0c;直接增加一個新的業務流。 右側是點擊的業務流詳情&#xff0c;展示名稱&#xff0c;名稱的編輯保存&…

碳化硅缺陷分類與原因

01一、碳化硅晶體材料中的缺陷到底是什么&#xff1f;碳化硅晶體材料中的缺陷是指在晶體生長、加工或使用過程中出現的不完美結構。這些缺陷可能表現為晶體內部的裂紋、表面的凹坑、原子排列的錯誤等。雖然缺陷看起來微不足道&#xff0c;但它們卻可能對晶體的電學、熱學和機械…

Jenkins 實現項目的構建和發布

作者&#xff1a;小凱 沉淀、分享、成長&#xff0c;讓自己和他人都能有所收獲&#xff01; 本文的宗旨在于通過簡單干凈實踐的方式教會讀者&#xff0c;如何在 Docker 中部署 Jenkins&#xff0c;并通過 Jenkins 完成對項目的打包構建并在 Docker 容器中部署。 Jenkins 的主要…

Django接口自動化平臺實現(三)

3.2 后臺 admin 添加數據 1&#xff09;注冊模型類到 admin&#xff1a; 1 from django.contrib import admin2 from . import models3 4 5 class ProjectAdmin(admin.ModelAdmin):6 list_display ("id", "name", "proj_owner", "tes…

CentOS 7 配置環境變量常見的4種方式

?博客主頁&#xff1a; https://blog.csdn.net/m0_63815035?typeblog &#x1f497;《博客內容》&#xff1a;.NET、Java.測試開發、Python、Android、Go、Node、Android前端小程序等相關領域知識 &#x1f4e2;博客專欄&#xff1a; https://blog.csdn.net/m0_63815035/cat…

k8s:手動創建PV,解決postgis數據庫本地永久存儲

1.離線環境CPU:Hygon C86 7285 32-core Processor 操作系統&#xff1a;麒麟操作系統 containerd&#xff1a;1.7.27 Kubernetes:1.26.12 KubeSphere:4.1.2 kubekey&#xff1a;3.1.10 Harbor:2.13.1 Postgis:17-3.52創建StorageClass2.1創建 apiVersion: storage.k8s.io/v1kin…

谷歌瀏覽器Chrome的多用戶配置文件功能

谷歌瀏覽器Chrome的多用戶配置文件功能允許在同一設備上創建多個獨立賬戶,每個賬戶擁有完全隔離的瀏覽數據(如書簽、歷史記錄、擴展、Cookies等),非常適合工作/生活賬戶分離、家庭共享或臨時多賬號登錄場景。 如何使用Chrome的多用戶配置文件功能? 一、創建與切換用戶 1.…

傲軟錄屏 專業高清錄屏軟件 ApowerREC Pro 下載與保姆級安裝教程!!

小編今天分享一款強大的電腦屏幕錄像軟件 傲軟錄屏 ApowerREC&#xff0c;能夠幫助用戶錄制中電腦桌面屏幕上的所有內容&#xff0c;包括畫面和聲音&#xff0c;支持全屏錄制、區域錄制、畫中畫以及攝像頭錄制等多種視頻錄制模式&#xff0c;此外&#xff0c;還支持計劃任務錄制…

【計算機網絡】MAC地址與IP地址:網絡通信的雙重身份標識

在計算機網絡領域&#xff0c;MAC地址與IP地址是兩個核心概念&#xff0c;它們共同構成了數據傳輸的基礎。理解二者的區別與聯系&#xff0c;對于網絡配置、故障排查及安全管理至關重要。 一、基本概念 1. MAC地址&#xff08;物理地址&#xff09; 定義&#xff1a;固化在網絡…

如何用keepAlive實現標簽頁緩存

什么是KeepAlive首先&#xff0c;要明確所說的是TCP的 KeepAlive 還是HTTP的 Keep-Alive。TCP的KeepAlive和HTTP的Keep-Alive是完全不同的概念&#xff0c;不能混為一談。實際上HTTP的KeepAlive寫法是Keep-Alive&#xff0c;跟TCP的KeepAlive寫法上也有不同。TCP的KeepAliveTCP…

數據庫隔離級別

隔離級別決定了事務之間的可見性規則&#xff0c;直接影響數據庫的并發性能和數據一致性。SQL 標準定義了 4 種隔離級別&#xff0c;從低到高依次為&#xff1a;讀未提交→讀已提交→可重復讀→串行化。隔離級別越高&#xff0c;對并發問題的解決能力越強&#xff0c;但對性能的…

基于Python flask的電影數據分析及可視化系統的設計與實現,可視化內容很豐富

摘要&#xff1a;基于Python的電影數據分析及可視化系統是一個應用于電影市場的數據分析平臺&#xff0c;旨在為廣大電影愛好者提供更準確、更詳細、更實用的電影數據。數據分析部分主要是對來自貓眼電影網站上的數據進行清洗、分類處理、存儲等步驟&#xff0c;數據可視化則是…

TCP通訊開發注意事項及常見問題解析

文章目錄一、TCP協議特性與開發挑戰二、粘包與拆包問題深度解析1. 成因原理2. 典型場景與實例驗證3. 系統化解決方案接收方每次讀取10字節2. 丟包檢測與驗證工具3. 工程化解決方案四、連接管理關鍵實踐1. 超時機制設計2. TIME_WAIT狀態優化3. 異常處理最佳實踐五、高性能TCP開發…

2021 RoboCom 世界機器人開發者大賽-本科組(復賽)解題報告 | 珂學家

前言 題解 睿抗機器人開發者大賽CAIP-編程技能賽-歷年真題 匯總 2021 RoboCom 世界機器人開發者大賽-本科組&#xff08;復賽&#xff09;解題報告 感覺這個T1特別有意思&#xff0c;非典型題&#xff0c;著重推演下結論。 T2是一道玄學題&#xff0c;但是涉及一些優化技巧…