问题的产生:
需要对某程序HOOK,但是该程序无法使用seh和veh来hook,由于找不到检测机制,
在放弃的边缘突然想到,此程序可以调试,可以下内存断点.
硬着头皮做了以下的尝试...和大家分享一下,大牛们一笑而过...我是小白.
我理解的ring3下调试机制大概是这样的,由于我对这方面不是很了解,有错误请大家指出哈.
DebugActiveProcess 开始调试程序
pThis->print("开始调试");
DEBUG_EVENT debug;
BOOL bState = TRUE;
while(!pThis->m_bExit)
{
if(!WaitForDebugEvent(&debug,1000)) continue;
//唯一关心的,就是我们要处理的内存断点异常
//有时间就扩展一下其他的
if( EXCEPTION_DEBUG_EVENT == debug.dwDebugEventCode )
{
if(debug.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_ACCESS_VIOLATION)
{
//是否处理了异常,是靠ContinueDebugEvent的第三个参数来判断的
//没处理就传入DBG_EXCEPTION_NOT_HANDLED
//处理了以后,程序就不会崩溃
BOOL bHasHandled = OnException(pThis,debug);//自定义的处理异常的函数
if(!bHasHandled)
{
//交给别人处理了
ContinueDebugEvent(debug.dwProcessId,debug.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);
continue;
}
}
}
ContinueDebugEvent(debug.dwProcessId,debug.dwThreadId, DBG_CONTINUE);
}
DebugActiveProcessStop(pThis->m_pid);
pThis->print("停止调试");
然后,处理我们关心的那个内存断点异常,具体的处理还请看代码
BOOL CMyHook::OnException(CMyHook* pThis,DEBUG_EVENT& debug)
{
EXCEPTION_DEBUG_INFO info = debug.u.Exception;
if(g_Hook_Func == (DWORD)info.ExceptionRecord.ExceptionAddress)
{
pThis->print("内存断点命中了,开始处理异常");
HandleMyException(pThis,debug);
return TRUE;
}
return FALSE;
}
void CMyHook::HandleMyException(CMyHook* pThis,DEBUG_EVENT& debug)
{
HANDLE hThread = OpenThread(THREAD_ALL_ACCESS,FALSE,debug.dwThreadId);
if(hThread == NULL) pThis->print("OpenThread 失败了");
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,debug.dwProcessId);
if(hProcess == NULL) pThis->print("OpenProcess 失败了");
//获取线程上下文
CONTEXT context;
context.ContextFlags = CONTEXT_FULL;
GetThreadContext(hThread,&context);
//打印寄存器的值
pThis->print("EAX: %X EBX: %X ECX: %X EDX: %X",
context.Eax, context.Ebx, context.Ecx, context.Edx);
pThis->print("ESP: %X EBP: %X",
context.Esp, context.Ebp);
pThis->print("ESI: %X EDI: %X",
context.Esi,context.Edi);
pThis->print("EIP: %X ",context.Eip);
//要注意,被调试的进程在别的地址空间
DWORD addr = 0;
SIZE_T bytesRead;
ReadProcessMemory(hProcess,(LPCVOID)(context.Esp + 0x4),&addr,sizeof(DWORD),&bytesRead);
HWND h = (HWND)addr;
ReadProcessMemory(hProcess,(LPCVOID)(context.Esp + 0x8),&addr,sizeof(DWORD),&bytesRead);
char* text = (char*)addr;
ReadProcessMemory(hProcess,(LPCVOID)(context.Esp + 0xc),&addr,sizeof(DWORD),&bytesRead);
char* caption = (char*)addr;
pThis->print("HWND: %08X text: %s caption: %s",h,text,caption);
//跳到跳板函数
context.ContextFlags = CONTEXT_FULL;
context.Eip = (DWORD)jmpfunc;
//无需SuspendThread,进程的线程本来就全暂停了
if(0 == SetThreadContext(hThread,&context))
{
printf("SetThreadContext失败");
}
//关闭句柄
CloseHandle(hThread);
CloseHandle(hProcess);
}
//然后是我们的跳板函数
void __declspec(naked) jmpfunc(void)
{
//这函数应该用DLL搞到被调试进程的空间里
DWORD addr;
addr = (DWORD)CMyHook::MyFunc;
__asm
{
jmp [addr]
}
}
//HOOKed的函数,相信大家整天HOOK,一定很熟悉了...
int __stdcall CMyHook::MyFunc(HWND h,LPCSTR text,LPCSTR caption,UINT type)
{
if(!AllocConsole()) return 0;
FILE *stream;
freopen_s(&stream,"CONOUT$", "w", stdout);
SetConsoleTitle("Console");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
printf("大家好我是被跳的函数,你成功的hook了");
printf("h,%08x\n",h);
printf("text,%s\n",text);
printf("caption,%s\n",caption);
printf("type,%d\n",type);
Sleep(5000);
FreeConsole();
return 0;
}
代码看着有些乱,下载工程以后看看就不会了..
我的编译环境是vs2008+sp1,win7 64的系统,
一直向往大牛们神一样的英姿,无奈自己才疏学浅,发的贴子也没有技术含量,
但是努力在学习,希望有一天发的贴子能变成精华帖,小白我会努力的.
献上源码和截图....欢迎大家和我讨论.
源码在这边源码在这边源码在这边
Test.7z
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)