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);//第三步,完成IRPpIrp->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 iopDeviceObject->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\GroupOrderListNULL,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; }總結
- 上一篇: WIN10 关闭驱动签名
- 下一篇: 内核驱动漏洞与攻击预防--by MJ00