内核级HOOK的几种实现与应用1
创建时间:2003-03-26文章属性:原创
文章来源:http://www.whitecell.org
文章提交:sinister (jiasys_at_21cn.com)
内核级HOOK的几种实现与应用
Author : sinister
Email : sinister@whitecell.org
HomePage: http://www.whitecell.org
实现内核级 HOOK 对于拦截、分析、跟踪系统内核起着致关重要的作用。实现的方法不同意味着应用侧重点的不同。如想要拦截 NATIVE API 那么可能常用的就是 HOOK SERVICE TABLE 的方法。如果要分析一些系统调用,那么可能想到用 HOOK INT 2E 中断来实现。如果想要拦截或跟踪其他内核 DRIVER 的调用,那么就要用到HOOK PE 的方法来实现。这里我们更注重的是实现,原理方面已有不少高手在网上发表过文章。大家可以结合起来读。下面以我写的几个实例程序来讲解一下各种方法的实现。错误之处还望各位指正。
1、HOOK SERVICE TABLE 方法:
这种方法对于拦截 NATIVE API 来说用的比较多。原理就是通过替换系统导
出的一个 SERVICE TABLE 中相应的 NATIVE API 的地址来达到拦截的目的。
因为此方法较为简单,网上也有不少资料来介绍。所以这里就不给出实例程序了。SERVICE TABLE 的结构如下:
typedef struct ServiceDescriptorEntry {
unsigned int *ServiceTableBase;
unsigned int *ServiceCounterTableBase;
unsigned int NumberOfServices;
unsigned char *ParamTableBase;
} ServiceDescriptorTableEntry_t, *PServiceDescriptorTableEntry_t;
2、HOOK INT 2E 方法:
这种方法对于跟踪、分析系统调用来说用的比较多。原理是通过替换 IDT
表中的 INT 2E 中断,使之指向我们自己的中断服务处理例程来实现的。掌握
此方法需要你对保护模式有一定的基础。下面的程序演示了这一过程。
/*****************************************************************
文件名 : WssHookInt2e.c
描述 : 系统调用跟踪
作者 : sinister
最后修改日期 : 2002-11-02
*****************************************************************/
#include "ntddk.h"
#include "string.h"
#define DWORD unsigned __int32
#define WORD unsigned __int16
#define BYTE unsigned __int8
#define BOOL __int32
#define LOWORD(l) ((WORD)(l))
#define HIWORD(l) ((WORD)(((DWORD)(l) >> 16) & 0xFFFF))
#define LOBYTE(w) ((BYTE)(w))
#define HIBYTE(w) ((BYTE)(((WORD)(w) >> 8) & 0xFF))
#define MAKELONG(a, b) ((LONG) (((WORD) (a)) | ((DWORD) ((WORD) (b))) << 16))
#define SYSTEMCALL 0x2e
#define SYSNAME "System"
#define PROCESSNAMELEN 16
#pragma pack(1)
//定义 IDTR
typedef struct tagIDTR {
WORD IDTLimit;
WORD LowIDTbase;
WORD HiIDTbase;
}IDTR, *PIDTR;
//定义 IDT
typedef struct tagIDTENTRY{
WORD OffsetLow;
WORD selector;
BYTE unused_lo;
unsigned char unused_hi:5;
unsigned char DPL:2;
unsigned char P:1;
WORD OffsetHigh;
} IDTENTRY, *PIDTENTRY;
#pragma pack()
DWORD OldInt2eService;
ULONG ProcessNameOffset;
TCHAR ProcessName;
static NTSTATUS MydrvDispatch (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
VOID DriverUnload (IN PDRIVER_OBJECT pDriverObject);
ULONG GetProcessNameOffset();
VOID GetProcessName( PCHAR Name );
VOID InstallNewInt2e();
VOID UninstallNewInt2e();
VOID __fastcall NativeApiCall()
{
KIRQL OldIrql;
DWORD ServiceID;
DWORD ProcessId;
__asm mov ServiceID,eax;
ProcessId = (DWORD)PsGetCurrentProcessId();
GetProcessName(ProcessName);
KeRaiseIrql(HIGH_LEVEL, &OldIrql); // 提升当前的 IRQL 级别防止被中断
switch ( ServiceID )
{
case 0x20:
DbgPrint("NEWINT2E: ProcessName: %s; ProcessID: %d; Native Api: NtCreateFile() \n",ProcessName,ProcessId);
break;
case 0x2b:
DbgPrint("NEWINT2E: ProcessName: %s; ProcessID: %d; Native Api: NtCreateSection() \n",ProcessName,ProcessId);
break;
case 0x30:
DbgPrint("NEWINT2E: ProcessName: %s; ProcessID: %d; Native Api: NtCreateToken() \n",ProcessName,ProcessId);
break;
}
KeLowerIrql(OldIrql); //恢复原始 IRQL
}
__declspec(naked) NewInt2eService()
{
__asm{
pushad
pushfd
push fs
mov bx,0x30
mov fs,bx
push ds
push es
sti
call NativeApiCall; // 调用记录函数
cli
pop es
pop ds
pop fs
popfd
popad
jmp OldInt2eService; //跳到原始 INT 2E 继续工作
}
}
VOID InstallNewInt2e()
{
IDTR idtr;
PIDTENTRY OIdt;
PIDTENTRY NIdt;
//得到 IDTR 中得段界限与基地址
__asm {
sidt idtr;
}
//得到IDT基地址
OIdt = (PIDTENTRY)MAKELONG(idtr.LowIDTbase,idtr.HiIDTbase);
//保存原来的 INT 2E 服务例程
OldInt2eService = MAKELONG(OIdt.OffsetLow,OIdt.OffsetHigh);
NIdt = &(OIdt);
__asm {
cli
lea eax,NewInt2eService; //得到新的 INT 2E 服务例程偏移
mov ebx, NIdt;
mov ,ax; //INT 2E 服务例程低 16 位
shr eax,16 //INT 2E 服务例程高 16 位
mov ,ax;
lidt idtr //装入新的 IDT
sti
}
}
VOID UninstallNewInt2e()
{
IDTR idtr;
PIDTENTRY OIdt;
PIDTENTRY NIdt;
__asm {
sidt idtr;
}
OIdt = (PIDTENTRY)MAKELONG(idtr.LowIDTbase,idtr.HiIDTbase);
NIdt = &(OIdt);
_asm {
cli
lea eax,OldInt2eService;
mov ebx, NIdt;
mov ,ax;
shr eax,16
mov ,ax;
lidt idtr
sti
}
}
// 驱动入口
NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath )
{
UNICODE_STRING nameString, linkString;
PDEVICE_OBJECT deviceObject;
NTSTATUS status;
HANDLE hHandle;
int i;
//卸载驱动
DriverObject->DriverUnload = DriverUnload;
//建立设备
RtlInitUnicodeString( &nameString, L"\\Device\\WssHookInt2e" );
status = IoCreateDevice( DriverObject,
0,
&nameString,
FILE_DEVICE_UNKNOWN,
0,
TRUE,
&deviceObject
);
if (!NT_SUCCESS( status ))
return status;
RtlInitUnicodeString( &linkString, L"\\DosDevices\\WssHookInt2e" );
status = IoCreateSymbolicLink (&linkString, &nameString);
if (!NT_SUCCESS( status ))
{
IoDeleteDevice (DriverObject->DeviceObject);
return status;
}
for ( i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) {
DriverObject->MajorFunction = MydrvDispatch;
}
DriverObject->DriverUnload = DriverUnload;
ProcessNameOffset = GetProcessNameOffset();
InstallNewInt2e();
return STATUS_SUCCESS;
}
//处理设备对象操作
static NTSTATUS MydrvDispatch (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0L;
IoCompleteRequest( Irp, 0 );
return Irp->IoStatus.Status;
}
VOID DriverUnload (IN PDRIVER_OBJECT pDriverObject)
{
UNICODE_STRING nameString;
UninstallNewInt2e();
RtlInitUnicodeString( &nameString, L"\\DosDevices\\WssHookInt2e" );
IoDeleteSymbolicLink(&nameString);
IoDeleteDevice(pDriverObject->DeviceObject);
return;
}
ULONG GetProcessNameOffset()
{
PEPROCESS curproc;
int i;
curproc = PsGetCurrentProcess();
//
// Scan for 12KB, hopping the KPEB never grows that big!
//
for( i = 0; i < 3*PAGE_SIZE; i++ ) {
if( !strncmp( SYSNAME, (PCHAR) curproc + i, strlen(SYSNAME) )) {
return i;
}
}
//
// Name not found - oh, well
//
return 0;
}
VOID GetProcessName( PCHAR Name )
{
PEPROCESS curproc;
char *nameptr;
ULONG i;
if( ProcessNameOffset ) {
curproc = PsGetCurrentProcess();
nameptr = (PCHAR) curproc + ProcessNameOffset;
strncpy( Name, nameptr, 16 );
} else {
strcpy( Name, "???");
}
}
页:
[1]