首页
社区
课程
招聘
关于VEH+硬件断点打内存补丁
发表于: 2012-7-29 22:46 19446

关于VEH+硬件断点打内存补丁

2012-7-29 22:46
19446
看了bitt大哥的贴子,关于VEH+硬件断点打内存补丁的,自己也按照bitt大哥的代码思路,试了一下
发现怎么注入DLL后,设置的硬件断点都没有正常触发异常,异常地址变成系统领空的地址,并不是我设的0x004465D0,在OD中跟了一会,发现他在0x004465D0这个地方都没有触发异常;
下面是我按bitt大哥代码写的;
请问需要在什么条件下才能正常设置DRX的硬件断点,还是说不能用DLL直接注入,或者说需要在目标进程入口点中断才能成功设置DRX的断点呢?
还请各位指点一二,在此多谢!
void SetHwBreakpoint()
{
        CONTEXT ctx;
        ctx.ContextFlags = CONTEXT_ALL;
        GetThreadContext(GetCurrentThread(), &ctx);
        ctx.Dr0 = 0x004465D0;
        ctx.Dr7 = 0x405;
        SetThreadContext(GetCurrentThread(), &ctx);
}

DWORD NTAPI ExceptionHandler(EXCEPTION_POINTERS * ExceptionInfo)
{
        if ((DWORD)ExceptionInfo->ExceptionRecord->ExceptionAddress == 0x004465D0)
        {
                //直接改eip模拟jmp
                ExceptionInfo->ContextRecord->Eip += 0x004467E2;
                return EXCEPTION_CONTINUE_EXECUTION;
        }
        else
        {
                //在异常handler里重设drx防止断点被意外清除
                ExceptionInfo->ContextRecord->Dr0 = 0x004465D0;
                ExceptionInfo->ContextRecord->Dr7 = 0x405;
                return EXCEPTION_CONTINUE_SEARCH;
        }
}
BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                                         )
{
        switch (ul_reason_for_call)
        {
        case DLL_PROCESS_ATTACH:
                {
                        AddVectoredExceptionHandler(1, (PVECTORED_EXCEPTION_HANDLER)ExceptionHandler);
                        SetHwBreakpoint();
                }
        case DLL_THREAD_ATTACH:
                {
                        SetHwBreakpoint();
                }
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH:
                break;
        }

    return TRUE;
}

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (20)
雪    币: 8835
活跃值: (2404)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
2
设置断点需要遍历全部线程,每个线程都要设置一次。
2012-7-30 01:16
0
雪    币: 69
活跃值: (157)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
3
其实如果某个或者多个函数被处理了,遍历所有的线程也不会触发异常!  其实drx可以有全局的硬件断点,不需要遍历所有线程!
2012-7-30 09:38
0
雪    币: 435
活跃值: (1287)
能力值: ( LV13,RANK:388 )
在线值:
发帖
回帖
粉丝
4
异常时eip是0x004465D0

ExceptionInfo->ContextRecord->Eip += 0x004467E2;
这里+= 完了就是0x004465D0+0x004467E2了

改成=吧
+=是offset
2012-7-30 09:49
0
雪    币: 435
活跃值: (1287)
能力值: ( LV13,RANK:388 )
在线值:
发帖
回帖
粉丝
5
这个问题我是这么考虑的
我改了 导入表 所以dll是加载的时候就加载进去了
这样的话,新起的线程都会有DLL_THREAD_ATTACH消息,这时候再set一下,理论上所有线程都会设置好



你说的是dr7的g0位吧,这个全局有效不知道是什么意思,不过好像不是对所有线程都有效的意思
2012-7-30 11:16
0
雪    币: 13
活跃值: (22)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
那就是说我这样子直接注入DLL是不能设置DRX硬件断点成功的吗?
还需要修改导入表吗?具体是指修改导入表哪个地方呢?
DRX全局硬件又是如何设置呢?
2012-7-30 16:24
0
雪    币: 13
活跃值: (22)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7

异常时eip是0x004465D0

ExceptionInfo->ContextRecord->Eip += 0x004467E2;
这里+= 完了就是0x004465D0+0x004467E2了

改成=吧
+=是offset

这个地方不是关键问题,现在关键的问题是,我设置的DRX硬件断点无论如何都没有成功断下来

多谢bitt和liuqiangni以及cvcvxk几位大哥的解答,但小弟的问题还没弄明白!
能再具体一点吗,或者有其他资料可以指一条路吗
2012-7-30 16:27
0
雪    币: 150
活跃值: (36)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
要open thread
才能操作线程
2012-7-30 17:40
0
雪    币: 949
活跃值: (18)
能力值: ( LV9,RANK:330 )
在线值:
发帖
回帖
粉丝
9
硬件断点线程相关,每个线程都需要设置.
dll注入中设置硬件断点,当前的线程是你执行dll注入的线程,并非程序主线程,或者执行
ctx.Dr0 = 0x004465D0;
的线程.
2012-7-30 21:06
0
雪    币: 228
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
总算碰到了把这个思路公布出来的了;硬断内存补丁是躲避内存扫描的一项利器。
要特别注意的地方是线程的上下文,时刻要清楚的知道当前所运行的线程是哪一个。

SetThreadContext:
Do not try to set the context for a running thread; the results are unpredictable.

这是CSDN  上的对SetThreadContext 解释。
尤其是对自身的上下文进行设置,这很可能使得自身线程崩溃或者得不到想要的结果

历遍所有线程,SuspendThread,然后SetThreadContext ,再 ResumeThread ,同时排除自身线程。

至于全局硬断起不起作用,你想一下如果起作用会有什么后果就知道了,所以不用指望
2012-7-31 12:45
0
雪    币: 228
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
说错了,不是CSDN,是MSDN。其实关于Win32API 最权威的资料就是MSDN Library,楼主多看看
2012-7-31 12:59
0
雪    币: 13
活跃值: (22)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
历遍所有线程,SuspendThread,然后SetThreadContext ,再 ResumeThread ,同时排除自身线程。

那DLL注入的方式不就不可以实现了吗
2012-7-31 14:37
0
雪    币: 150
活跃值: (36)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
你的方法是对的!

因为我在2年前我就已经做过VEH向量型异常处理机制,所以我想告想讲2点你为什么不能实现VEH,不能实现硬件断点。

一 注入本身有问题,因为远程进程注入是对进程创建一条新的执行线程,所以你这个DLL是新的线程,不是游戏里面的主线程,GetCurrentThread(),取到的是自身的线程,不是主线程,所以你对自己的线程下断硬件断点根本就没有反应是正常的,你还没有理解什么是线程环境!请查看MSND,最好百度一下。

解决方法两种:
1 取消远程注入DLL方式采用消息钩子注入,消息钩子注入注入游戏主线程里面。
2 远程注入也可以,要遍历所有游戏进程所有线程,对每个线程下硬件断点,OD的硬件断点是这么实现的。

二 操作进程要openprocess  那操作线程也是要openthread,一样原理的,为什么TP人家要HOOK两个地方,一个是ntopenprocess,防止读写内存,一个ntopenthread,防止操作线程,例如暂停线程,结束线程,还有控制线程结构环境

下面附送上一段delphi 代码
rtlAddVectoredExceptionHandler(2311,@VectoredHandler);//安装向量异常处理机制
   hThread:=OpenThread(THREAD_SUSPEND_RESUME or THREAD_SET_CONTEXT,false, GetCurrentThreadId());
SuspendThread( hThread );
  ctx.ContextFlags :=CONTEXT_DEBUG_REGISTERS ;  // 这里要设置线程标志为
  BPadress:=strtoint('$'+Edit2.Text);
   ctx.Dr0 :=BPadress;
   ctx.Dr7 :=$401;
   SetThreadContext(hThread ,ctx);
   ResumeThread(hThread);
2012-7-31 16:44
0
雪    币: 228
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
你的方法在思路上没错,但是需要一个技巧避开SetThreadContext的限制:

修改你的 SetHwBreakpoint ,这样来设置Context : 先注册一个SEH,然后引发一个能修正的异常,在SEH里面处理异常的时候设置 Context , 接着让代码继续在异常指令之后执行,这时候Context 就应设置好了

引发异常的时候,你要注意不要重复处理(VEH 和 SEH 之中),或者你把设置Context 的代码也放在VEH 之中,就不用SEH了
2012-7-31 19:04
0
雪    币: 8835
活跃值: (2404)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
15
SetThreadContext需要权限对才行。事情太多可能,最大的可能是注入的姿势不对,当前线程不是程序的线程。
2012-8-1 05:11
0
雪    币: 13
活跃值: (22)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
SetThreadContext需要权限对才行。事情太多可能,最大的可能是注入的姿势不对,当前线程不是程序的线程。

我是注入到我要设置硬件断点的目标程序中
比如我要在A中设置硬件断点达到通过VEH来实现HOOK处理,那么我是通过B(DLL)注入到A的,这样的流程,可行吗,还需要什么权限,能不能说更具体一些
在此谢谢各位大哥的真诚回复
2012-8-1 17:57
0
雪    币: 107
活跃值: (37)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
我也是Delphier

我也想用Delphi写的DLL下硬件断点,可惜太多都是C语言的...

求完整代码,
2012-8-1 18:17
0
雪    币: 13
活跃值: (22)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
::SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC)KeyboardProc, theApp.m_hInstance, 0);也就是说我用这种全局的键盘钩子进行注入是存在问题的是吗,要采用消息钩子才可以对吧,知道的大哥请解答一下,谢谢
2012-12-4 20:59
0
雪    币: 2504
活跃值: (1695)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
//函数名:debugProc
//参数  :debuger结构体,使用前必须初始化
//返回值:-
//作用  :设置断点

DWORD WINAPI         debugProc(LPVOID lpParameter )
{
        if(debuger1.caozuo==1)
        {
               
                RefreshThreadList(GetCurrentProcessId());
                for(int i=0;i<100;i++)
                {
                        if(lst[i]==0)
                        {
                        break;
                        }
                        if(lst[i]!=GetCurrentThreadId())
                        {
                        HANDLE thd=OpenThread(THREAD_ALL_ACCESS,true,lst[i]);
                        SuspendThread(thd);
                        CONTEXT con;
                        con.ContextFlags=CONTEXT_CONTROL|CONTEXT_DEBUG_REGISTERS;
                        GetThreadContext(thd,&con);
                        if(debuger1.dr==0)
                        {
                        con.Dr0=debuger1.addr;
                        con.Dr7=con.Dr7|0x3;
                        }
                        if(debuger1.dr==1)
                        {
                                con.Dr1=debuger1.addr;
                                con.Dr7=con.Dr7|0xc;
                        }
                        if(debuger1.dr==2)
                        {
                                con.Dr2=debuger1.addr;
                                con.Dr7=con.Dr7|0x30;
                        }
                        if(debuger1.dr==3)
                        {
                                con.Dr3=debuger1.addr;
                                con.Dr7=con.Dr7|0xc0;
                        }
                       
                        con.ContextFlags= CONTEXT_CONTROL|CONTEXT_DEBUG_REGISTERS;
                        SetThreadContext(thd,&con);
                        ResumeThread(thd);
                        }
                }
        }else
        {
  
                RefreshThreadList(GetCurrentProcessId());
                for(int i=0;i<100;i++)
                {
                        if(lst[i]==0)
                        {
                                break;
                        }
                        if(lst[i]!=GetCurrentThreadId())
                        {
                                HANDLE thd=OpenThread(THREAD_ALL_ACCESS,true,lst[i]);
                                SuspendThread(thd);
                                CONTEXT con;
                                con.ContextFlags=CONTEXT_CONTROL|CONTEXT_DEBUG_REGISTERS;
                                GetThreadContext(thd,&con);
                                if(debuger1.dr==0)
                                {
                                        con.Dr0=debuger1.addr;
                                        con.Dr7=con.Dr7&~0x3;
                                }
                                if(debuger1.dr==1)
                                {
                                        con.Dr1=debuger1.addr;
                                        con.Dr7=con.Dr7&~0xc;
                                }
                                if(debuger1.dr==2)
                                {
                                        con.Dr2=debuger1.addr;
                                        con.Dr7=con.Dr7&~0x30;
                                }
                                if(debuger1.dr==3)
                                {
                                        con.Dr3=debuger1.addr;
                                        con.Dr7=con.Dr7&~0xc0;
                                }
                               
                                con.ContextFlags= CONTEXT_CONTROL|CONTEXT_DEBUG_REGISTERS;
                                SetThreadContext(thd,&con);
                                ResumeThread(thd);
                        }
                }

        }
2012-12-19 04:14
0
雪    币: 2504
活跃值: (1695)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
呃,还有一个是线程

CreateThread(NULL,255,(LPTHREAD_START_ROUTINE)debugProc,NULL,0,NULL);

以及设置VEH
       if(pExceptionInfo->ExceptionRecord->ExceptionAddress==(PVOID)0x005B9680)//address
           {
                   pExceptionInfo->ContextRecord->Eip=(DWORD)TouMingWudi; //设置eip

                   return   EXCEPTION_CONTINUE_EXECUTION;
                        }
2012-12-19 04:19
0
雪    币: 22
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
我HOOK INT 01 这样下硬件断点可以成功.
        __asm
        {
                PUSH        EAX
                MOV                EAX, 断点一
                MOV                DR0, EAX
                MOV                EAX, 断点二
                MOV                DR1, EAX
                MOV                EAX, DR7
                OR                EAX, 0x270F
                MOV                DR7, EAX
                POP                EAX
        }
        可是为什么我取消断点 :
        __asm
        {
                PUSH        EAX
                MOV                EAX, 0
                MOV                DR0, EAX
                MOV                DR1, EAX
                MOV                EAX, DR7
                AND                EAX, 0xFFFFFFF0
                MOV                DR7, EAX
                POP                EAX
        }
        这样取消断点不行呢...希望大牛指点.

        比如我重新设硬断断点也不行.

        __asm
        {
                PUSH        EAX
                MOV                EAX, 新断点一
                MOV                DR0, EAX
                MOV                EAX, 新断点二
                MOV                DR1, EAX
                MOV                EAX, DR7
                OR                EAX, 0x270F
                MOV                DR7, EAX
                POP                EAX
        }
        望各位大牛指点...解惑.
        难道必须用NtSetContextThread 和异常来设置硬件断点么?
2012-12-22 10:37
0
游客
登录 | 注册 方可回帖
返回
//