硬件断点 DrxHook
硬件断点的实现需要依赖于调试寄存器
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相关推荐
- 硬件断点反跳似乎_高性能应用程序:多路复用,反跳,系统字体和其他技巧
硬件断点反跳似乎 by Atila Fassina 通过阿蒂拉·法西纳(Atila Fassina) 高性能应用程序:多路复用,反跳,系统字体和其他技巧 (High Performance Apps: ...
- 【Windows 逆向】OD 调试器工具 ( 分析 OD 硬件断点处的关键代码 | 添加硬件断点 | 关键代码 | MOV 指令 | EAX 寄存器值分析 | 使用命令查看 esi+0cc 地址 )
文章目录 一.添加硬件断点 二.关键代码 三.MOV 汇编指令格式 四.EAX 寄存器值分析 五.使用命令查看 esi+0cc 地址 一.添加硬件断点 在上一篇博客中 , 在子弹个数数据内存地址 07 ...
- 【Windows 逆向】OD 调试器工具 ( OD 调试数据时硬件断点对应的关键代码 | 删除硬件端点恢复运行 )
文章目录 前言 一.OD 调试数据时硬件断点对应的关键代码 二.删除硬件端点恢复运行 前言 在 [Windows 逆向]OD 调试器工具 ( CE 中获取子弹动态地址前置操作 | OD 中调试指定地址 ...
- 软件调试学习笔记(六)—— 硬件断点
软件调试学习笔记(六)-- 硬件断点 硬件断点 设置硬件断点 触发硬件断点 处理硬件断点 实验:硬件断点的设置与处理 硬件断点 描述: 与软件断点与内存断点不同,硬件断点不依赖被调试程序,而是依赖于C ...
- [系统安全] 二十四.逆向分析之OllyDbg调试INT3断点、反调试、硬件断点与内存断点
您可能之前看到过我写的类似文章,为什么还要重复撰写呢?只是想更好地帮助初学者了解病毒逆向分析和系统安全,更加成体系且不破坏之前的系列.因此,我重新开设了这个专栏,准备系统整理和深入学习系统安全.逆向分 ...
- OD的 CC断点,内存访问断点,硬件断点 解析
1.F2断点,API断点 1)本质CC断点 2)以API断点为例 xxxx=GetProcAddress//获得函数首 地址 VitualProtectEx()//修改函数首地址权限为 可写 ...
- X86逆向教程10:学会使用硬件断点
本节课我们将学习硬件断点的使用技巧,硬件断点是由硬件提供给我们的一组寄存器,我们可以对这些硬件寄存器设置相应的值,然后让硬件帮我们断在需要下断点的地址上面,这就是硬件断点,硬件断点依赖于寄存器,这些寄 ...
- 如何对抗硬件断点--- 调试寄存器
1.前言 在我跨入ollydbg的门的时候,就对ollydbg里面的各种断点充满了疑问,以前我总是不明白普通断点,内存断点,硬件断点有什么区别,他们为什么 有些时候不能混用,他们的原理是什么,在学习了 ...
- 小甲鱼 OllyDbg 教程系列 (四) : 逆向 VisualSite Designer 之 硬件断点
去掉程序开始之前的界面:https://www.bilibili.com/video/av6889190?p=9 去掉关闭程序后的广告:https://www.bilibili.com/video/a ...
最新文章
- 3D 可视化,卷积、池化清清楚楚!网友:终于能看懂神经网络到底在干啥了......
- 人工智能缺陷与误觉:让机器产生幻觉的「怪异事件」 1
- @Autowired注解警告Field injection is not recommended
- scala简明教程:偏函数、高阶函数、Future异步编程、隐式转换
- python2打开文件_关于python:何时以二进制模式打开文件(b)?
- go 怎么等待所有的协程完成_理解真实世界中 Go 的并发 BUG
- Lazarus 1.6 增加了新的窗体编辑器——Sparta_DockedFormEditor.ipk
- Python 使用pdfplumber 提取PDF页面表格的内容
- 同一个IP段ping不通同事的电脑
- DI使用value属性与value标签的区别以及xml预定义实体引用
- [译] Bulma: 2018年你应该关注的CSS框架
- 设计模式(一):代理模式
- 190405每日一句
- 用 JavaScript 实现内存位翻转漏洞
- python成语接龙代码_Python实现成语接龙
- MicroRNAs在HBV阳性肝细胞癌免疫耐受形成中的功能及机制研究
- canvas实现走势图实现
- 【厚积薄发系列】C++项目总结20—pdb和dump服务器部署以及结合windbg自动下载
- A星融合DWA的路径规划算法,可实现静态避障碍及动态避障,代码注释详细,matlab源码
- 不要慌,我有亿点小建议!万字长文
热门文章
- 目前电子计算机已经发展到______阶段,《全国高校计算机联合考试广西考区一级笔试试题卷.doc...
- 【mysql】SCOPE_IDENTITY 和 @@IDENTITY的区别
- Eclipse 打开文件出现乱码情况总结
- mfc 饼图绘画_绘画技能干货 | 【人体头颈】的绘画技巧(三)(内含母亲节抽奖公布)...
- java程序设计_JAVA基础程序设计之方法
- hadoop删除DataNode节点
- spring 通过EsClientFactory注入elasticsearch
- eclipse菜单字体乱码的解决
- Pandas数据探索分析,分享两个神器!
- Python可变数据类型高效编程