1. 程式人生 > >VC利用調試寄存器實現硬件斷點源碼

VC利用調試寄存器實現硬件斷點源碼

.com new 繼續 add proc 興趣 xe8 else if 發生

【文章標題】:VC利用調試寄存器實現硬件斷點源碼
【文章作者】:yhswwr(SilenceRet)
【作者QQ】:3412259
【編寫語言】:C++
【使用工具】:VS2008.VC++9
【本文鏈接】:http://bbs.pediy.com/showthread.php?p=1122838
【參考鏈接】:http://bbs.pediy.com/showthread.php?t=107515
【作者聲明】:只是感興趣,沒有其他目的。失誤之處敬請諸位大俠賜教!(當前行剽竊自justhxy)
/************************************************************************
SetHardWareBP:
設置線程硬件斷點
hThread:	線程句柄
dwAddr:		斷點地址
dwDrIndex:	硬件寄存器(0~3)
nType:		斷點類型(0:執行,1:讀取,2:寫入)
nLen:		讀寫斷點數據長度(1,2,4)
/************************************************************************/

BOOL SetHardWareBP(HANDLE hThread,DWORD dwAddr,DWORD dwDrIndex=0,UINT nType=0,UINT nLen=1)
{
	BOOL bResult=FALSE;
	
	CONTEXT context = {0};
	context.ContextFlags=CONTEXT_DEBUG_REGISTERS;
	if(::GetThreadContext(hThread,&context))
	{
		DWORD dwDrFlags=context.Dr7;


		//將斷點地址復制進入對應Dr寄存器(參考CONTEXT結構)
		memcpy(((BYTE *)&context)+4+dwDrIndex*4,&dwAddr,4);	
		
		//決定使用哪個寄存器
		dwDrFlags|=(DWORD)0x1<<(2*dwDrIndex);

		//見OD讀寫斷點時 這個置位了,執行沒有(置位也正常-_-)
		dwDrFlags|=0x100;
		

		//先[COLOR="Sienna"]將對應寄存器對應4個控制位清零(先或,再異或,還有其它好方法嗎)[/COLOR] =.= 悲催的小學生
		dwDrFlags|=(DWORD)0xF<<(16+4*dwDrIndex);
		dwDrFlags^=(DWORD)0xF<<(16+4*dwDrIndex);
		

		//設置斷點類型,執行:00 讀取:11 寫入:01
		//([B][COLOR="Olive"]不知何故,測試時發現不論是11還是01,讀寫數據時均會斷下來[/COLOR][/B])
		if (nType==1)		
			dwDrFlags|=(DWORD)0x3<<(16+4*dwDrIndex);	//讀取
		else if(nType==2)	
			dwDrFlags|=(DWORD)0x1<<(16+4*dwDrIndex);	//寫入
		//else if(nType==0) 
			//dwDrFlags=dwDrFlags						//執行
		

		//設置讀寫斷點時數據長度
		if (nType!=0)
		{
			if(nLen==2 && dwAddr%2==0)			
				dwDrFlags|=(DWORD)0x1<<(18+4*dwDrIndex);	//2字節
			else if(nLen==4  && dwAddr%4==0)	
				dwDrFlags|=(DWORD)0x3<<(18+4*dwDrIndex);	//4字節
		}
		
		context.Dr7=dwDrFlags;
		if (::SetThreadContext(hThread,&context)) bResult=TRUE;
	}
	return bResult;
}



//異常處理
//直接從工程中拷出來的
typedef ULONG (WINAPI *pfnRtlDispatchException)(PEXCEPTION_RECORD pExcptRec,CONTEXT * pContext);
static pfnRtlDispatchException m_fnRtlDispatchException=NULL;

BOOL RtlDispatchException(PEXCEPTION_RECORD pExcptRec,CONTEXT * pContext);

ULONG WINAPI CSysHook::_RtlDispatchException( PEXCEPTION_RECORD pExcptRec,CONTEXT * pContext )
{
	if(RtlDispatchException(pExcptRec,pContext)) return 1;
	return m_fnRtlDispatchException(pExcptRec,pContext);
}

//Hook程序異常處理,當程序發生異常時,由ring0轉回ring3時調用的第一個函數:KiUserExceptionDispatcher
BOOL CSysHook::HookSystemSEH()
{
	BOOL bResult=FALSE;
	BYTE *pAddr=(BYTE *)::GetProcAddress(::GetModuleHandleA("ntdll"),"KiUserExceptionDispatcher");
	if (pAddr)
	{
		while (*pAddr!=0xE8)pAddr++;  //XP~Win7正常,Win8尚無緣得見
		m_fnRtlDispatchException=(pfnRtlDispatchException)((*(DWORD *)(pAddr+1))+5+(DWORD)pAddr);	//得到原函數地址
		DWORD dwNewAddr=(DWORD)_RtlDispatchException-(DWORD)pAddr-5;								//計算新地址
		CMemory::WriteMemory((DWORD)pAddr+1,(BYTE *)&dwNewAddr,4);	//這個寫內存的自己改造吧
		bResult=TRUE;
	}
	return bResult;
}

[COLOR="Olive"]//異常處理函數
BOOL RtlDispatchException(PEXCEPTION_RECORD pExcptRec,CONTEXT * pContext)
{
   返回TRUE,這個異常我已經處理好了,繼續運行程序
   返回FALSE,這個異常不是我的,找別人處理去
}[/COLOR]

jpg改rar技術分享圖片

VC利用調試寄存器實現硬件斷點源碼