Sunday, September 4, 2011

Hook Specials 28 : Realize hook with VEH

Author:方圆科技
The ways of hook have many methods , They have strengths and weaknesses . Hook of IAT need watch functions like LIABRARY,GETPROCESS . Real realize is trouble. Patch memory and jump to oneself code , That need realize original command on oneself code.....

Now I talk a new thinking , Exception is used to realize hook. You know, When a program happen exception, Exception pass on like this path: 1.debuger  2. Vectorization exception, mean VEH  3.SEH...

If don't use debugger, VEH is first receive exception. Like that We can inset int3 on want to space of hook code, Then through VEH to dispose hook, Realize hook final. Axiom is simple. 

Code:

// Hook.h: interface for the CHook class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_HOOK_H__C0F41F39_4EB7_4129_BFB7_156CB203826F__INCLUDED_)
#define AFX_HOOK_H__C0F41F39_4EB7_4129_BFB7_156CB203826F__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000


#include <list>
using namespace std;

typedef void (*HOOKHANDLEFUN)(EXCEPTION_POINTERS *pExceptionInfo,void *pExtendData);
struct t_HookInfo
{
  DWORD dwAddr;
  HOOKHANDLEFUN pFn;
  BYTE byOldCode;
};


class CHook
{
private:
  static CHook *m_Instance;  //单件模式
protected:
  CHook();                   //保证只生成一个实例
public:
  static CHook* GetInstance();
  t_HookInfo *m_pCurrentBP;
  BOOL m_bSingleFlag;
  EXCEPTION_POINTERS *m_pException;
 
  void SetTF();
  static LONG WINAPI VectoredHandler(PEXCEPTION_POINTERS ExceptionInfo);
  list<t_HookInfo*> m_listHook;
  BOOL AddHook(DWORD dwHookAddr, HOOKHANDLEFUN pFn);
  BOOL RemoveHook(DWORD dwHookAddr);
  BOOL SetBP(t_HookInfo*);
  BOOL UnSetBP(t_HookInfo*);
 
  virtual ~CHook();

};

#endif // !defined(AFX_HOOK_H__C0F41F39_4EB7_4129_BFB7_156CB203826F__INCLUDED_)

Code:
// Hook.cpp: implementation of the CHook class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "HookDll.h"
#include "Hook.h"


#define  TEST
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif


#ifdef TEST
#define TESTMSG(str) AfxMessageBox(str)
#else
#define TESTMSG(str)
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
#define  BREAKPOINTLEN 2
typedef PVOID (WINAPI *ADDVECTOREDEXCEPTIONHANDLER)(ULONG,PVOID);

CHook* CHook::m_Instance;

CHook::CHook()
{
  //Empty chain table
  m_listHook.empty();
  //Install top exception
  HINSTANCE  hMod = LoadLibrary("kernel32.dll");
  ADDVECTOREDEXCEPTIONHANDLER pfn = (ADDVECTOREDEXCEPTIONHANDLER)
    GetProcAddress(hMod,"AddVectoredExceptionHandler");
  PVOID ret = pfn(1,VectoredHandler);

  m_bSingleFlag = FALSE;
  m_pCurrentBP = NULL;
}

//Function name: GetInstance
//Funtion paramter: Non 
//Function feature: return a class instance
//Return Value:  CHook*

CHook* CHook::GetInstance()
{
  if (!m_Instance)
  {
    m_Instance = new CHook;
  }
  return m_Instance;
}
CHook::~CHook()
{
  list<t_HookInfo*>::iterator it;
 
  for (it = m_listHook.begin(); it!=m_listHook.end(); it++)
  {
    UnSetBP((*it));
    delete (*it);
  }
  m_listHook.empty();
}
//Function name: AddHook
//Funtion paramter: 1.Need hook address 2.Dispose pointer of hook function
//Function feature: Add a HOOKINFO to chain table and install a hook
//Return Value:  succeed return TRUE, Otherwise FALSE
//Notice: The function isn't check validity of paramter address, By caller check
BOOL CHook::AddHook(DWORD dwHookAddr, HOOKHANDLEFUN pFn)
{
  t_HookInfo *pHookInfo = new t_HookInfo;
  if (!pHookInfo)
  {
    return FALSE;
  }
  pHookInfo->dwAddr = dwHookAddr;
  pHookInfo->pFn = pFn;
  m_listHook.push_back(pHookInfo);
  return SetBP(pHookInfo);

}


//Function name: RemoveHook
//Funtion paramter: 1. address of REMOVEHOOK
//Function feature: Delete a hook
//Return Value:  succeed return TRUE, Otherwise FALSE
//Notice: The function isn't check validity of paramter address, By caller check
BOOL CHook::RemoveHook(DWORD dwHookAddr)
{
  list<t_HookInfo*>::iterator it;
 
  for (it = m_listHook.begin(); it!=m_listHook.end(); it++)
  {
    if ((*it)->dwAddr == dwHookAddr)
    {
      UnSetBP(*it);
      delete (*it);
      m_listHook.remove(*it);
      return TRUE;
    }
  }
  return FALSE;
 
}
//Function name: SetBP
//Funtion paramter:1. Information of t_HookInfo hook
//Function feature: Write a INT3
//Return Value:  succeed return TRUE, Otherwise FALSE
//Notice: The function isn't check validity of paramter address, By caller check
BOOL CHook::SetBP(t_HookInfo *pHookInfo)
{
  DWORD dwOldProtect,dwNewProtect = PAGE_EXECUTE_READWRITE;
  if (!pHookInfo)
  {
    return FALSE;
  }
 
  VirtualProtect((void*)pHookInfo->dwAddr,BREAKPOINTLEN,dwNewProtect,&dwOldProtect);
  pHookInfo->byOldCode = *(BYTE*)(pHookInfo->dwAddr);
  *(BYTE*)(pHookInfo->dwAddr) = 0xcc;
  VirtualProtect((void*)pHookInfo->dwAddr,BREAKPOINTLEN,dwOldProtect,&dwNewProtect);
  return TRUE;

}

//Function name: SetBP
//Funtion paramter:1.Information of t_HookInfo hook
//Function feature: Delete break
//Return Value:  succeed return TRUE, Otherwise FALSE
//Notice: The function isn't check validity of paramter address, By caller check
BOOL CHook::UnSetBP(t_HookInfo *pHookInfo)
{
  DWORD dwOldProtect,dwNewProtect = PAGE_EXECUTE_READWRITE;
  if (!pHookInfo)
  {
    return FALSE;
  }
 
  VirtualProtect((void*)pHookInfo->dwAddr,BREAKPOINTLEN,dwNewProtect,&dwOldProtect); 
  *(BYTE*)(pHookInfo->dwAddr) = pHookInfo->byOldCode;
  VirtualProtect((void*)pHookInfo->dwAddr,BREAKPOINTLEN,dwOldProtect,&dwNewProtect);
  return TRUE;
 
}
//Function name: VectoredHandler
//Funtion paramter: Exception information structure pointer
//Function feature: Dispose exception
//Return Value:  Oneself exception return EXCEPTION_CONTINUE_EXECUTION,Otherwise return EXCEPTION_CONTINUE_SEARCH
LONG WINAPI CHook::VectoredHandler(PEXCEPTION_POINTERS ExceptionInfo)
{
  CHook *pHook = CHook::GetInstance();
  //检测是否INT3断点
  if (ExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT)
  {
    CString str;
    str.Format("%-8x",ExceptionInfo->ExceptionRecord->ExceptionAddress);
//    TESTMSG(str);
    list<t_HookInfo*>::iterator it;
    //Check whether oneself break
    for (it = pHook->m_listHook.begin(); it!=pHook->m_listHook.end(); it++)
    {
      if ((*it)->dwAddr ==(DWORD) ExceptionInfo->ExceptionRecord->ExceptionAddress)
      {
        //Log current break, Set step flag, Delete break,
        pHook->m_pException = ExceptionInfo;
        pHook->SetTF();
        pHook->UnSetBP(*it);
        pHook->m_pCurrentBP = *it;
        //Call related function
        (*it)->pFn(ExceptionInfo,NULL);
        return EXCEPTION_CONTINUE_EXECUTION;
      }
    }
    return EXCEPTION_CONTINUE_SEARCH;
  }
  //Dispose step break 
  else if ( ExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_SINGLE_STEP )
  {
    //Judge wether step break onself
    if (pHook->m_bSingleFlag && pHook->m_pCurrentBP)
    {
      //Restore break, flag
      pHook->SetBP(pHook->m_pCurrentBP);
      pHook->m_bSingleFlag = FALSE;
      pHook->m_pCurrentBP = NULL;
      return EXCEPTION_CONTINUE_EXECUTION;
    }
    else
    {
      return  EXCEPTION_CONTINUE_SEARCH;
    }
  }

  else
  {
    return  EXCEPTION_CONTINUE_SEARCH;
  }
}


//Function name: SetTF
//Funtion paramter:Non
//Function feature: Set step break
//Return Value:  Non

void CHook::SetTF()
{
 
  if (m_pException)
  {
    m_pException->ContextRecord->EFlags |= 0x100;
    m_bSingleFlag = TRUE;
  }
 
}

No comments:

Post a Comment