硬件断点的实现需要依赖于调试寄存器

DR0~DR7  调试寄存器

DR0~DR3-----调试地址寄存器
DR4~DR5-----保留
DR6 -----调试状态寄存器 指示哪个调试寄存器被命中
DR7 -----调试控制寄存器

关于Dr7寄存器每个标志位的解释:

总结如下

DR7调试控制寄存器:
R/W0~R/W3:与DR0~DR3相对应,用来指定监控地址的访问类型,表示意义如下:
              00:仅当执行对应的地址时中断
              01:仅当写入对应的地址时中断
              10:基本不用
              11:读取对应的地址时中断,读取指令的指令除外

LEN0~LEN3:与DR0~DR3相对应,用来指定监控地址的长度,意义如下:
               00:一个字节长
               01:两个字节长
               10:未定义或者代表8字节,具体视CPU而定
               11:四个字节长

L0~L3:与DR0~DR3相对应,意思表示仅对当前

接下来看看两个Windows提供的两个API函数,GetThreadContext和SetThreadContext来获取或者时设置线程的上下文,什么是线程的上下文,就是线程运行时的各种寄存器的信息,比如调试寄存器,浮点寄存器,控制寄存器等等,在应用层是不能直接操作Drx寄存器的值,但可以调用这两个api来读写线程的上下文,来达到设置硬件断点的目的,如果想对某个进程设置硬件断点,就需要对它的每个线程都调用SetThreadContext()函数,设置Drx寄存器的值。

BOOL WINAPI GetThreadContext(__in     HANDLE hThread,__inout  LPCONTEXT lpContext
);

BOOL WINAPI SetThreadContext(__in  HANDLE hThread,__in  const CONTEXT *lpContext
);

在SSDT表中对应的NtGetContextThread和NtSetContextThread

NTSTATUS
NtGetContextThread(__in HANDLE ThreadHandle,__inout PCONTEXT ThreadContext)

NTSTATUS
NtSetContextThread(__in HANDLE ThreadHandle,__in PCONTEXT ThreadContext)

这两个函数都是调用了PsSet/GetContextThread函数

NTSTATUS
PsSetContextThread(__in PETHREAD Thread,__in PCONTEXT ThreadContext,__in KPROCESSOR_MODE Mode)NTSTATUS
PsGetContextThread(__in PETHREAD Thread,__inout PCONTEXT ThreadContext,__in KPROCESSOR_MODE Mode)

我们可以对PsGet/SetContextTread函数Hook来达到对设置硬件断点的一个过滤,对于目标进程获取或者设置线程的Context进行处理。

oid __stdcall FilterSetGetContextThread(PETHREAD Thread,PCONTEXT Context,KPROCESSOR_MODE AccessMode)
{__try{if (AccessMode == UserMode){//wrk 参数校验ProbeForReadSmallStructure(Context,sizeof(CONTEXT),PROBE_ALIGNMENT(CONTEXT));}else{*Context = *Context;}if (strstr(GetProcessNameByThread(Thread),"test.exe")!=NULL){if (strstr((char*)PsGetCurrentProcess()+0x16c,"ollydbg") != NULL){return;}//如果是要获得调试寄存器的值,将Flags 的获得调试寄存器清零,if (Context->ContextFlags | CONTEXT_DEBUG_REGISTERS){Context->ContextFlags = ~CONTEXT_DEBUG_REGISTERS;}}}__except(EXCEPTION_EXECUTE_HANDLER){return;}
}

typedef NTSTATUS (*PSGETCONTEXTTHREAD)(PETHREAD Thread,PCONTEXT Context,KPROCESSOR_MODE AccessMode);typedef NTSTATUS (*PSSETCONTEXTTHREAD)(PETHREAD Thread,PCONTEXT Context,KPROCESSOR_MODE AccessMode);//global
PSGETCONTEXTTHREAD PsGetContextThread;
PSSETCONTEXTTHREAD PsSetContextThread;ULONG    g_JmpGetContextThread;
UCHAR    g_cGetContextCode[5];
BOOLEAN    g_bHookGetContextSuccess;
ULONG    g_JmpSetContextThread;
UCHAR    g_cSetContextCode[5];
BOOLEAN    g_bHookSetContextSuccess;char* GetProcessNameByThread(PETHREAD Thread)
{ULONG    ProcessObj;if (MmIsAddressValid(Thread)){ProcessObj = *(ULONG*)((ULONG)Thread + 0x150);return (char*)(ProcessObj+0x16C);}return 0;
}void PageProtectOn()
{__asm{//恢复内存保护
        mov  eax,cr0or   eax,10000hmov  cr0,eaxsti}
}void PageProtectOff()
{__asm{//去掉内存保护
        climov  eax,cr0and  eax,not 10000hmov  cr0,eax}
}BOOLEAN    Jmp_HookFunction(IN ULONG Destination,IN ULONG Source,IN UCHAR *Ori_Code)
{ULONG    Jmp_Offest;UCHAR    Jmp_Code[5] = {0xE9};KSPIN_LOCK lock;KIRQL irql;if (Destination==0||Source==0){DbgPrint("Params error!");return FALSE;}RtlCopyMemory(Ori_Code,(PVOID)Destination,5);Jmp_Offest = Source - Destination-5;*(ULONG*)&Jmp_Code[1] = Jmp_Offest;KeInitializeSpinLock (&lock );KeAcquireSpinLock(&lock,&irql);PageProtectOff();RtlCopyMemory((PVOID)Destination,Jmp_Code,5);PageProtectOn();KeReleaseSpinLock (&lock,irql);return TRUE;
}VOID Res_HookFunction(IN ULONG    Destination,IN UCHAR    *Ori_Code,IN ULONG    Length)
{KSPIN_LOCK lock;KIRQL irql;if (Destination==0||Ori_Code==0){    return;    }KeInitializeSpinLock (&lock );KeAcquireSpinLock(&lock,&irql);PageProtectOff();RtlCopyMemory((PVOID)Destination,Ori_Code,Length);PageProtectOn();KeReleaseSpinLock (&lock,irql);
}FORCEINLINEVOIDProbeForReadSmallStructure (IN PVOID Address,IN SIZE_T Size,IN ULONG Alignment)  //wrk源码
{ASSERT((Alignment == 1) || (Alignment == 2) ||(Alignment == 4) || (Alignment == 8) ||(Alignment == 16));if ((Size == 0) || (Size >= 0x10000)) {ASSERT(0);ProbeForRead(Address, Size, Alignment);} else {if (((ULONG_PTR)Address & (Alignment - 1)) != 0) {ExRaiseDatatypeMisalignment();}if ((PUCHAR)Address >= (UCHAR * const)MM_USER_PROBE_ADDRESS) {Address = (UCHAR * const)MM_USER_PROBE_ADDRESS;}_ReadWriteBarrier();*(volatile UCHAR *)Address;}
}void __stdcall FilterSetGetContextThread(PETHREAD Thread,PCONTEXT Context,KPROCESSOR_MODE AccessMode)
{__try{if (AccessMode == UserMode){//wrk 参数校验ProbeForReadSmallStructure(Context,sizeof(CONTEXT),PROBE_ALIGNMENT(CONTEXT));}else{*Context = *Context;}if (strstr(GetProcessNameByThread(Thread),"test.exe")!=NULL){if (strstr((char*)PsGetCurrentProcess()+0x16c,"ollydbg") != NULL){return;}//如果是要获得调试寄存器的值,将Flags 的获得调试寄存器清零,if (Context->ContextFlags | CONTEXT_DEBUG_REGISTERS){Context->ContextFlags = ~CONTEXT_DEBUG_REGISTERS;}}}__except(EXCEPTION_EXECUTE_HANDLER){return;}
}void __declspec(naked) NewGetContextThread()
{__asm{mov        edi,edipush    ebpmov        ebp,esppush    [ebp+0x10]push    [ebp+0xc]push    [ebp+0x8]call    FilterSetGetContextThreadmov        esp,ebppop        ebpmov        edi,edipush    ebpmov        ebp,espjmp        g_JmpGetContextThread}
}void __declspec(naked) NewSetContextThread()
{__asm{mov        edi,edipush    ebpmov        ebp,esppush    [ebp+0x10]push    [ebp+0xc]push    [ebp+0x8]call    FilterSetGetContextThreadmov        esp,ebppop        ebpmov        edi,edipush    ebpmov        ebp,espjmp        g_JmpSetContextThread}
}void HookSetGetContextThread()
{g_JmpGetContextThread = (ULONG)PsGetContextThread + 0x5;g_bHookGetContextSuccess = Jmp_HookFunction((ULONG)PsGetContextThread,(ULONG)NewGetContextThread,g_cGetContextCode);g_JmpSetContextThread = (ULONG)PsSetContextThread + 0x5;g_bHookSetContextSuccess = Jmp_HookFunction((ULONG)PsSetContextThread,(ULONG)NewSetContextThread,g_cSetContextCode);
}void UnHookSetGetContextThread()
{if (g_bHookGetContextSuccess){Res_HookFunction((ULONG)PsGetContextThread,g_cGetContextCode,5);}if (g_bHookSetContextSuccess){Res_HookFunction((ULONG)PsSetContextThread,g_cSetContextCode,5);}
}void DriverUnLoad(PDRIVER_OBJECT pDriverObject)
{UnHookSetGetContextThread();
}NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject,PUNICODE_STRING usRegistPath)
{UNICODE_STRING    usFuncName1,usFuncName2;RtlInitUnicodeString(&usFuncName1,L"PsGetContextThread");RtlInitUnicodeString(&usFuncName2,L"PsSetContextThread");PsGetContextThread = (PSGETCONTEXTTHREAD)MmGetSystemRoutineAddress(&usFuncName1);PsSetContextThread = (PSSETCONTEXTTHREAD)MmGetSystemRoutineAddress(&usFuncName2);HookSetGetContextThread();pDriverObject->DriverUnload = DriverUnLoad;return STATUS_SUCCESS;
}

在ring0可以直接改变Drx寄存器的值,设置硬件断点来达到对某个函数的hook,这里以NtOpenProcess为例。我们知道内核层产生的异常都会由RtlDispatchException函数进行分发处理,所以我们首先要InlineHook RtlDispatchException函数,在对异常进行分发时先对异常进行过滤,如果异常地址是我们设置的硬件断点“监控”的地址,则改变EIP,达到对目标函数“hook”的目的。

先InlineHook RtlDispatchException ,RtlDispatchException未导出,在KiDispatchException中被调用,KiDispatchException也未导出,采用的方法是暴力搜索整个内核文件Ntoskrnl.exe来匹配特征码

VOID HookRtlDispatchException()
{PLDR_DATA_TABLE_ENTRY Ldr = NULL;//构建RtlDispatchException 的特征码//     nt!KiDispatchException+0x160://     83eff040 53              push    ebx//     83eff041 ff750c          push    dword ptr [ebp+0Ch]//     83eff044 ff7510          push    dword ptr [ebp+10h]//     83eff047 ff15bc49fb83    call    dword ptr [nt!KiDebugRoutine (83fb49bc)]//     83eff04d 84c0            test    al,al//     83eff04f 0f859d000000    jne     nt!KiDispatchException+0x211 (83eff0f2)//     83eff055 57              push    edi//     83eff056 53              push    ebx//     83eff057 e8 a372ffff      call    nt!RtlDispatchException (83ef62ff)//     kd> u 83ef62ff//     nt!RtlDispatchException://     83ef62ff 8bff            mov     edi,edi//     83ef6301 55              push    ebp//     83ef6302 8bec            mov     ebp,esp//     83ef6304 83e4f8          and     esp,0FFFFFFF8h//     83ef6307 83ec6c          sub     esp,6Ch//     83ef630a 53              push    ebx//     83ef630b 56              push    esi//     83ef630c 57              push    edi
SIGNATURE_INFO SignCode[] = {{0x84,10},{0xc0,9},{0x57,2},{0x53,1},{0xE8,0}};
#ifndef _DEBUG__asm int 3
#endif g_bHookSuccess  = FALSE;Ldr = SearchDriver(g_LocalDriverObj,L"ntoskrnl.exe");if (!Ldr)   return;g_RtlDispatchExeceptionAddress = SearchAddressForSignFromPE((ULONG_PTR)(Ldr->DllBase),Ldr->SizeOfImage,SignCode);    if (!MmIsAddressValid((PVOID)g_RtlDispatchExeceptionAddress))  return;//利用偏移转成绝对地址                                    +5 过e8 a372ffff 这五个字节g_RtlDispatchExeceptionAddress = g_RtlDispatchExeceptionAddress+5 + *(ULONG_PTR*)(g_RtlDispatchExeceptionAddress+1);//过被占的前5个字节,继续执行的代码DbgPrint("RtlDispatchExceptionAddresss:%x",g_RtlDispatchExeceptionAddress);g_JmpOrigDispatchException = g_RtlDispatchExeceptionAddress + 5;g_bHookSuccess = Jmp_HookFunction(g_RtlDispatchExeceptionAddress,(ULONG_PTR)NewRtlDispatchException,g_cDisExceptionCode);
}

然后将要“监控”的目标地址写入Dr0寄存器,当目标地址被执行的时候,触发异常,执行RtlDispatchException函数,

VOID SetMonitor(PVOID Address)
{__asm{mov eax , Addressmov DR0 , eaxmov eax , 0x02  //全局的,仅当执行时产生异常
        mov DR7 , eax}
}VOID CancelMonitor(PVOID Address)
{__asm{xor eax , eaxmov DR0 , eaxmov DR7 , eax}
}

RtlDispatchException的过滤函数,在这里改变Eip的值,异常处理完毕以后,开始执行NewNtOpenProcess

ULONG_PTR _stdcallFilterRtlDispatchException (IN PEXCEPTION_RECORD ExceptionRecord,IN PCONTEXT ContextRecord)
{//DbgPrint("Address:%x -- ExceptionCode:%x\r\n",ExceptionRecord->ExceptionAddress,ExceptionRecord->ExceptionCode);//如果是NtOpenProcess处的异常if (ExceptionRecord->ExceptionAddress == (PVOID)KeServiceDescriptorTable.ServiceTableBase[190]){KdPrint(("<Except addresss>:%X <seh callBack>:%X -- <Except code>:%X",ContextRecord->Eip,ExceptionRecord->ExceptionAddress,ExceptionRecord->ExceptionCode));//将执行的下一条指令置为NewNtOpenProcess() 函数的地址,CPU接着去执行NewNtOpenProcessContextRecord->Eip = (ULONG_PTR)NewNtOpenProcess;//返回TRUE,异常不再进行派发return 1;}return 0;
}

NewNtOpenProcess只是简单地调用FilterNtOpenProcess进行简单的调用,打印一些基本的信息。

void __declspec(naked)  NewNtOpenProcess()
{__asm{pushadpushfdcall FilterNtOpenProcesspopfdpopadmov        edi , edipush       espmov        ebp , esp//跳过NtOpenProcess的前五个字节,//避免再次触发异常
        jmp        g_JmpOrigNtOpenProcess}
}

完整的工程代码

#ifndef CXX_DRXHOOK_H
#define CXX_DRXHOOK_H#include <ntifs.h>
#include <devioctl.h>
#endif    typedef struct _SYSTEM_SERVICE_TABLE32 {ULONG_PTR*   ServiceTableBase;ULONG_PTR*   ServiceCounterTableBase;ULONG32 NumberOfServices;ULONG_PTR*   ParamTableBase;
} SYSTEM_SERVICE_TABLE32, *PSYSTEM_SERVICE_TABLE32;typedef struct _SYSTEM_SERVICE_TABLE64{ULONG_PTR*         ServiceTableBase; ULONG_PTR*         ServiceCounterTableBase; ULONG64          NumberOfServices; ULONG_PTR*         ParamTableBase;
} SYSTEM_SERVICE_TABLE64, *PSYSTEM_SERVICE_TABLE64;#ifndef _WIN64
#define        _SYSTEM_SERVICE_TABLE   _SYSTEM_SERVICE_TABLE64
#define        SYSTEM_SERVICE_TABLE     SYSTEM_SERVICE_TABLE64
#define        PSYSTEM_SERVICE_TABLE     PSYSTEM_SERVICE_TABLE64
#else
#define        _SYSTEM_SERVICE_TABLE   _SYSTEM_SERVICE_TABLE32
#define        SYSTEM_SERVICE_TABLE     SYSTEM_SERVICE_TABLE32
#define        PSYSTEM_SERVICE_TABLE     PSYSTEM_SERVICE_TABLE32
#endif__declspec(dllimport) SYSTEM_SERVICE_TABLE KeServiceDescriptorTable;//结构声明
typedef struct _SIGNATURE_INFO{UCHAR    cSingature;int        Offset;
}SIGNATURE_INFO,*PSIGNATURE_INFO;typedef struct _LDR_DATA_TABLE_ENTRY                         // 24 elements, 0x78 bytes (sizeof)
{                                                                                                /*0x000*/     struct _LIST_ENTRY InLoadOrderLinks;       // 2 elements, 0x8 bytes (sizeof)   /*0x008*/     PVOID ExceptionTable;  /*0x00C*/      ULONG ExceptionTableSize;/*0x010*/     struct _LIST_ENTRY InInitializationOrderLinks; // 2 elements, 0x8 bytes (sizeof)   /*0x018*/     VOID*        DllBase;                                                                        /*0x01C*/     VOID*        EntryPoint;                                                                     /*0x020*/     ULONG32      SizeOfImage;                                                                    /*0x024*/     struct _UNICODE_STRING FullDllName;             // 3 elements, 0x8 bytes (sizeof)   /*0x02C*/     struct _UNICODE_STRING BaseDllName;             // 3 elements, 0x8 bytes (sizeof)   /*0x034*/     ULONG32      Flags;                                                                          /*0x038*/     UINT16       LoadCount;                                                                      /*0x03A*/     UINT16       TlsIndex;                                                                       union                                                    // 2 elements, 0x8 bytes (sizeof)
    {                                                                                            /*0x03C*/     struct _LIST_ENTRY HashLinks;           // 2 elements, 0x8 bytes (sizeof)   struct                                          // 2 elements, 0x8 bytes (sizeof)
        {                                                                                        /*0x03C*/             VOID*        SectionPointer;                                                         /*0x040*/             ULONG32      CheckSum;                                                               };                                                                                       };                                                                                           union                                                    // 2 elements, 0x4 bytes (sizeof)
    {                                                                                            /*0x044*/         ULONG32      TimeDateStamp;                                                              /*0x044*/         VOID*        LoadedImports;                                                              };                                                                                           /*0x048*/     VOID* EntryPointActivationContext;                                     /*0x04C*/     VOID*        PatchInformation;                                                               /*0x050*/     struct _LIST_ENTRY ForwarderLinks;                       // 2 elements, 0x8 bytes (sizeof)   /*0x058*/     struct _LIST_ENTRY ServiceTagLinks;                      // 2 elements, 0x8 bytes (sizeof)   /*0x060*/     struct _LIST_ENTRY StaticLinks;                          // 2 elements, 0x8 bytes (sizeof)   /*0x068*/     VOID*        ContextInformation;                                                             /*0x06C*/     ULONG32      OriginalBase;                                                                   /*0x070*/     union _LARGE_INTEGER LoadTime;                           // 4 elements, 0x8 bytes (sizeof)
}LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;ULONG_PTR _stdcallFilterRtlDispatchException (IN PEXCEPTION_RECORD ExceptionRecord,IN PCONTEXT ContextRecord);
VOID HookRtlDispatchException();
VOID UnloadDriver(PDRIVER_OBJECT DriverObject);
PLDR_DATA_TABLE_ENTRY SearchDriver(PDRIVER_OBJECT pDriverObject,wchar_t *strDriverName);
BOOLEAN    Jmp_HookFunction(IN ULONG Destination,IN ULONG Source,IN UCHAR *Ori_Code);
VOID ResumeHookFunction(IN ULONG    Destination,IN UCHAR    *Ori_Code,IN ULONG    Length);
ULONG_PTR SearchAddressForSignFromPE(ULONG_PTR uStartBase,ULONG_PTR uSearchLength,SIGNATURE_INFO SignatureInfo[5]);
VOID WPOFF();
NTSTATUS  _stdcall FilterNtOpenProcess ();
VOID WPON();
VOID SetMonitor(PVOID Address);
VOID CancelMonitor(PVOID Address);#ifndef CXX_DRXHOOK_H
#    include "DrxHook.h"
#endif#include <ntimage.h>KIRQL  Irql;
PDRIVER_OBJECT g_LocalDriverObj;
BOOLEAN        g_bHookSuccess;
ULONG_PTR      g_RtlDispatchExeceptionAddress;
ULONG_PTR      g_JmpOrigDispatchException;
UCHAR           g_cDisExceptionCode[5];ULONG_PTR g_JmpOrigNtOpenProcess;void __declspec(naked)  NewNtOpenProcess()
{__asm{pushadpushfdcall FilterNtOpenProcesspopfdpopadmov        edi , edipush       espmov        ebp , esp//跳过NtOpenProcess的前五个字节,//避免再次触发异常
        jmp        g_JmpOrigNtOpenProcess}
}void __declspec(naked) NewRtlDispatchException()
{__asm{mov   edi,edipush  ebpmov   ebp , esppushad     //保存所有寄存器pushfd     //保存标志寄存器push    [ebp+0xc]push    [ebp+0x8]call    FilterRtlDispatchException//检测返回值是否为0
        test    eax , eaxjz        __SafeExit  // 若eax为0 跳转__SafeExit
        popfdpopadmov        esp , ebppop        ebp//  将KiDispatchException中对于RtlDispatchException的返回值进行校验,//  如果为0 则对异常进行重新派发,为1则不再做处理mov        eax ,0x01   retn    0x8     //平衡堆栈,两个参数8字节

__SafeExit:popfdpopadmov        esp , ebppop        ebp//先执行RtlDispatchException原来的5个字节的内容
        mov        edi , edipush    ebpmov        ebp , espjmp g_JmpOrigDispatchException}
}NTSTATUS  _stdcall FilterNtOpenProcess ()
{DbgPrint("FilterNtOpenProcess---%s\r\n",(ULONG_PTR)PsGetCurrentProcess()+0x16c);return  STATUS_SUCCESS;
}ULONG_PTR _stdcallFilterRtlDispatchException (IN PEXCEPTION_RECORD ExceptionRecord,IN PCONTEXT ContextRecord)
{//DbgPrint("Address:%x -- ExceptionCode:%x\r\n",ExceptionRecord->ExceptionAddress,ExceptionRecord->ExceptionCode);//如果是NtOpenProcess处的异常if (ExceptionRecord->ExceptionAddress == (PVOID)KeServiceDescriptorTable.ServiceTableBase[190]){KdPrint(("<Except addresss>:%X <seh callBack>:%X -- <Except code>:%X",ContextRecord->Eip,ExceptionRecord->ExceptionAddress,ExceptionRecord->ExceptionCode));//将执行的下一条指令置为NewNtOpenProcess() 函数的地址,CPU接着去执行NewNtOpenProcessContextRecord->Eip = (ULONG_PTR)NewNtOpenProcess;//返回TRUE,异常不再进行派发return 1;}return 0;
}
VOID SetMonitor(PVOID Address)
{__asm{mov eax , Addressmov DR0 , eaxmov eax , 0x02  //全局的,仅当执行时产生异常
        mov DR7 , eax}
}VOID CancelMonitor(PVOID Address)
{__asm{xor eax , eaxmov DR0 , eaxmov DR7 , eax}
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING RegistryString)
{NTSTATUS    Status = STATUS_SUCCESS;g_LocalDriverObj = pDriverObject;HookRtlDispatchException();g_JmpOrigNtOpenProcess = (ULONG_PTR)(KeServiceDescriptorTable.ServiceTableBase[190] + 0x5);//为了方便,这里写死了,NtOpenProcess  Win7 x86 SetMonitor((PVOID)KeServiceDescriptorTable.ServiceTableBase[190]);return Status;
}VOID HookRtlDispatchException()
{PLDR_DATA_TABLE_ENTRY Ldr = NULL;//构建RtlDispatchException 的特征码//     nt!KiDispatchException+0x160://     83eff040 53              push    ebx//     83eff041 ff750c          push    dword ptr [ebp+0Ch]//     83eff044 ff7510          push    dword ptr [ebp+10h]//     83eff047 ff15bc49fb83    call    dword ptr [nt!KiDebugRoutine (83fb49bc)]//     83eff04d 84c0            test    al,al//     83eff04f 0f859d000000    jne     nt!KiDispatchException+0x211 (83eff0f2)//     83eff055 57              push    edi//     83eff056 53              push    ebx//     83eff057 e8 a372ffff      call    nt!RtlDispatchException (83ef62ff)//     kd> u 83ef62ff//     nt!RtlDispatchException://     83ef62ff 8bff            mov     edi,edi//     83ef6301 55              push    ebp//     83ef6302 8bec            mov     ebp,esp//     83ef6304 83e4f8          and     esp,0FFFFFFF8h//     83ef6307 83ec6c          sub     esp,6Ch//     83ef630a 53              push    ebx//     83ef630b 56              push    esi//     83ef630c 57              push    edi
SIGNATURE_INFO SignCode[] = {{0x84,10},{0xc0,9},{0x57,2},{0x53,1},{0xE8,0}};
#ifndef _DEBUG__asm int 3
#endif g_bHookSuccess  = FALSE;Ldr = SearchDriver(g_LocalDriverObj,L"ntoskrnl.exe");if (!Ldr)   return;g_RtlDispatchExeceptionAddress = SearchAddressForSignFromPE((ULONG_PTR)(Ldr->DllBase),Ldr->SizeOfImage,SignCode);    if (!MmIsAddressValid((PVOID)g_RtlDispatchExeceptionAddress))  return;//利用偏移转成绝对地址                                    +5 过e8 a372ffff 这五个字节g_RtlDispatchExeceptionAddress = g_RtlDispatchExeceptionAddress+5 + *(ULONG_PTR*)(g_RtlDispatchExeceptionAddress+1);//过被占的前5个字节,继续执行的代码DbgPrint("RtlDispatchExceptionAddresss:%x",g_RtlDispatchExeceptionAddress);g_JmpOrigDispatchException = g_RtlDispatchExeceptionAddress + 5;g_bHookSuccess = Jmp_HookFunction(g_RtlDispatchExeceptionAddress,(ULONG_PTR)NewRtlDispatchException,g_cDisExceptionCode);
}//搜索整个PE文件的
ULONG_PTR SearchAddressForSignFromPE(ULONG_PTR uStartBase,ULONG_PTR uSearchLength,SIGNATURE_INFO SignatureInfo[5])
{UCHAR *p;ULONG_PTR u_index1,u_index2;//ULONG uIndex;
    PIMAGE_DOS_HEADER pimage_dos_header;PIMAGE_NT_HEADERS pimage_nt_header;PIMAGE_SECTION_HEADER pimage_section_header;if(!MmIsAddressValid((PVOID)uStartBase)){    return 0;    }pimage_dos_header = (PIMAGE_DOS_HEADER)uStartBase;pimage_nt_header = (PIMAGE_NT_HEADERS)((ULONG)uStartBase+pimage_dos_header->e_lfanew);pimage_section_header = (PIMAGE_SECTION_HEADER)((ULONG)pimage_nt_header+sizeof(IMAGE_NT_HEADERS));for (u_index1 = 0;u_index1<pimage_nt_header->FileHeader.NumberOfSections;u_index1++){//#define IMAGE_SCN_MEM_EXECUTE                0x20000000  // Section is executable.//#define IMAGE_SCN_MEM_READ                   0x40000000  // Section is readable.//#define IMAGE_SCN_MEM_WRITE                  0x80000000  // Section is writeable.//0x60000000 = IMAGE_SCN_MEM_EXECUTE|IMAGE_SCN_MEM_READif (pimage_section_header[u_index1].Characteristics&0x60000000){p = (UCHAR*)uStartBase + pimage_section_header[u_index1].VirtualAddress;for (u_index2 = 0;u_index2<pimage_section_header[u_index1].Misc.VirtualSize;u_index2++){if (!MmIsAddressValid((p-SignatureInfo[0].Offset))||!MmIsAddressValid((p-SignatureInfo[4].Offset))){p++;continue;}__try{if (*(p-SignatureInfo[0].Offset)==SignatureInfo[0].cSingature&&*(p-SignatureInfo[1].Offset)==SignatureInfo[1].cSingature&&*(p-SignatureInfo[2].Offset)==SignatureInfo[2].cSingature&&*(p-SignatureInfo[3].Offset)==SignatureInfo[3].cSingature&&*(p-SignatureInfo[4].Offset)==SignatureInfo[4].cSingature){return (ULONG_PTR)p;}}__except(EXCEPTION_EXECUTE_HANDLER){DbgPrint("Search error!");}p++;}}}return 0;
}BOOLEAN    Jmp_HookFunction(IN ULONG Destination,IN ULONG Source,IN UCHAR *Ori_Code)
{ULONG    jmp_offset;UCHAR    jmp_code[5] = {0xE9};KSPIN_LOCK lock;KIRQL irql;if (Destination==0||Source==0){DbgPrint("Params error!");return FALSE;}RtlCopyMemory(Ori_Code,(PVOID)Destination,5);jmp_offset = Source - (Destination+5);*(ULONG*)&jmp_code[1] = jmp_offset;   //放入偏移
KeInitializeSpinLock (&lock );KeAcquireSpinLock(&lock,&irql);WPOFF();RtlCopyMemory((PVOID)Destination,jmp_code,5);WPON();KeReleaseSpinLock (&lock,irql);return TRUE;
}VOID WPOFF()
{ULONG_PTR cr0 = 0;Irql = KeRaiseIrqlToDpcLevel();cr0 =__readcr0();cr0 &= 0xfffffffffffeffff;__writecr0(cr0);}VOID WPON()
{ULONG_PTR cr0=__readcr0();cr0 |= 0x10000;__writecr0(cr0);KeLowerIrql(Irql);
}//简单的通过链表获得内核模块的基本信息
PLDR_DATA_TABLE_ENTRY SearchDriver(PDRIVER_OBJECT pDriverObject,wchar_t *strDriverName)
{LDR_DATA_TABLE_ENTRY    *pdata_table_entry,*ptemp_data_table_entry;PLIST_ENTRY                plist;UNICODE_STRING            str_module_name;RtlInitUnicodeString(&str_module_name,strDriverName);pdata_table_entry = (LDR_DATA_TABLE_ENTRY*)pDriverObject->DriverSection;if (!pdata_table_entry){return 0;}plist = pdata_table_entry->InLoadOrderLinks.Flink;while(plist!= &pdata_table_entry->InLoadOrderLinks){ptemp_data_table_entry = (LDR_DATA_TABLE_ENTRY *)plist;//DbgPrint("%wZ",&pTempDataTableEntry->BaseDllName);if (0==RtlCompareUnicodeString(&ptemp_data_table_entry->BaseDllName,&str_module_name,FALSE)){return ptemp_data_table_entry;}plist = plist->Flink;}return 0;
}VOID UnloadDriver(PDRIVER_OBJECT DriverObject)
{if (g_bHookSuccess){ResumeHookFunction(g_RtlDispatchExeceptionAddress,g_cDisExceptionCode,0x5);}}VOID ResumeHookFunction(IN ULONG    Destination,IN UCHAR    *Ori_Code,IN ULONG    Length)
{KSPIN_LOCK lock;KIRQL irql;if (Destination==0||Ori_Code==0)    return;    KeInitializeSpinLock (&lock );KeAcquireSpinLock(&lock,&irql);WPOFF();RtlCopyMemory((PVOID)Destination,Ori_Code,Length);WPON();KeReleaseSpinLock (&lock,irql);
}

转载于:https://www.cnblogs.com/lanrenxinxin/p/4680320.html

硬件断点 DrxHook相关推荐

  1. 硬件断点反跳似乎_高性能应用程序:多路复用,反跳,系统字体和其他技巧

    硬件断点反跳似乎 by Atila Fassina 通过阿蒂拉·法西纳(Atila Fassina) 高性能应用程序:多路复用,反跳,系统字体和其他技巧 (High Performance Apps: ...

  2. 【Windows 逆向】OD 调试器工具 ( 分析 OD 硬件断点处的关键代码 | 添加硬件断点 | 关键代码 | MOV 指令 | EAX 寄存器值分析 | 使用命令查看 esi+0cc 地址 )

    文章目录 一.添加硬件断点 二.关键代码 三.MOV 汇编指令格式 四.EAX 寄存器值分析 五.使用命令查看 esi+0cc 地址 一.添加硬件断点 在上一篇博客中 , 在子弹个数数据内存地址 07 ...

  3. 【Windows 逆向】OD 调试器工具 ( OD 调试数据时硬件断点对应的关键代码 | 删除硬件端点恢复运行 )

    文章目录 前言 一.OD 调试数据时硬件断点对应的关键代码 二.删除硬件端点恢复运行 前言 在 [Windows 逆向]OD 调试器工具 ( CE 中获取子弹动态地址前置操作 | OD 中调试指定地址 ...

  4. 软件调试学习笔记(六)—— 硬件断点

    软件调试学习笔记(六)-- 硬件断点 硬件断点 设置硬件断点 触发硬件断点 处理硬件断点 实验:硬件断点的设置与处理 硬件断点 描述: 与软件断点与内存断点不同,硬件断点不依赖被调试程序,而是依赖于C ...

  5. [系统安全] 二十四.逆向分析之OllyDbg调试INT3断点、反调试、硬件断点与内存断点

    您可能之前看到过我写的类似文章,为什么还要重复撰写呢?只是想更好地帮助初学者了解病毒逆向分析和系统安全,更加成体系且不破坏之前的系列.因此,我重新开设了这个专栏,准备系统整理和深入学习系统安全.逆向分 ...

  6. OD的 CC断点,内存访问断点,硬件断点 解析

    1.F2断点,API断点 1)本质CC断点 2)以API断点为例 xxxx=GetProcAddress//获得函数首 地址 VitualProtectEx()//修改函数首地址权限为 可写     ...

  7. X86逆向教程10:学会使用硬件断点

    本节课我们将学习硬件断点的使用技巧,硬件断点是由硬件提供给我们的一组寄存器,我们可以对这些硬件寄存器设置相应的值,然后让硬件帮我们断在需要下断点的地址上面,这就是硬件断点,硬件断点依赖于寄存器,这些寄 ...

  8. 如何对抗硬件断点--- 调试寄存器

    1.前言 在我跨入ollydbg的门的时候,就对ollydbg里面的各种断点充满了疑问,以前我总是不明白普通断点,内存断点,硬件断点有什么区别,他们为什么 有些时候不能混用,他们的原理是什么,在学习了 ...

  9. 小甲鱼 OllyDbg 教程系列 (四) : 逆向 VisualSite Designer 之 硬件断点

    去掉程序开始之前的界面:https://www.bilibili.com/video/av6889190?p=9 去掉关闭程序后的广告:https://www.bilibili.com/video/a ...

最新文章

  1. 3D 可视化,卷积、池化清清楚楚!网友:终于能看懂神经网络到底在干啥了......
  2. 人工智能缺陷与误觉:让机器产生幻觉的「怪异事件」 1
  3. @Autowired注解警告Field injection is not recommended
  4. scala简明教程:偏函数、高阶函数、Future异步编程、隐式转换
  5. python2打开文件_关于python:何时以二进制模式打开文件(b)?
  6. go 怎么等待所有的协程完成_理解真实世界中 Go 的并发 BUG
  7. Lazarus 1.6 增加了新的窗体编辑器——Sparta_DockedFormEditor.ipk
  8. Python 使用pdfplumber 提取PDF页面表格的内容
  9. 同一个IP段ping不通同事的电脑
  10. DI使用value属性与value标签的区别以及xml预定义实体引用
  11. [译] Bulma: 2018年你应该关注的CSS框架
  12. 设计模式(一):代理模式
  13. 190405每日一句
  14. 用 JavaScript 实现内存位翻转漏洞
  15. python成语接龙代码_Python实现成语接龙
  16. MicroRNAs在HBV阳性肝细胞癌免疫耐受形成中的功能及机制研究
  17. canvas实现走势图实现
  18. 【厚积薄发系列】C++项目总结20—pdb和dump服务器部署以及结合windbg自动下载
  19. A星融合DWA的路径规划算法,可实现静态避障碍及动态避障,代码注释详细,matlab源码
  20. 不要慌,我有亿点小建议!万字长文

热门文章

  1. 目前电子计算机已经发展到______阶段,《全国高校计算机联合考试广西考区一级笔试试题卷.doc...
  2. 【mysql】SCOPE_IDENTITY 和 @@IDENTITY的区别
  3. Eclipse 打开文件出现乱码情况总结
  4. mfc 饼图绘画_绘画技能干货 | 【人体头颈】的绘画技巧(三)(内含母亲节抽奖公布)...
  5. java程序设计_JAVA基础程序设计之方法
  6. hadoop删除DataNode节点
  7. spring 通过EsClientFactory注入elasticsearch
  8. eclipse菜单字体乱码的解决
  9. Pandas数据探索分析,分享两个神器!
  10. Python可变数据类型高效编程