摘要:
最近在分析一个驱动级别的脱壳器OllyBonE(OllyDbg的一个插件), 遂即对驱动做了简单的了解,驱动程序主要分为两类:一类是不支持即插即用的NT是驱动程序如NTDDK.h;另外一类是支持即插即用的WDM驱动程序,如WDM.h。 由于OllyBonE是一个NT式驱动,所以仅仅熟悉了NT式驱动的相关知识。本文主要对NT式驱动的三类加载方式:工具加载、手动加载、程序加载,并通过具体实验做以介绍。
方式一(工具):利用Driver Monitor加载NT式驱动
File->OpenDriver,选择需要加载的驱动.sys文件。
File->Start Driver加载驱动。
成功加载如下图:
方式二(手动):与方式一原理一样,都是在注册表中填写相应的字段,
注册表是windows中最重要的文件之一,Windows注册表是帮助Windows控制硬件、软件、用户环境的重要东东,其实如何打开注册表,只需打开“开始菜单”—点“运行”—输入“regedit”,点确定,即可打开,如下图所示.注册表编辑器实际上也可以在系统根目录下找到windows\system中找到。
在HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services中添加新项目,这个项目名称为这个驱动名称,例如,HelloDDK.
‚添加一下子键:
ƒ在命令行方式运行netstart驱动名称,例如,net start HelloDDK.这是驱动会被I/O管理器加载,并且调用入口函数DriverEntry。停止驱动的方式很类似,运行netstop 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, //SCM数据库,NULL代表使用缺省数据库
DWORD dwDesiredAccess //使用权限
);
2.关闭服务的句柄
WINADVAPI
BOOL
WINAPI
CloseServiceHandle(
SC_HANDLE hSCObject //关闭SCM管理器的句柄
);
3.创建服务
WINADVAPI
SC_HANDLE
WINAPI
CreateService(
SC_HANDLE hSCManager,
LPCSTR lpServiceName,
LPCSTR lpDisplayName,
DWORD dwDesiredAccess,
DWORD dwServiceType,
DWORD dwStartType,
DWORD dwErrorControl,
LPCSTR lpBinaryPathName,
LPCSTR lpLoadOrderGroup,
LPDWORD lpdwTagId,
LPCSTR lpDependencies,
LPCSTR lpServiceStartName,
LPCSTR lpPassword
);
4.打开服务
WINADVAPI
SC_HANDLE
WINAPI
OpenService(
SC_HANDLE hSCManager,
LPCSTR lpServiceName,
DWORD dwDesiredAccess
);
5.控制服务
WINADVAPI
BOOL
WINAPI
ControlService(
SC_HANDLE hService, //服务器的句柄
DWORD dwControl, //控制码
LPSERVICE_STATUS lpServiceStatus //返回码的状态
);
加载NT驱动的流程图:
卸载NT驱动流程图:
附代码如下:
#include<windows.h>
#include<winuser.h>
#include<stdlib.h>
#include<string.h>
#include<winsvc.h>
#include<iostream>
usingnamespace std;
SC_HANDLEhServiceMgr = NULL;
SC_HANDLEhServiceDDK = NULL;
voidBeforeLeave()
{
if(hServiceMgr)
{
CloseServiceHandle(hServiceMgr);
}
if(hServiceDDK)
{
CloseServiceHandle(hServiceDDK);
}
}
boolLoadNTDriver(char * name, char* path)
{
int temp = 0;
// char * Imagepath = path + "\\"+name;
char * Imagepath ="D:\\Code\\ollybone.sys";
hServiceMgr = OpenSCManager( NULL, // machine (NULL == local)
NULL, // 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 = CreateService(hServiceMgr, // SCManagerdatabase
name, // name of service
name, // name to display
SERVICE_ALL_ACCESS, // desired access
SERVICE_KERNEL_DRIVER, // service type
SERVICE_DEMAND_START, // starttype
SERVICE_ERROR_NORMAL, // errorcontrol type
Imagepath, // service's binary
NULL, // no load ordering group
NULL, // no tag identifier
NULL, // no dependencies
NULL, // LocalSystem account
NULL // 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() Failedis ERROR_IO_PENDING
orERROR_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
{
printf("OpenService() OK!\n");
}
}
else
{
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() FailedERROR_IO_PENDING\n");
temp = 0;
BeforeLeave();
}
else
{
printf("startService() FailedERROR_SERVICE_ALREADY_RUNNING\n");
temp = 1;
BeforeLeave();
}
}
}
temp = 1;
BeforeLeave();
return temp;
}
boolUnloadNTDriver(char *name)
{
int temp = 0;
SERVICE_STATUS SvrSta;
hServiceMgr = OpenSCManager( NULL, // machine (NULL == local)
NULL, // 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("LoadNTDrivererror\n");
// cout<<"LoadNTDrivererror\n";
}
Sleep(500);
UnloadNTDriver(name);
if(temp == 0)
{
printf("UnloadNTDrivererror\n");
// cout<<"UnloadNTDrivererror!\n";
}
}