小弟新手,有空写了个调试寄存器Hook(硬件中断),问题如下:
1.直接双击exe,debug版本没有问题;release版本hook不成功,仍然调用原函数???
2.由VC调试,运行后,直接在原API处断下,按F5没有用,一直断下.为什么会会一直停留在原API处?
整个工程也附上了,VS2008平台,还请兄弟们帮忙看下 哈:)
代码如下:
/************************************************************************
SetHardWareBP:
设置线程硬件断点
hThread: 线程句柄
dwAddr: 断点地址
dwDrIndex: 硬件寄存器(0~3)
nType: 断点类型(0:执行,1:读取,2:写入 3:读写)
nLen: 读写断点数据长度(1,2,4)
/************************************************************************/
BOOL SetHardWareBP(HANDLE hThread,DWORD dwAddr,DWORD dwDrIndex,UINT nType=0,UINT nLen=1)
{
BOOL bResult=FALSE;
WORD wLen;
TRACE("SetHardWareBP Enter:hThread=0x%p, dwAddr=0x%p, dwDrIndex=%d, nType=%d, nLen=%d ...\n",
hThread, dwAddr, dwDrIndex, nType, nLen);
//参数校验
if (dwDrIndex < 0 || dwDrIndex >= 4)
{
TRACE("invalid para dwDrIndex");
return FALSE;
}
if (IsBadCodePtr((FARPROC)dwAddr))
{
TRACE("invalid para dwAddr");
return FALSE;
}
if (nType < 0 || nType > 3)
{
TRACE("invalid para nType");
return FALSE;
}
/*
6. LEN0-LEN3:(由第18.19.22.23.26.27.30位控制):指定内存操作的大小。
00:1字节(执行断点只能是1字节长)
01:2字节
10:未定义或者是8字节(和cpu的系列有关系)
11:4字节
*/
if (nLen == 1)
{
wLen = 0;
}
else if (nType == 0)
{
wLen = 0;
}
else if (nLen == 2)
{
if (dwAddr % 2 != 0)
{
TRACE("invalid para dwAddr:not mod 2");
return FALSE;
}
else
{
wLen = 1;
}
}
else if (nLen == 4)
{
if (dwAddr % 4 != 0)
{
TRACE("invalid para dwAddr:not mod 4");
return FALSE;
}
else
{
wLen = 3;
}
}
else
{
TRACE("invalid para dwAddr");
return FALSE;
}
CONTEXT context = {0};
context.ContextFlags=CONTEXT_DEBUG_REGISTERS;
if(::GetThreadContext(hThread,&context))
{
DWORD dwDrFlags=context.Dr7;
TRACE("begin Dr7=0x%x\n", dwDrFlags);
//将断点地址复制进入对应Dr寄存器(参考CONTEXT结构)
memcpy(((BYTE *)&context)+4+dwDrIndex*4,&dwAddr,4);
//决定使用哪个寄存器
dwDrFlags|=(DWORD)0x1<<(2*dwDrIndex);
TRACE("Dr7=0x%x\n", dwDrFlags);
//见OD读写断点时 这个置位了,执行没有(置位也正常-_-)
dwDrFlags|=0x100;
TRACE("Dr7=0x%x\n", dwDrFlags);
//先将对应寄存器对应4个控制位清零(先或,再异或,还有其它好方法吗) =.= 悲催的小学生
// dwDrFlags|=(DWORD)0xF<<(16+4*dwDrIndex);
// dwDrFlags^=(DWORD)0xF<<(16+4*dwDrIndex);
DWORD dwTemp = (~((DWORD)0xF<<(16+4*dwDrIndex)));
TRACE("dwTemp=0x%x\n", dwTemp);
dwDrFlags &= dwTemp;
TRACE("Dr7=0x%x\n", dwDrFlags);
//设置断点类型,执行:00 读取:10 写入:01 读写:11
dwDrFlags|=(DWORD)nType<<(16+4*dwDrIndex); //读取
TRACE("Dr7=0x%x\n", dwDrFlags);
//设置读写断点时数据长度
dwDrFlags|=(DWORD)wLen<<(18+4*dwDrIndex);
context.Dr7=dwDrFlags;
TRACE("end Dr7=0x%x\n", dwDrFlags);
if (::SetThreadContext(hThread,&context))
{
bResult=TRUE;
TRACE("SetThreadContext successfully.\n");
}
else
{
TRACE("SetThreadContext failed.err=0x%x", GetLastError());
}
}
return bResult;
}
/************************************************************************
ClearHardWareBP:
取消线程硬件断点
hThread: 线程句柄
dwAddr: 断点地址
dwDrIndex: 硬件寄存器(0~3)
nType: 断点类型(0:执行,1:读取,2:写入 3:读写)
nLen: 读写断点数据长度(1,2,4)
/************************************************************************/
BOOL ClearHardWareBP(HANDLE hThread, DWORD dwDrIndex)
{
BOOL bResult=FALSE;
// WORD wLen;
TRACE("ClearHardWareBP Enter:hThread=0x%p, dwDrIndex=%d \n",
hThread, dwDrIndex);
//参数校验
if (dwDrIndex < 0 || dwDrIndex >= 4)
{
TRACE("invalid para dwDrIndex");
return FALSE;
}
CONTEXT context = {0};
context.ContextFlags=CONTEXT_DEBUG_REGISTERS;
if(::GetThreadContext(hThread,&context))
{
DWORD dwDrFlags=context.Dr7;
TRACE("begin Dr7=0x%x\n", dwDrFlags);
//将断点地址复制进入对应Dr寄存器(参考CONTEXT结构)
memset(((BYTE *)&context)+4+dwDrIndex*4, 0, 4);
//决定使用哪个寄存器 L0-3/G0-3 清0
dwDrFlags &= (~((DWORD)0x3<<(2*dwDrIndex)));
//见OD读写断点时 这个置位了,执行没有(置位也正常-_-) --LE清0
/*dwDrFlags &= !((DWORD)0x100);*/
//先将对应寄存器对应4个控制位清零(先或,再异或,还有其它好方法吗) =.= 悲催的小学生
dwDrFlags &= (~((DWORD)0xF<<(16+4*dwDrIndex)));
//设置断点类型,执行:00 读取:10 写入:01 读写:11
//dwDrFlags|=(DWORD)nType<<(16+4*dwDrIndex); //读取
//设置读写断点时数据长度
//dwDrFlags|=(DWORD)wLen<<(18+4*dwDrIndex);
context.Dr7=dwDrFlags;
TRACE("end Dr7=0x%x\n", dwDrFlags);
if (::SetThreadContext(hThread,&context))
{
TRACE("SetThreadContext successfully.\n");
bResult=TRUE;
}
else
{
TRACE("SetThreadContext failed.err=0x%x\n", GetLastError());
}
}
return bResult;
}
PVOID g_pSehHandle = NULL;
BOOL AddSystemSehHandler() //添加异常处理SEH
{
TRACE("AddSystemSehHandler Enter... \n");
if (g_pSehHandle)
{
TRACE("SEH have been added");
return FALSE;
}
if (g_pSehHandle = AddVectoredExceptionHandler(1, (PVECTORED_EXCEPTION_HANDLER)ExceptionHandler))
{
TRACE("AddSystemSehHandler successfully \n");
return TRUE;
}
else
{
TRACE("AddSystemSehHandler failed \n");
return FALSE;
}
}
BOOL DelSystemSehHandler()
{
TRACE("DelSystemSehHandler Enter... \n");
if (!g_pSehHandle)
{
TRACE("SEH not added");
return FALSE;
}
if (RemoveVectoredExceptionHandler(g_pSehHandle))
{
TRACE("DelSystemSehHandler successfully \n");
g_pSehHandle = NULL;
return TRUE;
}
else
{
TRACE("DelSystemSehHandler failed \n");
}
g_pSehHandle = NULL;
return FALSE;
}
//异常处理函数 ---若调试器启动状态下,异常不会进入此处,因为内核优先分发异常给调试器
DWORD NTAPI ExceptionHandler(EXCEPTION_POINTERS * ExceptionInfo)
{
//if (ExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_SINGLE_STEP) //硬件断点执行触发的是单步调试
{
if ((DWORD)ExceptionInfo->ExceptionRecord->ExceptionAddress == (DWORD)TestFun)
{
//直接改eip为目的函数,原函数直接被过滤
ExceptionInfo->ContextRecord->Eip = (DWORD)HookedTestFun;
return EXCEPTION_CONTINUE_EXECUTION;
}
else if ((DWORD)ExceptionInfo->ExceptionRecord->ExceptionAddress == (DWORD)TestFun2)
{
//直接改eip为目的函数,原函数直接被过滤
ExceptionInfo->ContextRecord->Eip = (DWORD)HookedTestFun2;
return EXCEPTION_CONTINUE_EXECUTION;
}
else if ((DWORD)ExceptionInfo->ExceptionRecord->ExceptionAddress == (DWORD)TestFun3)
{
//直接改eip为目的函数,原函数直接被过滤
ExceptionInfo->ContextRecord->Eip = (DWORD)HookedTestFun3;
return EXCEPTION_CONTINUE_EXECUTION;
}
else if ((DWORD)ExceptionInfo->ExceptionRecord->ExceptionAddress == (DWORD)TestFun4)
{
//直接改eip为目的函数,原函数直接被过滤
ExceptionInfo->ContextRecord->Eip = (DWORD)HookedTestFun4;
return EXCEPTION_CONTINUE_EXECUTION;
}
}
return EXCEPTION_CONTINUE_SEARCH;
// else
// {
// //在异常handler里重设drx防止断点被意外清除
// ExceptionInfo->ContextRecord->Dr0 = 0x6f3a20dd;
// ExceptionInfo->ContextRecord->Dr1 = 0x6f361f7b;
// ExceptionInfo->ContextRecord->Dr7 = 0x405;
// return EXCEPTION_CONTINUE_SEARCH;
// }
}
void TestFun()
{
_asm
{
mov eax,eax
mov eax,eax
}
OutputDebugString("TestFun is running...\n");
AfxMessageBox("TestFun");
}
void HookedTestFun()
{
_asm
{
mov ebx,ebx
mov ebx,ebx
}
OutputDebugString("HookedTestFun is running...\n");
AfxMessageBox("HookedTestFun");
}
//////////////////////////////////////////////////////////////////////////
void CDrxHookTestDlg::OnBnClickedButton4()
{
// TODO: 在此添加控件通知处理程序代码
TestFun();
TestFun2();
TestFun3();
TestFun4();
}
void CDrxHookTestDlg::OnBnClickedButton5()
{
// TODO: 在此添加控件通知处理程序代码
AddSystemSehHandler();
_asm
{
mov ecx,ecx
mov ecx,ecx
}
SetHardWareBP(GetCurrentThread(), (DWORD)TestFun, 1, 0, 1);
SetHardWareBP(GetCurrentThread(), (DWORD)TestFun2, 2, 0, 1);
SetHardWareBP(GetCurrentThread(), (DWORD)TestFun3, 3, 0, 1);
SetHardWareBP(GetCurrentThread(), (DWORD)TestFun4, 0, 0, 1);
//SetHardWareBP(GetCurrentThread(), (DWORD)0x004131D0, 1, 0, 1);
}
void CDrxHookTestDlg::OnBnClickedButton6()
{
// TODO: 在此添加控件通知处理程序代码
ClearHardWareBP(GetCurrentThread(), 0);
ClearHardWareBP(GetCurrentThread(), 1);
ClearHardWareBP(GetCurrentThread(), 2);
ClearHardWareBP(GetCurrentThread(), 3);
DelSystemSehHandler();
}
复件 DrxHookTest.zip
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)