一个 C++ 类封装,用于加载/卸载设备驱动程序






4.80/5 (15投票s)
一个用于注册和启动设备驱动程序的 C++ 类。
引言
如果你经常玩弄设备驱动程序,那么一个加载/卸载工具会非常有用。有很多好用的工具,我认为最受欢迎的是 OSRLoader。但是,我决定编写这个封装,以解释哪些 Win32 API 参与了这个过程。
Win32 API
设备驱动程序与普通的用户级程序不同,因此它的安装和执行更加复杂,因为我们在内核空间中。我们必须执行两个主要操作:
- 将驱动程序注册为 Windows 服务。
- 将驱动程序作为服务启动。
原因在于 Windows 将设备驱动程序视为普通服务。现在,我们可以探索允许我们处理进程的 API。服务控制管理器 (SCM) 是管理一个包含所有已安装的服务和设备驱动程序的数据库的组件。让我们看看用于连接到我们机器上的 SCM 的 API。
SC_HANDLE WINAPI OpenSCManager(
__in_opt LPCTSTR lpMachineName,
__in_opt LPCTSTR lpDatabaseName,
__in DWORD dwDesiredAccess
);
之后,我们可以创建一个新服务,如下所示:
SC_HANDLE WINAPI CreateService(
__in SC_HANDLE hSCManager,
__in LPCTSTR lpServiceName,
__in_opt LPCTSTR lpDisplayName,
__in DWORD dwDesiredAccess,
__in DWORD dwServiceType,
__in DWORD dwStartType,
__in DWORD dwErrorControl,
__in_opt LPCTSTR lpBinaryPathName,
__in_opt LPCTSTR lpLoadOrderGroup,
__out_opt LPDWORD lpdwTagId,
__in_opt LPCTSTR lpDependencies,
__in_opt LPCTSTR lpServiceStartName,
__in_opt LPCTSTR lpPassword
);
MSDN 上提供了对每个参数的解释。现在,我将向您展示如何使用此 API 创建一个新服务
DWORD CService::CreateSvc(void)
{
if (!IsInit())
return SVC_NOT_INIT;
if (IsLoaded())
return SVC_OK;
SC_HANDLE hSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_CREATE_SERVICE);
if (hSCManager == NULL)
return SVC_ERROR_SCMANAGER;
hService = CreateService(hSCManager,lpServiceName,lpDisplayName,
SERVICE_ALL_ACCESS,
SERVICE_KERNEL_DRIVER,
dwStartType,
SERVICE_ERROR_NORMAL,
lpFilePath,
NULL,
NULL,
NULL,
NULL,
NULL);
if (hService == NULL){
hService = OpenService(hSCManager, lpServiceName, SERVICE_ALL_ACCESS);
if (hService == NULL) {
CloseServiceHandle(hSCManager);
return SVC_ERROR_CREATE;
}
}
loaded = true;
CloseServiceHandle(hSCManager);
return SVC_OK;
}
OpenSCManager(…)
返回 SCM 的句柄,因此我们将其用于 CreateService(…)
中以安装设备驱动程序。 hService
是已安装服务的句柄。现在,我们可以启动它。 API
BOOL WINAPI StartService(
__in SC_HANDLE hService,
__in DWORD dwNumServiceArgs,
__in_opt LPCTSTR *lpServiceArgVectors
);
这是代码
DWORD CService::StartSvc(void)
{
if (!IsLoaded())
return SVC_NOT_CREATE;
if (IsStarted())
return SVC_OK;
SC_HANDLE hSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_CREATE_SERVICE);
if (hSCManager == NULL)
return SVC_ERROR_SCMANAGER;
hService = OpenService(hSCManager, lpServiceName, SERVICE_ALL_ACCESS);
if (hService == NULL) {
CloseServiceHandle(hSCManager);
return SVC_ERROR_OPEN;
}
if (StartService(hService,0,NULL)== NULL){
CloseServiceHandle(hSCManager);
CloseServiceHandle(hService);
return SVC_ERROR_START;
}
CloseServiceHandle(hSCManager);
started = true;
return SVC_OK;
}
StartService
函数接受三个参数:服务的句柄、参数的数量以及一个包含参数的数组。
好的,在工作之后,是时候关闭驱动程序了。要停止驱动程序,我们使用此 API
BOOL WINAPI ControlService(
__in SC_HANDLE hService,
__in DWORD dwControl,
__out LPSERVICE_STATUS lpServiceStatus
);
这会将控制消息发送到服务,在我们的例子中是 dwControl = SERVICE_CONTROL_STOP
。输出的 SERVICE_STATUS
结构包含有关服务的状态信息。
DWORD CService::StopSvc(void)
{
SERVICE_STATUS ss;
if (!IsStarted())
return SVC_OK;
SC_HANDLE hSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_CREATE_SERVICE);
if (hSCManager == NULL)
return SVC_ERROR_SCMANAGER;
hService = OpenService(hSCManager, lpServiceName, SERVICE_ALL_ACCESS);
if (hService == NULL) {
CloseServiceHandle(hSCManager);
return SVC_ERROR_OPEN;
}
if (ControlService(hService,SERVICE_CONTROL_STOP,&ss) == NULL){
CloseServiceHandle(hSCManager);
CloseServiceHandle(hService);
return SVC_ERROR_STOP;
}
started = false;
CloseServiceHandle(hSCManager);
CloseServiceHandle(hService);
return SVC_OK;
}
最后,我们必须卸载驱动程序。
BOOL WINAPI DeleteService(
__in SC_HANDLE hService
);
这是从 SCM 中删除驱动程序的 API,这就是我们使用它的方式
DWORD CService::UnloadSvc(void)
{
if (!IsLoaded())
return SVC_OK;
if (IsStarted())
if (StopSvc() != SVC_OK)
return SVC_ERROR_UNLOAD;
SC_HANDLE hSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_CREATE_SERVICE);
if (hSCManager == NULL)
return SVC_ERROR_SCMANAGER;
hService = OpenService(hSCManager, lpServiceName, SERVICE_ALL_ACCESS);
if (hService == NULL) {
CloseServiceHandle(hSCManager);
return SVC_ERROR_OPEN;
}
DeleteService(hService);
CloseServiceHandle(hSCManager);
loaded = false;
return SVC_OK;
}
使用代码
好吧,如果你很懒,或者你不能浪费时间去理解所有这些 API 的工作原理,我已经编写了这个简单的封装,我希望你会发现它很有用
#include <windows.h>
#include "stdafx.h"
//Error codes
#define SVC_OK (DWORD)0
#define SVC_NOT_CREATE (DWORD)1
#define SVC_NOT_START (DWORD)2
#define SVC_NOT_INIT (DWORD)3
#define SVC_ERROR_SCMANAGER (DWORD)4
#define SVC_ERROR_CREATE (DWORD)5
#define SVC_ERROR_START (DWORD)6
#define SVC_ERROR_OPEN (DWORD) 7
#define SVC_ERROR_STOP (DWORD)8
#define SVC_ERROR_UNLOAD (DWORD) 9
class CService
{
public:
//Constructor
CService(void);
CService(LPTSTR _lpFilePath,LPTSTR _lpServiceName,
LPTSTR _lpDisplayName,DWORD _dwStartType);
//Destructor
~CService(void);
//init function
DWORD InitSvc(LPTSTR _lpFilePath,LPTSTR _lpServiceName,
LPTSTR _lpDisplayName,DWORD _dwStartType);
DWORD CreateSvc(void); //create service
DWORD UnloadSvc(void); //unload service
DWORD StartSvc(void); //start service
DWORD StopSvc(void); //stop service
BOOL IsInit(void); //check if service is init
BOOL IsLoaded(void); //check if service is loaded
BOOL IsStarted(void); //check if service is started
private:
LPTSTR lpFilePath; //driver file path
LPTSTR lpServiceName; //service name
LPTSTR lpDisplayName; //service's dos name
DWORD dwStartType; //start type
SC_HANDLE hService; //service's handle
// Status variables
BOOL init;
BOOL loaded;
BOOL started;
};
CService
对象创建
CService svc(“C:\\test.sys”,”Test”,”Test”,SERVICE_DEMAND_START);
驱动程序注册
if (svc.CreateSvc() == SVC_OK)
…
else{
…
}
驱动程序启动
if (svc.StartSvc() == SVC_OK)
…
else{
…
}
驱动程序停止
if (svc.StopSvc() == SVC_OK)
…
else{
…
}
驱动程序擦除
if (svc.UnloadSvc() == SVC_OK)
…
else{
…
}
结论
好的,就这样。我还编写了一个使用 CService
类的小应用程序。我希望你会发现这几行代码很有用。