TA的每日心情 | 开心 2024-12-9 18:45 |
---|
签到天数: 124 天 [LV.7]常住居民III
|
欢迎您注册加入!这里有您将更精采!
您需要 登录 才可以下载或查看,没有账号?注册
x
创建时间: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[PROCESSNAMELEN];
- 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[SYSTEMCALL].OffsetLow,OIdt[SYSTEMCALL].OffsetHigh);
-
- NIdt = &(OIdt[SYSTEMCALL]);
- __asm {
- cli
- lea eax,NewInt2eService; //得到新的 INT 2E 服务例程偏移
- mov ebx, NIdt;
- mov [ebx],ax; //INT 2E 服务例程低 16 位
- shr eax,16 //INT 2E 服务例程高 16 位
- mov [ebx+6],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[SYSTEMCALL]);
- _asm {
- cli
- lea eax,OldInt2eService;
- mov ebx, NIdt;
- mov [ebx],ax;
- shr eax,16
- mov [ebx+6],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[i] = 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, "???");
- }
- }
复制代码 |
|