首页
社区
课程
招聘
[原创]使用调试机制进行HOOK来躲避检测的一次尝试
发表于: 2015-8-24 08:56 11096

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

2015-8-24 08:56
11096

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

上传的附件:
收藏
免费 3
支持
分享
最新回复 (7)
雪    币: 74
活跃值: (748)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
感谢分享~
2015-8-24 09:23
0
雪    币: 615
活跃值: (590)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
3
这种HOOK会造成软件运行很卡的,中断下来会暂停目标进程的所有线程然后处理下再恢复,对目标进程性能速度影响还是很大的。  HOOK  这个函数KiUserExceptionDisptcher  处理异常对目标程序的性能影响会好一点
2015-8-24 09:29
0
雪    币: 89
活跃值: (71)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
4
谢谢大神的回复,我再研究研究...
我忘记考虑程序的性能了..
2015-8-24 09:32
0
雪    币: 1042
活跃值: (500)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
代码量比较少的软件用这个还差不多~
2015-8-24 12:36
0
雪    币: 116
活跃值: (48)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
页面异常的方法.. 没法作为实际用处 自己调试用下还行
2015-8-24 14:15
0
雪    币: 4614
活跃值: (4532)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
硬件断点寄存器只有四个,如果补丁数大于4个需要怎么写,有没有相应的例子
2016-1-14 22:11
0
雪    币: 14
活跃值: (80)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
如果禁止线程产生调试事件 这个就失效了吧
2016-4-9 14:35
0
游客
登录 | 注册 方可回帖
返回
//