zoukankan      html  css  js  c++  java
  • minidebug学习分析 01 基本框架

    0x01  基本框架

        基本框架就是CreateProcess启动目标程序,再通过调试事件DEBUG_EVENT在调试循环中监控程序的行为。

        (1)CreatProcess  

    BOOL CreateProcess( 
    LPCTSTR lpApplicationName, // 要创建的进程模块名 
    LPTSTR lpCommandLine, // 命令行字符串 LPSECURITY_ATTRIBUTES lpProcessAttributes, // 进程安全属性
    LPSECURITY_ATTRIBUTES lpThreadAttributes, // 线程安全属性
    BOOL bInheritHandles, // 句柄继承选项 DWORD dwCreationFlags, // 进程创建选项 LPVOID lpEnvironment, // 进程环境块数据指针
    LPCTSTR lpCurrentDirectory, // 当前目录名
    LPSTARTUPINFO lpStartupInfo, // 启动信息 LPPROCESS_INFORMATION lpProcessInformation // 进程信息
    );

      双击一个EXE可执行文件时,Windows内核也就会自动调用CreatProcess  函数创建我们双击的文件所对应的进程。

      CreateProcess函数的第六个成员dwCreationFlags进程创建选项,指明了要如何创建目标进程,在minidebug中,它指定的是DEBUG_ONLY_THIS_PROCESS | CREATE_NEW_CONSOLE | CREATE_SUSPENDED。

      DEBUG_ONLY_THIS_PROCESS表明调用CreateProcess的进程成为调试器,而它启动的子进程成为被调试的进程。DEBUG_ONLY_THIS_PROCESS与DEBUG_PROCESS的不同在于:DEBUG_PROCESS会调试被调试进程以及它的所有子进程,而DEBUG_ONLY_THIS_PROCESS只调试被调试进程,不调试它的子进程。

      CreateProcess函数的最后一个成员LPPROCESS_INFORMATION指向一个进程信息结构体PROCESS_INFORMATION,进程创建后的相关信息会放到PROCESS_INFORMATION信息块中:

      LPPROCESS_INFORMATION结构: 

    typedef struct _PROCESS_INFORMATION {
        HANDLE hProcess;
        HANDLE hThread;
        DWORD dwProcessId;
        DWORD dwThreadId;
    } PROCESS_INFORMATION, *PPROCESS_INFORMATION, *LPPROCESS_INFORMATION;
    

      启动被调试进程:

    STARTUPINFO StartupInfo = { 0 };
    	StartupInfo.cb = sizeof(STARTUPINFO);
    
    	PROCESS_INFORMATION ProcessInfo = { 0 };
    
    	if (CreateProcess(
    		Command[1].c_str(),
    		NULL,
    		NULL,
    		NULL,
    		FALSE,
    		DEBUG_ONLY_THIS_PROCESS | CREATE_NEW_CONSOLE | CREATE_SUSPENDED,
    		NULL,
    		NULL,
    		&StartupInfo,
    		&ProcessInfo) == FALSE) {
    
    		std::wcout << TEXT("CreateProcess Failed") << GetLastError() << std::endl;
    		return;
    	}
    
    	__ProcessHandle = ProcessInfo.hProcess;
    	__ThreadHandle = ProcessInfo.hThread;
    	__ProcessID = (HANDLE)ProcessInfo.dwProcessId;
    	__ThreadID  = (HANDLE)ProcessInfo.dwThreadId;
    
    	__DebuggerStatus = STATUS_SUSPENDED;
    

      

      (2)调试循环DEBUG LOOP监控调试事件DEBUG_EVENT

    void OnGo(const CommandVector& Commmd)
    {
    	//SetSingleInstruction(FALSE);
    
    	if (Commmd.size() < 2)
    	{
    		HandledException(FALSE);   //g   调试器未处理异常
    		ContinueDebugSession();    //
    		return;
    	}
        
              ......
    }
    
    
    void ContinueDebugSession() {
    
    	if (__DebuggerStatus == STATUS_NONE) {
    
    		std::wcout << TEXT("Debuggee Is Not Started Yet") << std::endl;
    		return;
    	}
    
    	if (__DebuggerStatus == STATUS_SUSPENDED) {
    
    		ResumeThread(__ThreadHandle);
    	}
    	else {
    
    		ContinueDebugEvent(
    			(DWORD)__ProcessID,
    			(DWORD)__ThreadID,
    			__AlwaysContinue == TRUE ? DBG_CONTINUE : __ContinueStatus);
    
    		__AlwaysContinue = FALSE;
    	}
    
    	DEBUG_EVENT DebugEvent;
    
    	while (WaitForDebugEvent(&DebugEvent, INFINITE) == TRUE)
    	{
    
    		if (DispatchDebugEvent(&DebugEvent) == TRUE) {
    
    			ContinueDebugEvent((DWORD)__ProcessID, (DWORD)__ThreadID, __ContinueStatus);
    		}
    		else {
    
    			break;
    		}
    	}
    }
    

      

      1>调试事件DEBUG_EVENT

       结构:

    typedef struct _DEBUG_EVENT {
        DWORD dwDebugEventCode;
        DWORD dwProcessId;
        DWORD dwThreadId;
        union {
            EXCEPTION_DEBUG_INFO Exception;
            CREATE_THREAD_DEBUG_INFO CreateThread;
            CREATE_PROCESS_DEBUG_INFO CreateProcessInfo;
            EXIT_THREAD_DEBUG_INFO ExitThread;
            EXIT_PROCESS_DEBUG_INFO ExitProcess;
            LOAD_DLL_DEBUG_INFO LoadDll;
            UNLOAD_DLL_DEBUG_INFO UnloadDll;
            OUTPUT_DEBUG_STRING_INFO DebugString;
            RIP_INFO RipInfo;
        } u;
    } DEBUG_EVENT, *LPDEBUG_EVENT;
    

      调试事件是被调试进程让系统通知调试器的事件,它包含了创建进程、创建线程、加载DLL、卸载DLL、发送输出字符串、发生异常等。如果调试器等待调试事件时刚好发生了一个调试事件,系统将填写WaitForDebugEvent函数的DEBUG_EVENT结构体的相关调试信息。 当系统通知调试器调试事件时,同时会挂起相关进程的所有线程,直到调试器使用ContinueDebugEvent继续调试事件时,被挂起的线程才继续执行。当进程被调试时,后续的调试事件也可能发生。

      调试事件的具体含义可见:http://blog.csdn.net/wlsgzl/article/details/18629635

       

      2>WaitForDebugEvent与ContinueDebugEvent

         

    BOOL WaiteForDebugEvent(
    LPDEBUG_EVENT _DEBUG_EVENT,  
    //指向调试事件的指针
    DWORD dwMilliseconds
    //等待事件的毫秒数
    )
    

      

    BOOL ContinueDebugEvent(
     DWORD dwProcessId,          // 目标进程ID 
    DWORD dwThreadId,            // 目标线程ID 
    DWORD dwContinueStatus    // 线程继续的标志
     ); 
    

      目标进程ID和目标线程ID这就是CreateProcess调用后,ProcessInfo结构中所包含的信息。该函数通过目标进程/线程ID来唯一标识目标进/线程,并且通过设置不同的ContinueStatus来通知目标进/线程继续运行的动作。

      第三成员最主ContinueStatus有两个值可供设定:一个是DBG_CONTINUE,表明调试事件已经被Debugger处理完毕,目标进/线程可以照常继续运行;另一个是DBG_EXCEPTION_NOT_HANDLED,表明Debugger并未处理该调试事件,目标进程收到该标志位后,将会将调试事件沿着Windows异常调用链继续往下发送。直至该调试事件被处理完为止——当然,如果目标进程发出的Debug Event没有任何调试器能够处理,那最后Windows只有祭出自己的杀手锏:应用程序XXX异常,即将被关闭。

  • 相关阅读:
    VirtualBox安装及使用说明和虚拟机安装XP系统图文教程
    jbpm入门样例
    39个让你受益的HTML5教程
    JAVA反射机制
    怎样学好C语言,一个成功人士的心得!
    golang使用pprof检查goroutine泄露
    GridView编辑删除操作
    初识Servlet
    严苛模式(StrictMode)
    严苛模式(StrictMode)
  • 原文地址:https://www.cnblogs.com/lsh123/p/7826939.html
Copyright © 2011-2022 走看看