欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

[原创]使用调试机制进行HOOK来躲避检测的一次尝试

[原创]使用调试机制进行HOOK来躲避检测的一次尝试

问题的产生:
需要对某程序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

上传的附件 aaa.jpg
Test.7z

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功