-
-
[求助]关于DebugAPI的问题
-
发表于: 2010-1-17 15:32 3661
-

看雪在加密书的第三版《软件加密技术内幕》,对DebugAPI函数进行了介绍,也给也了一些代码例子。
调试一个程序可以用CreateProcess的方式,也可以用DebugActiveProcess方式,不论哪种方式,都会先产生一个EXCEPTION_BREAKPOINT(断点错误)。
问题一:要在指定的EIP下断点,是在调试事件为:CREATE_PROCESS_DEBUG_EVENT时呢?还是在调试事件为:EXCEPTION_DEBUG_EVENT时,且异常为:EXCEPTION_BREAKPOINT昵呢?
对指定的EIP下断点,可以用WriteProcessMemory写0xCC下断点(INT 3)方式(响应异常为EXCEPTION_BREAKPOINT),也可以置Dr0和Dr7调试寄存器(响应异常为EXCEPTION_SINGLE_STEP)。
问题二:用DebugActiveProceee调试进程,用Drx寄存器下断点是不是像《技术内幕》中所说的要经过一个NtContinue的跳板?还有,被调试进程为多线,用Drx寄存器下断点时,取/设置线程上下文函数参数:线程句柄,是主线程句柄?还是用当前线程句柄?当前线程句柄是用OpenThread(THREAD_ALL_ACCESS, FALSE, (DWORD)DBE.dwThreadId);获取?
按《技术内幕》中相关代码,作了一些修改,为什么不能中断在单步异常中?
//===========================
//
// Debug线程执行体
// 返回:失败返加零值
//
//===========================
UINT ThreadProc(LPVOID pParam)
{
CMyDlg* pDlg=(CMyDlg*)pParam;
CString mssg;
if(!::DebugActiveProcess((DWORD)dwProcessId))
{
mssg.Format("Debug挂接失败!\n代码:%d",::GetLastError());
::MessageBox(NULL,mssg,"挂接进程",0x1040);
return 0;
}
DEBUG_EVENT DBE;
CONTEXT Regs ;
DWORD dwState; //取值DBG_EXCEPTION_NOT_HANDLED (程序不处理的异常,由系统处理)
//或 DBG_CONTINUE;(程序不处理的异常,系统不会处理)
DWORD dwBpCnt; //断点错误的执行次数
DWORD dwSsCnt; //单步异常的执行数
dwBpCnt = dwSsCnt = 1 ;
IsActiveStop = false; //设置脱离进程标志为FALSE(即不脱离)
Regs.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
IsActiveStop = FALSE;
while(TRUE)
{
::WaitForDebugEvent(&DBE, INFINITE);
dwState = DBG_EXCEPTION_NOT_HANDLED;
//调试事件
switch(DBE.dwDebugEventCode)
{
//创建进程
case CREATE_PROCESS_DEBUG_EVENT:
MainThreadHandle = DBE.u.CreateProcessInfo.hThread;
ProcessHandle = DBE.u.CreateProcessInfo.hProcess;
MainProcessID = DBE.dwProcessId;
dwBpCnt = 1;
dwSsCnt = 1;
/*
::GetThreadContext(DBE.u.CreateProcessInfo.hThread,&Regs);
Regs.Dr0 = 0x722158fe;
Regs.Dr7 = 0x101;
if(::SetThreadContext(DBE.u.CreateProcessInfo.hThread,&Regs) == 0)
{
mssg.Format("创建进程时,设置Context失败!\n代码:%08X",::GetLastError());
::MessageBox(NULL,mssg,"Set Context fail",0x1040);
}
*/
break;
//创建线程
case CREATE_THREAD_DEBUG_EVENT:
break;
//退出进程
case EXIT_PROCESS_DEBUG_EVENT:
break;
//退出线程
case EXIT_THREAD_DEBUG_EVENT:
break;
//装载DLL
case LOAD_DLL_DEBUG_EVENT:
break;
//卸载DLL
case UNLOAD_DLL_DEBUG_EVENT:
break;
//发送DEBUG String
case OUTPUT_DEBUG_STRING_EVENT:
break;
//异常中断
case EXCEPTION_DEBUG_EVENT:
switch(DBE.u.Exception.ExceptionRecord.ExceptionCode)
{
case EXCEPTION_BREAKPOINT://断点错误
if(dwBpCnt == 1) //挂接进程后,会产生一次断点错误,地址在0x7CXXXXXX处
{
// 722158fe
//Dr0时,Dr7=0x101 = 100000001b
//Dr1时,Dr7=0x104 = 100000100b
//Dr2时,Dr7=0x110 = 100010000b
//Dr3时,Dr7=0x140 = 101000000b
//Dr1 - Dr4四个都使用时,Dr7=0x155 = 101010101;
// HANDLE TempThreadHandle = MyOpenThread(THREAD_ALL_ACCESS, FALSE, (DWORD)DBE.dwThreadId);
::GetThreadContext(MainThreadHandle,&Regs);
Regs.Dr0 = (DWORD)(::GetProcAddress(::GetModuleHandle(_T("ntdll.dll")),_T("NtContinue")));
Regs.Dr7 = 0x155;
::SetThreadContext(MainThreadHandle,&Regs);
dwBpCnt = 2;
dwSsCnt = 1;
mssg.Format("中断在:%08X\n下新断点:%08X\n",DBE.u.Exception.ExceptionRecord.ExceptionAddress,Regs.Dr0);
::MessageBox(NULL,mssg,"Int 3 Setp",0x1040);
// ::CloseHandle(TempThreadHandle);
// dwState = DBG_CONTINUE; //产生的异常由我们的程序处理。
}
break;
case EXCEPTION_SINGLE_STEP://单步异常,用Dr0 - Dr4下断点,会产生单步异常
::MessageBox(NULL,"进入单步异常!","Single Setp",0x1040);
if(dwSsCnt == 1)
{
::GetThreadContext(MainThreadHandle,&Regs);
Regs.Dr0 = 0;
Regs.Dr7 = 0;
::SetThreadContext(MainThreadHandle,&Regs);
::ReadProcessMemory(ProcessHandle,(LPVOID)(Regs.Esp+4),&dwAddrProc,4,NULL);
::ReadProcessMemory(ProcessHandle,(LPVOID)dwAddrProc,&Regs,sizeof(CONTEXT),NULL);
Regs.Dr0 = 0x722158fe;
Regs.Dr7 = 0x155;
::WriteProcessMemory(ProcessHandle,(LPVOID)dwAddrProc,&Regs,sizeof(CONTEXT),NULL);
dwState = DBG_CONTINUE; //产生的异常由我们的程序处理。
dwSsCnt = 2;
mssg.Format("中断在:%08X\n下新断点:%08X\n",DBE.u.Exception.ExceptionRecord.ExceptionAddress,Regs.Dr0);
::MessageBox(NULL,mssg,"Single Setp",0x1040);
}
else if(dwSsCnt == 2)
{
DWORD dwEsp = 0; //ESP寄存器
DWORD FuncReturn = 0; //中断时ESP中存放的地址(如果在函数中,此即返回地址)
::GetThreadContext(MainThreadHandle,&Regs);
Regs.Dr0 = 0;
Regs.Dr7 = 0;
dwEsp = Regs.Esp;
Regs.Eip = (DWORD)DBE.u.Exception.ExceptionRecord.ExceptionAddress;
::SetThreadContext(MainThreadHandle,&Regs);
::ReadProcessMemory(ProcessHandle,(LPVOID)(dwEsp+4*3),&FuncReturn,4,NULL);
mssg.Format("中断在:%08X时,取键盘输入的Buffer在:%08X",
DBE.u.Exception.ExceptionRecord.ExceptionAddress,
FuncReturn);
::MessageBox(NULL,mssg,"单步异常",0x1040);
dwSsCnt++;
dwState = DBG_CONTINUE;
}
else
{
mssg.Format("中断在:%08X时!",
DBE.u.Exception.ExceptionRecord.ExceptionAddress);
::MessageBox(NULL,mssg,"单步异常",0x1040);
}
break;
}
break;
}
if(IsActiveStop)
{
if(MyDebugActiveProcessStop(DBE.dwProcessId) == 0)//非零值则成功
{
mssg.Format("脱离进程失败!\n代码:%d",::GetLastError());
::MessageBox(NULL,mssg,"脱离进程",0x1040);
return 0;
}
}
::ContinueDebugEvent(DBE.dwProcessId, DBE.dwThreadId, dwState);
}
return 0;
}
赞赏
他的文章
- 内存写速度低于内存读的速度? 3799
- [分享]发个老游戏抗日地雷战资源部分读取及内存修改器 13095
- [求助]只有位图数据情况下怎样显示位图? 7513
- [讨论]飞秋2013的授权码算法好复杂,能写注册机? 36957
赞赏
雪币:
留言: