Windows内核驱动的装载

@lzeroyuee  May 2, 2020

驱动装载和卸载的过程

驱动的装载和卸载依靠于服务,安装一个驱动等同于安装一个服务

在操作服务的过程中,在不使用服务相关的句柄时要及时释放

驱动的装载

  1. 打开服务管理器
  2. 创建驱动的服务
  3. 启动服务

驱动的卸载

  1. 打开服务管理器
  2. 打开驱动的服务
  3. 停止服务
  4. 删除服务

相关API

  • 打开服务管理器

    SC_HANDLE OpenSCManagerA(
        LPCSTR lpMachineName,     // 目标计算机的名称,为NULL则是本地
        LPCSTR lpDatabaseName,     // 数据库的名称,为NULL则默认打开SERVICES_ACTIVE_DATABASE数据库
        DWORD dwDesiredAccess     // 访问控制,为SC_MANAGER_ALL_ACCESS则是所有权限
    );                            // 成功返回服务管理器句柄,失败则为NULL
  • 创建或打开服务

    SC_HANDLE CreateServiceA(
        SC_HANDLE hSCManager,         // 服务管理器句柄
        LPCSTR lpServiceName,         // 服务名称
        LPCSTR lpDisplayName,         // 显示名称
        DWORD dwDesiredAccess,         // 访问控制,SERVICE_ALL_ACCESS为所有权限
        DWORD dwServiceType,         // 服务类型,SERVICE_KERNEL_DRIVER为内核驱动
        DWORD dwStartType,             // 启动类型,SERVICE_DEMAND_START为后续调用StartService才启动
        DWORD dwErrorControl,         // 如果此服务无法启动,则错误的严重程度和所采取的操作,SERVICE_ERROR_NORMAL为默认
        LPCSTR lpBinaryPathName,     // 驱动路径
        LPCSTR lpLoadOrderGroup,     // 服务所属组名,可为NULL
        LPDWORD lpdwTagId,             // 可为NULL
        LPCSTR lpDependencies,         // 可为NULL
        LPCSTR lpServiceStartName,     // 服务应该在其下运行的帐户的名称,可为NULL
        LPCSTR lpPassword             // 账户密码,,可为NULL
    );                                 // CreateService成功返回服务句柄,失败则返回NULL
    
    SC_HANDLE OpenServiceA(
        SC_HANDLE hSCManager,         // 服务管理器句柄
        LPCSTR lpServiceName,         // 服务名称
        DWORD dwDesiredAccess         // 访问控制
    );                                 // OpenService成功返回服务句柄,失败则返回NULL
  • 启动服务

    BOOL StartServiceA(
        SC_HANDLE hService,             // 服务句柄
        DWORD dwNumServiceArgs,         // lpServiceArgVectors数组的个数,可为0
        LPCSTR *lpServiceArgVectors     // 可为NULL
    );
  • 停止与卸载服务

    // 控制服务
    BOOL ControlService(
        SC_HANDLE hService,                 // 服务句柄
        DWORD dwControl,                     // SERVICE_CONTROL_STOP为停止
        LPSERVICE_STATUS lpServiceStatus     // SERVICE_STATUS结构的指针
    );
    BOOL DeleteService(
        SC_HANDLE hService     // 服务句柄
    );
  • 关闭服务句柄

    BOOL CloseServiceHandle(
        SC_HANDLE hSCObject // 服务句柄
    );

实现DriverManager类

/**************************DriverManager.h*********************************/
#ifndef DRIVERMANAGER_H
#define DRIVERMANAGER_H

#include <Windows.h>

#define SERVICE_NAME TEXT("MyHunter")    // 服务名
#define SERVICE_SHOW SERVICE_NAME        // 服务显示名

class DriverManager
{
public:
    DriverManager();
    virtual ~DriverManager();

    bool install_driver();      // 安装驱动
    bool start_driver();        // 启动驱动
    bool stop_driver();         // 停止驱动
    bool uninstall_driver();    // 卸载驱动

    bool connect_driver(const TCHAR *symbol_name);      // 链接驱动
    void disconnect_driver();

    /*
     * 驱动控制
     *      control_code: 控制码
     *      in_buf:输入缓冲区
     *      in_buf_size:输入缓冲区大小
     *      out_buf:输出缓冲区
     *      out_buf_size:输出缓冲区大小
     *      ret_bytes:返回字节数
     */
    bool io_control(DWORD control_code, LPVOID in_buf, 
                    DWORD in_buf_size, LPVOID out_buf, DWORD out_buf_size, LPDWORD ret_bytes);

    void set_driver(const TCHAR *path);   // 设置驱动路径

    inline DWORD get_last_error() const { return last_error_; } // 获取错误码

private:
    TCHAR *driver_path = nullptr;       // 驱动路径
    SC_HANDLE scm_manager_ = nullptr;   // 服务管理器句柄
    SC_HANDLE service_ = nullptr;       // 服务句柄
    HANDLE driver_ = INVALID_HANDLE_VALUE;  // 驱动句柄

    DWORD last_error_ = 0;  // 错误码
};

#endif // DRIVERMANAGER_H
/**************************DriverManager.cpp*********************************/
#include "drivermanager.h"
#include <tchar.h>

DriverManager::DriverManager()
{

}

DriverManager::~DriverManager()
{
    // 清理资源
    if (driver_path)
        delete[] driver_path;
    if (service_)
        ::CloseServiceHandle(service_);
    if (scm_manager_)
        ::CloseServiceHandle(scm_manager_);
}

bool DriverManager::install_driver()
{
    // 建立与指定计算机上的服务控制管理器的连接,并打开指定的服务控制管理器数据库
    scm_manager_ = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    if(!scm_manager_) {
        // 获取错误码
        last_error_ = ::GetLastError();
        return false;
    }

    // 创建服务
    service_ = ::CreateService(scm_manager_, SERVICE_NAME, SERVICE_SHOW, SERVICE_ALL_ACCESS,
        SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, driver_path,
        nullptr, nullptr, nullptr, nullptr, nullptr);
    if(!service_) {
        // 获取错误码并关闭服务管理器句柄
        last_error_ = ::GetLastError();
        ::CloseServiceHandle(scm_manager_);
        scm_manager_ = nullptr;
        return false;
    }

    // 关闭句柄
    ::CloseServiceHandle(service_);
    ::CloseServiceHandle(scm_manager_);
    service_ = nullptr;
    scm_manager_ = nullptr;

    return true;
}

bool DriverManager::start_driver()
{
    // 建立与指定计算机上的服务控制管理器的连接,并打开指定的服务控制管理器数据库
    scm_manager_ = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    if (!scm_manager_) {
        // 获取错误码
        last_error_ = ::GetLastError();
        return false;
    }

    // 打开现有服务
    service_ = ::OpenService(scm_manager_, SERVICE_NAME, SERVICE_ALL_ACCESS);
    if (!service_) {
        // 获取错误码并关闭服务管理器句柄
        last_error_ = ::GetLastError();
        ::CloseServiceHandle(scm_manager_);
        scm_manager_ = nullptr;
        return false;
    }

    // 启动服务
    bool ret = ::StartService(service_, 0, nullptr);
    if(!ret) {
        // 启动失败,获取错误码
        last_error_ = ::GetLastError();
    }

    // 关闭句柄
    ::CloseServiceHandle(service_);
    ::CloseServiceHandle(scm_manager_);
    service_ = nullptr;
    scm_manager_ = nullptr;

    return ret;
}

bool DriverManager::stop_driver()
{
    // 建立与指定计算机上的服务控制管理器的连接,并打开指定的服务控制管理器数据库
    scm_manager_ = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    if (!scm_manager_) {
        // 获取错误码
        last_error_ = ::GetLastError();
        return false;
    }

    // 打开现有服务
    service_ = ::OpenService(scm_manager_, SERVICE_NAME, SERVICE_ALL_ACCESS);
    if (!service_) {
        // 获取错误码并关闭服务管理器句柄
        last_error_ = ::GetLastError();
        ::CloseServiceHandle(scm_manager_);
        scm_manager_ = nullptr;
        return false;
    }

    // 停止服务
    SERVICE_STATUS status = { 0 };
    bool ret = ::ControlService(service_, SERVICE_CONTROL_STOP, &status);
    if (!ret) {
        // 启动失败,获取错误码
        last_error_ = ::GetLastError();
    }

    // 关闭句柄
    ::CloseServiceHandle(service_);
    ::CloseServiceHandle(scm_manager_);
    service_ = nullptr;
    scm_manager_ = nullptr;

    return ret;
}

bool DriverManager::uninstall_driver()
{
    // 建立与指定计算机上的服务控制管理器的连接,并打开指定的服务控制管理器数据库
    scm_manager_ = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    if (!scm_manager_) {
        // 获取错误码
        last_error_ = ::GetLastError();
        return false;
    }

    // 打开现有服务
    service_ = ::OpenService(scm_manager_, SERVICE_NAME, SERVICE_ALL_ACCESS);
    if (!service_) {
        // 获取错误码并关闭服务管理器句柄
        last_error_ = ::GetLastError();
        ::CloseServiceHandle(scm_manager_);
        scm_manager_ = nullptr;
        return false;
    }

    bool ret = ::DeleteService(service_);
    if (!ret) {
        // 启动失败,获取错误码
        last_error_ = ::GetLastError();
    }

    // 关闭句柄
    ::CloseServiceHandle(service_);
    ::CloseServiceHandle(scm_manager_);
    service_ = nullptr;
    scm_manager_ = nullptr;

    return ret;
}

bool DriverManager::connect_driver(const TCHAR *symbol_name)
{
    // 连接驱动
    driver_ = ::CreateFile(symbol_name, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
    if(driver_ == INVALID_HANDLE_VALUE) {
        // 连接失败,获取返回值
        last_error_ = ::GetLastError();
        return false;
    }
    return true;
}

void DriverManager::disconnect_driver()
{
    if(driver_ != INVALID_HANDLE_VALUE)
        ::CloseHandle(driver_);
}

bool DriverManager::io_control(DWORD control_code, LPVOID in_buf, DWORD in_buf_size, LPVOID out_buf, DWORD out_buf_size,
    LPDWORD ret_bytes)
{
    if(!::DeviceIoControl(driver_, control_code, in_buf, in_buf_size, out_buf, out_buf_size, ret_bytes, NULL)) {
        last_error_ = ::GetLastError();
        return false;
    }
    return true;
}

void DriverManager::set_driver(const TCHAR *path)
{
    // 释放空间
    if (driver_path)
        delete[] driver_path;

    // 申请空间
    DWORD length = _tcslen(path);
    DWORD bytes = (length + 1) * sizeof(TCHAR);
    driver_path = new TCHAR[bytes];
    // 拷贝字符串
    _tcsncpy(driver_path, path, length + 1);
}

添加新评论