【系統安全003】NT驅動框架
介紹
這是一份NT驅動框架的原始碼,包含了驅動和載入器,驅動編譯環境是 vs2019+wdk10,載入器編譯環境是vs2010。下面給出在 win10 上的執行結果:
驅動程式碼
#include <ntddk.h>
#define DEVICE_NAME L"\\device\\ntdrv"
#define LINK_NAME L"\\dosdevices\\ntdrv"
#define IOCTRL_BASE 0x800
#define MYIOCTRL_CODE(i) \
CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTRL_BASE+i, METHOD_BUFFERED,FILE_ANY_ACCESS)
#define CTL_HELLO MYIOCTRL_CODE(0)
#define CTL_PRINT MYIOCTRL_CODE(1)
#define CTL_BYE MYIOCTRL_CODE(2)
NTSTATUS DispatchCommon(PDEVICE_OBJECT pObject, PIRP pIrp)
{
pIrp->IoStatus.Status = STATUS_SUCCESS; // 返回給應用層
pIrp->IoStatus.Information = 0; // 讀寫位元組數
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_SUCCESS; // 返回給核心層IO管理器
}
NTSTATUS DispatchCreate(PDEVICE_OBJECT pObject, PIRP pIrp)
{
pIrp->IoStatus.Status = STATUS_SUCCESS;
pIrp->IoStatus.Information = 0;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS DispatchRead(PDEVICE_OBJECT pObject, PIRP pIrp)
{
PVOID pReadBuffer = NULL;
ULONG uReadLength = 0;
PIO_STACK_LOCATION pStack = NULL;
ULONG uMin = 0;
ULONG uHelloStr = 0;
uHelloStr = (wcslen(L"wchar msg from R0") + 1) * sizeof(WCHAR);
//第一步,拿到快取的地址和長度
//從頭部拿快取地址
pReadBuffer = pIrp->AssociatedIrp.SystemBuffer;
//從棧上拿快取長度
pStack = IoGetCurrentIrpStackLocation(pIrp);
uReadLength = pStack->Parameters.Read.Length;
//第二步:讀,寫等操作
uMin = uReadLength > uHelloStr ? uHelloStr : uReadLength;
RtlCopyMemory(pReadBuffer, L"wchar msg from R0", uMin);
//第三步,完成IRP
pIrp->IoStatus.Status = STATUS_SUCCESS;
pIrp->IoStatus.Information = uMin;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS DispatchWrite(PDEVICE_OBJECT pObject, PIRP pIrp)
{
PVOID pWriteBuff = NULL;
ULONG uWriteLength = 0;
PIO_STACK_LOCATION pStack = NULL;
PVOID pBuffer = NULL;
pWriteBuff = pIrp->AssociatedIrp.SystemBuffer;
pStack = IoGetCurrentIrpStackLocation(pIrp);
uWriteLength = pStack->Parameters.Write.Length;
// tag 的作用是除錯時定位記憶體洩漏的,反過來寫是方便小端儲存觀察
pBuffer = ExAllocatePoolWithTag(PagedPool, uWriteLength, 'TSET');
if (pBuffer == NULL)
{
pIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
pIrp->IoStatus.Information = 0;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_INSUFFICIENT_RESOURCES;
}
memset(pBuffer, 0, uWriteLength);
RtlCopyMemory(pBuffer, pWriteBuff, uWriteLength);
DbgPrint("%ws\n", (WCHAR*)pBuffer); // 列印一下3環傳進來的字串
ExFreePool(pBuffer);
pBuffer = NULL;
pIrp->IoStatus.Status = STATUS_SUCCESS;
pIrp->IoStatus.Information = uWriteLength;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS DispatchIoctrl(PDEVICE_OBJECT pObject, PIRP pIrp)
{
ULONG uIoctrlCode = 0;
PVOID pInputBuff = NULL;
PVOID pOutputBuff = NULL;
ULONG uInputLength = 0;
ULONG uOutputLength = 0;
PIO_STACK_LOCATION pStack = NULL;
pInputBuff = pOutputBuff = pIrp->AssociatedIrp.SystemBuffer;
pStack = IoGetCurrentIrpStackLocation(pIrp);
uInputLength = pStack->Parameters.DeviceIoControl.InputBufferLength;
uOutputLength = pStack->Parameters.DeviceIoControl.OutputBufferLength;
uIoctrlCode = pStack->Parameters.DeviceIoControl.IoControlCode;
switch (uIoctrlCode)
{
case CTL_HELLO:
DbgPrint("Hello iocontrol\n");
break;
case CTL_PRINT:
DbgPrint("%ws\n", (WCHAR*)pInputBuff);
break;
case CTL_BYE:
DbgPrint("Goodbye iocontrol\n");
break;
default:
DbgPrint("Unknown iocontrol\n");
}
pIrp->IoStatus.Status = STATUS_SUCCESS;
pIrp->IoStatus.Information = 0;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS DispatchClean(PDEVICE_OBJECT pObject, PIRP pIrp)
{
pIrp->IoStatus.Status = STATUS_SUCCESS;
pIrp->IoStatus.Information = 0;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS DispatchClose(PDEVICE_OBJECT pObject, PIRP pIrp)
{
pIrp->IoStatus.Status = STATUS_SUCCESS;
pIrp->IoStatus.Information = 0;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
UNICODE_STRING uLinkName = { 0 };
RtlInitUnicodeString(&uLinkName, LINK_NAME);
IoDeleteSymbolicLink(&uLinkName);
IoDeleteDevice(pDriverObject->DeviceObject);
DbgPrint("Driver unloaded\n");
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject,
PUNICODE_STRING pRegPath)
{
UNICODE_STRING uDeviceName = { 0 };
UNICODE_STRING uLinkName = { 0 };
NTSTATUS ntStatus = 0;
PDEVICE_OBJECT pDeviceObject = NULL;
ULONG i = 0;
DbgPrint("Driver load begin\n");
RtlInitUnicodeString(&uDeviceName, DEVICE_NAME);
RtlInitUnicodeString(&uLinkName, LINK_NAME);
ntStatus = IoCreateDevice(pDriverObject,
0, &uDeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDeviceObject);
if (!NT_SUCCESS(ntStatus))
{
DbgPrint("IoCreateDevice failed:%x", ntStatus);
return ntStatus;
}
//DO_BUFFERED_IO規定R3和R0之間read和write通訊的方式:
//1,buffered io
//2,direct io
//3,neither io
pDeviceObject->Flags |= DO_BUFFERED_IO;
ntStatus = IoCreateSymbolicLink(&uLinkName, &uDeviceName);
if (!NT_SUCCESS(ntStatus))
{
IoDeleteDevice(pDeviceObject);
DbgPrint("IoCreateSymbolicLink failed:%x\n", ntStatus);
return ntStatus;
}
for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION + 1; i++)
{
pDriverObject->MajorFunction[i] = DispatchCommon;
}
pDriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
pDriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead;
pDriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchWrite;
pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctrl;
pDriverObject->MajorFunction[IRP_MJ_CLEANUP] = DispatchClean;
pDriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
pDriverObject->DriverUnload = DriverUnload;
DbgPrint("Driver load ok!\n");
return STATUS_SUCCESS;
}
載入程式
#include <windows.h>
#include <winsvc.h>
#include <conio.h>
#include <stdio.h>
#include <winioctl.h>
#define DRIVER_NAME "ntdrv"
#define DRIVER_PATH ".\\ntdrv.sys"
#define LINK_NAME "\\\\.\\ntdrv"
#define IOCTRL_BASE 0x800
#define MYIOCTRL_CODE(i) \
CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTRL_BASE+i, METHOD_BUFFERED,FILE_ANY_ACCESS)
#define CTL_HELLO MYIOCTRL_CODE(0)
#define CTL_PRINT MYIOCTRL_CODE(1)
#define CTL_BYE MYIOCTRL_CODE(2)
//裝載NT驅動程式
BOOL LoadDriver(const char *lpszDriverName, const char *lpszDriverPath)
{
char szDriverImagePath[256] = { 0 };
//得到完整的驅動路徑
GetFullPathNameA(lpszDriverPath, 256, szDriverImagePath, NULL);
BOOL bRet = FALSE;
SC_HANDLE hServiceMgr = NULL;//SCM管理器的控制程式碼
SC_HANDLE hServiceDDK = NULL;//NT驅動程式的服務控制程式碼
//開啟服務控制管理器
hServiceMgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (hServiceMgr == NULL)
{
//OpenSCManager失敗
printf("OpenSCManager() Failed %d ! \n", GetLastError());
bRet = FALSE;
goto BeforeLeave;
}
else
{
OpenSCManager成功
printf("OpenSCManager() ok ! \n");
}
//建立驅動所對應的服務
hServiceDDK = CreateServiceA(hServiceMgr,
lpszDriverName, //驅動程式的在登錄檔中的名字
lpszDriverName, // 登錄檔驅動程式的 DisplayName 值
SERVICE_ALL_ACCESS, // 載入驅動程式的訪問許可權
SERVICE_KERNEL_DRIVER,// 表示載入的服務是驅動程式
SERVICE_DEMAND_START, // 登錄檔驅動程式的 Start 值
SERVICE_ERROR_IGNORE, // 登錄檔驅動程式的 ErrorControl 值
szDriverImagePath, // 登錄檔驅動程式的 ImagePath 值
NULL, //GroupOrder HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\GroupOrderList
NULL,
NULL,
NULL,
NULL);
DWORD dwRtn;
//判斷服務是否失敗
if (hServiceDDK == NULL)
{
dwRtn = GetLastError();
if (dwRtn != ERROR_IO_PENDING && dwRtn != ERROR_SERVICE_EXISTS)
{
//由於其他原因建立服務失敗
printf("CrateService() Failed %d ! \n", dwRtn);
bRet = FALSE;
goto BeforeLeave;
}
else
{
//服務建立失敗,是由於服務已經創立過
printf("CrateService() Failed Service is ERROR_IO_PENDING or ERROR_SERVICE_EXISTS! \n");
}
// 驅動程式已經載入,只需要開啟
hServiceDDK = OpenServiceA(hServiceMgr, lpszDriverName, SERVICE_ALL_ACCESS);
if (hServiceDDK == NULL)
{
//如果開啟服務也失敗,則意味錯誤
dwRtn = GetLastError();
printf("OpenService() Failed %d ! \n", dwRtn);
bRet = FALSE;
goto BeforeLeave;
}
else
{
printf("OpenService() ok ! \n");
}
}
else
{
printf("CrateService() ok ! \n");
}
//開啟此項服務
bRet = StartService(hServiceDDK, 0, NULL);
if (!bRet)
{
DWORD dwRtn = GetLastError();
if (dwRtn != ERROR_IO_PENDING && dwRtn != ERROR_SERVICE_ALREADY_RUNNING)
{
printf("StartService() Failed %d ! \n", dwRtn);
bRet = FALSE;
goto BeforeLeave;
}
else
{
if (dwRtn == ERROR_IO_PENDING)
{
//裝置被掛住
printf("StartService() Failed ERROR_IO_PENDING ! \n");
bRet = FALSE;
goto BeforeLeave;
}
else
{
//服務已經開啟
printf("StartService() Failed ERROR_SERVICE_ALREADY_RUNNING ! \n");
bRet = TRUE;
goto BeforeLeave;
}
}
}
bRet = TRUE;
//離開前關閉控制程式碼
BeforeLeave:
if (hServiceDDK)
{
CloseServiceHandle(hServiceDDK);
}
if (hServiceMgr)
{
CloseServiceHandle(hServiceMgr);
}
return bRet;
}
//解除安裝驅動程式
BOOL UnloadDriver(char *szSvrName)
{
BOOL bRet = FALSE;
SC_HANDLE hServiceMgr = NULL;//SCM管理器的控制程式碼
SC_HANDLE hServiceDDK = NULL;//NT驅動程式的服務控制程式碼
SERVICE_STATUS SvrSta;
//開啟SCM管理器
hServiceMgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (hServiceMgr == NULL)
{
//帶開SCM管理器失敗
printf("OpenSCManager() Failed %d ! \n", GetLastError());
bRet = FALSE;
goto BeforeLeave;
}
else
{
//帶開SCM管理器失敗成功
printf("OpenSCManager() ok ! \n");
}
//開啟驅動所對應的服務
hServiceDDK = OpenServiceA(hServiceMgr, szSvrName, SERVICE_ALL_ACCESS);
if (hServiceDDK == NULL)
{
//開啟驅動所對應的服務失敗
printf("OpenService() Failed %d ! \n", GetLastError());
bRet = FALSE;
goto BeforeLeave;
}
else
{
printf("OpenService() ok ! \n");
}
//停止驅動程式,如果停止失敗,只有重新啟動才能,再動態載入。
if (!ControlService(hServiceDDK, SERVICE_CONTROL_STOP, &SvrSta))
{
printf("ControlService() Failed %d !\n", GetLastError());
}
else
{
//開啟驅動所對應的失敗
printf("ControlService() ok !\n");
}
//動態解除安裝驅動程式。
if (!DeleteService(hServiceDDK))
{
//解除安裝失敗
printf("DeleteSrevice() Failed %d !\n", GetLastError());
}
else
{
//解除安裝成功
printf("DelServer:deleteSrevice() ok !\n");
}
bRet = TRUE;
BeforeLeave:
//離開前關閉開啟的控制程式碼
if (hServiceDDK)
{
CloseServiceHandle(hServiceDDK);
}
if (hServiceMgr)
{
CloseServiceHandle(hServiceMgr);
}
return bRet;
}
void TestDriver()
{
//測試驅動程式
HANDLE hDevice = CreateFileA(LINK_NAME,
GENERIC_WRITE | GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
0,
NULL);
if (hDevice != INVALID_HANDLE_VALUE)
{
printf("Create Device ok ! \n");
}
else
{
printf("Create Device Failed %d ! \n", GetLastError());
return;
}
WCHAR bufRead[1024] = { 0 };
WCHAR bufWrite[1024] = L"wchar msg from R3...";
DWORD dwRead = 0;
DWORD dwWrite = 0;
ReadFile(hDevice, bufRead, 1024, &dwRead, NULL);
wprintf(L"Read done!:%s\n", bufRead);
printf("Please press any key to write\n");
_getch();
WriteFile(hDevice, bufWrite, (wcslen(bufWrite) + 1) * sizeof(WCHAR), &dwWrite, NULL);
printf("Write done!\n");
printf("Please press any key to deviceiocontrol\n");
_getch();
char bufInput[1024] = "Hello, world";
char bufOutput[1024] = { 0 };
DWORD dwRet = 0;
WCHAR bufFileInput[1024] = L"R3 msg send by iocontrol!";
printf("Please press any key to send PRINT\n");
_getch();
DeviceIoControl(hDevice,
CTL_PRINT,
bufFileInput,
sizeof(bufFileInput),
bufOutput,
sizeof(bufOutput),
&dwRet,
NULL);
printf("Please press any key to send HELLO\n");
_getch();
DeviceIoControl(hDevice,
CTL_HELLO,
NULL,
0,
NULL,
0,
&dwRet,
NULL);
printf("Please press any key to send BYE\n");
_getch();
DeviceIoControl(hDevice,
CTL_BYE,
NULL,
0,
NULL,
0,
&dwRet,
NULL);
printf("DeviceIoControl done!\n");
CloseHandle(hDevice);
}
int main(int argc, char *argv[])
{
//載入驅動
BOOL bRet = LoadDriver(DRIVER_NAME, DRIVER_PATH);
if (!bRet)
{
printf("LoadNTDriver error\n");
return 0;
}
//載入成功
printf("press any key to create device!\n");
_getch();
TestDriver();
//這時候你可以通過登錄檔,或其他檢視符號連線的軟體驗證。
printf("press any key to stop service!\n");
_getch();
//解除安裝驅動
bRet = UnloadDriver(DRIVER_NAME);
if (!bRet)
{
printf("UnloadNTDriver error\n");
return 0;
}
return 0;
}
相關文章
- 載入NT驅動的類 C++C++
- 新字元驅動框架驅動LED字元框架
- 字元驅動框架字元框架
- golang驅動系統印表機Golang
- SPI驅動框架一框架
- 字元裝置驅動 —— 字元裝置驅動框架字元框架
- 驅動Driver-input子系統
- Debian系統顯示卡驅動從官方驅動回退到Nouveau
- 作業系統——裝置驅動和檔案系統作業系統
- Linux驅動之GPIO子系統和pinctrl子系統Linux
- 驅動Driver-Pinctrl-GPIO子系統
- 系統設計思想之Domain驅動AI
- 無伺服器事件驅動系統伺服器事件
- 【linux】驅動-11-gpio子系統Linux
- 【linux】驅動-10-pinctrl子系統Linux
- win10系統如何關閉自動更新驅動 win10怎麼關閉系統自動更新驅動Win10
- win10系統odbc驅動怎麼安裝_win10系統odbc驅動如何安裝Win10
- 無作業系統時的裝置驅動和有作業系統時的裝置驅動作業系統
- 分享一個LCD驅動框架框架
- ESP32-LVGL驅動框架框架
- win10系統怎麼更新MSI驅動程式_win10系統更新MSI驅動程式的方法Win10
- 利用驅動精靈更新win10系統硬體驅動的方法Win10
- 【linux】驅動-5-驅動框架分層分離&實戰Linux框架
- win10系統怎麼更新驅動 win10更新驅動的方法Win10
- win10系統驅動崩潰怎麼辦_win10系統驅動經常崩潰解決方法Win10
- windows10系統如何回退網路卡驅動Windows
- 開放世界:系統驅動型的遊戲遊戲
- win10系統下如何更新驅動程式Win10
- win10 自帶驅動的嗎_win10系統是否自帶驅動Win10
- win7系統怎麼安裝ahci驅動?win7系統安裝ahci驅動的詳細步驟Win7
- win10如何關閉系統驅動更新 怎麼禁止win10自動更新驅動Win10
- win10 anci驅動如何安裝_win10系統anci驅動安裝教程Win10
- Linux驅動開發: Ubuntu(PC機)系統上編譯驅動並載入測試LinuxUbuntu編譯
- win10系統怎麼使用自帶程式對驅動更新_怎樣在Win10系統下更新驅動程式Win10
- 【原創】Linux PCI驅動框架分析(二)Linux框架
- 【原創】Linux PCI驅動框架分析(一)Linux框架
- MTK eCos系統的有線驅動收包流程
- 事件驅動系統中不同型別的事件 - frankdejonge事件型別