Пример #1
0
/**
 * @brief	
 * @param	
 * @see		
 * @remarks	
 * @code		
 * @endcode	
 * @return	
**/
bool 
ModuleInfo::initialize(
	_In_ const LOAD_DLL_DEBUG_INFO* dll_debug_info, 
	_In_ DWORD module_size
	)
{
	_ASSERTE(NULL != dll_debug_info);
	if (NULL==dll_debug_info) return false;

	_file_handle			= dll_debug_info->hFile;
	_dll_base_address		= (DWORD_PTR)dll_debug_info->lpBaseOfDll;
	_debug_info_file_offset	= dll_debug_info->dwDebugInfoFileOffset;
	_debug_info_size		= dll_debug_info->nDebugInfoSize;
	_is_unicode				= (0 != dll_debug_info->fUnicode) ? true : false;
	
	if (true != get_filepath_by_handle(_file_handle, _image_name))
	{
		log_err L"get_filepath_by_handle(proces = 0x%08x, file = 0x%08x)" log_end
		return false;
	}
Пример #2
0
/// @brief
int main()
{
    // create process with /dbg
    STARTUPINFO			si = {0};
	PROCESS_INFORMATION pi = {0};
    wchar_t* target = L".\\debuggee.exe";

	if (TRUE != CreateProcessW(
					target, 
					NULL, 
					NULL, 
					NULL, 
					FALSE, 
					CREATE_NEW_CONSOLE | DEBUG_PROCESS,
					NULL, 
					NULL, 
					&si, 
					&pi))
	{
        log("CreateProcess() failed. gle = %u", GetLastError());
		return -1;
	}

    log("process created. pid = %u", pi.dwProcessId);

	CloseHandle(pi.hThread);
	CloseHandle(pi.hProcess);

    DEBUG_EVENT debug_event = {0};	
	while (true)
	{
		if (TRUE != WaitForDebugEvent(&debug_event, 100)) continue;
        
        DWORD continue_status = DBG_CONTINUE;

		switch (debug_event.dwDebugEventCode)
        {
        case EXCEPTION_DEBUG_EVENT:
            {
                PDEBUGGEE dbge = NULL;
                for (int i = 0; i < sizeof(_debuggees) / sizeof(DEBUGGEE); ++i)
                {
                    if (_debuggees[i]._pid == debug_event.dwProcessId)
                    {
                        dbge = &_debuggees[i];
                    }
                }
                if (NULL == dbge) break;
                
                LPEXCEPTION_DEBUG_INFO edi = &debug_event.u.Exception;
                switch (edi->ExceptionRecord.ExceptionCode)
                {
                case EXCEPTION_BREAKPOINT:
                    if (true != dbge->_initial_bp_hit)
                    {
                        dbge->_initial_bp_hit = true;
                        log(
                            "\n"
                            "[EXCEPTION_DEBUG_EVENT] \n"\
                            "   img = %ws \n"\
                            "   pid = %u, tid = %u \n"\
                            "   + initial bp triggered at 0x%llx",
                            dbge->_image_name.c_str(),
                            debug_event.dwProcessId,
                            debug_event.dwThreadId,
                            edi->ExceptionRecord.ExceptionAddress);

                        // 
                        // install breakpoint at ep.
                        //

                        dbge->_bp_param = { 0 };
                        HANDLE thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, debug_event.dwThreadId);
                        if (NULL == thread_handle)
                        {
                            _ASSERTE(!"oops");
                            break;
                        }

                        dbge->_bp_param.hthread = thread_handle;
                        dbge->_bp_param.hproc = dbge->_proc_handle;
                        dbge->_bp_addr = dbge->_start_address;
                        bool bp_ret = set_break_point(
                            &dbge->_bp_param,
                            (DWORD_PTR)dbge->_bp_addr,
                            &dbge->_opcode);
                        if (true != bp_ret)
                        {
                            _ASSERTE(true == bp_ret);
                            break;
                        }

                        continue_status = DBG_EXCEPTION_HANDLED;
                        log("   + break point installed at 0x%llx", dbge->_bp_addr);
                        _pause;
                    }
                    else
                    {
                        log(
                            "\n"
                            "[EXCEPTION_DEBUG_EVENT] \n"\
                            "   img = %ws \n"\
                            "   pid = %u, tid = %u \n"\
                            "   + break point at 0x%llx",
                            dbge->_image_name.c_str(),
                            debug_event.dwProcessId,
                            debug_event.dwThreadId,
                            edi->ExceptionRecord.ExceptionAddress);

                        // 
                        // restore opcode and resume
                        //
                        if (edi->ExceptionRecord.ExceptionAddress != dbge->_bp_addr)
                        {
                            _ASSERTE(!"oops");
                            break;
                        }

                        dbge->_bp_param.context.ContextFlags = CONTEXT_ALL;
                        if (TRUE != GetThreadContext(
                            dbge->_bp_param.hthread,
                            &dbge->_bp_param.context))
                        {
                            _ASSERTE(!"oops!");
                            break;
                        }
                        if (true != clear_break_point(
                            &dbge->_bp_param,
                            (DWORD_PTR)dbge->_bp_addr,
                            dbge->_opcode, true))
                        {
                            _ASSERTE(!"oops");
                            break;
                        }

                        continue_status = DBG_EXCEPTION_HANDLED;
                        log("   + breakpoint un-installed at 0x%llx", dbge->_bp_addr);

                        // single step enable
                        ch_param param = { 0 };
                        param.hthread = OpenThread(THREAD_ALL_ACCESS, FALSE, debug_event.dwThreadId);
                        if (NULL != param.hthread)
                        {
                            param.context.ContextFlags = CONTEXT_ALL;
                            if (TRUE != GetThreadContext(param.hthread, &param.context))
                            {
                                _ASSERTE(!"oops!");
                                break;
                            }
                            set_single_step(&param);
                        }
                        _pause;
                    }
                    break;

                case EXCEPTION_SINGLE_STEP:
                    {
                    //log(
                    //    "\n"
                    //    "[EXCEPTION_DEBUG_EVENT] \n"\
                    //    "   pid = %u, tid = %u\n"\
                    //    "   + handle single step at 0x%llx", 
                    //    debug_event.dwProcessId,
                    //    debug_event.dwThreadId, 
                    //    edi->ExceptionRecord.ExceptionAddress);

                    
                    // call 명령이라면 log
                    log_branch(edi->ExceptionRecord.ExceptionAddress,
                               debug_event.dwProcessId,
                               debug_event.dwThreadId);

                    //continue_status = DBG_EXCEPTION_NOT_HANDLED;
                    continue_status = DBG_EXCEPTION_HANDLED;
                    break;
                    }
                default:
                    if (0 != edi->dwFirstChance)
                    {   
                        log("\n"
                            "[EXCEPTION_DEBUG_EVENT]\n"\
                            "   pid = %u, tid = %u\n"\
                            "   + %s (first chance) at 0x%llx",
                            debug_event.dwProcessId,
                            debug_event.dwThreadId, 
                            exception_code_str(edi->ExceptionRecord.ExceptionCode),
                            edi->ExceptionRecord.ExceptionAddress
                            );
                    }
                    else
                    {
                        log("\n"
                            "[EXCEPTION_DEBUG_EVENT]\n"\
                            "   + %s (second chance) at 0x%llx, can't handle anymore.",
                            exception_code_str(edi->ExceptionRecord.ExceptionCode),
                            edi->ExceptionRecord.ExceptionAddress
                            );
                    }

                    continue_status = DBG_EXCEPTION_NOT_HANDLED;
                    break;
                }
                break;
            }
        case CREATE_THREAD_DEBUG_EVENT:
            {
                //str = "CREATE_THREAD_DEBUG_EVENT";
                break;
            }
        case CREATE_PROCESS_DEBUG_EVENT:
            {
                LPCREATE_PROCESS_DEBUG_INFO cpi = &debug_event.u.CreateProcessInfo;
                std::wstring image;
                if (true != get_filepath_by_handle(cpi->hFile, image))
                {
                    image = L"unknown image path";
                }
                
                log("\n"\
                    "[CREATE_PROCESS_DEBUG_EVENT]\n"\
                    "   img = %ws\n"\
                    "   pid = %u, tid = %u, ep = 0x%llx",
                    image.c_str(), 
                    debug_event.dwProcessId,
                    debug_event.dwThreadId,
                    cpi->lpStartAddress
                    );
                
                for (int i = 0; i < sizeof(_debuggees) / sizeof(DEBUGGEE); ++i)
                {
                    if (_debuggees[i]._pid == 0)
                    {
                        _debuggees[i]._initial_bp_hit = 0;
                        _debuggees[i]._pid = debug_event.dwProcessId;

                        _debuggees[i]._file_handle = debug_event.u.CreateProcessInfo.hFile;
                        _debuggees[i]._proc_handle = debug_event.u.CreateProcessInfo.hProcess;
                        _debuggees[i]._thread_handle = debug_event.u.CreateProcessInfo.hThread;
                        _debuggees[i]._base_of_image = debug_event.u.CreateProcessInfo.lpBaseOfImage;
                        _debuggees[i]._thread_local_base = debug_event.u.CreateProcessInfo.lpThreadLocalBase;
                        _debuggees[i]._start_address = debug_event.u.CreateProcessInfo.lpStartAddress;
                        _debuggees[i]._image_name = image;

                        break;
                    }
                }
                break;
            }
        case EXIT_THREAD_DEBUG_EVENT:
            {
                //str = "EXIT_THREAD_DEBUG_EVENT";
                break;
            }
        //case EXIT_PROCESS_DEBUG_EVENT:
        //    {
        //        str = "EXIT_PROCESS_DEBUG_EVENT";
        //        break;
        //    }
        case LOAD_DLL_DEBUG_EVENT:
            {
                LPLOAD_DLL_DEBUG_INFO lddi = &debug_event.u.LoadDll;
                std::wstring dll_path;
                if (true != get_filepath_by_handle(lddi->hFile, dll_path))
                {
                    dll_path = L"Unknown dll path";
                }

                // get dll file size
                if (0 != k32_base)  break;

                HANDLE hFile = CreateFileW(dll_path.c_str(),
                                           GENERIC_READ,
                                           FILE_SHARE_READ,
                                           NULL,
                                           OPEN_ALWAYS,
                                           FILE_ATTRIBUTE_NORMAL,
                                           NULL);
                if (NULL == hFile) break;


                LARGE_INTEGER file_size = { 0 };
                if (TRUE != GetFileSizeEx(lddi->hFile, &file_size))
                {
                    return false;
                }

                if (std::wstring::npos != dll_path.rfind(L"ntdll.dll"))
                {
                    log("\n"
                        "gotcha!\n"\
                        "   pid = %u, tid = %u, img = %ws, addr ragne = 0x%08x ~ 0x%08x",
                        debug_event.dwProcessId,
                        debug_event.dwThreadId,
                        dll_path.c_str(),
                        lddi->lpBaseOfDll,
                        (DWORD_PTR)lddi->lpBaseOfDll + file_size.LowPart
                        );

                    k32_base = (DWORD_PTR)lddi->lpBaseOfDll;
                    k32_max = (DWORD_PTR)lddi->lpBaseOfDll + file_size.LowPart;

                }
                
                //log("\n"
                //    "[LOAD_DLL_DEBUG_EVENT]\n"\
                //    "   pid = %u, tid = %u, img = %ws",
                //    debug_event.dwProcessId,
                //    debug_event.dwThreadId,
                //    dll_path.c_str()
                //    );
                break;
            }
        case UNLOAD_DLL_DEBUG_EVENT:
            {
                LPUNLOAD_DLL_DEBUG_INFO uddi = &debug_event.u.UnloadDll;
                // todo 3
                break;
            }
        case OUTPUT_DEBUG_STRING_EVENT:
            {
                
                break;
            }
        case RIP_EVENT:
            {
                //str = "RIP_EVENT";
                break;
            }
        default:
            //str = "unknown";
            break;
        }

        


		//> continue_status 값이
		//>
		//>	DBG_CONTINUE
		//>		EXCEPTION_DEBUG_EVENT 인 경우
		//>			모든 exception processing 을 멈추고 스레드를 계속 실행
		//>		EXCEPTION_DEBUG_EVENT 이 아닌 경우 
		//>			스레드 계속 실행 
		//>
		//>	DBG_EXCEPTION_NOT_HANDLED
		//>		EXCEPTION_DEBUG_EVENT 인 경우
		//>			exception processing 을 계속 진행.
		//>			first-chance exception 인 경우 seh 핸들러의 search, dispatch 로직이 실행
		//>			first-chance exception 이 아니라면 프로세스는 종료 됨
		//>		EXCEPTION_DEBUG_EVENT 이 아닌 경우 
		//>			스레드 계속 실행 
        ContinueDebugEvent(debug_event.dwProcessId,debug_event.dwThreadId,continue_status);

		//> debuggee is terminating
		if (EXIT_PROCESS_DEBUG_EVENT == debug_event.dwDebugEventCode)
		{
            int i = 0;
            for (; i < sizeof(_debuggees) / sizeof(DEBUGGEE); ++i)
            {
                if (_debuggees[i]._pid == debug_event.dwProcessId)
                {
                    _debuggees[i]._initial_bp_hit = 0;
                    _debuggees[i]._pid = 0;
                    break;
                }
            }

            if (i == 0)
            {
                log("\n"\
                    "[EXIT_PROCESS_DEBUG_EVENT] \n"\
                    "   img = %ws\n"\
                    "   pid = %u, tid = %u\n"\
                    "   + debuggee is terminated.",
                    _debuggees[i]._image_name.c_str(),
                    debug_event.dwProcessId, debug_event.dwThreadId);
                _pause;
                break;
            }
            // do nothing...
		}
	}

    //log("press any key to terminate...");
    //getchar();

}