加载windows驱动的几种方式

本文介绍了在Windows操作系统中加载驱动的三种方法:1)使用OpenSCManagerCreateServiceA等API;2)手动修改注册表并调用ZwLoadDriver;3)通过ZwSetSystemInformation函数。示例代码详细展示了如何实现这些操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 OpenSCManager CreateServiceA等方式。这种例子很多,此处不再赘述。
例子代码:



#pragma once

#include <windows.h>
#include <winsvc.h>
#include <conio.h>
#include <stdio.h>

BOOL LoadNTDriver(WCHAR* lpszDriverName, WCHAR* lpszDriverPath, int servicetype, int boottype, WCHAR* groupname);

#define DRIVER_NAME L"veracrypt"

#define DRIVER_PATH L"D:\\Program Files\\VeraCrypt\\VeraCrypt\\veracrypt.sys"


BOOL LoadNTDriver(WCHAR* lpszDriverName, WCHAR* lpszDriverPath, int servicetype, int boottype, WCHAR* groupname)
{
	WCHAR szshow[256];
	WCHAR szDriverImagePath[256];
	//得到完整的驱动路径
	GetFullPathNameW(lpszDriverPath, 256, szDriverImagePath, NULL);

	char szfullpath[1024] = { 0 };
	int len = WideCharToMultiByte(CP_ACP, 0, szDriverImagePath, -1, szfullpath, sizeof(szfullpath), 0, 0);
	szfullpath[len] = 0;
	printf("full path:%s\r\n", szfullpath);

	BOOL bRet = FALSE;

	SC_HANDLE hServiceMgr = NULL;
	SC_HANDLE hServiceDDK = NULL;


	hServiceMgr = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);

	if (hServiceMgr == NULL)
	{
		printf("OpenSCManager() Faild %d ! \n", GetLastError());
		bRet = FALSE;
		goto BeforeLeave;
	}
	else
	{
		printf("OpenSCManager() ok ! \n");
	}

	//创建驱动所对应的服务
	hServiceDDK = CreateServiceW(hServiceMgr,
		lpszDriverName, //驱动程序的在注册表中的名字
		lpszDriverName, // 注册表驱动程序的 DisplayName 值
		SERVICE_ALL_ACCESS, // 加载驱动程序的访问权限
		servicetype,
		//SERVICE_KERNEL_DRIVER,// 表示加载的服务是驱动程序
		boottype,
		//SERVICE_AUTO_START, // 注册表驱动程序的 Start 值
		SERVICE_ERROR_NORMAL, // 注册表驱动程序的 ErrorControl 值
		szDriverImagePath, // 注册表驱动程序的 ImagePath 值
		groupname,
		NULL,
		NULL,
		NULL,
		NULL);

	DWORD dwRtn;
	//判断服务是否失败
	if (hServiceDDK == NULL)
	{
		dwRtn = GetLastError();
		if (dwRtn != ERROR_IO_PENDING && dwRtn != ERROR_SERVICE_EXISTS)
		{
			//由于其他原因创建服务失败
			printf("CreateServiceW() Faild %d ! \n", dwRtn);

			wsprintfW(szshow, L"CreateServiceW() Faild %d!driver name:%ws,path:%ws,service type:%d,boot:%d\n",
				dwRtn, lpszDriverName, szDriverImagePath, servicetype, boottype);
			MessageBoxW(0, szshow, szshow, MB_OK);

			bRet = FALSE;
			goto BeforeLeave;
		}
		else
		{
			//服务创建失败,是由于服务已经创立过
			printf("CreateServiceW() Faild Service is ERROR_IO_PENDING or ERROR_SERVICE_EXISTS! \n");
		}

		// 驱动程序已经加载,只需要打开
		hServiceDDK = OpenServiceW(hServiceMgr, lpszDriverName, SERVICE_ALL_ACCESS);
		if (hServiceDDK == NULL)
		{
			//如果打开服务也失败,则意味错误
			dwRtn = GetLastError();
			printf("OpenService() Faild %d ! \n", dwRtn);

			wsprintfW(szshow, L"OpenService() Faild %d ! \n", dwRtn);
			MessageBoxW(0, szshow, szshow, MB_OK);

			bRet = FALSE;
			goto BeforeLeave;
		}
		else
		{
			printf("OpenService() ok ! \n");
		}
	}
	else
	{
		printf("CreateServiceW() ok ! \n");
	}

	//开启此项服务
	bRet = StartServiceW(hServiceDDK, 0, 0);
	if (!bRet)
	{
		DWORD dwRtn = GetLastError();
		if (dwRtn != ERROR_IO_PENDING && dwRtn != ERROR_SERVICE_ALREADY_RUNNING)
		{
			wsprintfW(szshow, L"StartService() Faild %d ! \n", dwRtn);
			MessageBoxW(0, szshow, szshow, MB_OK);

			bRet = FALSE;
			goto BeforeLeave;
		}
		else
		{
			if (dwRtn == ERROR_IO_PENDING)
			{
				//设备被挂住
				printf("StartService() Faild ERROR_IO_PENDING ! \n");
				bRet = FALSE;
				goto BeforeLeave;
			}
			else
			{
				//服务已经开启
				printf("StartService() Faild ERROR_SERVICE_ALREADY_RUNNING ! \n");
				bRet = TRUE;
				goto BeforeLeave;
			}
		}
	}
	bRet = TRUE;
	//离开前关闭句柄
BeforeLeave:
	if (hServiceDDK)
	{
		CloseServiceHandle(hServiceDDK);
	}
	if (hServiceMgr)
	{
		CloseServiceHandle(hServiceMgr);
	}
	return bRet;
}

//卸载驱动程序
BOOL UnloadNTDriver(WCHAR* szSvrName)
{
	BOOL bRet = FALSE;
	SC_HANDLE hServiceMgr = NULL;//SCM管理器的句柄
	SC_HANDLE hServiceDDK = NULL;//NT驱动程序的服务句柄
	SERVICE_STATUS SvrSta;
	//打开SCM管理器
	hServiceMgr = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
	if (hServiceMgr == NULL)
	{
		//带开SCM管理器失败
		printf("OpenSCManager() Faild %d ! \n", GetLastError());
		bRet = FALSE;
		goto BeforeLeave;
	}
	else
	{
		//带开SCM管理器失败成功
		printf("OpenSCManager() ok ! \n");
	}
	//打开驱动所对应的服务
	hServiceDDK = OpenServiceW(hServiceMgr, szSvrName, SERVICE_ALL_ACCESS);

	if (hServiceDDK == NULL)
	{
		//打开驱动所对应的服务失败
		printf("OpenService() Faild %d ! \n", GetLastError());
		bRet = FALSE;
		goto BeforeLeave;
	}
	else
	{
		printf("OpenService() ok ! \n");
	}
	//停止驱动程序,如果停止失败,只有重新启动才能,再动态加载。
	if (!ControlService(hServiceDDK, SERVICE_CONTROL_STOP, &SvrSta))
	{
		printf("ControlService() Faild %d !\n", GetLastError());
	}
	else
	{
		//打开驱动所对应的失败
		printf("ControlService() ok !\n");
	}
	//动态卸载驱动程序。
	if (!DeleteService(hServiceDDK))
	{
		//卸载失败
		printf("DeleteSrevice() Faild %d !\n", GetLastError());
	}
	else
	{
		//卸载成功
		printf("DelServer:eleteSrevice() ok !\n");
	}
	bRet = TRUE;
BeforeLeave:
	//离开前关闭打开的句柄
	if (hServiceDDK)
	{
		CloseServiceHandle(hServiceDDK);
	}
	if (hServiceMgr)
	{
		CloseServiceHandle(hServiceMgr);
	}
	return bRet;
}

void TestDriver()
{
	//测试驱动程序
	HANDLE hDevice = CreateFileA("\\\\.\\HelloDDK",
		GENERIC_WRITE | GENERIC_READ,
		0,
		NULL,
		OPEN_EXISTING,
		0,
		NULL);
	if (hDevice != INVALID_HANDLE_VALUE)
	{
		printf("Create Device ok ! \n");
	}
	else
	{
		printf("Create Device faild %d ! \n", GetLastError());
	}
	CloseHandle(hDevice);
}

int main(int argc, char* argv[])
{
	if (argc < 3) {
		return FALSE;
	}

	wchar_t drvname[1024] = { 0 };
	wchar_t drvpath[1024] = { 0 };
	MultiByteToWideChar(CP_ACP, 0, argv[1], -1, drvname, sizeof(drvname)/2);
	MultiByteToWideChar(CP_ACP, 0, argv[2], -1, drvpath, sizeof(drvpath)/2);
	//加载驱动
	BOOL bRet = LoadNTDriver(drvname, drvpath, SERVICE_KERNEL_DRIVER, SERVICE_AUTO_START, L"");
	if (!bRet)
	{
		printf("LoadNTDriver error\n");
		return 0;
	}
	//加载成功
	return 0;

	printf("press any to create device!\n");
	_getch();

	TestDriver();

	//这时候你可以通过注册表,或其他查看符号连接的软件验证。
	printf("press any to unload the driver!\n");
	_getch();

	//卸载驱动
	UnloadNTDriver(DRIVER_NAME);
	if (!bRet)
	{
		printf("UnloadNTDriver error\n");
		return 0;
	}

	return 0;
}

2 手动修改注册表和调用ZwLoadDriver

代码例子:

#include <windows.h>
#include <stdio.h>

typedef struct _LSA_UNICODE_STRING {
	USHORT Length;
	USHORT MaximumLength;
	PVOID Buffer;
} LSA_UNICODE_STRING, * PLSA_UNICODE_STRING;

typedef LSA_UNICODE_STRING UNICODE_STRING, * PUNICODE_STRING;

// 申明ntdll中使用的函数
typedef DWORD(CALLBACK* RTLANSISTRINGTOUNICODESTRING)(PVOID, PVOID, DWORD);
RTLANSISTRINGTOUNICODESTRING lpRtlAnsiStringToUnicodeString;
typedef DWORD(CALLBACK* RTLFREEUNICODESTRING)(PVOID);
RTLFREEUNICODESTRING RtlFreeUnicodeString;
typedef DWORD(CALLBACK* ZWLOADDRIVER)(PVOID);
ZWLOADDRIVER ZwLoadDriver;

int LoadDriver(char* szDrvName, char* szDrvPath)
{
	//修改注册表启动驱动程序
	char szSubKey[200], szDrvFullPath[256];
	LSA_UNICODE_STRING buf1;
	LSA_UNICODE_STRING buf2;
	int iBuffLen;
	HKEY hkResult;
	char Data[4];
	DWORD dwOK;
	iBuffLen = sprintf(szSubKey, "System\\CurrentControlSet\\Services\\%s", szDrvName);
	szSubKey[iBuffLen] = 0;
	dwOK = RegCreateKeyA(HKEY_LOCAL_MACHINE, szSubKey, &hkResult);
	if (dwOK != ERROR_SUCCESS)
		return false;
	Data[0] = 1;
	Data[1] = 0;
	Data[2] = 0;
	Data[3] = 0;
	dwOK = RegSetValueExA(hkResult, "Type", 0, 4, (const unsigned char*)Data, 4);
	dwOK = RegSetValueExA(hkResult, "ErrorControl", 0, 4, (const unsigned char*)Data, 4);
	dwOK = RegSetValueExA(hkResult, "Start", 0, 4, (const unsigned char*)Data, 4);
	GetFullPathNameA(szDrvPath, 256, szDrvFullPath, NULL);
	printf("Loading driver: %s\r\n", szDrvFullPath);
	iBuffLen = sprintf(szSubKey, "\\??\\%s", szDrvFullPath);
	szSubKey[iBuffLen] = 0;
	dwOK = RegSetValueExA(hkResult, "ImagePath", 0, 1, (const unsigned char*)szSubKey, iBuffLen);
	RegCloseKey(hkResult);
	iBuffLen = sprintf(szSubKey, "\\Registry\\Machine\\System\\CurrentControlSet\\Services\\%s", szDrvName);
	szSubKey[iBuffLen] = 0;
	buf2.Buffer = (PVOID)szSubKey;
	buf2.Length = iBuffLen;
	lpRtlAnsiStringToUnicodeString(&buf1, &buf2, 1);
	//加载驱动程序
	dwOK = ZwLoadDriver(&buf1);
	RtlFreeUnicodeString(&buf1);
	iBuffLen = sprintf(szSubKey, "%s%s\\Enum", "System\\CurrentControlSet\\Services\\", szDrvName);
	szSubKey[iBuffLen] = 0;
	//删除注册表项
	RegDeleteKeyA(HKEY_LOCAL_MACHINE, szSubKey);
	iBuffLen = sprintf(szSubKey, "%s%s\\Security", "System\\CurrentControlSet\\Services\\", szDrvName);
	szSubKey[iBuffLen] = 0;
	RegDeleteKeyA(HKEY_LOCAL_MACHINE, szSubKey);
	iBuffLen = sprintf(szSubKey, "%s%s", "System\\CurrentControlSet\\Services\\", szDrvName);
	szSubKey[iBuffLen] = 0;
	RegDeleteKeyA(HKEY_LOCAL_MACHINE, szSubKey);
	iBuffLen = sprintf(szSubKey, "\\\\.\\%s", szDrvName);
	szSubKey[iBuffLen] = 0;
	return true;
}

int main_test2(int argc, char* argv[])
{
	printf("Load driver with ZwLoadDriver( )\r\n");
	printf("Date: 8th May 2007\r\n");
	printf("Modifed by: GaRY <wofeiwo_at_gmail_dot_com>\r\n\r\n");
	if (argc != 3)
	{
		printf("Usage: %s <DriverFilename> <DriverPath>\r\n", argv[0]);
		exit(-1);
	}
	HMODULE hNtdll = NULL;
	hNtdll = LoadLibraryA("ntdll.dll");

	//从ntdll.dll里获取函数
	if (!hNtdll)
	{
		printf("LoadLibrary( NTDLL.DLL ) Error:%d\n", GetLastError());
		return false;
	}

	lpRtlAnsiStringToUnicodeString = (RTLANSISTRINGTOUNICODESTRING)
		GetProcAddress(hNtdll, "RtlAnsiStringToUnicodeString");
	RtlFreeUnicodeString = (RTLFREEUNICODESTRING)
		GetProcAddress(hNtdll, "RtlFreeUnicodeString");
	ZwLoadDriver = (ZWLOADDRIVER)
		GetProcAddress(hNtdll, "ZwLoadDriver");

	//注册驱动程序
	if (LoadDriver(argv[1], argv[2]) == false) return false;
	return true;
}

3 ZwSetSystemInformation方式

代码例子:

#include <windows.h>
#include <stdio.h>
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
#define SystemLoadAndCallImage 38

typedef struct _UNICODE_STRING {
    USHORT Length;
    USHORT MaximumLength;
    PVOID Buffer;
} UNICODE_STRING, * PUNICODE_STRING;

//typedef unsigned long NTSTATUS;

typedef struct _SYSTEM_LOAD_AND_CALL_IMAGE
{
    UNICODE_STRING ModuleName;
} SYSTEM_LOAD_AND_CALL_IMAGE, * PSYSTEM_LOAD_AND_CALL_IMAGE;

typedef DWORD(CALLBACK* ZWSETSYSTEMINFORMATION)(DWORD, PVOID, ULONG);
ZWSETSYSTEMINFORMATION ZwSetSystemInformation;
typedef DWORD(CALLBACK* RTLINITUNICODESTRING)(PUNICODE_STRING, PCWSTR);
RTLINITUNICODESTRING RtlInitUnicodeString;
typedef DWORD(CALLBACK* RTLANSISTRINGTOUNICODESTRING)(PVOID, PVOID, DWORD);
RTLANSISTRINGTOUNICODESTRING RtlAnsiStringToUnicodeString;

int main_test(int argc, char* argv[])
{
    SYSTEM_LOAD_AND_CALL_IMAGE GregsImage;
    UNICODE_STRING TmpBuff;
    char  szDrvFullPath[256], szTmp[256];
    int iBuffLen;

    printf("Load driver with ZwSetSystemInformation( )\r\n");
    printf("Date: 8th May 2007\r\n");
    printf("Modifed by: GaRY <wofeiwo_at_gmail_dot_com>\r\n\r\n");
    if (argc != 2 || _stricmp(argv[1], "-h") == 0 || _stricmp(argv[1], "-?") == 0 || _stricmp(argv[1], "/?") == 0)
    {
        printf("Usage: %s <DriverPath>\r\n", argv[0]);
        exit(-1);
    }

    // 从ntll.dll获取函数
    if (!(RtlInitUnicodeString = (RTLINITUNICODESTRING)GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlInitUnicodeString")))
    {
        printf("GetProcAddress(\"RtlInitUnicodeString\") Error:%d\n", GetLastError());
        exit(1);
    }
    if (!(ZwSetSystemInformation = (ZWSETSYSTEMINFORMATION)GetProcAddress(GetModuleHandleA("ntdll.dll"), "ZwSetSystemInformation")))
    {
        printf("GetProcAddress(\"ZwSetSystemInformation\") Error:%d\n", GetLastError());
        exit(1);
    }
    if (!(RtlAnsiStringToUnicodeString = (RTLANSISTRINGTOUNICODESTRING)GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlAnsiStringToUnicodeString")))
    {
        printf("GetProcAddress(\"ZwSetSystemInformation\") Error:%d\n", GetLastError());
        exit(1);
    }

    GetFullPathNameA(argv[1], 256, szTmp, NULL);
    printf("Loading driver: %s\r\n", szTmp);
    iBuffLen = sprintf(szDrvFullPath, "\\??\\%s", szTmp);
    szDrvFullPath[iBuffLen] = 0;
    TmpBuff.Buffer = (PVOID)szDrvFullPath;
    TmpBuff.Length = iBuffLen;
    RtlAnsiStringToUnicodeString(&(GregsImage.ModuleName), &TmpBuff, 1);

    if (NT_SUCCESS(ZwSetSystemInformation(SystemLoadAndCallImage, &GregsImage, sizeof(SYSTEM_LOAD_AND_CALL_IMAGE))))   //加载进内核空间
    {
        printf("Driver: %s loaded.\r\n", szDrvFullPath);
    }
    else
    {
        printf("Driver: %s not loaded.\r\n", szDrvFullPath);
    }
    return true;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值