找回密码
 加入我们

QQ登录

只需一步,快速开始

搜索
查看: 8604|回复: 1

[开源] Ring3顶级SEH HOOK,能够完全代替DebugAPI

[复制链接]

2

主题

7

回帖

0

精华

铜牌会员

积分
202
发表于 2010-12-10 13:38:57 | 显示全部楼层 |阅读模式
本帖最后由 SilenceNet 于 2010-12-10 13:44 编辑

typedef struct
{
FARPROC funcaddr; //函数地址
byte    olddata[5]; //原数据
byte    newdata[5]; //新数据
}HOOK_INFO;
HOOK_INFO hookInfo; //勾子信息
typedef NTSTATUS(NTAPI *pRtlDispatchException)(PEXCEPTION_RECORD pExcptRec,CONTEXT * pContext);
pRtlDispatchException RtlDispatchException=NULL;
VOID NTAPI KiUserExceptionDispatcher_BT(PEXCEPTION_RECORD pExcptRec,PCONTEXT pContext)
{   
/*在这里面可以处理任何一个自己引发的异常,硬件断点单步这些都成,完全可以代替Debug API中的调试事件,但千万不能有错误,否则在这里是个死循环,如果自己处理完了,直接调用:ZwContinue就可以了,本函数,以及本函数中调用的另外两个函数,都可能不会返回,本函数是绝对不会返回,返回的话程序肯定也跑飞了,也不需要恢复HOOK啥的,
*/
/*这下面是函数原有结构,自己不处理的异常交给下面的,下面这两个函数未导出,需GG一下ntdll.lib库*/
DWORD retValue;
if (RtlDispatchException(pExcptRec,pContext))
{
  retValue=::ZwContinue( pContext,0);
}else{
  retValue=::ZwRaiseException(pExcptRec,pContext,0);
}
::AfxMessageBox("BT居然执行到这来了");
}
VOID NTAPI KiUserExceptionDispatcher(PEXCEPTION_RECORD pExcptRec,PCONTEXT pContext)
{
//这里面什么都不做,只作跳板用.
//有关这个跳板疑问的见:http://blog.csdn.net/SilenceNet/archive/2010/12/04/6054254.aspx
__asm
{
  ;push [esp+4]
  ;push [esp+4]
  call KiUserExceptionDispatcher_BT
}
}
DWORD GetRDEAddress()
{
/*取Win7 64位的RtlDispatchException地址,ntdll基址+0x5865B */
DWORD dwBase=NULL;
dwBase=GetModuleBaseFromName(::GetCurrentProcessId(),"ntdll.dll");  //获取ntdll的基址
if(dwBase==NULL) return NULL;
dwBase=0x5865B+dwBase;     //计算函数地址
return dwBase;
}
//初始化HOOK SEH
BOOL InitHookSEH()
{

::RtlZeroMemory(&hookInfo,sizeof(hookInfo));

HMODULE hModule = LoadLibraryA("ntdll.dll");
hookInfo.funcaddr=::GetProcAddress(hModule,"KiUserExceptionDispatcher");
if(hookInfo.funcaddr==NULL) return FALSE;

memcpy(hookInfo.olddata, hookInfo.funcaddr, 6);  //保存原API数据
    hookInfo.newdata[0] = 0xe9; //写入JMP
    DWORD jmpaddr = (DWORD)KiUserExceptionDispatcher - (DWORD)hookInfo.funcaddr - 5; //目标地址-当前JMP指令地址=相对地址
    memcpy(&hookInfo.newdata[1], &jmpaddr, 5);

DWORD dwOldProtect;
if(!::VirtualProtect((LPVOID)hookInfo.funcaddr,5,PAGE_EXECUTE_READWRITE,&dwOldProtect)) return FALSE;
::memcpy(hookInfo.funcaddr,hookInfo.newdata,5); //写入数据

DWORD dwBase=GetRDEAddress(); //取得ntdll中的未导出函数RtlDispatchException地址:
if(dwBase==NULL) return FALSE;
RtlDispatchException=(pRtlDispatchException)dwBase;   
return TRUE;
}
--------------------------------------------------------------------
//可以在这价代码里面测试一下单步
CONTEXT ct;
ct.ContextFlags=CONTEXT_FULL;
GetThreadContext(hT,&ct)
ct.EFlags|=0x100;
SetThreadContext(hT,&ct)

// SEH将收到:EXCEPTION_SINGLE_STEP异常
//设置单步后,把自己的异常处理完,调用ZwContinue,紧接着后面一条指令就会引发EXCEPTION_SINGLE_STEP异常,这个异常中什么都不要处理,直接调用ZwContinue就行了,好玩的话就一直设置单步{:2_27:} ,

30

主题

693

回帖

0

精华

钻石会员

积分
2815
发表于 2015-8-29 10:28:40 | 显示全部楼层
每日一贴 精品精华
您需要登录后才可以回帖 登录 | 加入我们

本版积分规则

快速回复 返回顶部 返回列表