NT 驱动加载方式
摘要:
最近在分析一个驱动级别的脱壳器 OllyBonE(OllyDbg 的一个插件), 遂即对驱动做了简
单的了解,驱动程序主要分为两类:一类是不支持即插即用的 NT 是驱动程序如 NTDDK.h;
另外一类是支持即插即用的 WDM 驱动程序,如 WDM.h。 由于 OllyBonE 是一个 NT 式驱
动,所以仅仅熟悉了 NT 式驱动的相关知识。本文主要对 NT 式驱动的三类加载方式:工具
加载、手动加载、程序加载,并通过具体实验做以介绍。
方式一(工具):利用 Driver Monitor 加载 NT 式驱动
File->Open Driver,选择需要加载的驱动.sys 文件。
File-> Start Driver 加载驱动。
成功加载如下图:
方式二(手动):与方式一原理一样,都是在注册表中填写相应的字段,
注册表是 windows 中最重要的文件之一,Windows 注册表是帮助 Windows 控制硬件、软
件、用户环境的重要东东,其实如何打开注册表,只需打开“开始菜单”—点“运行”—输入“rege
dit”,点确定,即可打开,如下图所示.注册表编辑器实际上也可以在系统根目录下找到 window
s\system 中找到。
在 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services 中添加新项目,这
个项目名称为这个驱动名称,例如,HelloDDK.
添加一下子键:
在命令行方式运行 net start 驱动名称,例如,net start HelloDDK.这是驱动会被 I/O 管
理器加载,并且调用入口函数 DriverEntry。停止驱动的方式很类似,运行 net stop HelloDDK。
如果不采用命令行的方式,可以在设备管理器中运行或停止,如下图。
方式三(代码):Windows 服务程序遵循服务控制管理器。基于服务控制管理程序(Service
Control Manager, SCM)系统组建完成。在“WINSAC.H”中有定义了 SCM 组建。
加载和卸载 NT 驱动分为四个步骤:
为 NT 驱动创建新的服务。
开启此项服务。
关闭此项服务。
删除 NT 驱动所创建的服务。
以下为常用的 SCM 组建 API 相关函数(直接从 WINSAC.H 中拷贝的)
1.打开 SCM 管理器的函数
WINADVAPI
SC_HANDLE
WINAPI
OpenSCManagerA(
LPCSTR lpMachineName,
//计算机名称,NULL 代表本机
LPCSTR lpDatabaseName,
DWORD
);
dwDesiredAccess
//SCM 数据库,NULL 代表使用缺省数据库
//使用权限
2.关闭服务的句柄
WINADVAPI
BOOL
WINAPI
CloseServiceHandle(
SC_HANDLE
);
3.创建服务
WINADVAPI
SC_HANDLE
WINAPI
CreateService(
hSCObject
//关闭 SCM 管理器的句柄
SC_HANDLE
LPCSTR
LPCSTR
DWORD
DWORD
DWORD
DWORD
LPCSTR
LPCSTR
LPDWORD
LPCSTR
LPCSTR
LPCSTR
);
hSCManager,
lpServiceName,
lpDisplayName,
dwDesiredAccess,
dwServiceType,
dwStartType,
dwErrorControl,
lpBinaryPathName,
lpLoadOrderGroup,
lpdwTagId,
lpDependencies,
lpServiceStartName,
lpPassword
4.打开服务
WINADVAPI
SC_HANDLE
WINAPI
OpenService(
hSCManager,
lpServiceName,
SC_HANDLE
LPCSTR
DWORD
);
dwDesiredAccess
5.控制服务
WINADVAPI
BOOL
WINAPI
ControlService(
SC_HANDLE
hService,
//服务器的句柄
dwControl,
lpServiceStatus
//控制码
//返回码的状态
DWORD
LPSERVICE_STATUS
);
加载 NT 驱动的流程图:
卸载 NT 驱动流程图:
附代码如下:
#include
#include
#include
#include
#include
#include
using namespace std;
SC_HANDLE hServiceMgr = NULL;
SC_HANDLE hServiceDDK = NULL;
void BeforeLeave()
{
if(hServiceMgr)
{
CloseServiceHandle(hServiceMgr);
}
if(hServiceDDK)
{
CloseServiceHandle(hServiceDDK);
}
}
bool LoadNTDriver(char * name, char* path)
{
//
int temp = 0;
char * Imagepath = path + "\\"+ name;
char * Imagepath = "D:\\Code\\ollybone.sys";
hServiceMgr = OpenSCManager( NULL,
NULL,
SC_MANAGER_ALL_ACCESS // access required
);
// machine (NULL == local)
// database (NULL == default)
if(hServiceMgr==NULL)
{
printf("OpenSCManager() Failed %d!\n", GetLastError());
temp = 0;
BeforeLeave();
}
else
{
printf("OpenSCManager() OK !\n");
}
//创建驱动所对应的服务
hServiceDDK = CreateService( hServiceMgr,
// SCManager database
// desired access
// name of service
// name to display
name,
name,
SERVICE_ALL_ACCESS,
SERVICE_KERNEL_DRIVER, // service type
SERVICE_DEMAND_START,
SERVICE_ERROR_NORMAL,
Imagepath,
NULL,
// start type
// error control type
// service's binary
// no load ordering group
NULL,
NULL,
NULL,
NULL
);
// no tag identifier
// no dependencies
// LocalSystem account
// no password
DWORD dwRtn;
if(hServiceDDK==NULL)
{
dwRtn = GetLastError();
if(dwRtn!= ERROR_IO_PENDING && dwRtn!=ERROR_SERVICE_EXISTS)
{
printf("CreateService() Failed %d!\n", dwRtn);
temp = 0;
BeforeLeave();
}
else
{
printf( "CreateService() Failed is ERROR_IO_PENDING
or ERROR_SERVICE_EXISTS! \n");
}
hServiceDDK = OpenService( hServiceMgr, name, SERVICE_ALL_ACCESS );
if(hServiceDDK==NULL)
{
dwRtn = GetLastError();
printf("OpenService() Failed %d!\n", dwRtn);
temp = 0;
BeforeLeave();
}
else
{
}
}
else
{
printf("OpenService() OK !\n");
printf("CreateService() OK !\n");
}
temp = StartService(hServiceDDK,NULL,NULL);
if(!temp)
{
DWORD dwRtn = GetLastError();
if( dwRtn != ERROR_IO_PENDING
&& dwRtn != ERROR_SERVICE_ALREADY_RUNNING )
{
printf("startService() Failed %d!\n", dwRtn);
temp = 0;
BeforeLeave();
}
else
{
if(dwRtn== ERROR_IO_PENDING)
{
printf("startService() Failed ERROR_IO_PENDING\n");
temp = 0;
BeforeLeave();
}
else
{
printf("startService() Failed ERROR_SERVICE_ALREADY_RUNNING\n");
temp = 1;
BeforeLeave();
}
}
}
temp = 1;
BeforeLeave();
return temp;
}
bool UnloadNTDriver(char *name)
{
int temp = 0;
SERVICE_STATUS SvrSta;
hServiceMgr = OpenSCManager( NULL,
NULL,
// machine (NULL == local)
// database (NULL == default)
SC_MANAGER_ALL_ACCESS // access required
);
if(hServiceMgr==NULL)
{
printf("OpenSCManager() Failed %d!\n", GetLastError());
temp = 0;
BeforeLeave();
}
else
{
}
printf("OpenSCManager() OK !\n");
hServiceDDK = OpenService( hServiceMgr, name, SERVICE_ALL_ACCESS );
if(hServiceDDK==NULL)
{
printf("OpenService() Failed %d!\n", GetLastError());
temp = 0;
BeforeLeave();
}
else
{
printf("OpenService() OK !\n");
}
if( !ControlService( hServiceDDK, SERVICE_CONTROL_STOP, &SvrSta ))
{
printf("ControlService() Failed %d!\n", GetLastError());
}
else
{
printf("ControlService() OK !\n");
}
if(!DeleteService(hServiceDDK))
{
printf("DeleteService() Failed %d!\n", GetLastError());
}
else
{
}
printf("DeleteService() OK !\n");
temp = 1;
BeforeLeave();
return temp;
}
void main()
{
char * name = "ollybone.sys";
char * path = "D:\\Code";
int temp = LoadNTDriver(name, path);
if(temp == 0)
{
printf("LoadNTDriver error\n");
cout<<"LoadNTDriver error\n";
//
}
Sleep(500);
UnloadNTDriver(name);
if(temp == 0)