一个 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 类的小应用程序。我希望你会发现这几行代码很有用。


