首页
社区
课程
招聘
[求助]关于DebugAPI的问题
发表于: 2010-1-17 15:32 3661

[求助]关于DebugAPI的问题

2010-1-17 15:32
3661

      看雪在加密书的第三版《软件加密技术内幕》,对DebugAPI函数进行了介绍,也给也了一些代码例子。
    调试一个程序可以用CreateProcess的方式,也可以用DebugActiveProcess方式,不论哪种方式,都会先产生一个EXCEPTION_BREAKPOINT(断点错误)。

问题一:要在指定的EIP下断点,是在调试事件为:CREATE_PROCESS_DEBUG_EVENT时呢?还是在调试事件为:EXCEPTION_DEBUG_EVENT时,且异常为:EXCEPTION_BREAKPOINT昵呢?

    对指定的EIP下断点,可以用WriteProcessMemory写0xCC下断点(INT 3)方式(响应异常为EXCEPTION_BREAKPOINT),也可以置Dr0和Dr7调试寄存器(响应异常为EXCEPTION_SINGLE_STEP)。

问题二:用DebugActiveProceee调试进程,用Drx寄存器下断点是不是像《技术内幕》中所说的要经过一个NtContinue的跳板?还有,被调试进程为多线,用Drx寄存器下断点时,取/设置线程上下文函数参数:线程句柄,是主线程句柄?还是用当前线程句柄?当前线程句柄是用OpenThread(THREAD_ALL_ACCESS, FALSE, (DWORD)DBE.dwThreadId);获取?

按《技术内幕》中相关代码,作了一些修改,为什么不能中断在单步异常中?
//===========================
//
//    Debug线程执行体
//        返回:失败返加零值
//
//===========================
UINT ThreadProc(LPVOID pParam)
{
        CMyDlg* pDlg=(CMyDlg*)pParam;
        CString mssg;

        if(!::DebugActiveProcess((DWORD)dwProcessId))
        {
                mssg.Format("Debug挂接失败!\n代码:%d",::GetLastError());
                ::MessageBox(NULL,mssg,"挂接进程",0x1040);
                return 0;
        }
        DEBUG_EVENT                DBE;
        CONTEXT                        Regs ;
        DWORD                        dwState;        //取值DBG_EXCEPTION_NOT_HANDLED (程序不处理的异常,由系统处理)
                                                                //或  DBG_CONTINUE;(程序不处理的异常,系统不会处理)
        DWORD                        dwBpCnt;        //断点错误的执行次数
        DWORD                        dwSsCnt;        //单步异常的执行数
        dwBpCnt = dwSsCnt = 1 ;
        IsActiveStop = false;                //设置脱离进程标志为FALSE(即不脱离)
        Regs.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
        IsActiveStop = FALSE;
        while(TRUE)
        {
                ::WaitForDebugEvent(&DBE, INFINITE);
                dwState = DBG_EXCEPTION_NOT_HANDLED;
                //调试事件
                switch(DBE.dwDebugEventCode)
                {
                //创建进程
                case CREATE_PROCESS_DEBUG_EVENT:
                        MainThreadHandle = DBE.u.CreateProcessInfo.hThread;
                        ProcessHandle = DBE.u.CreateProcessInfo.hProcess;
                        MainProcessID = DBE.dwProcessId;

                        dwBpCnt = 1;
                        dwSsCnt = 1;
/*
                        ::GetThreadContext(DBE.u.CreateProcessInfo.hThread,&Regs);
                        Regs.Dr0 = 0x722158fe;
                        Regs.Dr7 = 0x101;
                        if(::SetThreadContext(DBE.u.CreateProcessInfo.hThread,&Regs) == 0)
                        {
                                mssg.Format("创建进程时,设置Context失败!\n代码:%08X",::GetLastError());
                                ::MessageBox(NULL,mssg,"Set Context fail",0x1040);
                        }
*/
                        break;
                //创建线程
                case CREATE_THREAD_DEBUG_EVENT:
                        break;
                //退出进程
                case EXIT_PROCESS_DEBUG_EVENT:
                        break;
                //退出线程
                case EXIT_THREAD_DEBUG_EVENT:
                        break;
                //装载DLL
                case LOAD_DLL_DEBUG_EVENT:
                        break;
                //卸载DLL
                case UNLOAD_DLL_DEBUG_EVENT:
                        break;
                //发送DEBUG String
                case OUTPUT_DEBUG_STRING_EVENT:
                        break;
                //异常中断
                case EXCEPTION_DEBUG_EVENT:
                        switch(DBE.u.Exception.ExceptionRecord.ExceptionCode)
                        {
                        case EXCEPTION_BREAKPOINT://断点错误
                                if(dwBpCnt == 1)                //挂接进程后,会产生一次断点错误,地址在0x7CXXXXXX处
                                {
                                        // 722158fe
                                        //Dr0时,Dr7=0x101 = 100000001b
                                        //Dr1时,Dr7=0x104 = 100000100b
                                        //Dr2时,Dr7=0x110 = 100010000b
                                        //Dr3时,Dr7=0x140 = 101000000b
                                        //Dr1 - Dr4四个都使用时,Dr7=0x155 = 101010101;
//                                        HANDLE TempThreadHandle = MyOpenThread(THREAD_ALL_ACCESS, FALSE, (DWORD)DBE.dwThreadId);
                                        ::GetThreadContext(MainThreadHandle,&Regs);

                                        Regs.Dr0 = (DWORD)(::GetProcAddress(::GetModuleHandle(_T("ntdll.dll")),_T("NtContinue")));
                                        Regs.Dr7 = 0x155;
                                        ::SetThreadContext(MainThreadHandle,&Regs);
                                        dwBpCnt = 2;
                                        dwSsCnt = 1;
                                        mssg.Format("中断在:%08X\n下新断点:%08X\n",DBE.u.Exception.ExceptionRecord.ExceptionAddress,Regs.Dr0);
                                        ::MessageBox(NULL,mssg,"Int 3 Setp",0x1040);

//                                        ::CloseHandle(TempThreadHandle);
//                                        dwState = DBG_CONTINUE;                                //产生的异常由我们的程序处理。
                                }
                                break;
                        case EXCEPTION_SINGLE_STEP://单步异常,用Dr0 - Dr4下断点,会产生单步异常
                                ::MessageBox(NULL,"进入单步异常!","Single Setp",0x1040);
                                if(dwSsCnt == 1)
                                {
                                        ::GetThreadContext(MainThreadHandle,&Regs);
                                        Regs.Dr0 = 0;
                                        Regs.Dr7 = 0;
                                        ::SetThreadContext(MainThreadHandle,&Regs);

                                        ::ReadProcessMemory(ProcessHandle,(LPVOID)(Regs.Esp+4),&dwAddrProc,4,NULL);
                                        ::ReadProcessMemory(ProcessHandle,(LPVOID)dwAddrProc,&Regs,sizeof(CONTEXT),NULL);
                                        Regs.Dr0 = 0x722158fe;
                                        Regs.Dr7 = 0x155;
                                        ::WriteProcessMemory(ProcessHandle,(LPVOID)dwAddrProc,&Regs,sizeof(CONTEXT),NULL);

                                        dwState = DBG_CONTINUE;                                //产生的异常由我们的程序处理。
                                        dwSsCnt = 2;
                                        mssg.Format("中断在:%08X\n下新断点:%08X\n",DBE.u.Exception.ExceptionRecord.ExceptionAddress,Regs.Dr0);
                                        ::MessageBox(NULL,mssg,"Single Setp",0x1040);
                                }
                                else if(dwSsCnt == 2)
                                {
                                        DWORD        dwEsp = 0;                        //ESP寄存器
                                        DWORD        FuncReturn = 0;                //中断时ESP中存放的地址(如果在函数中,此即返回地址)

                                        ::GetThreadContext(MainThreadHandle,&Regs);
                                        Regs.Dr0 = 0;
                                        Regs.Dr7 = 0;
                                        dwEsp = Regs.Esp;
                                        Regs.Eip = (DWORD)DBE.u.Exception.ExceptionRecord.ExceptionAddress;
                                        ::SetThreadContext(MainThreadHandle,&Regs);

                                        ::ReadProcessMemory(ProcessHandle,(LPVOID)(dwEsp+4*3),&FuncReturn,4,NULL);
                                        mssg.Format("中断在:%08X时,取键盘输入的Buffer在:%08X",
                                                DBE.u.Exception.ExceptionRecord.ExceptionAddress,
                                                FuncReturn);
                                        ::MessageBox(NULL,mssg,"单步异常",0x1040);
                                        dwSsCnt++;
                                        dwState = DBG_CONTINUE;
                                }
                                else
                                {
                                        mssg.Format("中断在:%08X时!",
                                                DBE.u.Exception.ExceptionRecord.ExceptionAddress);
                                        ::MessageBox(NULL,mssg,"单步异常",0x1040);
                                }
                                break;
                        }
                        break;
                }
                if(IsActiveStop)
                {
                        if(MyDebugActiveProcessStop(DBE.dwProcessId) == 0)//非零值则成功
                        {
                                mssg.Format("脱离进程失败!\n代码:%d",::GetLastError());
                                ::MessageBox(NULL,mssg,"脱离进程",0x1040);
                                return 0;
                        }
                }
                ::ContinueDebugEvent(DBE.dwProcessId, DBE.dwThreadId, dwState);
        }
        return 0;
}

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回