首页
社区
课程
招聘
Win32调试API的另类应用
发表于: 2005-1-21 15:11 8261

Win32调试API的另类应用

2005-1-21 15:11
8261

俺写一个虚拟CPU,可出错不容易找到,就想到这个办法。让一个程序单步执行,每执行一步就与虚拟CPU执行的结果相比较,不同的地方就是我的错。
下面是我的代码,高手别笑!

//比较程序执行的每一步,找到不同的地方
void CDebugDlg::Run(HCurrentThread &currentThread)
{
        DEBUG_EVENT debug_event;
        LPEXCEPTION_DEBUG_INFO pdebug_info;
        STARTUPINFO starupInfo;
        BYTE codebuf[30];
        CONTEXT context;
        HANDLE hTread;
        HANDLE hProc;

        PE32Loader * w32;
        STOP_CONDITION cond;
        DWORD rip,readsize;
        HFile file;
        if(!file.OpenForRead(m_path))
                return;
        if(!(w32= new PE32Loader))
                return;
        w32->Attach(&file);
        w32->LoadModule(m_vm);
        m_vm.SetMemory(w32);
        rip=w32->m_pe.GetEntry();
        memset(codebuf,0,sizeof(codebuf));
        ::GetStartupInfo(&starupInfo);
        if(::CreateProcess(m_path,"",NULL,NULL,FALSE,DEBUG_PROCESS|DEBUG_ONLY_THIS_PROCESS,NULL,NULL,&starupInfo,&pi))
        {
                for(;;)
                {
                        if(WaitForDebugEvent(&debug_event,INFINITE))
                        {
                                switch(debug_event.dwDebugEventCode)
                                {
                                case CREATE_PROCESS_DEBUG_EVENT://
                                        //保存线程和进程句柄
                                        hTread=debug_event.u.CreateProcessInfo.hThread;
                                        hProc=debug_event.u.CreateProcessInfo.hProcess;
                                        //把程序入口指令改为单步中断int 3
                                        readsize=0;
                                        ::ReadProcessMemory(hProc,(LPCVOID)rip,codebuf,1,&readsize);//保存原入口指令字节
                                        codebuf[10]=0xcc;//中断int 3的机器码
                                        readsize=0;
                                        ::WriteProcessMemory(hProc,(LPVOID)rip,&codebuf[10],1,&readsize);
                                        ContinueDebugEvent(debug_event.dwProcessId,debug_event.dwThreadId,DBG_CONTINUE);
                                        break;
                                case EXCEPTION_DEBUG_EVENT:
                                        pdebug_info=&debug_event.u.Exception;
                                        switch(pdebug_info->ExceptionRecord.ExceptionCode)
                                        {       
                                        case EXCEPTION_BREAKPOINT:
                                       
                                                context.ContextFlags=CONTEXT_CONTROL|CONTEXT_INTEGER;
                                                ::GetThreadContext(hTread ,&context);
                                                if(context.Eip==rip+1)
                                                {
                                                        //如果是修改过的入口则恢复为原来的指令重新执行。
                                                        readsize=0;
                                                        ::ReadProcessMemory(hProc,(LPCVOID)rip,&codebuf[10],10,&readsize);
                                                        if(codebuf[10]==0xcc)
                                                        {
                                                                context.EFlags|=0x100;//开始单步

                                                                context.Eip=rip;//重新执行

                                                                //设置虚拟CPU的寄存器内容
                                                                m_vm.m_cpu.rReg[AMD_RIP_INDEX].qword=context.Eip;
                                                                m_vm.m_cpu.rReg[AMD_RAX_INDEX].qword=context.Eax;
                                                                m_vm.m_cpu.rReg[AMD_RBX_INDEX].qword=context.Ebx;
                                                                m_vm.m_cpu.rReg[AMD_RCX_INDEX].qword=context.Ecx;
                                                                m_vm.m_cpu.rReg[AMD_RDX_INDEX].qword=context.Edx;
                                                                m_vm.m_cpu.rReg[AMD_RSI_INDEX].qword=context.Esi;
                                                                m_vm.m_cpu.rReg[AMD_RDI_INDEX].qword=context.Edi;
                                                                m_vm.m_cpu.rReg[AMD_RBP_INDEX].qword=context.Ebp;
                                                                //恢复为原来的指令。
                                                                readsize=0;
                                                                ::WriteProcessMemory(hProc,(LPVOID)rip,&codebuf,1,&readsize);
                                                                ::SetThreadContext(hTread,&context);
                                                        }
                                                }
                                                ContinueDebugEvent(debug_event.dwProcessId,debug_event.dwThreadId,DBG_CONTINUE);
                                                break;
                                        case EXCEPTION_SINGLE_STEP:
                                               
                                                context.ContextFlags=CONTEXT_CONTROL|CONTEXT_INTEGER;
                                                ::GetThreadContext(hTread ,&context);
                                               
                                                cond.type=STOP_STEP;
                                                cond.cond_info.dwords[0]=m_vm.GetCurrentSetpCount()+1;
                                                m_vm.Run(&cond);

                                                if(!CmpCpu(context))
                                                {
                                                        MessageBox("EXCEPTION_SINGLE_STEP");
                                                }
                                               
                                               

                                                context.EFlags|=0x100;//开始单步
                                                ::SetThreadContext(hTread,&context);
                                                ContinueDebugEvent(debug_event.dwProcessId,debug_event.dwThreadId,DBG_CONTINUE);
                                                break;
                                        }
                                        break;
                                case EXIT_PROCESS_DEBUG_EVENT:
                                        return;
                                        break;
                                case RIP_EVENT:
                                        ContinueDebugEvent(debug_event.dwProcessId,debug_event.dwThreadId,DBG_TERMINATE_PROCESS);
                                        break;
                                default:
                                        ContinueDebugEvent(debug_event.dwProcessId,debug_event.dwThreadId,DBG_EXCEPTION_NOT_HANDLED);
                                }
                        }
                }
        }
}
比较CPU寄存器内容是否相同
BOOL CDebugDlg::CmpCpu(CONTEXT &context)
{
        if(m_vm.m_cpu.rReg[AMD_RAX_INDEX].dwords[0]!=context.Eax||
                m_vm.m_cpu.rReg[AMD_RBX_INDEX].dwords[0]!=context.Ebx||
                m_vm.m_cpu.rReg[AMD_RCX_INDEX].dwords[0]!=context.Ecx||
                m_vm.m_cpu.rReg[AMD_RDX_INDEX].dwords[0]!=context.Edx||
                m_vm.m_cpu.rReg[AMD_RSI_INDEX].dwords[0]!=context.Esi||
                m_vm.m_cpu.rReg[AMD_RDI_INDEX].dwords[0]!=context.Edi||
                m_vm.m_cpu.rReg[AMD_RBP_INDEX].dwords[0]!=context.Ebp||
                m_vm.m_cpu.rReg[AMD_RIP_INDEX].dwords[0]!=context.Eip)
                return FALSE;
        return TRUE;
}

俺写的虚拟CPU是hdasm64,请大家下载试用:
本身是一个Win32程序(PE32格式)在下载的包里有64位的PE和ELF文件各一个,32位ELF文件一个,供大家研究!
支持实模式、保护模式、64位模式三种模式指令集的动态反汇编. 支持DOS系统COM和EXE可执行文件格式,支持32位和64位PE文件格式(windows可执行文件),支持32位和64位ELF文件格式(Linux可执行文件),共计六种文件格式。支持部分指令的虚拟执行调试。

下载页面:
http://pay500.com/s/s56504.htm


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

收藏
免费 7
支持
分享
最新回复 (7)
雪    币: 1593
活跃值: (811)
能力值: ( LV13,RANK:370 )
在线值:
发帖
回帖
粉丝
2
思路不错 :)
2005-1-22 01:43
0
雪    币: 603
活跃值: (617)
能力值: ( LV12,RANK:660 )
在线值:
发帖
回帖
粉丝
3
好办法!学习了。
2005-1-22 10:40
0
雪    币: 0
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
4
慢慢仔细看一下
2005-1-22 11:06
0
雪    币: 97697
活跃值: (200824)
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
5
支持一下!!!
2005-1-22 11:57
0
雪    币: 223
能力值: (RANK:130 )
在线值:
发帖
回帖
粉丝
6
写的不错啊,能够开源吗?
2005-1-22 12:08
0
雪    币: 339
活跃值: (1510)
能力值: ( LV13,RANK:970 )
在线值:
发帖
回帖
粉丝
7
牛人啊
2005-1-22 12:36
0
雪    币: 213
活跃值: (96)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
8
支持:p :p :p
2005-1-23 11:30
0
游客
登录 | 注册 方可回帖
返回
//