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;
}