Пример #1
0
/*
 * loadProg - load the task to sample
 */
static void loadProg( const char *exe, char *cmdline )
{
    STARTUPINFO         sinfo;
    PROCESS_INFORMATION pinfo;
    int                 rc;

    memset( &sinfo, 0, sizeof( sinfo ) );
    sinfo.cb = sizeof( sinfo );
    // set ShowWindow default value for nCmdShow parameter
    sinfo.dwFlags = STARTF_USESHOWWINDOW;
    sinfo.wShowWindow = SW_SHOWNORMAL;
    rc = CreateProcess( NULL,           /* application name */
                        cmdline,        /* command line */
                        NULL,           /* process attributes */
                        NULL,           /* thread attributes */
                        FALSE,          /* inherit handles */
                        DEBUG_PROCESS,//DEBUG_ONLY_THIS_PROCESS, /* creation flags */
                        NULL,           /* environment block */
                        NULL,           /* starting directory */
                        &sinfo,         /* startup info */
                        &pinfo          /* process info */
                    );
    if( !rc ) {
        internalError( MsgArray[MSG_SAMPLE_3 - ERR_FIRST_MESSAGE] );
    }
    rc = WaitForDebugEvent( &debugEvent, INFINITE );
    if( !rc || (debugEvent.dwDebugEventCode != CREATE_PROCESS_DEBUG_EVENT) ||
                (debugEvent.dwProcessId != pinfo.dwProcessId) ) {
        internalError( MsgArray[MSG_SAMPLE_3 - ERR_FIRST_MESSAGE] );
    }
    taskPid = debugEvent.dwProcessId;
    processHandle = debugEvent.u.CreateProcessInfo.hProcess;
    newThread( debugEvent.dwThreadId, debugEvent.u.CreateProcessInfo.hThread );
    codeLoad( debugEvent.u.CreateProcessInfo.hFile,
                (DWORD)debugEvent.u.CreateProcessInfo.lpBaseOfImage,
                exe,
                SAMP_MAIN_LOAD );

} /* loadProg */
Пример #2
0
BOOL CDbgHook::DbgAttatch(DWORD dwPid)
{
	CProcessChecker pck;

	/*
	pck.SetData(dwPid);
	if (!pck.IsProcess())
	return FALSE;
	*/
	if (!DebugActiveProcess(dwPid))
		return FALSE;

	if (!WaitForDebugEvent(&m_de, INFINITE))
		return FALSE;

	if (m_de.dwDebugEventCode != CREATE_PROCESS_DEBUG_EVENT)
		return FALSE;

	memcpy(&m_cpdi, &m_de.u.CreateProcessInfo, sizeof(CREATE_PROCESS_DEBUG_INFO));

	return TRUE;
}
void DebugLoop()
{
	DEBUG_EVENT de;
	//int dwContinuesStatus;
	
	//wait for event....
	while(WaitForDebugEvent(&de,INFINITE))
	{
		//dwContinuesStatus=0x00010002;
		//被调试进程生成或者附加事件
		if(CREATE_PROCESS_DEBUG_EVENT==de.dwDebugEventCode) 
			{
				printf("created debug !\n");
				OnCreateProcessDebugEvent(&de);
				printf("seccessfully created int 3\n");
			}
		//异常事件
		else if (EXCEPTION_DEBUG_EVENT==de.dwDebugEventCode) 
			{
				printf("Exception debug event !code =%X\n",de.dwDebugEventCode);
				if(OnExceptionDebugEvent(&de))
					{
						printf("on exception debug event\n");
						continue;
					}
			}
			
	
	//被调试进程终止事件
	else if (EXIT_PROCESS_DEBUG_EVENT==de.dwDebugEventCode) //被调试者终止-调试器终止 
		{
			printf("debugee exited \n");
			break;
		}
	//再次运行被调试者
	ContinueDebugEvent(de.dwProcessId,de.dwThreadId,0x00010002) ;
	}
}
Пример #4
0
void ContextOverride::OnPreExecute( PreExecuteEvent &event, bool firstTime )
{
    if (!firstTime) return;
    if (m_done) return;
    u32 entry = LxEmulator.Proc()->GetEntryPoint();
    if (event.Cpu->EIP != entry) return;

    CONTEXT ctx;
    RefProcess *refproc = LxEmulator.RefProc();
    m_pi = refproc->GetProcessInformation();
    m_event = refproc->GetDebugEvent();

    byte origByte = refproc->SetInt3(entry);
    ContinueDebugEvent(m_pi->dwProcessId, m_pi->dwThreadId, DBG_CONTINUE);
    while (WaitForDebugEvent(m_event, INFINITE)) {
        if (m_event->dwDebugEventCode == EXCEPTION_DEBUG_EVENT &&
            m_event->u.Exception.ExceptionRecord.ExceptionCode == STATUS_BREAKPOINT)
        {
            refproc->GetMainContext(&ctx, CONTEXT_CONTROL);
            ctx.Eip--;
            if (ctx.Eip != entry) {
                LxFatal("SyncDiff: Unexpected sync address %08x, should be %08x\n",
                    ctx.Eip, entry);
            }
            refproc->SetMainContext(&ctx);
            refproc->RestoreInt3(ctx.Eip, origByte);
            break;
        }
        ContinueDebugEvent(m_pi->dwProcessId, m_pi->dwThreadId, DBG_CONTINUE);
    }
    refproc->SetTF();

    LxInfo("Overriding Context..\n");
    OverrideContext(event.Cpu);
    m_done = true;
}
Пример #5
0
/* Kill all inferiors.  */
static void
win32_kill (void)
{
  if (current_process_handle == NULL)
    return;

  TerminateProcess (current_process_handle, 0);
  for (;;)
    {
      if (!child_continue (DBG_CONTINUE, -1))
	break;
      if (!WaitForDebugEvent (&current_event, INFINITE))
	break;
      if (current_event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)
	break;
      else if (current_event.dwDebugEventCode == OUTPUT_DEBUG_STRING_EVENT)
	{
  	  struct target_waitstatus our_status = { 0 };
	  handle_output_debug_string (&our_status);
  	}
    }

  win32_clear_inferiors ();
}
Пример #6
0
int _tmain( int argc, _TCHAR* argv[] )
{
    BOOL                bRet = FALSE;
    STARTUPINFO         startupInfo = { sizeof startupInfo };
    PROCESS_INFORMATION procInfo = { 0 };
    DEBUG_EVENT         event = { 0 };
    _EventCallback   callback;
    Exec        exec;
    HRESULT     hr = S_OK;
    LaunchInfo  info = { 0 };

    InitDebug();

    //char*   s1 = new ( _NORMAL_BLOCK, __FILE__, __LINE__ ) char[100];
    //strcpy( s1, "hello, yo!" );
    //char*   s2 = (char*) malloc( 300 );
    //strcpy( s2, "say what?" );

    callback.SetExec( &exec );

    hr = exec.Init( &callback );
    if ( FAILED( hr ) )
        goto Error;
    
#if 0
    bRet = CreateProcess( L"F:\\Users\\Magus\\Documents\\Visual Studio 2008\\Projects\\test1\\Debug\\test1.exe",
    //bRet = CreateProcess( L"F:\\Users\\Magus\\Documents\\Visual Studio 2008\\Projects\\test1\\x64\\Debug\\test1.exe",
        NULL,
        NULL,
        NULL,
        FALSE,
        DEBUG_ONLY_THIS_PROCESS,
        NULL,
        NULL,
        &startupInfo,
        &procInfo );
    if ( !bRet )
        goto Error;
#else

//#define TEST_APP64

#ifndef TEST_APP64
    info.CommandLine = L"\"F:\\Users\\Magus\\Documents\\Visual Studio 2008\\Projects\\Debugger1\\Debug\\test1.exe\"";
    info.Exe = L"F:\\Users\\Magus\\Documents\\Visual Studio 2008\\Projects\\Debugger1\\Debug\\test1.exe";
#else
    info.CommandLine =L"\"F:\\Users\\Magus\\Documents\\Visual Studio 2008\\Projects\\Debugger1\\x64\\Debug\\test1.exe\"";
    info.Exe = L"\"F:\\Users\\Magus\\Documents\\Visual Studio 2008\\Projects\\Debugger1\\x64\\Debug\\test1.exe\"";
#endif

    IProcess*   proc = NULL;

    //hr = exec.Attach( 5336, proc );
    hr = exec.Launch( &info, proc );
    if ( FAILED( hr ) )
        goto Error;
#endif

#if 0
    bRet = WaitForDebugEvent( &event, INFINITE );
    if ( !bRet )
        goto Error;
#else
    int stepCount = 0;

    for ( int i = 0; /* doesn't end */ ; i++ )
    {
        hr = exec.WaitForEvent( 1000 );
        if ( FAILED( hr ) )
            goto Error;

        hr = exec.DispatchEvent();
        if ( FAILED( hr ) )
            goto Error;

#if 1
        if ( proc->IsStopped() )
        {
            if ( callback.GetHitBp() )
            {
                stepCount++;

                //11728
                IModule*    mod = NULL;
                UINT_PTR    baseAddr = 0;

                callback.GetModule( mod );
                baseAddr = (UINT_PTR) mod->GetImageBase();
                mod->Release();

                //hr = exec.StepOut( proc, (void*) (baseAddr + 0x00011728) );
                //hr = exec.StepInstruction( proc, true );

                if ( stepCount > 1 )
                    hr = exec.StepInstruction( proc, true, true );
                else
                {
                    //113A5
                    AddressRange    range = { baseAddr + 0x0001137A, baseAddr + 0x000113A5 };
                    hr = exec.StepRange( proc, false, range, true );
                }

                if ( FAILED( hr ) )
                    goto Error;
            }
            else
            {
                hr = exec.Continue( proc, true );
                if ( FAILED( hr ) )
                    goto Error;
            }
        }
#endif

#if 1
        if ( i == 0 )
        {
            IModule*    mod = NULL;
            UINT_PTR    baseAddr = 0;

            callback.GetModule( mod );
            baseAddr = (UINT_PTR) mod->GetImageBase();

            // 0x003C137A, 0x003C1395
            // 1137A, 11395

            //exec.SetBreakpoint( proc, baseAddr + 0x0001138C, 255 );
            exec.SetBreakpoint( proc, baseAddr + 0x0001137A );
            //exec.SetBreakpoint( proc, baseAddr + 0x00011395, 129 );

            mod->Release();
        }
#endif
    }
#endif

Error:
    //exec.Detach( proc );

    // when the debugger goes away, so does the debuggee automatically

    //if ( procInfo.hThread != NULL )
    //{
    //    CloseHandle( procInfo.hThread );
    //}

    //if ( procInfo.hProcess != NULL )
    //{
    //    TerminateProcess( procInfo.hProcess, MAXINT );
    //    CloseHandle( procInfo.hProcess );
    //}

    if ( proc != NULL )
        proc->Release();

    return 0;
}
Пример #7
0
/*
 * StartProg - start sampling a program
 */
void StartProg( char *cmd, char *prog, char *full_args, char *dos_args )
{
    DWORD       code;
    DWORD       tid;
    CONTEXT     con;
    BOOL        waiting_for_first_bp;
    SIZE_T      len;
    DWORD       continue_how;
    BOOL        rc;
    seg_offset  where;
    DWORD       ttid;
    HANDLE      tth;

    cmd = cmd;

    strcpy( utilBuff, prog );
    strcat( utilBuff, " " );
    strcat( utilBuff, full_args );

    loadProg( prog, utilBuff );
    tid = debugEvent.dwThreadId;

    tth = CreateThread( NULL, 1024, TimerThread, NULL, 0, &ttid );
    if( !tth ) {
        internalError( MsgArray[MSG_SAMPLE_3 - ERR_FIRST_MESSAGE] );
    }
    /* attempt to ensure that we can get all of our samples in one shot */
    SetThreadPriority( tth, THREAD_PRIORITY_TIME_CRITICAL );

    Output( MsgArray[MSG_SAMPLE_1 - ERR_FIRST_MESSAGE] );
    Output( prog );
    Output( "\r\n" );

    waiting_for_first_bp = TRUE;
    continue_how = DBG_CONTINUE;

    for( ;; ) {
        ContinueDebugEvent( taskPid, tid, continue_how );
        rc = WaitForDebugEvent( &debugEvent, INFINITE );
        continue_how = DBG_CONTINUE;
        tid = debugEvent.dwThreadId;
        switch( debugEvent.dwDebugEventCode ) {
        case EXCEPTION_DEBUG_EVENT:
            code = debugEvent.u.Exception.ExceptionRecord.ExceptionCode;
            switch( code ) {
            case STATUS_SINGLE_STEP:
                if( timeOut ) {
                    myGetThreadContext( tid, &con );
                    RecordSample( con.Eip, con.SegCs, tid );
                    timeOut = FALSE;
                }
                break;
            case STATUS_BREAKPOINT:
                if( !waiting_for_first_bp ) {
                    myGetThreadContext( tid, &con );
                    con.Eip--;
                    if( (con.Edx & 0xffff) != 0 ) {    /* this is a mark */
                        ReadProcessMemory( processHandle, (LPVOID)con.Eax, utilBuff, BUFF_SIZE - 1, len );
                        utilBuff[len] = '\0';
                        where.segment = con.SegCs;
                        where.offset = con.Eip;
                        WriteMark( utilBuff, where );
                    } else {            /* this passes CommonAddr */
                        commonAddr.segment = con.Ecx & 0xffff;
                        commonAddr.offset = con.Ebx;
                    }
                } else {
                    waiting_for_first_bp = FALSE;
                }
                break;
            case STATUS_DATATYPE_MISALIGNMENT:
            case STATUS_ACCESS_VIOLATION:
            case STATUS_IN_PAGE_ERROR:
            case STATUS_NO_MEMORY:
            case STATUS_ILLEGAL_INSTRUCTION:
            case STATUS_NONCONTINUABLE_EXCEPTION:
            case STATUS_INVALID_DISPOSITION:
            case STATUS_ARRAY_BOUNDS_EXCEEDED:
            case STATUS_FLOAT_DENORMAL_OPERAND:
            case STATUS_FLOAT_DIVIDE_BY_ZERO:
            case STATUS_FLOAT_INVALID_OPERATION:
            case STATUS_FLOAT_OVERFLOW:
            case STATUS_FLOAT_STACK_CHECK:
            case STATUS_FLOAT_UNDERFLOW:
            case STATUS_INTEGER_DIVIDE_BY_ZERO:
            case STATUS_INTEGER_OVERFLOW:
            case STATUS_PRIVILEGED_INSTRUCTION:
            case STATUS_STACK_OVERFLOW:
            case STATUS_CONTROL_C_EXIT:
                if( debugEvent.u.Exception.dwFirstChance ) {
                    continue_how = DBG_EXCEPTION_NOT_HANDLED;
                } else {
                    Output( MsgArray[MSG_SAMPLE_4 - ERR_FIRST_MESSAGE] );
                    Output( "\r\n" );
                    doneSample = TRUE;
                    TerminateProcess( processHandle, 0 );
                    report();
                    return;
                }
                break;
            default:
                continue_how = DBG_EXCEPTION_NOT_HANDLED;
                break;
            }
            break;
        case LOAD_DLL_DEBUG_EVENT:
            if( GetDllName( &debugEvent.u.LoadDll, utilBuff, sizeof( utilBuff ) ) ) {
                codeLoad( debugEvent.u.LoadDll.hFile,
                            (DWORD) debugEvent.u.LoadDll.lpBaseOfDll,
                            utilBuff,
                            SAMP_CODE_LOAD );
            }
            break;
        case CREATE_THREAD_DEBUG_EVENT:
            newThread( debugEvent.dwThreadId, debugEvent.u.CreateThread.hThread );
            break;
        case EXIT_THREAD_DEBUG_EVENT:
            deadThread( debugEvent.dwThreadId );
            break;
        case EXIT_PROCESS_DEBUG_EVENT:
            doneSample = TRUE;
//          TerminateProcess( processHandle, 0 ); - already gone!!
            report();
            return;
        }
    }

} /* StartProg */
Пример #8
0
bool Pdb::RunToException()
{
	DR_LOG("RunToException");
	LLOG("RUN TO EXCEPTION");
	TimeStop ts;
	bool disasfocus = disas.HasFocus();
	bool locked = false;
	bool frestored = false;
	invalidpage.Clear();
	mempage.Clear();
	int opn = 0;
	for(;;) {
		if(terminated) {
			if(locked)
				Unlock();
			return false;
		}
		opn++;
		DR_LOG("WaitForDebugEvent");
		if(WaitForDebugEvent(&event, 0)) {
			DR_LOG("WaitForDebugEvent ended");
			debug_threadid = event.dwThreadId;
			opn = 0;
			running = false;
			switch(event.dwDebugEventCode) {
			case EXCEPTION_DEBUG_EVENT: {
				DR_LOG("EXCEPTION_DEBUG_EVENT");
				LLOG("Exception: " << FormatIntHex(event.u.Exception.ExceptionRecord.ExceptionCode) <<
				     " at: " << FormatIntHex(event.u.Exception.ExceptionRecord.ExceptionAddress) <<
				     " first: " << event.u.Exception.dwFirstChance);
				SaveForeground();
				const EXCEPTION_RECORD& x = event.u.Exception.ExceptionRecord;
				if(findarg(x.ExceptionCode, EXCEPTION_BREAKPOINT, EXCEPTION_SINGLE_STEP,
				                            STATUS_WX86_BREAKPOINT, STATUS_WX86_SINGLE_STEP) < 0)
				{
					LLOG("Non-debug EXCEPTION");
					if(event.u.Exception.dwFirstChance) {
						LLOG("First chance " << FormatIntHex(x.ExceptionCode));
						break;
					}
					String desc = Format("Exception: [* %lX] at [* %16llX]&",
					                     (int64)x.ExceptionCode, (int64)x.ExceptionAddress);
					for(int i = 0; i < __countof(ex_desc); i++)
						if(ex_desc[i].code == x.ExceptionCode)
							desc << "[* " << DeQtf(ex_desc[i].text) << "]&";
					if(x.ExceptionCode == EXCEPTION_ACCESS_VIOLATION) {
						desc << (x.ExceptionInformation[0] ? "[*@3 writing]" : "[*@4 reading]");
						desc << Format(" at [* %08llX]", (int64)x.ExceptionInformation[1]);
					}
					ToForeground();
					PromptOK(desc);
				}
#ifdef CPU_64
				if(!win64 && x.ExceptionCode == EXCEPTION_BREAKPOINT && !break_running) // Ignore x64 breakpoint in wow64
					break;
#endif
				if(break_running)
					debug_threadid = mainThreadId;
				break_running = false;
				ToForeground();
				if(disasfocus)
					disas.SetFocus();
				if(locked)
					Unlock();
				if(refreshmodules)
					LoadModuleInfo();
				LLOG("event.dwThreadId = " << event.dwThreadId);
				bool isbreakpoint = findarg(x.ExceptionCode, EXCEPTION_BREAKPOINT, STATUS_WX86_BREAKPOINT) >= 0;
				for(int i = 0; i < threads.GetCount(); i++) {
					Thread& t = threads[i];
					(Context&)t = ReadContext(threads[i].hThread);
					if(event.dwThreadId == threads.GetKey(i)) {
						LLOG("Setting current context");
						if(isbreakpoint
#ifdef CPU_64
						   && bp_set.Find((win64 ? t.context64.Rip : t.context32.Eip) - 1) >= 0
#else
						   && bp_set.Find(t.context32.Eip - 1) >= 0
#endif
						) // We have stopped at breakpoint, need to move address back
					#ifdef CPU_64
							if(win64)
								t.context64.Rip--;
							else
					#endif
								t.context32.Eip--;
						context = t;
					}
				}
				RemoveBp();
				return true;
			}
			case CREATE_THREAD_DEBUG_EVENT:
				DR_LOG("CREATE_THREAD_DEBUG_EVENT");
				LLOG("Create thread: " << event.dwThreadId);
				AddThread(event.dwThreadId, event.u.CreateThread.hThread);
				break;
			case EXIT_THREAD_DEBUG_EVENT:
				DR_LOG("EXIT_THREAD_DEBUG_EVENT");
				LLOG("Exit thread: " << event.dwThreadId);
				RemoveThread(event.dwThreadId);
				break;
			case CREATE_PROCESS_DEBUG_EVENT:
				DR_LOG("CREATE_PROCESS_DEBUG_EVENT");
				LLOG("Create process: " << event.dwProcessId);
				processid = event.dwProcessId;
				AddThread(event.dwThreadId, event.u.CreateProcessInfo.hThread);
				CloseHandle(event.u.CreateProcessInfo.hFile);
				CloseHandle(event.u.CreateProcessInfo.hProcess);
				break;
			case EXIT_PROCESS_DEBUG_EVENT:
				DR_LOG("EXIT_PROCESS_DEBUG_EVENT");
				LLOG("Exit process: " << event.dwProcessId);
				if(locked)
					Unlock();
				terminated = true;
				return false;
			case LOAD_DLL_DEBUG_EVENT: {
				DR_LOG("LOAD_DLL_DEBUG_EVENT");
				LLOG("Load dll: " << event.u.LoadDll.lpBaseOfDll);
				CloseHandle(event.u.LoadDll.hFile);
				refreshmodules = true;
				break;
			}
			case UNLOAD_DLL_DEBUG_EVENT:
				DR_LOG("UNLOAD_DLL_DEBUG_EVENT");
				LLOG("UnLoad dll: " << event.u.UnloadDll.lpBaseOfDll);
				refreshmodules = true;
				break;
			case RIP_EVENT:
				DR_LOG("RIP_EVENT");
				LLOG("RIP!");
				Exclamation("Process being debugged died unexpectedly!");
				terminated = true;
				if(locked)
					Unlock();
				return false;
			}
			DR_LOG("ContinueDebugEvent");
			ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);
			running = true;
		}
		if(ts.Elapsed() > 200) {
			DR_LOG("ts.Elpsed() > 200");
			if(!lock) {
				Lock();
				locked = true;
			}
			if(!frestored) {
				RestoreForeground();
				frestored = true;
			}
		}
		if(lock) {
			DR_LOG("GuiSleep");
			GuiSleep(opn < 1000 ? 0 : 100);
			Ctrl::ProcessEvents();
		}
		else {
			DR_LOG("Sleep");
			Sleep(opn < 1000 ? 0 : 100);
		}
	}
}
Пример #9
0
static void test_debug_loop(int argc, char **argv)
{
    const char *arguments = " debugger child ";
    struct child_blackbox blackbox;
    char blackbox_file[MAX_PATH];
    PROCESS_INFORMATION pi;
    STARTUPINFOA si;
    BOOL debug;
    DWORD pid;
    char *cmd;
    BOOL ret;

    if (!pDebugActiveProcessStop || !pCheckRemoteDebuggerPresent)
    {
        win_skip("DebugActiveProcessStop or CheckRemoteDebuggerPresent not available, skipping test.\n");
        return;
    }

    pid = GetCurrentProcessId();
    ret = DebugActiveProcess(pid);
    ok(!ret, "DebugActiveProcess() succeeded on own process.\n");

    get_file_name(blackbox_file);
    cmd = HeapAlloc(GetProcessHeap(), 0, strlen(argv[0]) + strlen(arguments) + strlen(blackbox_file) + 10);
    sprintf(cmd, "%s%s%08x %s", argv[0], arguments, pid, blackbox_file);

    memset(&si, 0, sizeof(si));
    si.cb = sizeof(si);
    ret = CreateProcessA(NULL, cmd, NULL, NULL, FALSE, DEBUG_PROCESS, NULL, NULL, &si, &pi);
    ok(ret, "CreateProcess failed, last error %#x.\n", GetLastError());

    HeapFree(GetProcessHeap(), 0, cmd);

    ret = pCheckRemoteDebuggerPresent(pi.hProcess, &debug);
    ok(ret, "CheckRemoteDebuggerPresent failed, last error %#x.\n", GetLastError());
    ok(debug, "Expected debug != 0, got %#x.\n", debug);

    for (;;)
    {
        DEBUG_EVENT ev;

        ret = WaitForDebugEvent(&ev, INFINITE);
        ok(ret, "WaitForDebugEvent failed, last error %#x.\n", GetLastError());
        if (!ret) break;

        if (ev.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) break;

        ret = ContinueDebugEvent(ev.dwProcessId, ev.dwThreadId, DBG_CONTINUE);
        ok(ret, "ContinueDebugEvent failed, last error %#x.\n", GetLastError());
        if (!ret) break;
    }

    ret = CloseHandle(pi.hThread);
    ok(ret, "CloseHandle failed, last error %#x.\n", GetLastError());
    ret = CloseHandle(pi.hProcess);
    ok(ret, "CloseHandle failed, last error %#x.\n", GetLastError());

    load_blackbox(blackbox_file, &blackbox, sizeof(blackbox));
    ok(!blackbox.failures, "Got %d failures from child process.\n", blackbox.failures);

    ret = DeleteFileA(blackbox_file);
    ok(ret, "DeleteFileA failed, last error %#x.\n", GetLastError());
}
Пример #10
0
BOOL DebugMainLoop(const DebugOptions *pOptions)
{
    BOOL fFinished = FALSE;
    BOOL fBreakpointSignalled = FALSE;
    BOOL fWowBreakpointSignalled = FALSE;
    BOOL fTerminating = FALSE;

    while(!fFinished)
    {
        DEBUG_EVENT DebugEvent;            // debugging event information
        DWORD dwContinueStatus = DBG_CONTINUE;    // exception continuation
        PPROCESS_INFO pProcessInfo;
        PTHREAD_INFO pThreadInfo;
        HANDLE hProcess;

        // Wait for a debugging event to occur. The second parameter indicates
        // that the function does not return until a debugging event occurs.
        if(!WaitForDebugEvent(&DebugEvent, INFINITE))
        {
            OutputDebug("WaitForDebugEvent: 0x%08lx", GetLastError());

            return FALSE;
        }

        // Process the debugging event code.
        switch (DebugEvent.dwDebugEventCode) {
        case EXCEPTION_DEBUG_EVENT: {
            PEXCEPTION_RECORD pExceptionRecord = &DebugEvent.u.Exception.ExceptionRecord;
            NTSTATUS ExceptionCode = pExceptionRecord->ExceptionCode;

            // Process the exception code. When handling
            // exceptions, remember to set the continuation
            // status parameter (dwContinueStatus). This value
            // is used by the ContinueDebugEvent function.
            if (pOptions->verbose_flag) {
                lprintf("EXCEPTION PID=%lu TID=%lu ExceptionCode=0x%lx dwFirstChance=%lu\r\n",
                        DebugEvent.dwProcessId,
                        DebugEvent.dwThreadId,
                        pExceptionRecord->ExceptionCode,
                        DebugEvent.u.Exception.dwFirstChance
                );
            }

            // Find the process in the process list
            pProcessInfo = &g_Processes[DebugEvent.dwProcessId];

            dwContinueStatus = DBG_EXCEPTION_NOT_HANDLED;

            if (DebugEvent.u.Exception.dwFirstChance) {
                if (pExceptionRecord->ExceptionCode == (DWORD)STATUS_BREAKPOINT) {
                    // Signal the aedebug event
                    if (!fBreakpointSignalled) {
                        fBreakpointSignalled = TRUE;

                        if (pOptions->hEvent) {
                            SetEvent(pOptions->hEvent);
                            CloseHandle(pOptions->hEvent);
                        }

                        if (pOptions->dwThreadId) {
                            DWORD dwThreadId = pOptions->dwThreadId;
                            const DWORD dwFailed = (DWORD)-1;
                            DWORD dwRet = dwFailed;
                            pThreadInfo = &pProcessInfo->Threads[dwThreadId];
                            HANDLE hThread = pThreadInfo->hThread;
                            if (hThread != NULL) {
                                dwRet = ResumeThread(hThread);
                            }
                            if (dwRet == dwFailed) {
                                lprintf("error: failed to resume thread %lu\n", dwThreadId);
                            }
                        }

                        /*
                         * We ignore first-chance breakpoints by default.
                         *
                         * We get one of these whenever we attach to a process.
                         * But in some cases, we never get a second-chance, e.g.,
                         * when we're attached through MSVCRT's abort().
                         */
                        if (!pOptions->breakpoint_flag) {
                            dwContinueStatus = DBG_CONTINUE;
                            break;
                        }
                    }
                }

                if (ExceptionCode == STATUS_WX86_BREAKPOINT) {
                    if (!fWowBreakpointSignalled) {
                        fWowBreakpointSignalled = TRUE;
                        dwContinueStatus = DBG_CONTINUE;
                        break;
                    }
                }

               /*
                 * Ignore thread naming exception.
                 *
                 * http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
                 *
                 * TODO: Note down the thread name
                 */
                if (ExceptionCode == 0x406d1388) {
                    dwContinueStatus = DBG_CONTINUE;
                    break;
                }

                if (!pOptions->first_chance) {
                    break;
                }
            }

            // XXX: Deferred symbols don't get loaded without this
            SymRefreshModuleList(pProcessInfo->hProcess);

            dumpException(pProcessInfo->hProcess,
                          &DebugEvent.u.Exception.ExceptionRecord);

            // Find the thread in the thread list
            THREAD_INFO_LIST::const_iterator it;
            for (it = pProcessInfo->Threads.begin(); it != pProcessInfo->Threads.end(); ++it) {
                DWORD dwThreadId = it->first;
                HANDLE hThread = it->second.hThread;
                if (dwThreadId != DebugEvent.dwThreadId &&
                    ExceptionCode != STATUS_BREAKPOINT &&
                    ExceptionCode != STATUS_WX86_BREAKPOINT) {
                        continue;
                }

                dumpStack(pProcessInfo->hProcess, hThread, NULL);
            }

            if (!DebugEvent.u.Exception.dwFirstChance) {
                /*
                 * Terminate the process. As continuing would cause the JIT debugger
                 * to be invoked again.
                 */
                fTerminating = TRUE;
                TerminateProcess(pProcessInfo->hProcess, (UINT)ExceptionCode);
            }

            break;
        }

        case CREATE_THREAD_DEBUG_EVENT:
            if (pOptions->verbose_flag) {
                lprintf("CREATE_THREAD PID=%lu TID=%lu\r\n",
                        DebugEvent.dwProcessId,
                        DebugEvent.dwThreadId
                );
            }

            // Add the thread to the thread list
            pProcessInfo = &g_Processes[DebugEvent.dwProcessId];
            pThreadInfo = &pProcessInfo->Threads[DebugEvent.dwThreadId];
            pThreadInfo->hThread = DebugEvent.u.CreateThread.hThread;
            break;

        case CREATE_PROCESS_DEBUG_EVENT: {
            HANDLE hFile = DebugEvent.u.CreateProcessInfo.hFile;

            char szImageName[MAX_PATH];
            char *lpImageName = NULL;
            if (hFile && GetFileNameFromHandle(hFile, szImageName, _countof(szImageName))) {
                lpImageName = szImageName;
            }

            if (pOptions->verbose_flag) {
                PCSTR lpModuleName = lpImageName ? getBaseName(lpImageName) : "";

                lprintf("CREATE_PROCESS PID=%lu TID=%lu lpBaseOfImage=%p %s\r\n",
                        DebugEvent.dwProcessId,
                        DebugEvent.dwThreadId,
                        DebugEvent.u.CreateProcessInfo.lpBaseOfImage,
                        lpModuleName
                );
            }

            hProcess = DebugEvent.u.CreateProcessInfo.hProcess;

            pProcessInfo = &g_Processes[DebugEvent.dwProcessId];
            pProcessInfo->hProcess = hProcess;

            pThreadInfo = &pProcessInfo->Threads[DebugEvent.dwThreadId];
            pThreadInfo->hThread = DebugEvent.u.CreateProcessInfo.hThread;

            if (!InitializeSym(hProcess, FALSE)) {
                OutputDebug("error: SymInitialize failed: 0x%08lx\n", GetLastError());
                exit(EXIT_FAILURE);
            }

            SymRegisterCallback64(hProcess, &symCallback, 0);

            loadModule(hProcess, hFile, lpImageName, DebugEvent.u.CreateProcessInfo.lpBaseOfImage);

            break;
        }

        case EXIT_THREAD_DEBUG_EVENT:
            if (pOptions->verbose_flag) {
                lprintf("EXIT_THREAD PID=%lu TID=%lu dwExitCode=0x%lx\r\n",
                        DebugEvent.dwProcessId,
                        DebugEvent.dwThreadId,
                        DebugEvent.u.ExitThread.dwExitCode
                );
            }

            // Remove the thread from the thread list
            pProcessInfo = &g_Processes[DebugEvent.dwProcessId];
            hProcess = pProcessInfo->hProcess;

            // Dump the stack on abort()
            if (!fTerminating && isAbnormalExitCode(DebugEvent.u.ExitThread.dwExitCode)) {
                pThreadInfo = &pProcessInfo->Threads[DebugEvent.dwThreadId];
                refreshSymbolsAndDumpStack(hProcess, pThreadInfo->hThread);
            }

            pProcessInfo->Threads.erase(DebugEvent.dwThreadId);
            break;

        case EXIT_PROCESS_DEBUG_EVENT: {
            if (pOptions->verbose_flag) {
                lprintf("EXIT_PROCESS PID=%lu TID=%lu dwExitCode=0x%lx\r\n",
                        DebugEvent.dwProcessId,
                        DebugEvent.dwThreadId,
                        DebugEvent.u.ExitProcess.dwExitCode
                );
            }

            pProcessInfo = &g_Processes[DebugEvent.dwProcessId];
            hProcess = pProcessInfo->hProcess;

            // Dump the stack on abort()
            if (!fTerminating && isAbnormalExitCode(DebugEvent.u.ExitThread.dwExitCode)) {
                pThreadInfo = &pProcessInfo->Threads[DebugEvent.dwThreadId];
                refreshSymbolsAndDumpStack(hProcess, pThreadInfo->hThread);
            }

            // Remove the process from the process list
            g_Processes.erase(DebugEvent.dwProcessId);

            if (!SymCleanup(hProcess)) {
                OutputDebug("SymCleanup failed with 0x%08lx\n", GetLastError());
            }

            if (g_Processes.empty()) {
                fFinished = TRUE;
            }

            break;
        }

        case LOAD_DLL_DEBUG_EVENT: {
            HANDLE hFile = DebugEvent.u.LoadDll.hFile;

            char szImageName[MAX_PATH];
            char *lpImageName = NULL;
            if (hFile && GetFileNameFromHandle(hFile, szImageName, _countof(szImageName))) {
                lpImageName = szImageName;
            }

            if (pOptions->verbose_flag) {
                PCSTR lpModuleName = lpImageName ? getBaseName(lpImageName) : "";

                lprintf("LOAD_DLL PID=%lu TID=%lu lpBaseOfDll=%p %s\r\n",
                        DebugEvent.dwProcessId,
                        DebugEvent.dwThreadId,
                        DebugEvent.u.LoadDll.lpBaseOfDll,
                        lpModuleName
                );
            }

            pProcessInfo = &g_Processes[DebugEvent.dwProcessId];
            hProcess = pProcessInfo->hProcess;

            loadModule(hProcess, hFile, lpImageName, DebugEvent.u.LoadDll.lpBaseOfDll);

            break;
        }

        case UNLOAD_DLL_DEBUG_EVENT:
            if (pOptions->verbose_flag) {
                lprintf("UNLOAD_DLL PID=%lu TID=%lu lpBaseOfDll=%p\r\n",
                        DebugEvent.dwProcessId,
                        DebugEvent.dwThreadId,
                        DebugEvent.u.UnloadDll.lpBaseOfDll
                );
            }

            pProcessInfo = &g_Processes[DebugEvent.dwProcessId];
            hProcess = pProcessInfo->hProcess;

            SymUnloadModule64(hProcess, (UINT_PTR)DebugEvent.u.UnloadDll.lpBaseOfDll);

            break;

        case OUTPUT_DEBUG_STRING_EVENT: {
            if (pOptions->verbose_flag) {
                lprintf("OUTPUT_DEBUG_STRING PID=%lu TID=%lu\r\n",
                        DebugEvent.dwProcessId,
                        DebugEvent.dwThreadId
                );
            }

            pProcessInfo = &g_Processes[DebugEvent.dwProcessId];

            assert(!DebugEvent.u.DebugString.fUnicode);

            LPSTR lpDebugStringData = readProcessString(pProcessInfo->hProcess,
                                                        DebugEvent.u.DebugString.lpDebugStringData,
                                                        DebugEvent.u.DebugString.nDebugStringLength);

            lprintf("%s", lpDebugStringData);

            free(lpDebugStringData);
            break;
        }

        case RIP_EVENT:
            if (pOptions->verbose_flag) {
                lprintf("RIP PID=%lu TID=%lu\r\n",
                        DebugEvent.dwProcessId,
                        DebugEvent.dwThreadId
                );
            }
            break;

        default:
            if (pOptions->verbose_flag) {
                lprintf("EVENT%lu PID=%lu TID=%lu\r\n",
                    DebugEvent.dwDebugEventCode,
                    DebugEvent.dwProcessId,
                    DebugEvent.dwThreadId
                );
            }
            break;
        }

        // Resume executing the thread that reported the debugging event.
        ContinueDebugEvent(
            DebugEvent.dwProcessId,
            DebugEvent.dwThreadId,
            dwContinueStatus
        );
    }

    return TRUE;
}
Пример #11
0
ErrorCode Process::wait(int *status, bool hang) {
  if (_terminated)
    return kSuccess;

  DEBUG_EVENT de;
  bool keepGoing = true;

  while (keepGoing) {
    BOOL result = WaitForDebugEvent(&de, hang ? INFINITE : 0);
    if (!result)
      return Platform::TranslateError();

    keepGoing = false;

    switch (de.dwDebugEventCode) {
    case CREATE_PROCESS_DEBUG_EVENT:
#define CHECK_AND_CLOSE(HAN)                                                   \
  do {                                                                         \
    if ((de.u.CreateProcessInfo.HAN) != NULL)                                  \
      CloseHandle(de.u.CreateProcessInfo.HAN);                                 \
  } while (0)
      CHECK_AND_CLOSE(hFile);
      CHECK_AND_CLOSE(hProcess);
      CHECK_AND_CLOSE(hThread);
#undef CHECK_AND_CLOSE
      return kSuccess;

    case EXIT_PROCESS_DEBUG_EVENT:
      _terminated = true;
      return kSuccess;

    case CREATE_THREAD_DEBUG_EVENT: {
      auto threadHandle = de.u.CreateThread.hThread;
      auto tid = GetThreadId(threadHandle);
      // No need to save the new thread pointer, as it gets added automatically
      // to the process.
      new Thread(this, tid, threadHandle);
      resume();
      keepGoing = true;
    } break;

    case EXIT_THREAD_DEBUG_EVENT: {
      auto threadIt = _threads.find(de.dwThreadId);
      DS2ASSERT(threadIt != _threads.end());
      auto tid = threadIt->second->tid();
      ContinueDebugEvent(_pid, tid, DBG_CONTINUE);
      removeThread(threadIt->second->tid());
      keepGoing = true;
    } break;

    case RIP_EVENT:
      DS2LOG(Fatal, "debug event RIP");

    case EXCEPTION_DEBUG_EVENT:
    case LOAD_DLL_DEBUG_EVENT:
    case UNLOAD_DLL_DEBUG_EVENT:
    case OUTPUT_DEBUG_STRING_EVENT: {
      auto threadIt = _threads.find(de.dwThreadId);
      DS2ASSERT(threadIt != _threads.end());
      threadIt->second->updateState(de);
    } break;

    default:
      DS2BUG("unknown debug event code: %lu", de.dwDebugEventCode);
    }
  }

  return kSuccess;
}
Пример #12
0
void DoParentProcess()
{
    TCHAR                   szPath[MAX_PATH] = {0,};
    STARTUPINFO				si = {sizeof(STARTUPINFO),};
    PROCESS_INFORMATION		pi = {0,};
    DEBUG_EVENT             de = {0,};
    CONTEXT                 ctx = {0,};
    BYTE                    pBuf[0x20] = {0,};
    DWORD                   dwExcpAddr = 0, dwExcpCode = 0;
    const DWORD             DECODING_SIZE = 0x14;
    const DWORD             DECODING_KEY = 0x7F;
    const DWORD             EXCP_ADDR_1 = 0x0040103F;
    const DWORD             EXCP_ADDR_2 = 0x00401048;
    
    // create debug process
    GetModuleFileName(
        GetModuleHandle(NULL), 
        szPath, 
        MAX_PATH);

    if( !CreateProcess(
            NULL,
            szPath,
            NULL, NULL,
            FALSE,
            DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS,
            NULL, NULL,
            &si,
            &pi) )
    {
        printf("CreateProcess() failed! [%d]\n", GetLastError());
        return;
    }

    printf("Parent Process\n");

    // debug loop
    while( TRUE )
    {
        ZeroMemory(&de, sizeof(DEBUG_EVENT));

        if( !WaitForDebugEvent(&de, INFINITE) )
        {
            printf("WaitForDebugEvent() failed! [%d]\n", GetLastError());
            break;
        }

        if( de.dwDebugEventCode == EXCEPTION_DEBUG_EVENT )
        {
            dwExcpAddr = (DWORD)de.u.Exception.ExceptionRecord.ExceptionAddress;
            dwExcpCode = de.u.Exception.ExceptionRecord.ExceptionCode;

            if( dwExcpCode == EXCEPTION_ILLEGAL_INSTRUCTION )
            {
                if( dwExcpAddr == EXCP_ADDR_1 )
                {
                    // decoding
                    ReadProcessMemory(
                        pi.hProcess, 
                        (LPCVOID)(dwExcpAddr + 2),
                        pBuf,
                        DECODING_SIZE,
                        NULL);

                    for(DWORD i = 0; i < DECODING_SIZE; i++)
                        pBuf[i] ^= DECODING_KEY;

                    WriteProcessMemory(
                        pi.hProcess,
                        (LPVOID)(dwExcpAddr + 2),
                        pBuf,
                        DECODING_SIZE,
                        NULL);
                    
                    // change EIP
                    ctx.ContextFlags = CONTEXT_FULL;
                    GetThreadContext(pi.hThread, &ctx);
                    ctx.Eip += 2;
                    SetThreadContext(pi.hThread, &ctx);
                }
                else if( dwExcpAddr == EXCP_ADDR_2 )
                {
                    pBuf[0] = 0x68;
                    pBuf[1] = 0x1C;
                    WriteProcessMemory(
                        pi.hProcess,
                        (LPVOID)dwExcpAddr,
                        pBuf,
                        2,
                        NULL);
                }
            }
        }
        else if( de.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT )
        {
            break;
        }

        ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
    }
}
Пример #13
0
static void *Ploopcreate(LPVOID args)
{
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    DEBUG_EVENT  dbg;
    DWORD cont;
    BOOL wow = 0;
    DWORD Options = SymGetOptions(), excep, size = 0;
    TCHAR pszFilename[MAX_PATH+1];
    struct proc_uc *tmp = args;
    struct ps_prochandle *P = tmp->ps;
    int first_execp = 0;
    char *s, targs[256], *ctmp;
    char *const *argv = tmp->args;
    int len;

    ctmp = targs;
    while (*argv != NULL) {
        len = strlen(*argv);
        sprintf(ctmp, "%s ", *argv);
        ctmp = ctmp + len + 1;
        argv++;
    }

    *ctmp = '\0';
    ZeroMemory( &si, sizeof(si) );
    si.cb = sizeof(si);
    ZeroMemory( &pi, sizeof(pi) );
    if(!CreateProcess( NULL,   //  module name
                       targs,        // Command line
                       NULL,           // Process handle not inheritable
                       NULL,           // Thread handle not inheritable
                       FALSE,          // Set handle inheritance to FALSE
                       DEBUG_ONLY_THIS_PROCESS,              // No creation flags
                       NULL,           // Use parent's environment block
                       NULL,           // Use parent's starting directory
                       &si,            // Pointer to STARTUPINFO structure
                       &pi )           // Pointer to PROCESS_INFORMATION structure
      ) {
        pthread_mutex_lock(&P->mutex);
        P->status = PS_STOP;
        P->flags = CREATE_FAILED;
        pthread_cond_signal(&P->cond);
        pthread_mutex_unlock(&P->mutex);
        return NULL;
    }
    P->pid = pi.dwProcessId;
    P->tid = pi.dwThreadId;
    P->wstat = 0;
    P->exitcode = 0;
    P->event = CreateEvent(NULL,FALSE,FALSE,NULL);
    P->dll_load_order = 1;
#if __amd64__
    /* There seems to be a bug in 64 bit version of dbghelp.dll
     * when SYMOPT_DEFERRED_LOADS is set,
     * dtrace -n "pid$target:kernel32::entry, pid$target:KernelBase::entry" -c test.exe,
     * when SymEnumSymbols (Psymbol_iter_by_addr) is called on this two dll,
     * the second call (KernelBase) will enumerate the
     * symbols from the previous enumurated (kernel32) dll (from the first call).
     * This behaviour is not present in 32 bit.
     */
    Options &= ~SYMOPT_DEFERRED_LOADS;
#endif
    SymSetOptions(Options|SYMOPT_INCLUDE_32BIT_MODULES|SYMOPT_DEBUG);

    while (1) {
        if (WaitForDebugEvent(&dbg, INFINITE) == 0) {
            return NULL;
        }
        cont = DBG_CONTINUE;
        pthread_mutex_lock(&P->mutex);

        switch (dbg.dwDebugEventCode) {
        case CREATE_PROCESS_DEBUG_EVENT:

            P->phandle = dbg.u.CreateProcessInfo.hProcess;
            P->thandle = dbg.u.CreateProcessInfo.hThread;
            if ((SymInitialize(P->phandle, 0, FALSE) == FALSE)) {
                dprintf("SymInitialize failed: %d\n", GetLastError());
                break;
            }

            s = GetFileNameFromHandle(dbg.u.CreateProcessInfo.hFile, pszFilename);
            addmodule(P, dbg.u.CreateProcessInfo.hFile, s, dbg.u.CreateProcessInfo.lpBaseOfImage,
                      PE_TYPE_EXE, P->dll_load_order);
            size = GetFileSize(dbg.u.CreateProcessInfo.hFile, NULL);
            if (size == INVALID_FILE_SIZE) {
                size = 0;
            }
            if (SymLoadModuleEx(P->phandle, dbg.u.CreateProcessInfo.hFile, s, NULL,
                                (ULONG_PTR) dbg.u.CreateProcessInfo.lpBaseOfImage, size, NULL, 0) == 0) {
                dprintf("SymLoadModule64 failed for %s:%d\n", s, GetLastError());
                break;
            }

#if __amd64__
            if (Is32bitProcess(P->phandle)) {
                P->model = PR_MODEL_ILP32;
                wow = 1;
            } else
                P->model = PR_MODEL_ILP64;
#else
            P->model = PR_MODEL_ILP32;
#endif
            P->status = PS_STOP;
            P->msg.type = 0;
            CloseHandle(dbg.u.CreateProcessInfo.hFile);
            pthread_cond_signal(&P->cond);
            break;
        case CREATE_THREAD_DEBUG_EVENT:
            P->status = PS_RUN;
            P->msg.type = 0;
            break;
        case LOAD_DLL_DEBUG_EVENT:
            s = GetFileNameFromHandle(dbg.u.LoadDll.hFile, pszFilename);
            if (first_execp == 2) {
                P->dll_load_order++;
            }
            addmodule(P, dbg.u.LoadDll.hFile, s, dbg.u.LoadDll.lpBaseOfDll, PE_TYPE_DLL, P->dll_load_order);

            size = GetFileSize(dbg.u.LoadDll.hFile, NULL);
            if (size == INVALID_FILE_SIZE) {
                size = 0;
            }
#if __amd64__
            /* Not tracing 64 bit dlls for 32 bit process */
            if (P->model == PR_MODEL_ILP32 && is64bitmodule(dbg.u.LoadDll.lpBaseOfDll, s)) {
                CloseHandle(dbg.u.LoadDll.hFile );
                break;
            }
#endif
            if (SymLoadModuleEx(P->phandle, dbg.u.LoadDll.hFile, s, NULL,
                                (ULONG_PTR) dbg.u.LoadDll.lpBaseOfDll, size, NULL, 0) == FALSE) {
                dprintf("SymLoadModule64 dailed for %s:%d\n", s, GetLastError());
                break;
            }

            CloseHandle(dbg.u.LoadDll.hFile );
            P->status = PS_STOP;
            P->msg.type = RD_DLACTIVITY;
            break;
        case UNLOAD_DLL_DEBUG_EVENT:
            if (SymUnloadModule64(P->phandle, (ULONG_PTR) dbg.u.UnloadDll.lpBaseOfDll) ==  FALSE) {
                dprintf("SymUnloadModule64 failed-Imagebase %p:%d\n", dbg.u.UnloadDll.lpBaseOfDll, GetLastError());
                break;
            }
            delmodule(P, (ULONG64) dbg.u.UnloadDll.lpBaseOfDll);
            P->status = PS_RUN;
            P->msg.type = RD_DLACTIVITY;
            break;
        case EXIT_PROCESS_DEBUG_EVENT:
            P->exitcode = dbg.u.ExitProcess.dwExitCode;
            P->status = PS_UNDEAD;
            P->msg.type = RD_NONE;
            break;
        case EXIT_THREAD_DEBUG_EVENT:
            P->status = PS_RUN;
            P->msg.type = 0;
            break;
        case EXCEPTION_DEBUG_EVENT:
            switch(excep = dbg.u.Exception.ExceptionRecord.ExceptionCode) {
            case EXCEPTION_BREAKPOINT:
            case 0x4000001F:	/* WOW64 exception breakpoint */
                /* NOTE: Dtrace sets a BP at main (entry point of the process), which is implemented
                 * with Psetbkpt, Pdelbkpt & Pexecbkpt. But I have implemnted it here.
                 */
                if ((excep == EXCEPTION_BREAKPOINT && first_execp == 0 && wow == 0) ||
                        (excep == 0x4000001F && first_execp == 0 && wow == 1) ) {
                    SYMBOL_INFO *Symbol;
                    GElf_Sym sym;
                    ULONG64 buffer[(sizeof(SYMBOL_INFO) +  MAX_SYM_NAME * sizeof(TCHAR) + sizeof(ULONG64) - 1) / sizeof(ULONG64)];

                    Symbol = (SYMBOL_INFO *) buffer;
                    Symbol->SizeOfStruct= sizeof(SYMBOL_INFO );
                    Symbol->MaxNameLen = MAX_SYM_NAME;

                    if (Pxlookup_by_name(P, LM_ID_BASE, "a.out", "main", &sym, NULL) != 0 &&
                            Pxlookup_by_name(P, LM_ID_BASE, "a.out", "WinMain", &sym, NULL) != 0) {
                        dprintf("failed to find entry point (main):%d\n", GetLastError());
                        break;
                    }

                    if (setbkpt(P, (uintptr_t) sym.st_value) != 0) {
                        dprintf("failed to set breakpoint for %s at address %p\n", Symbol->Name, Symbol->Address);
                        break;
                    }

                    first_execp = 1;
                    P->status = PS_RUN;
                    P->msg.type = 0;
                    break;
                }

                if (dbg.u.Exception.ExceptionRecord.ExceptionAddress != (PVOID) P->addr) {
                    dprintf("expecting execption at %p:but recived from %p\n", P->addr,
                            dbg.u.Exception.ExceptionRecord.ExceptionAddress);
                    P->status = PS_RUN;
                    cont = DBG_EXCEPTION_NOT_HANDLED;
                    break;
                }

                if (delbkpt(P, P->addr) != 0) {
                    dprintf("failed to delete brk point at %p:(main)\n", P->addr);
                    break;
                }

                if (adjbkpt(P, wow) != 0) {
                    dprintf("failed to normalize brk point (main)\n");
                    break;
                }
                first_execp = 2;
                P->status = PS_STOP;
                P->msg.type = RD_MAININIT;
                break;/*
				if (first_execp == 0) {
					P->status = PS_STOP;
					P->msg.type = RD_MAININIT;
					first_execp = 2;
				} else {
					P->status = PS_RUN;
					cont = DBG_EXCEPTION_NOT_HANDLED;
				}
				break;*/

            default:
                if (dbg.u.Exception.dwFirstChance == 0)
                    P->wstat = dbg.u.Exception.ExceptionRecord.ExceptionCode;
                P->status = PS_RUN;
                cont = DBG_EXCEPTION_NOT_HANDLED;
                break;
            }
            break;
        default:
            P->status = PS_RUN;
            dprintf("Debug Event not processed: %d\n", dbg.dwDebugEventCode);
            break;
        }

        if (P->status != PS_RUN)
            SetEvent(P->event);
        while (P->status == PS_STOP)
            pthread_cond_wait(&P->cond, &P->mutex);
        pthread_mutex_unlock(&P->mutex);

        ContinueDebugEvent(dbg.dwProcessId, dbg.dwThreadId, cont);
    }

}
Пример #14
0
// Algo benchmark, crash-safe, system-dependent stage
static double bench_algo_stage2(
	enum sha256_algos algo
)
{
	// Here, the gig is to safely run a piece of code that potentially
	// crashes. Unfortunately, the Right Way (tm) to do this is rather
	// heavily platform dependent :(

	double rate = -1.23457;

	#if defined(unix)

		// Make a pipe: [readFD, writeFD]
		int pfd[2];
		int r = pipe(pfd);
		if (r<0) {
			perror("pipe - failed to create pipe for --algo auto");
			exit(1);
		}

		// Make pipe non blocking
		set_non_blocking(pfd[0], 1);
		set_non_blocking(pfd[1], 1);

		// Don't allow a crashing child to kill the main process
		sighandler_t sr0 = signal(SIGPIPE, SIG_IGN);
		sighandler_t sr1 = signal(SIGPIPE, SIG_IGN);
		if (SIG_ERR==sr0 || SIG_ERR==sr1) {
			perror("signal - failed to edit signal mask for --algo auto");
			exit(1);
		}

		// Fork a child to do the actual benchmarking
		pid_t child_pid = fork();
		if (child_pid<0) {
			perror("fork - failed to create a child process for --algo auto");
			exit(1);
		}

		// Do the dangerous work in the child, knowing we might crash
		if (0==child_pid) {

			// TODO: some umask trickery to prevent coredumps

			// Benchmark this algorithm
			double r = bench_algo_stage3(algo);

			// We survived, send result to parent and bail
			int loop_count = 0;
			while (1) {
				ssize_t bytes_written = write(pfd[1], &r, sizeof(r));
				int try_again = (0==bytes_written || (bytes_written<0 && EAGAIN==errno));
				int success = (sizeof(r)==(size_t)bytes_written);

				if (success)
					break;

				if (!try_again) {
					perror("write - child failed to write benchmark result to pipe");
					exit(1);
				}

				if (5<loop_count) {
					applog(LOG_ERR, "child tried %d times to communicate with parent, giving up", loop_count);
					exit(1);
				}
				++loop_count;
				sleep(1);
			}
			exit(0);
		}

		// Parent waits for a result from child
		int loop_count = 0;
		while (1) {

			// Wait for child to die
			int status;
			int r = waitpid(child_pid, &status, WNOHANG);
			if ((child_pid==r) || (r<0 && ECHILD==errno)) {

				// Child died somehow. Grab result and bail
				double tmp;
				ssize_t bytes_read = read(pfd[0], &tmp, sizeof(tmp));
				if (sizeof(tmp)==(size_t)bytes_read)
					rate = tmp;
				break;

			} else if (r<0) {
				perror("bench_algo: waitpid failed. giving up.");
				exit(1);
			}

			// Give up on child after a ~60s
			if (60<loop_count) {
				kill(child_pid, SIGKILL);
				waitpid(child_pid, &status, 0);
				break;
			}

			// Wait a bit longer
			++loop_count;
			sleep(1);
		}

		// Close pipe
		r = close(pfd[0]);
		if (r<0) {
			perror("close - failed to close read end of pipe for --algo auto");
			exit(1);
		}
		r = close(pfd[1]);
		if (r<0) {
			perror("close - failed to close read end of pipe for --algo auto");
			exit(1);
		}

	#elif defined(WIN32)

		// Get handle to current exe
		HINSTANCE module = GetModuleHandle(0);
		if (!module) {
			applog(LOG_ERR, "failed to retrieve module handle");
			exit(1);
		}

		// Create a unique name
		char unique_name[33];
		snprintf(
			unique_name,
			sizeof(unique_name)-1,
			"bfgminer-%p",
			(void*)module
		);

		// Create and init a chunked of shared memory
		HANDLE map_handle = CreateFileMapping(
			INVALID_HANDLE_VALUE,   // use paging file
			NULL,                   // default security attributes
			PAGE_READWRITE,         // read/write access
			0,                      // size: high 32-bits
			4096,			// size: low 32-bits
			unique_name		// name of map object
		);
		if (NULL==map_handle) {
			applog(LOG_ERR, "could not create shared memory");
			exit(1);
		}

		void *shared_mem = MapViewOfFile(
			map_handle,	// object to map view of
			FILE_MAP_WRITE, // read/write access
			0,              // high offset:  map from
			0,              // low offset:   beginning
			0		// default: map entire file
		);
		if (NULL==shared_mem) {
			applog(LOG_ERR, "could not map shared memory");
			exit(1);
		}
		SetEnvironmentVariable("BFGMINER_SHARED_MEM", unique_name);
		CopyMemory(shared_mem, &rate, sizeof(rate));

		// Get path to current exe
		char cmd_line[256 + MAX_PATH];
		const size_t n = sizeof(cmd_line)-200;
		DWORD size = GetModuleFileName(module, cmd_line, n);
		if (0==size) {
			applog(LOG_ERR, "failed to retrieve module path");
			exit(1);
		}

		// Construct new command line based on that
		char *p = strlen(cmd_line) + cmd_line;
		sprintf(p, " --bench-algo %d", algo);
		SetEnvironmentVariable("BFGMINER_BENCH_ALGO", "1");

		// Launch a debug copy of BFGMiner
		STARTUPINFO startup_info;
		PROCESS_INFORMATION process_info;
		ZeroMemory(&startup_info, sizeof(startup_info));
		ZeroMemory(&process_info, sizeof(process_info));
		startup_info.cb = sizeof(startup_info);

		BOOL ok = CreateProcess(
			NULL,			// No module name (use command line)
			cmd_line,		// Command line
			NULL,			// Process handle not inheritable
			NULL,			// Thread handle not inheritable
			FALSE,			// Set handle inheritance to FALSE
			DEBUG_ONLY_THIS_PROCESS,// We're going to debug the child
			NULL,			// Use parent's environment block
			NULL,			// Use parent's starting directory
			&startup_info,		// Pointer to STARTUPINFO structure
			&process_info		// Pointer to PROCESS_INFORMATION structure
		);
		if (!ok) {
			applog(LOG_ERR, "CreateProcess failed with error %ld\n", (long)GetLastError() );
			exit(1);
		}

		// Debug the child (only clean way to catch exceptions)
		while (1) {

			// Wait for child to do something
			DEBUG_EVENT debug_event;
			ZeroMemory(&debug_event, sizeof(debug_event));

			BOOL ok = WaitForDebugEvent(&debug_event, 60 * 1000);
			if (!ok)
				break;

			// Decide if event is "normal"
			int go_on =
				CREATE_PROCESS_DEBUG_EVENT== debug_event.dwDebugEventCode	||
				CREATE_THREAD_DEBUG_EVENT == debug_event.dwDebugEventCode	||
				EXIT_THREAD_DEBUG_EVENT   == debug_event.dwDebugEventCode	||
				EXCEPTION_DEBUG_EVENT     == debug_event.dwDebugEventCode	||
				LOAD_DLL_DEBUG_EVENT      == debug_event.dwDebugEventCode	||
				OUTPUT_DEBUG_STRING_EVENT == debug_event.dwDebugEventCode	||
				UNLOAD_DLL_DEBUG_EVENT    == debug_event.dwDebugEventCode;
			if (!go_on)
				break;

			// Some exceptions are also "normal", apparently.
			if (EXCEPTION_DEBUG_EVENT== debug_event.dwDebugEventCode) {

				int go_on =
					EXCEPTION_BREAKPOINT== debug_event.u.Exception.ExceptionRecord.ExceptionCode;
				if (!go_on)
					break;
			}

			// If nothing unexpected happened, let child proceed
			ContinueDebugEvent(
				debug_event.dwProcessId,
				debug_event.dwThreadId,
				DBG_CONTINUE
			);
		}

		// Clean up child process
		TerminateProcess(process_info.hProcess, 1);
		CloseHandle(process_info.hProcess);
		CloseHandle(process_info.hThread);

		// Reap return value and cleanup
		CopyMemory(&rate, shared_mem, sizeof(rate));
		(void)UnmapViewOfFile(shared_mem);
		(void)CloseHandle(map_handle);

	#else

		// Not linux, not unix, not WIN32 ... do our best
		rate = bench_algo_stage3(algo);

	#endif // defined(unix)

	// Done
	return rate;
}
Пример #15
0
static int fork_and_ptraceme(const char *cmd) {
	PROCESS_INFORMATION pi;
        STARTUPINFO si = { sizeof (si) };
        DEBUG_EVENT de;
	int pid, tid;
	HANDLE th = INVALID_HANDLE_VALUE;
	if (!*cmd)
		return -1;
	setup_tokens ();
        /* TODO: with args */
        if (!CreateProcess (cmd, NULL,
                        NULL, NULL, FALSE,
                        CREATE_NEW_CONSOLE | DEBUG_ONLY_THIS_PROCESS,
                        NULL, NULL, &si, &pi)) {
                r_sys_perror ("CreateProcess");
                return -1;
        }

        /* get process id and thread id */
        pid = pi.dwProcessId;
        tid = pi.dwThreadId;

#if 0
        /* load thread list */
	{
		HANDLE h;
		THREADENTRY32 te32;
		HANDLE WINAPI (*win32_openthread)(DWORD, BOOL, DWORD) = NULL;
		win32_openthread = (HANDLE WINAPI (*)(DWORD, BOOL, DWORD))
			GetProcAddress (GetModuleHandle ("kernel32"), "OpenThread");

		th = CreateToolhelp32Snapshot (TH32CS_SNAPTHREAD, pid);
		if (th == INVALID_HANDLE_VALUE || !Thread32First(th, &te32))
			r_sys_perror ("CreateToolhelp32Snapshot");

		do {
			if (te32.th32OwnerProcessID == pid) {
				h = win32_openthread (THREAD_ALL_ACCESS, 0, te32.th32ThreadID);
				if (h == NULL) r_sys_perror ("OpenThread");
				else eprintf ("HANDLE=%p\n", h);
			}
		} while (Thread32Next (th, &te32));
	}
#endif

#if 0
	// Access denied here :?
	if (ContinueDebugEvent (pid, tid, DBG_CONTINUE) == 0) {
		r_sys_perror ("ContinueDebugEvent");
		goto err_fork;
	}
#endif

        /* catch create process event */
        if (!WaitForDebugEvent (&de, 10000))
                goto err_fork;

        /* check if is a create process debug event */
        if (de.dwDebugEventCode != CREATE_PROCESS_DEBUG_EVENT) {
                eprintf ("exception code 0x%04x\n", (ut32)de.dwDebugEventCode);
                goto err_fork;
        }

	if (th != INVALID_HANDLE_VALUE)
		CloseHandle (th);

	eprintf ("PID=%d\n", pid);
	eprintf ("TID=%d\n", tid);
        return pid;

err_fork:
	eprintf ("ERRFORK\n");
        TerminateProcess (pi.hProcess, 1);
	if (th != INVALID_HANDLE_VALUE)
		CloseHandle (th);
        return -1;
}
Пример #16
0
// EnterDebugLoop was taken from:
// http://msdn.microsoft.com/en-us/library/ms681675(VS.85).aspx
//
// Note that we don't actually *want* to be a debugger, but CreateProcess has
// some bug or security dependency which is leading it to (in some situations)
// not show the window of the process it launches.  Somehow, calling a debug
// loop addresses this.  I've left the full code from the sample here in order
// to make it easier to set breakpoints to discover what's going wrong if
// there is a problem with the technique of working around CreateProcess's
// flaw with the debug API.
//
DWORD WINAPI DebugLoopMain(LPVOID lpParam) // returns a MainReturn
{
	DebugArgs & debugArgs = *static_cast<DebugArgs *>(lpParam);

	HMODULE ntDllModule = sm_LoadNTDLLFunctions();

	debugInfo(L"Got to DebugLoopMain thread code.");

	PROCESS_INFORMATION processInfo;
	processInfo.hProcess = NULL;
	processInfo.hThread = NULL;

	// Windows can modify the command line, so we have to make a copy
	std::vector<WCHAR> commandLineCopy (
		debugArgs.commandLine.begin(),
		debugArgs.commandLine.end()
	);
	commandLineCopy.push_back(L'\0');

	DWORD dwCreationFlags =
#ifdef USE_STARTUPINFO_FOR_WINDOW_POSITION
			// These options don't work :-(
			(config->runWindowPosition ? STARTF_USEPOSITION : 0) |
			(config->runWindowSize ? STARTF_USESIZE : 0) |
#endif
			(config->shutdownEvent ? 0 : DEBUG_PROCESS) |
			STARTF_USESHOWWINDOW;

	// REVIEW: for security should lpApplicationName be the same as the 
	// name in the command line?
	WindowsVerify(
		L"CreateProcess",
		CreateProcess(
			0, // lpApplicationName
			&commandLineCopy[0], // lpCommandLine (no .data() in C++98)
			0, // lpProcessAttributes
			0, // lpThreadAttributes
			config->shutdownEvent == NULL ? TRUE : FALSE, // bInheritHandles
			dwCreationFlags,
			0, // lpEnvironment
			0, // lpCurrentDirectory
			debugArgs.startupInfo, // lpStartupInfo
			&processInfo // lpProcessInformation
		)
	);

	Verify(L"Thread or process was null.", 
		processInfo.hThread and processInfo.hProcess
	);

	debugInfo(L"CreateProcess(%s) - Id = %d\n", 
		debugArgs.commandLine.c_str(), processInfo.dwProcessId
	);

	debugInfo(L"Entering debugger loop...\n");

	HANDLE suspendedThread = NULL;
	BOOL previouslyWaited = FALSE;

	DEBUG_EVENT Ev;
	const LPDEBUG_EVENT DebugEv = &Ev;

	while (TRUE) {

		// Wait for a debugging event to occur. The second parameter indicates
		// that the function does not return until a debugging event occurs. 

		BOOL gotDebugEvent = FALSE;
		BOOL handledEvent = TRUE;

		DWORD tickBefore = GetTickCount();
		if (WaitForDebugEvent(
			DebugEv,
			suspendedThread ? 1000 : *debugArgs.msecLeft
		)) {
			gotDebugEvent = TRUE;
		} else {
			DWORD lastError = GetLastError();
			if (lastError == 0x79) {
				// The semaphore timeout period has expired, that is ok
			} else {
				ExitProgramOnWindowsError(L"WaitForDebugEvent", lastError);
			}
		}

		if (suspendedThread) {
			switch(WaitForSingleObject(debugArgs.retryEvent, 0)) {
			case WAIT_OBJECT_0: {
				WindowsVerify(L"ResetEvent", ResetEvent(debugArgs.retryEvent));
				// need to poll processes again...
				std::wstring exeImageName;
				if (PreviousStillRunning(exeImageName, 0)) {
					debugInfo(L"Retry failed, show message box again.");
					WindowsVerify(L"SetEvent", SetEvent(debugArgs.deferEvent));
				} else {
					debugInfo(L"Resuming thread handle 0x%x", suspendedThread);
					WindowsVerify(L"ResumeThread",
						ResumeThread(suspendedThread) != -1
					);
					WindowsVerify(L"CloseHandle", CloseHandle(suspendedThread));
					suspendedThread = NULL;
					previouslyWaited = TRUE;
				}
				break;
			}
			case WAIT_TIMEOUT:
				// nope, do nothing, try again in a second...
				break;
			default:
				WindowsVerify(L"WaitForSingleObject", FALSE);
			}
		}

		DWORD tickAfter = GetTickCount();
		if (*debugArgs.msecLeft != INFINITE) {
			bool timedOut = false;
			if (tickAfter < tickBefore) {
				// happens once every 28 days, the tick count rolls over...
				// account for the rollover only
				if (tickBefore > *debugArgs.msecLeft) {
					timedOut = true;
				} else {
					*debugArgs.msecLeft = *debugArgs.msecLeft - tickBefore;
				}
			} else {
				if (tickAfter - tickBefore > *debugArgs.msecLeft) {
					timedOut = true;
				} else {
					*debugArgs.msecLeft =
						*debugArgs.msecLeft - (tickAfter - tickBefore);
				}
			}
			if (timedOut) {
				// Need to take the screenshot here, because if we return from
				// the DebugLoop the windows will be closed and the state lost
				// by the time we return to the caller
				if (not config->timeoutSnapshot.empty()) {
					Verify(L"Screen Capture Failed", 
						TakeScreenshotToFile(config->timeoutSnapshot.c_str())
					);
				}
				return TitleWait::TimeoutReturn;
			}
		}

		// Process the debugging event code. 
		if (gotDebugEvent) {
			switch (DebugEv->dwDebugEventCode) { 

			case EXCEPTION_DEBUG_EVENT: {
				// Process the exception code. When handling 
				// exceptions, remember to set the continuation 
				// status parameter (dwContinueStatus). This value 
				// is used by the ContinueDebugEvent function. 
	 
				switch(DebugEv->u.Exception.ExceptionRecord.ExceptionCode) { 

				case EXCEPTION_ACCESS_VIOLATION: {
					// First chance: Pass this on to the system. 
					// Last chance: Display an appropriate error.

					debugInfo(L"EXCEPTION_ACCESS_VIOLATION");

					if (not config->crashSnapshot.empty()) {
						Verify(L"Screen Capture Failed",
							TakeScreenshotToFile(config->crashSnapshot.c_str())
						);
					}
	 				debugInfo(L"Child Process Crashed - Quitting");
					return TitleWait::CrashedReturn;
				}
	 
				case EXCEPTION_BREAKPOINT: {
					// First chance: Display the current 
					// instruction and register values.
					debugInfo(L"EXCEPTION_BREAKPOINT");
	
					// No process functions during CREATE_PROCESS_DEBUG_EVENT
					// have to wait for a later time
					if (!config->defer or previouslyWaited or suspendedThread)
						break;

					if (PreviousStillRunning(
						debugArgs.exeImageName, DebugEv->dwProcessId
					)) {
						WindowsVerify(L"SetEvent", SetEvent(debugArgs.deferEvent));

						// don't block, keep processing debug events...
						// but suspend the thread!
						debugInfo(
							L"About to suspend thread handle 0x%x", 
							DebugEv->dwThreadId
						);
						suspendedThread = OpenThread(
							THREAD_SUSPEND_RESUME, FALSE, DebugEv->dwThreadId
						);
						WindowsVerify(L"OpenThread", suspendedThread != NULL);
						WindowsVerify(L"Suspend Thread",
							SuspendThread(suspendedThread) != -1
						);
						}
					}
					break;
	 
				case EXCEPTION_DATATYPE_MISALIGNMENT: 
					// First chance: Pass this on to the system. 
					// Last chance: Display an appropriate error.
					debugInfo(L"EXCEPTION_DATATYPE_MISALIGNMENT");
					break;
	 
				case EXCEPTION_SINGLE_STEP: 
					// First chance: Update the display of the 
					// current instruction and register values.
					debugInfo(L"EXCEPTION_SINGLE_STEP");
					break;
	 
				case DBG_CONTROL_C: 
					// First chance: Pass this on to the system. 
					// Last chance: Display an appropriate error. 
					debugInfo(L"DBG_CONTROL_C");
					break;
	 
				default:
					debugInfo(
						L"EXCEPTION_(0x%x) (unrecognized, passing through)",
						DebugEv->u.Exception.ExceptionRecord.ExceptionCode
					);
					// We have debugger behaviors for everything we
					// understand, but not random exceptions...pass on up
					// the chain and say we don't handle it.
					handledEvent = false;
					break;
				}
				break;
			}
	 
			case CREATE_THREAD_DEBUG_EVENT: {
				// As needed, examine or change the thread's registers 
				// with the GetThreadContext and SetThreadContext functions; 
				// and suspend and resume thread execution with the 
				// SuspendThread and ResumeThread functions. 

				debugInfo(
					L"CREATE_THREAD_DEBUG_EVENT - H: 0x%x - P: 0x%x",
					DebugEv->u.CreateThread.hThread,
					DebugEv->dwProcessId
				);
				break;
			}

			case CREATE_PROCESS_DEBUG_EVENT: {
				// As needed, examine or change the registers of the
				// process's initial thread with the GetThreadContext and
				// SetThreadContext functions; read from and write to the
				// process's virtual memory with the ReadProcessMemory and
				// WriteProcessMemory functions; and suspend and resume
				// thread execution with the SuspendThread and ResumeThread
				// functions. 

				SetLastError(0);
				DWORD processId = GetProcessId(
					DebugEv->u.CreateProcessInfo.hProcess
				);
				DWORD lastError = GetLastError();
				if (lastError != ERROR_SUCCESS) {
					ExitProgramOnWindowsError(L"GetProcessId", lastError);
				}

				debugInfo(
					L"CREATE_PROCESS_DEBUG_EVENT - P: 0x%x - T: 0x%x",
					processId,
					DebugEv->dwThreadId
				);

				DWORD processMonThreadId;
				HANDLE processMonThread = CreateThread( 
					NULL, // default security attributes
					0, // use default stack size  
					ProcessMonitorMain, // thread function name
					// argument to thread function
					DebugEv->u.CreateProcessInfo.hProcess, 
					CREATE_SUSPENDED, // create the thread as suspended
					&processMonThreadId);   // returns thread identifier 
				if (processMonThread == NULL) {
					WindowsVerify(L"CreateThread", FALSE);
				}

				// lock process list mutex and append tracking data for thread
				if (WaitForSingleObject(processListMutex, INFINITE) != WAIT_OBJECT_0) {
					WindowsVerify(L"WaitForSingleObject", FALSE);
				}

				processIds[numProcesses] = processId;
				processMonThreads[numProcesses] = processMonThread;
				numProcesses++;

				WindowsVerify(L"ReleaseMutex", ReleaseMutex(processListMutex));

				WindowsVerify(L"ResumeThread",
					ResumeThread(processMonThread) != -1
				);

				// "Be sure to close the handle to the process image
				// file with CloseHandle."  Ok, sure.
				WindowsVerify(L"CloseHandle",
					CloseHandle(DebugEv->u.CreateProcessInfo.hFile)
				);
				break;
			}
	 
			case EXIT_THREAD_DEBUG_EVENT:
				debugInfo(L"EXIT_THREAD_DEBUG_EVENT");
				break;
	 
			case EXIT_PROCESS_DEBUG_EVENT: {
				// Display the process's exit code.  We should only get this if
		 		// the main spawn has returned.  This should not happen, ever,
		 		// but if we catch the first spawn we can perhaps watch on it
		 		// and pipe its result back.
				debugInfo(
					L"EXIT_PROCESS_DEBUG_EVENT - ExitCode: 0x%x",
					DebugEv->u.ExitProcess.dwExitCode
				);
			
#ifdef QUIT_WHEN_MAIN_PROCESS_EXITS
				// we used to exit here, but now we wait for the LAST
				// process exiting signal.  We could in theory return
				// ClosedReturn if we want the behavior of quitting
				// just because the main process we spawned quit...but that
				// is not a good default when people are using things like
				// iexplore which launches a child.... so 
				// make that a non-default option?
				if (WaitForSingleObject(lastProcessExitedEvent, INFINITE) 
					!= WAIT_OBJECT_0
				) {
					WindowsVerify(L"WaitForSingleObject", FALSE);
				}

				if (processInfo.hThread) {
					WindowsVerify(L"CloseHandle",
						CloseHandle(processInfo.hThread)
					);
				}

				if (processInfo.hProcess) {
					WindowsVerify(L"CloseHandle",
						CloseHandle(processInfo.hProcess)
					);
				}

				sm_FreeNTDLLFunctions(ntDllModule);

				return ClosedReturn;
#endif
				break;
			}

			case LOAD_DLL_DEBUG_EVENT:
				// Read the debugging information included in the newly 
				// loaded DLL. Be sure to close the handle to the loaded DLL 
				// with CloseHandle.
				WindowsVerify(L"CloseHandle", 
					CloseHandle(DebugEv->u.LoadDll.hFile)
				);
#ifdef DEBUG_DLL_EVENTS
				// A lot of these go by, disable by default
				debugInfo(L"LOAD_DLL_DEBUG_EVENT");
#endif
				break;

			case UNLOAD_DLL_DEBUG_EVENT:
#ifdef DEBUG_DLL_EVENTS
			// A lot of these go by, disable by default
				debugInfo(L"UNLOAD_DLL_DEBUG_EVENT");
#endif
				break;
	 
			case OUTPUT_DEBUG_STRING_EVENT:
				// Client wants us to display the output debug string.
				// Pass through to WinDbg or display ourselves?
				// For now, say we don't handle it. 
				handledEvent = false;
				debugInfo(
					L"OUTPUT_DEBUG_STRING_EVENT - ExceptionCode 0x%x",
					DebugEv->u.Exception.ExceptionRecord.ExceptionCode
				);
				break;

			case RIP_EVENT:
				debugInfo(L"RIP_EVENT");
				break;
			} 

		// Resume executing the thread that reported the debugging event. 
		WindowsVerify(
			L"ContinueDebugEvent",
			ContinueDebugEvent(
				DebugEv->dwProcessId, 
				DebugEv->dwThreadId, 
				handledEvent ? DBG_CONTINUE : DBG_EXCEPTION_NOT_HANDLED
			)
		);
		}		
 	} // end while(TRUE) loop

	if (processInfo.hThread) {
		WindowsVerify(L"CloseHandle", CloseHandle(processInfo.hThread));
	}

	if (processInfo.hProcess) {
		WindowsVerify(L"CloseHandle", CloseHandle(processInfo.hProcess));
	}

	sm_FreeNTDLLFunctions(ntDllModule);

	// unreachable point
	return TitleWait::InternalErrorReturn;
}
Пример #17
0
static void test_NtSuspendProcess(char *process_name)
{
    PROCESS_INFORMATION info;
    DEBUG_EVENT ev;
    STARTUPINFOA startup;
    NTSTATUS status;
    HANDLE event;
    char buffer[MAX_PATH];
    ULONG count;
    DWORD ret;

    status = pNtResumeProcess(GetCurrentProcess());
    ok(status == STATUS_SUCCESS, "NtResumeProcess failed: %x\n", status);

    event = CreateEventA(NULL, TRUE, FALSE, "wine_suspend_event");
    ok(!!event, "Failed to create event: %u\n", GetLastError());

    memset(&startup, 0, sizeof(startup));
    startup.cb = sizeof(startup);

    sprintf(buffer, "%s tests/process.c dummy_process wine_suspend_event", process_name);
    ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info);
    ok(ret, "CreateProcess failed with error %u\n", GetLastError());

    ret = WaitForSingleObject(event, 500);
    ok(ret == WAIT_OBJECT_0, "Event was not signaled: %d\n", ret);

    status = pNtSuspendProcess(info.hProcess);
    ok(status == STATUS_SUCCESS, "NtResumeProcess failed: %x\n", status);

    ResetEvent(event);

    ret = WaitForSingleObject(event, 200);
    ok(ret == WAIT_TIMEOUT, "Expected timeout, got: %d\n", ret);

    status = NtResumeThread(info.hThread, &count);
    ok(status == STATUS_SUCCESS, "NtResumeProcess failed: %x\n", status);
    ok(count == 1, "Expected count 1, got %d\n", count);

    ret = WaitForSingleObject(event, 200);
    ok(ret == WAIT_OBJECT_0, "Event was not signaled: %d\n", ret);

    status = pNtResumeProcess(info.hProcess);
    ok(status == STATUS_SUCCESS, "NtResumeProcess failed: %x\n", status);

    status = pNtSuspendThread(info.hThread, &count);
    ok(status == STATUS_SUCCESS, "NtSuspendThread failed: %x\n", status);
    ok(count == 0, "Expected count 0, got %d\n", count);

    ResetEvent(event);

    ret = WaitForSingleObject(event, 200);
    ok(ret == WAIT_TIMEOUT, "Expected timeout, got: %d\n", ret);

    status = pNtResumeProcess(info.hProcess);
    ok(status == STATUS_SUCCESS, "NtResumeProcess failed: %x\n", status);

    ret = WaitForSingleObject(event, 200);
    ok(ret == WAIT_OBJECT_0, "Event was not signaled: %d\n", ret);

    status = pNtSuspendThread(info.hThread, &count);
    ok(status == STATUS_SUCCESS, "NtSuspendThread failed: %x\n", status);
    ok(count == 0, "Expected count 0, got %d\n", count);

    status = pNtSuspendThread(info.hThread, &count);
    ok(status == STATUS_SUCCESS, "NtSuspendThread failed: %x\n", status);
    ok(count == 1, "Expected count 1, got %d\n", count);

    ResetEvent(event);

    ret = WaitForSingleObject(event, 200);
    ok(ret == WAIT_TIMEOUT, "Expected timeout, got: %d\n", ret);

    status = pNtResumeProcess(info.hProcess);
    ok(status == STATUS_SUCCESS, "NtResumeProcess failed: %x\n", status);

    ret = WaitForSingleObject(event, 200);
    ok(ret == WAIT_TIMEOUT, "Expected timeout, got: %d\n", ret);

    status = pNtResumeProcess(info.hProcess);
    ok(status == STATUS_SUCCESS, "NtResumeProcess failed: %x\n", status);

    ret = WaitForSingleObject(event, 200);
    ok(ret == WAIT_OBJECT_0, "Event was not signaled: %d\n", ret);

    ret = DebugActiveProcess(info.dwProcessId);
    ok(ret, "Failed to debug process: %d\n", GetLastError());

    ResetEvent(event);

    ret = WaitForSingleObject(event, 200);
    ok(ret == WAIT_TIMEOUT, "Expected timeout, got: %d\n", ret);

    for (;;)
    {
        ret = WaitForDebugEvent(&ev, INFINITE);
        ok(ret, "WaitForDebugEvent failed, last error %#x.\n", GetLastError());
        if (!ret) break;

        if (ev.dwDebugEventCode == OUTPUT_DEBUG_STRING_EVENT) break;

        ret = ContinueDebugEvent(ev.dwProcessId, ev.dwThreadId, DBG_CONTINUE);
        ok(ret, "ContinueDebugEvent failed, last error %#x.\n", GetLastError());
        if (!ret) break;
    }

    ResetEvent(event);

    ret = WaitForSingleObject(event, 200);
    ok(ret == WAIT_TIMEOUT, "Expected timeout, got: %d\n", ret);

    status = pNtResumeProcess(info.hProcess);
    ok(status == STATUS_SUCCESS, "NtResumeProcess failed: %x\n", status);

    ret = WaitForSingleObject(event, 200);
    ok(ret == WAIT_TIMEOUT, "Expected timeout, got: %d\n", ret);

    status = NtResumeThread(info.hThread, &count);
    ok(status == STATUS_SUCCESS, "NtResumeProcess failed: %x\n", status);
    ok(count == 0, "Expected count 0, got %d\n", count);

    ret = WaitForSingleObject(event, 200);
    ok(ret == WAIT_TIMEOUT, "Expected timeout, got: %d\n", ret);

    ret = ContinueDebugEvent(ev.dwProcessId, ev.dwThreadId, DBG_CONTINUE);
    ok(ret, "ContinueDebugEvent failed, last error %#x.\n", GetLastError());

    ret = WaitForSingleObject(event, 200);
    ok(ret == WAIT_OBJECT_0, "Event was not signaled: %d\n", ret);

    TerminateProcess(info.hProcess, 0);

    CloseHandle(info.hProcess);
    CloseHandle(info.hThread);
}
Пример #18
0
bool DebuggingLoop()
{
	DEBUG_EVENT DebugEvent;
	CONTEXT ctxThreadContext;
	DWORD dwDebugState = NULL;

	PTCHAR sTemp = (PTCHAR)malloc(255 * sizeof(TCHAR));
	szTempSym = (PCHAR)malloc(MAX_SYM_NAME);

	ctxThreadContext.ContextFlags = CONTEXT_FULL;
	
	while(bDebugging)
	{
		if(!WaitForDebugEvent(&DebugEvent,INFINITE))
		{
			free(sTemp);
			free(szTempSym);
			return false;
		}

		switch(DebugEvent.dwDebugEventCode)
		{
		case LOAD_DLL_DEBUG_EVENT:
			{
				SymRefreshModuleList(piProcInfo.hProcess);
				dwDebugState = DBG_CONTINUE;
				break;
			}
		case CREATE_PROCESS_DEBUG_EVENT:
			{
				if(!bSymInit)
					bSymInit = SymInitialize(piProcInfo.hProcess,NULL,FALSE);
				dwDebugState = DBG_CONTINUE;
				break;
			}
		case CREATE_THREAD_DEBUG_EVENT:
			{
				HANDLE hThread = OpenThread(THREAD_ALL_ACCESS,false,DebugEvent.dwThreadId);
				GetThreadContext(hThread,&ctxThreadContext);
				ctxThreadContext.EFlags |= 0x100;
				SetThreadContext(hThread,&ctxThreadContext);

				dwDebugState = DBG_CONTINUE;
				break;
			}
		case EXIT_PROCESS_DEBUG_EVENT:
			{
				bDebugging = false;
				dwDebugState = DBG_CONTINUE;
				break;
			}
		case EXCEPTION_DEBUG_EVENT:
			{
				switch(DebugEvent.u.Exception.ExceptionRecord.ExceptionCode)
				{
				case EXCEPTION_BREAKPOINT:
					{
						dwDebugState = DBG_CONTINUE;
						break;
					}
				case EXCEPTION_SINGLE_STEP:
					{	
						HANDLE hThread = OpenThread(THREAD_ALL_ACCESS,false,DebugEvent.dwThreadId);
						GetThreadContext(hThread,&ctxThreadContext);
						InsertInfo((DWORD)DebugEvent.u.Exception.ExceptionRecord.ExceptionAddress,DebugEvent.dwThreadId,sTemp);
						ctxThreadContext.EFlags |= 0x100;
						SetThreadContext(hThread,&ctxThreadContext);
						dwDebugState = DBG_CONTINUE;
						break;
					}
				default:
					dwDebugState = DBG_EXCEPTION_NOT_HANDLED;
				}
				break;
			}
		default:
			dwDebugState = DBG_EXCEPTION_NOT_HANDLED;
		}
		ContinueDebugEvent(DebugEvent.dwProcessId,DebugEvent.dwThreadId,dwDebugState);
	}
	free(sTemp);
	free(szTempSym);
	return false;
}
Пример #19
0
static int doldd(const char* filename)
{
	STARTUPINFO		si;
	HANDLE			ph; 
	DEBUG_EVENT		event;
	struct spawndata	sdata;
	char*			av[2];
	pid_t			pid;
	int			status;
	int			r = 0;
	char			dllname[PATH_MAX+1];
	char			dllpath[PATH_MAX+1];

	memset(&sdata, 0, sizeof(sdata));
	memset(&si, 0, sizeof(si));
	sdata.start = &si;
	sdata.flags = DEBUG_PROCESS;
	si.cb		= sizeof(si);
	si.dwFlags	= STARTF_FORCEONFEEDBACK|STARTF_USESHOWWINDOW;
	si.wShowWindow	= SW_SHOWNORMAL;
	av[0] = (char*)filename;
	av[1] = 0;
	if ((pid = uwin_spawn(filename, av, NULL, &sdata)) < 0)
	{
		error(ERROR_system(0), "%s cannot create process", filename);
		return -1;
	}
	ph = sdata.handle;
	for (;;)
	{
		if (!WaitForDebugEvent(&event, 1500))
			break;
		if (event.dwProcessId != uwin_ntpid(pid))
			continue;
		switch(event.dwDebugEventCode)
		{
		case EXIT_PROCESS_DEBUG_EVENT:
			CloseHandle(ph);
			ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_CONTINUE);
			wait(&status);
			return 0;
		case LOAD_DLL_DEBUG_EVENT:
			if (event.u.LoadDll.hFile)
			{
				if (modulenamepath(ph, &event.u.LoadDll, dllname, sizeof(dllname), dllpath, sizeof(dllpath)) < 0)
					r = -1;
				else
					sfprintf(sfstdout, "\t%s => %s\n", dllname, dllpath);
			}
			ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_CONTINUE);
			break;
		case CREATE_PROCESS_DEBUG_EVENT:
			ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_CONTINUE);
			break;
		case CREATE_THREAD_DEBUG_EVENT:
		case EXCEPTION_DEBUG_EVENT:
			kill(pid, SIGTERM);
			ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_TERMINATE_PROCESS);
			break;
		default:
			ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_CONTINUE);
			break;
		}
	}
	return 0;
}
Пример #20
0
/*
 * StartProg - start sampling a program
 */
void StartProg( const char *cmd, const char *prog, char *full_args, char *dos_args )
{
    DWORD       code;
    DWORD       tid;
    CONTEXT     con;
    BOOL        waiting_for_first_bp;
    DWORD       continue_how;
    BOOL        rc;
    DWORD       ttid;
    HANDLE      tth;
    uint_32     Fir;

    /* unused parameters */ (void)cmd;

    strcpy( utilBuff, prog );
    strcat( utilBuff, " " );
    strcat( utilBuff, full_args );

    loadProg( prog, utilBuff );
    tid = debugEvent.dwThreadId;

    tth = CreateThread( NULL, 2048, TimerThread, NULL, 0, &ttid );
    if( !tth ) {
        internalError( MsgArray[MSG_SAMPLE_3 - ERR_FIRST_MESSAGE] );
    }
    /* Attempt to ensure that we can record our samples in one shot */
    SetThreadPriority( tth, THREAD_PRIORITY_TIME_CRITICAL );

    Output( MsgArray[MSG_SAMPLE_1 - ERR_FIRST_MESSAGE] );
    Output( prog );
    Output( "\r\n" );

    waiting_for_first_bp = TRUE;
    continue_how = DBG_CONTINUE;

    for( ;; ) {
        ContinueDebugEvent( taskPid, tid, continue_how );
        rc = WaitForDebugEvent( &debugEvent, INFINITE );
        continue_how = DBG_CONTINUE;
        tid = debugEvent.dwThreadId;
        switch( debugEvent.dwDebugEventCode ) {
        case EXCEPTION_DEBUG_EVENT:
            code = debugEvent.u.Exception.ExceptionRecord.ExceptionCode;
            switch( code ) {
            case STATUS_SINGLE_STEP:
                if( timeOut ) {
                    myGetThreadContext( tid, &con );
                    Fir = LODWORD( con.Fir );
                    RecordSample( Fir, SEGMENT, tid );
                    timeOut = FALSE;
                }
                break;
            case STATUS_BREAKPOINT:
                /* Skip past the breakpoint in the startup code */
                if( waiting_for_first_bp ) {
                    SkipBreakpoint( tid );
                    waiting_for_first_bp = FALSE;
                }
                break;
            case STATUS_DATATYPE_MISALIGNMENT:
            case STATUS_ACCESS_VIOLATION:
            case STATUS_IN_PAGE_ERROR:
            case STATUS_NO_MEMORY:
            case STATUS_ILLEGAL_INSTRUCTION:
            case STATUS_NONCONTINUABLE_EXCEPTION:
            case STATUS_INVALID_DISPOSITION:
            case STATUS_ARRAY_BOUNDS_EXCEEDED:
            case STATUS_FLOAT_DENORMAL_OPERAND:
            case STATUS_FLOAT_DIVIDE_BY_ZERO:
            case STATUS_FLOAT_INVALID_OPERATION:
            case STATUS_FLOAT_OVERFLOW:
            case STATUS_FLOAT_STACK_CHECK:
            case STATUS_FLOAT_UNDERFLOW:
            case STATUS_INTEGER_DIVIDE_BY_ZERO:
            case STATUS_INTEGER_OVERFLOW:
            case STATUS_PRIVILEGED_INSTRUCTION:
            case STATUS_STACK_OVERFLOW:
            case STATUS_CONTROL_C_EXIT:
                if( debugEvent.u.Exception.dwFirstChance ) {
                    continue_how = DBG_EXCEPTION_NOT_HANDLED;
                } else {
                    Output( MsgArray[MSG_SAMPLE_4 - ERR_FIRST_MESSAGE] );
                    Output( "\r\n" );
                    doneSample = TRUE;
                    TerminateProcess( processHandle, 0 );
                    report();
                    return;
                }
                break;
            default:
                continue_how = DBG_EXCEPTION_NOT_HANDLED;
                break;
            }
            break;
        case LOAD_DLL_DEBUG_EVENT:
            if( GetDllName( &debugEvent.u.LoadDll, utilBuff, sizeof( utilBuff ) ) ) {
                codeLoad( debugEvent.u.LoadDll.hFile,
                            (DWORD) debugEvent.u.LoadDll.lpBaseOfDll,
                            utilBuff,
                            SAMP_CODE_LOAD );
            }
            break;
        case CREATE_THREAD_DEBUG_EVENT:
            newThread( debugEvent.dwThreadId, debugEvent.u.CreateThread.hThread );
            break;
        case EXIT_THREAD_DEBUG_EVENT:
            deadThread( debugEvent.dwThreadId );
            break;
        case EXIT_PROCESS_DEBUG_EVENT:
            doneSample = TRUE;
//          TerminateProcess( processHandle, 0 ); - already gone!!
            report();
            return;
        }
    }

} /* StartProg */
Пример #21
0
void
stAttachDebugger(
    DWORD           processId,
    std::string     fnIncludes,
    std::string     fnExcludes,
    bool            activeProcess = true)
/*++

Routine Description:
    
    Our mini-debugger implementation. It does following
    things:
    - Attach to a running process
    - On first breakpoint, inject the IAT patching DLL into target
    - Print information of any exception in target process
    - Print the debug spew from target process

Arguments:

    processId - PID of the process to attach
    
    fnIncludes - List of include filters

    fnExclude - List of exclude filters

    activeProcess - If we are attaching to an already running process
        then we pass activeProcess = true, this causes us to call
        DebugActiveProcess and not wait for process creation event

--*/
{
    int threadCount = 0;
    bool processInfected = false;

    if (activeProcess)
    {
        if (!DebugActiveProcess(processId))
        {
            gView->PrintError(L"\nCould not attach to the process (PID = %d).", processId);
            stHandleError(GetLastError());
            goto funcExit;
        }
    }

    HMODULE hMod = GetModuleHandle(L"Kernel32.dll");

    if (hMod)
    {
        PFNDEBUGSETPROCESSKILLONEXIT pfnDebugSetProcessKillOnExit =
                (PFNDEBUGSETPROCESSKILLONEXIT)GetProcAddress(hMod, "DebugSetProcessKillOnExit");

        if (pfnDebugSetProcessKillOnExit)
        {
            pfnDebugSetProcessKillOnExit(FALSE);
        }
    }

    gProcessId = processId;

    DEBUG_EVENT debugEvent;
    DWORD       dwContinueStatus = DBG_CONTINUE;

    bool keepAlive = true;

    while(keepAlive)
    {
        WaitForDebugEvent(&debugEvent, INFINITE);
        dwContinueStatus = DBG_CONTINUE;

        if (debugEvent.dwProcessId == processId)
        {
            switch (debugEvent.dwDebugEventCode)
            {
                case EXCEPTION_DEBUG_EVENT:
                {
                    switch (debugEvent.u.Exception.ExceptionRecord.ExceptionCode)
                    {
                        case EXCEPTION_BREAKPOINT:
                        {
                            //IHU_DBG_LOG(TRC_STRACE, HX_LEVEL_INFO, (L"EXCEPTION_BREAKPOINT\n"));

                            if (!processInfected)
                            {
                                if (gRemovePatchOnExit)
                                {
                                    HRSRC       hRes;
                                    HGLOBAL     hResG;
                                    LPVOID      pRes;
                                    DWORD       dwResSize;

                                    hRes = FindResource(
                                                    NULL,
                                                    MAKEINTRESOURCE(IDR_BIN_DLL),
                                                    L"BIN");

                                    hResG       = LoadResource(NULL, hRes);
                                    pRes        = LockResource(hResG);
                                    dwResSize   = SizeofResource(NULL, hRes);

                                    wchar_t tempPath[MAX_PATH];
                                    wchar_t tempFile[MAX_PATH];
                                    GetTempPath(MAX_PATH, tempPath);
                                    GetTempFileName(tempPath, L"", 0, tempFile);

                                    gInjectorDllPath = tempFile;

                                    HANDLE oFile = CreateFile(
                                                        gInjectorDllPath.c_str(),
                                                        GENERIC_READ | GENERIC_WRITE,
                                                        0,
                                                        NULL,
                                                        CREATE_ALWAYS,
                                                        FILE_ATTRIBUTE_NORMAL,
                                                        NULL);

                                    if (oFile == INVALID_HANDLE_VALUE)
                                    {
                                        gView->PrintError(
                                                L"Failed to create the temporary DLL [%s]. Error code = %x\n",
                                                gInjectorDllPath.c_str(),
                                                GetLastError());
                                        return;
                                    }

                                    DWORD bytesWritten;

                                    if (!WriteFile(
                                                oFile,
                                                pRes,
                                                dwResSize,
                                                &bytesWritten,
                                                NULL))
                                    {
                                        gView->PrintError(
                                                L"Failed to write the temporary DLL. Error code = %x\n",
                                                GetLastError());
                                        return;
                                    }
                                    
                                    CloseHandle(oFile);
                                }
                                else
                                {
                                    wchar_t exePath[MAX_PATH];

                                    if (GetModuleFileName(
                                                        NULL,
                                                        exePath,
                                                        MAX_PATH))
                                    {
                                        std::wstring dllPath = exePath;
                                        int slashPos = dllPath.find_last_of(L'\\');
                                        if (slashPos != -1)
                                        {
                                            dllPath = dllPath.substr(0, slashPos + 1);
                                        }
                                        dllPath += L"stserum.dll";

                                        gInjectorDllPath = dllPath;
                                    }
                                }

                                ihiInjectDll(
                                            ghProcess,
                                            (LPCWSTR)gInjectorDllPath.c_str(),
                                            (LPCSTR)fnIncludes.c_str(),
                                            (LPCSTR)fnExcludes.c_str());

                                processInfected = true;
                            }

                            break;
                        }
                        default:
                        {
                            if (debugEvent.u.Exception.dwFirstChance)
                            {
                                gView->PrintWarning(L"Exception = %x, Address = %x (first-chance!)\n",
                                    debugEvent.u.Exception.ExceptionRecord.ExceptionCode,
                                    debugEvent.u.Exception.ExceptionRecord.ExceptionAddress);
                            }
                            else
                            {
                                gView->PrintError(L"Exception = %x, Address = %x (second-chance!)\n",
                                    debugEvent.u.Exception.ExceptionRecord.ExceptionCode,
                                    debugEvent.u.Exception.ExceptionRecord.ExceptionAddress);
                            }

                            //
                            // If this was a second chance exception, it will cause
                            // the process to terminate
                            //
                            dwContinueStatus = DBG_EXCEPTION_NOT_HANDLED;
                            break;
                        }
                    }

                    break;
                }
                case CREATE_THREAD_DEBUG_EVENT:
                {
                    ++threadCount;
                    break;
                }
                case CREATE_PROCESS_DEBUG_EVENT:
                {
                    if (ghProcess == INVALID_HANDLE_VALUE)
                    {
                        ghProcess = debugEvent.u.CreateProcessInfo.hProcess;
                    }
                    //IHU_DBG_LOG(TRC_STRACE, HX_LEVEL_INFO, (L"Create Process\n"));                    
                    break;
                }
                case EXIT_THREAD_DEBUG_EVENT:
                {
                    --threadCount;
                    break;
                }
                case EXIT_PROCESS_DEBUG_EVENT:
                {
                    gView->PrintMessage(
                        L"Target process has been terminated. Exit Code = %d.\n",
                        debugEvent.u.ExitProcess.dwExitCode);

                    keepAlive = false;
                    break;
                }
                case LOAD_DLL_DEBUG_EVENT:
                {
                    break;
                }
                case UNLOAD_DLL_DEBUG_EVENT:
                {
                    break;
                }
                case OUTPUT_DEBUG_STRING_EVENT:
                {
                    DWORD cbRead = 0;

                    ReadProcessMemory(  ghProcess,
                                        debugEvent.u.DebugString.lpDebugStringData,
                                        gDbgString,
                                        debugEvent.u.DebugString.nDebugStringLength,
                                        &cbRead);

                    if (debugEvent.u.DebugString.fUnicode)
                    {
                        if (gDbgString[0] == L'$')
                        {   
                            gView->PrintTrace(L"%ws", &gDbgString[1]);
                        }
                        else if (gDbgString[0] == L'#')
                        {
                            gView->PrintError(L"%ws", &gDbgString[1]);
                        }
                        else
                        {
                            gView->PrintTraceOrig(L"%ws", gDbgString);
                        }
                        
                    }
                    else
                    {
                        if (gDbgString[0] == L'$')
                        {   
                            gView->PrintTraceA("%s", &gDbgString[1]);
                        }
                        else if (gDbgString[0] == L'#')
                        {
                            gView->PrintErrorA("%s", &gDbgString[1]);
                        }
                        else
                        {
                            gView->PrintTraceOrigA("%s", gDbgString);
                        }
                    }

                    break;
                }
            }
        }

        ContinueDebugEvent( debugEvent.dwProcessId,
                            debugEvent.dwThreadId,
                            dwContinueStatus);
    }

    //
    // If we need to remove the patching on exit, it means we created a
    // temporary injector dll, we should delete that now
    //
    if (gRemovePatchOnExit)
    {
        DeleteFile(gInjectorDllPath.c_str());
    }

    //IHU_DBG_LOG(TRC_STRACE, HX_LEVEL_INFO, (L"Total thread count = %d\n", threadCount));

funcExit:

    return;
}
Пример #22
0
int main(int argc, char **argv){
    if( argc<2){
        printf("Usage: %s <ip address>\n", argv[0]);
        return 1;
    }
    
    if( IsDebuggerPresent()){
        HANDLE iphlpapi=LoadLibrary("iphlpapi.dll");
        if( !iphlpapi){
            perror("iphlpapi.dll");
            return 1;
        }
        FARPROC IcmpSendEcho=GetProcAddress(iphlpapi, "IcmpSendEcho");
        FARPROC IcmpCreateFile=GetProcAddress(iphlpapi, "IcmpCreateFile");
        FARPROC IcmpCloseHandle=GetProcAddress(iphlpapi, "IcmpCloseHandle");
        if( (IcmpSendEcho && IcmpCreateFile && IcmpCloseHandle)==0){
            perror("icmp functions");
            return 1;
        }
        
        unsigned long ipaddr=INADDR_NONE, params[2];
        HANDLE hIcmpFile;
        char data[32], *reply;
        int replySize=sizeof(ICMP_ECHO_REPLY)+sizeof(data);
        
        if( (ipaddr=inet_addr(argv[1]))==INADDR_NONE){
            perror("Illegal IP address!");
            return 1;
        }
        
        if( (hIcmpFile=(HANDLE)IcmpCreateFile())==INVALID_HANDLE_VALUE){
            perror("IcmpCreateFile");
            return 1;
        }
        
        reply=(char *)malloc(replySize);
        ZeroMemory(data, sizeof(data));
        params[0]=PARAM;
        params[1]=(unsigned long)GetProcAddress(iphlpapi, "IcmpSendEcho2Ex");
        
        RaiseException(EXCEPTION_BREAKPOINT, 0, 2, params);
        puts("Exception raised!");
        IcmpSendEcho(hIcmpFile, ipaddr, data, sizeof(data), NULL, reply, replySize, 1000);
        puts("This line should never be shown...");
        IcmpCloseHandle(hIcmpFile);
        return 0;
    }
    
    PROCESS_INFORMATION pi;
    STARTUPINFO si;
    HANDLE hProcess, hThread;
    DEBUG_EVENT debugEvent;
    EXCEPTION_RECORD *ExceptionRecord=&debugEvent.u.Exception.ExceptionRecord;
    CONTEXT context;
    FARPROC IcmpSendEcho2Ex=NULL;
    char path[256], args[512], originalByte[1];
    
    ZeroMemory(?, sizeof(PROCESS_INFORMATION));
    ZeroMemory(&si, sizeof(STARTUPINFO));
    ZeroMemory(&debugEvent, sizeof(DEBUG_EVENT));
    ZeroMemory(&context, sizeof(CONTEXT));
    ZeroMemory(path, sizeof(path));
    ZeroMemory(args, sizeof(args));
    si.cb=sizeof(STARTUPINFO);
    si.dwFlags=STARTF_USESHOWWINDOW;
    si.wShowWindow=SW_HIDE;
    context.ContextFlags=CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
    
    GetModuleFileName(NULL, path, sizeof(path)-1);
    snprintf(args, sizeof(args)-1, "%s %s", path, argv[1]);
    
    if( !CreateProcess(
        NULL,
        args,
        NULL,
        NULL,
        FALSE,
        DEBUG_PROCESS,
        NULL,
        NULL,
        &si,
        ?
    )){
       perror("CreateProcess");
       return 1;
    }
    
    if( (hProcess=OpenProcess(PROCESS_ALL_ACCESS, FALSE, pi.dwProcessId))==NULL){
       perror("OpenProcess");
       return 1;
    }
    
    HANDLE kernel32=LoadLibrary("kernel32.dll");
    FARPROC DebugSetProcessKillOnExit=GetProcAddress(kernel32, "DebugSetProcessKillOnExit");
    FARPROC DebugActiveProcessStop=GetProcAddress(kernel32, "DebugActiveProcessStop");
    FARPROC OpenThread=GetProcAddress(kernel32, "OpenThread");
    CloseHandle(kernel32);
    DebugSetProcessKillOnExit(TRUE);
    
    while(WaitForDebugEvent(&debugEvent, INFINITE) && debugEvent.dwDebugEventCode!=EXIT_PROCESS_DEBUG_EVENT){
             if( debugEvent.dwDebugEventCode==EXCEPTION_DEBUG_EVENT && ExceptionRecord->ExceptionCode==EXCEPTION_BREAKPOINT){
                 if( ExceptionRecord->NumberParameters>1 && ExceptionRecord->ExceptionInformation[0]==PARAM){
                     IcmpSendEcho2Ex=(FARPROC)ExceptionRecord->ExceptionInformation[1];
                     printf("IcmpSendEcho2Ex %p\n", IcmpSendEcho2Ex);
                     if( !BreakpointSet(hProcess, IcmpSendEcho2Ex, &originalByte)){
                         perror("BreakpointSet");
                         break;
                     }
                 }
                 else if( ExceptionRecord->ExceptionAddress==IcmpSendEcho2Ex){
                      printf("EIP %p\n", IcmpSendEcho2Ex);
                      if( !BreakpointRetrieve(hProcess, IcmpSendEcho2Ex, &originalByte)){
                          perror("BreakpointRetrieve");
                          break;
                      }
                      if((hThread=(HANDLE)OpenThread(THREAD_ALL_ACCESS, FALSE, debugEvent.dwThreadId))==NULL) puts("OpenThread");
                      if(!GetThreadContext(hThread, &context)) puts("GetThreadContext");
                      context.Eip -= 1;
                      if(!SetThreadContext(hThread, &context)) puts("SetThreadContext");
                      CreateThread(NULL, 0, (void *)Terminate, hProcess, 0, NULL);
                 }
             }
             else if( debugEvent.dwDebugEventCode==EXCEPTION_DEBUG_EVENT){
                  puts("Exception!");
                  DebugActiveProcessStop(debugEvent.dwProcessId);
                  break;
             }
             ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, DBG_CONTINUE);
             ZeroMemory(&debugEvent, sizeof(DEBUG_EVENT));
    }
    
    return 0;
}
Пример #23
0
void ProcessDebugEvent()
{
	static wchar_t wszDbgText[1024];
	static char szDbgText[1024];
	BOOL lbNonContinuable = FALSE;
	DEBUG_EVENT evt = {0};
	BOOL lbEvent = WaitForDebugEvent(&evt,10);
	#ifdef _DEBUG
	DWORD dwErr = GetLastError();
	#endif
	static bool bFirstExitThreadEvent = false; // Чтобы вывести на экран подсказку по возможностям "дебаггера"
	//HMODULE hCOMDLG32 = NULL;
	//typedef BOOL (WINAPI* GetSaveFileName_t)(LPOPENFILENAMEW lpofn);
	//GetSaveFileName_t _GetSaveFileName = NULL;
	DWORD dwContinueStatus = DBG_EXCEPTION_NOT_HANDLED;
	

	if (lbEvent)
	{
		lbNonContinuable = FALSE;

		switch (evt.dwDebugEventCode)
		{
			case CREATE_PROCESS_DEBUG_EVENT:
			case CREATE_THREAD_DEBUG_EVENT:
			case EXIT_PROCESS_DEBUG_EVENT:
			case EXIT_THREAD_DEBUG_EVENT:
			case RIP_EVENT:
			{
				LPCSTR pszName = "Unknown";

				switch (evt.dwDebugEventCode)
				{
					case CREATE_PROCESS_DEBUG_EVENT: pszName = "CREATE_PROCESS_DEBUG_EVENT"; break;
					case CREATE_THREAD_DEBUG_EVENT: pszName = "CREATE_THREAD_DEBUG_EVENT"; break;
					case EXIT_PROCESS_DEBUG_EVENT: pszName = "EXIT_PROCESS_DEBUG_EVENT"; break;
					case EXIT_THREAD_DEBUG_EVENT: pszName = "EXIT_THREAD_DEBUG_EVENT"; break;
					case RIP_EVENT: pszName = "RIP_EVENT"; break;
				}

				_wsprintfA(szDbgText, SKIPLEN(countof(szDbgText)) "{%i.%i} %s\n", evt.dwProcessId,evt.dwThreadId, pszName);
				_printf(szDbgText);
				if (!bFirstExitThreadEvent && evt.dwDebugEventCode == EXIT_THREAD_DEBUG_EVENT)
				{
					bFirstExitThreadEvent = true;
					if (gpSrv->DbgInfo.nDebugDumpProcess == 0)
					{
						_printf("ConEmuC: Press Ctrl+Break to create minidump of debugging process\n");
					}
					else
					{
						// Сразу сделать дамп и выйти
						HandlerRoutine(CTRL_BREAK_EVENT);
					}
				}

				if (evt.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT)
				{
					gpSrv->DbgInfo.nProcessCount++;

					_ASSERTE(gpSrv->DbgInfo.pDebugTreeProcesses!=NULL);
					CEDebugProcessInfo pi = {evt.dwProcessId};
					gpSrv->DbgInfo.pDebugTreeProcesses->Set(evt.dwProcessId, pi);

					UpdateDebuggerTitle();
				}
				else if (evt.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)
				{
					CEDebugProcessInfo pi = {};
					if (gpSrv->DbgInfo.pDebugTreeProcesses
						&& gpSrv->DbgInfo.pDebugTreeProcesses->Get(evt.dwProcessId, &pi, true)
						&& pi.hProcess)
					{
						CloseHandle(pi.hProcess);
					}

					if (gpSrv->DbgInfo.nProcessCount > 0)
						gpSrv->DbgInfo.nProcessCount--;

					UpdateDebuggerTitle();
				}

				break;
			}
			case LOAD_DLL_DEBUG_EVENT:
			case UNLOAD_DLL_DEBUG_EVENT:
			{
				LPCSTR pszName = "Unknown";
				char szBase[32] = {};
				char szFile[MAX_PATH+128] = {};

				struct MY_FILE_NAME_INFO
				{
					DWORD FileNameLength;
					WCHAR FileName[1];
				};
				typedef BOOL (WINAPI* GetFileInformationByHandleEx_t)(HANDLE hFile, int FileInformationClass, LPVOID lpFileInformation, DWORD dwBufferSize);
				static GetFileInformationByHandleEx_t _GetFileInformationByHandleEx = NULL;

				switch (evt.dwDebugEventCode)
				{
					case LOAD_DLL_DEBUG_EVENT:
						//6 Reports a load-dynamic-link-library (DLL) debugging event. The value of u.LoadDll specifies a LOAD_DLL_DEBUG_INFO structure.
						pszName = "LOAD_DLL_DEBUG_EVENT";

						if (evt.u.LoadDll.hFile)
						{
							if (gnOsVer >= 0x0600)
							{
								if (!_GetFileInformationByHandleEx)
									_GetFileInformationByHandleEx = (GetFileInformationByHandleEx_t)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "GetFileInformationByHandleEx");

								if (_GetFileInformationByHandleEx)
								{
									DWORD nSize = sizeof(MY_FILE_NAME_INFO)+MAX_PATH*sizeof(wchar_t);
									MY_FILE_NAME_INFO* pfi = (MY_FILE_NAME_INFO*)calloc(nSize+2,1);
									if (pfi)
									{
										pfi->FileNameLength = MAX_PATH;
										if (_GetFileInformationByHandleEx(evt.u.LoadDll.hFile, 2/*FileNameInfo*/, pfi, nSize)
											&& pfi->FileName[0])
										{
											wchar_t szFullPath[MAX_PATH+1] = {}, *pszFile;
											DWORD n = GetFullPathName(pfi->FileName, countof(szFullPath), szFullPath, &pszFile);
											if (!n || (n >= countof(szFullPath)))
											{
												lstrcpyn(szFullPath, pfi->FileName, countof(szFullPath));
												pszFile = (wchar_t*)PointToName(pfi->FileName);
											}
											else if (!pszFile)
											{
												pszFile = (wchar_t*)PointToName(szFullPath);
											}
											lstrcpyA(szFile, ", ");
											WideCharToMultiByte(CP_OEMCP, 0, pszFile, -1, szFile+lstrlenA(szFile), 80, 0,0);
											lstrcatA(szFile, "\n\t");
											WideCharToMultiByte(CP_OEMCP, 0, szFullPath, -1, szFile+lstrlenA(szFile), MAX_PATH, 0,0);
										}
										free(pfi);
									}
								}
							}
							CloseHandle(evt.u.LoadDll.hFile);
						}
						_wsprintfA(szBase, SKIPLEN(countof(szBase))
						           " at " WIN3264TEST("0x%08X","0x%08X%08X"),
						           WIN3264WSPRINT((DWORD_PTR)evt.u.LoadDll.lpBaseOfDll));

						break;
					case UNLOAD_DLL_DEBUG_EVENT:
						//7 Reports an unload-DLL debugging event. The value of u.UnloadDll specifies an UNLOAD_DLL_DEBUG_INFO structure.
						pszName = "UNLOAD_DLL_DEBUG_EVENT";
						_wsprintfA(szBase, SKIPLEN(countof(szBase))
						           " at " WIN3264TEST("0x%08X","0x%08X%08X"),
						           WIN3264WSPRINT((DWORD_PTR)evt.u.UnloadDll.lpBaseOfDll));
						break;
				}

				_wsprintfA(szDbgText, SKIPLEN(countof(szDbgText)) "{%i.%i} %s%s%s\n", evt.dwProcessId,evt.dwThreadId, pszName, szBase, szFile);
				_printf(szDbgText);
				break;
			}
			case EXCEPTION_DEBUG_EVENT:
				//1 Reports an exception debugging event. The value of u.Exception specifies an EXCEPTION_DEBUG_INFO structure.
			{
				lbNonContinuable = (evt.u.Exception.ExceptionRecord.ExceptionFlags&EXCEPTION_NONCONTINUABLE)==EXCEPTION_NONCONTINUABLE;

				//static bool bAttachEventRecieved = false;
				//if (!bAttachEventRecieved)
				//{
				//	bAttachEventRecieved = true;
				//	StringCchPrintfA(szDbgText, countof(szDbgText),"{%i.%i} Debugger attached successfully. (0x%08X address 0x%08X flags 0x%08X%s)\n",
				//		evt.dwProcessId,evt.dwThreadId,
				//		evt.u.Exception.ExceptionRecord.ExceptionCode,
				//		evt.u.Exception.ExceptionRecord.ExceptionAddress,
				//		evt.u.Exception.ExceptionRecord.ExceptionFlags,
				//		(evt.u.Exception.ExceptionRecord.ExceptionFlags&EXCEPTION_NONCONTINUABLE) ? "(EXCEPTION_NONCONTINUABLE)" : "");
				//}
				//else
				switch (evt.u.Exception.ExceptionRecord.ExceptionCode)
				{
					case EXCEPTION_ACCESS_VIOLATION: // The thread tried to read from or write to a virtual address for which it does not have the appropriate access.
					{
						if (evt.u.Exception.ExceptionRecord.NumberParameters>=2)
						{
							_wsprintfA(szDbgText, SKIPLEN(countof(szDbgText))
							           "{%i.%i} EXCEPTION_ACCESS_VIOLATION at " WIN3264TEST("0x%08X","0x%08X%08X") " flags 0x%08X%s %s of " WIN3264TEST("0x%08X","0x%08X%08X") " FC=%u\n", evt.dwProcessId,evt.dwThreadId,
							           WIN3264WSPRINT((DWORD_PTR)evt.u.Exception.ExceptionRecord.ExceptionAddress),
							           evt.u.Exception.ExceptionRecord.ExceptionFlags,
							           ((evt.u.Exception.ExceptionRecord.ExceptionFlags&EXCEPTION_NONCONTINUABLE) ? "(EXCEPTION_NONCONTINUABLE)" : ""),
							           ((evt.u.Exception.ExceptionRecord.ExceptionInformation[0]==0) ? "Read" :
							            (evt.u.Exception.ExceptionRecord.ExceptionInformation[0]==1) ? "Write" :
							            (evt.u.Exception.ExceptionRecord.ExceptionInformation[0]==8) ? "DEP" : "???"),
							           WIN3264WSPRINT(evt.u.Exception.ExceptionRecord.ExceptionInformation[1]),
							           evt.u.Exception.dwFirstChance
							          );
						}
						else
						{
							_wsprintfA(szDbgText, SKIPLEN(countof(szDbgText))
							           "{%i.%i} EXCEPTION_ACCESS_VIOLATION at " WIN3264TEST("0x%08X","0x%08X%08X") " flags 0x%08X%s FC=%u\n", evt.dwProcessId,evt.dwThreadId,
							           WIN3264WSPRINT((DWORD_PTR)evt.u.Exception.ExceptionRecord.ExceptionAddress),
							           evt.u.Exception.ExceptionRecord.ExceptionFlags,
							           (evt.u.Exception.ExceptionRecord.ExceptionFlags&EXCEPTION_NONCONTINUABLE) ? "(EXCEPTION_NONCONTINUABLE)" : "",
							           evt.u.Exception.dwFirstChance);
						}

						_printf(szDbgText);
					}
					break;
					default:
					{
						char szName[32]; LPCSTR pszName; pszName = szName;
#define EXCASE(s) case s: pszName = #s; break

							switch(evt.u.Exception.ExceptionRecord.ExceptionCode)
							{
									EXCASE(EXCEPTION_ARRAY_BOUNDS_EXCEEDED); // The thread tried to access an array element that is out of bounds and the underlying hardware supports bounds checking.
									EXCASE(EXCEPTION_BREAKPOINT); // A breakpoint was encountered.
									EXCASE(EXCEPTION_DATATYPE_MISALIGNMENT); // The thread tried to read or write data that is misaligned on hardware that does not provide alignment. For example, 16-bit values must be aligned on 2-byte boundaries; 32-bit values on 4-byte boundaries, and so on.
									EXCASE(EXCEPTION_FLT_DENORMAL_OPERAND); // One of the operands in a floating-point operation is denormal. A denormal value is one that is too small to represent as a standard floating-point value.
									EXCASE(EXCEPTION_FLT_DIVIDE_BY_ZERO); // The thread tried to divide a floating-point value by a floating-point divisor of zero.
									EXCASE(EXCEPTION_FLT_INEXACT_RESULT); // The result of a floating-point operation cannot be represented exactly as a decimal fraction.
									EXCASE(EXCEPTION_FLT_INVALID_OPERATION); // This exception represents any floating-point exception not included in this list.
									EXCASE(EXCEPTION_FLT_OVERFLOW); // The exponent of a floating-point operation is greater than the magnitude allowed by the corresponding type.
									EXCASE(EXCEPTION_FLT_STACK_CHECK); // The stack overflowed or underflowed as the result of a floating-point operation.
									EXCASE(EXCEPTION_FLT_UNDERFLOW); // The exponent of a floating-point operation is less than the magnitude allowed by the corresponding type.
									EXCASE(EXCEPTION_ILLEGAL_INSTRUCTION); // The thread tried to execute an invalid instruction.
									EXCASE(EXCEPTION_IN_PAGE_ERROR); // The thread tried to access a page that was not present, and the system was unable to load the page. For example, this exception might occur if a network connection is lost while running a program over the network.
									EXCASE(EXCEPTION_INT_DIVIDE_BY_ZERO); // The thread tried to divide an integer value by an integer divisor of zero.
									EXCASE(EXCEPTION_INT_OVERFLOW); // The result of an integer operation caused a carry out of the most significant bit of the result.
									EXCASE(EXCEPTION_INVALID_DISPOSITION); // An exception handler returned an invalid disposition to the exception dispatcher. Programmers using a high-level language such as C should never encounter this exception.
									EXCASE(EXCEPTION_NONCONTINUABLE_EXCEPTION); // The thread tried to continue execution after a noncontinuable exception occurred.
									EXCASE(EXCEPTION_PRIV_INSTRUCTION); // The thread tried to execute an instruction whose operation is not allowed in the current machine mode.
									EXCASE(EXCEPTION_SINGLE_STEP); // A trace trap or other single-instruction mechanism signaled that one instruction has been executed.
									EXCASE(EXCEPTION_STACK_OVERFLOW); // The thread used up its stack.
								default:
									_wsprintfA(szName, SKIPLEN(countof(szName))
									           "Exception 0x%08X", evt.u.Exception.ExceptionRecord.ExceptionCode);
							}

							_wsprintfA(szDbgText, SKIPLEN(countof(szDbgText))
							           "{%i.%i} %s at " WIN3264TEST("0x%08X","0x%08X%08X") " flags 0x%08X%s FC=%u\n",
							           evt.dwProcessId,evt.dwThreadId,
							           pszName,
							           WIN3264WSPRINT((DWORD_PTR)evt.u.Exception.ExceptionRecord.ExceptionAddress),
							           evt.u.Exception.ExceptionRecord.ExceptionFlags,
							           (evt.u.Exception.ExceptionRecord.ExceptionFlags&EXCEPTION_NONCONTINUABLE)
							           ? "(EXCEPTION_NONCONTINUABLE)" : "",
							           evt.u.Exception.dwFirstChance);
							_printf(szDbgText);
						}
				}

				BOOL bDumpOnBreakPoint = gpSrv->DbgInfo.bDebuggerRequestDump;

				if (gpSrv->DbgInfo.bDebugProcessTree
					&& (!lbNonContinuable && (evt.u.Exception.ExceptionRecord.ExceptionCode==EXCEPTION_BREAKPOINT)))
				{
					// Когда отладчик цепляется к процессу в первый раз - возникает EXCEPTION_BREAKPOINT
					CEDebugProcessInfo pi = {};
					if (gpSrv->DbgInfo.pDebugTreeProcesses
						&& gpSrv->DbgInfo.pDebugTreeProcesses->Get(evt.dwProcessId, &pi))
					{
						if (!pi.bWasBreak)
						{
							pi.bWasBreak = TRUE;
							gpSrv->DbgInfo.pDebugTreeProcesses->Set(evt.dwProcessId, pi);
						}
						else
						{
							bDumpOnBreakPoint = TRUE;
						}
					}
				}

				if (gpSrv->DbgInfo.bDebuggerRequestDump
					|| (!lbNonContinuable && !gpSrv->DbgInfo.bDebugProcessTree
						&& (evt.u.Exception.ExceptionRecord.ExceptionCode != EXCEPTION_BREAKPOINT))
					|| (gpSrv->DbgInfo.bDebugProcessTree
						&& ((evt.u.Exception.ExceptionRecord.ExceptionCode>=0xC0000000)
							|| (bDumpOnBreakPoint && (evt.u.Exception.ExceptionRecord.ExceptionCode==EXCEPTION_BREAKPOINT))))
					)
				{
					BOOL bGenerateTreeBreak = gpSrv->DbgInfo.bDebugProcessTree
						&& (gpSrv->DbgInfo.bDebuggerRequestDump || lbNonContinuable);

					if (gpSrv->DbgInfo.bDebugProcessTree
						&& !bGenerateTreeBreak
						&& (evt.u.Exception.ExceptionRecord.ExceptionCode==EXCEPTION_BREAKPOINT))
					{
						if (gpSrv->DbgInfo.nWaitTreeBreaks == 0)
						{
							bGenerateTreeBreak = TRUE;
							gpSrv->DbgInfo.nWaitTreeBreaks++;
						}
					}

					gpSrv->DbgInfo.bDebuggerRequestDump = FALSE; // один раз

					char szConfirm[2048];

					if (evt.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT)
					{
						if (gpSrv->DbgInfo.nDebugDumpProcess)
							szConfirm[0] = 0;
						else
							lstrcpynA(szConfirm, szDbgText, countof(szConfirm));
					}
					else
					{
						_wsprintfA(szConfirm, SKIPLEN(countof(szConfirm)) "%s exception (FC=%u)\n",
							lbNonContinuable ? "Non continuable" : "Continuable",
							evt.u.Exception.dwFirstChance);
						StringCchCatA(szConfirm, countof(szConfirm), szDbgText);
					}
					StringCchCatA(szConfirm, countof(szConfirm), "\nCreate minidump (<No> - fulldump)?");

					//GenerateTreeDebugBreak

					WriteMiniDump(evt.dwProcessId, evt.dwThreadId, &evt.u.Exception.ExceptionRecord, szConfirm, bGenerateTreeBreak);

					if (gpSrv->DbgInfo.bDebugProcessTree && (evt.u.Exception.ExceptionRecord.ExceptionCode==EXCEPTION_BREAKPOINT))
					{
						if (gpSrv->DbgInfo.nWaitTreeBreaks > 0)
							gpSrv->DbgInfo.nWaitTreeBreaks--;
					}
				}

				if (!lbNonContinuable /*|| (evt.u.Exception.ExceptionRecord.ExceptionCode==EXCEPTION_BREAKPOINT)*/)
				{
					dwContinueStatus = DBG_CONTINUE;
				}
			}
			break;
			case OUTPUT_DEBUG_STRING_EVENT:
				//8 Reports an output-debugging-string debugging event. The value of u.DebugString specifies an OUTPUT_DEBUG_STRING_INFO structure.
			{
				wszDbgText[0] = 0;

				if (evt.u.DebugString.nDebugStringLength >= 1024) evt.u.DebugString.nDebugStringLength = 1023;

				DWORD_PTR nRead = 0;

				HANDLE hProcess = GetProcessHandleForDebug(evt.dwProcessId);

				if (evt.u.DebugString.fUnicode)
				{
					if (!ReadProcessMemory(hProcess, evt.u.DebugString.lpDebugStringData, wszDbgText, 2*evt.u.DebugString.nDebugStringLength, &nRead))
					{
						wcscpy_c(wszDbgText, L"???");
					}
					else
					{
						wszDbgText[min(1023,nRead+1)] = 0;
					}

					static int nPrefixLen = lstrlen(CONEMU_CONHOST_CREATED_MSG);
					if (memcmp(wszDbgText, CONEMU_CONHOST_CREATED_MSG, nPrefixLen*sizeof(wszDbgText[0])) == 0)
					{
						LPWSTR pszEnd = NULL;
						DWORD nConHostPID = wcstoul(wszDbgText+nPrefixLen, &pszEnd, 10);
						if (nConHostPID && !gpSrv->DbgInfo.pDebugTreeProcesses->Get(nConHostPID, NULL))
						{
							AttachConHost(nConHostPID);
						}
					}
				}
				else
				{
					if (!ReadProcessMemory(hProcess, evt.u.DebugString.lpDebugStringData, szDbgText, evt.u.DebugString.nDebugStringLength, &nRead))
					{
						wcscpy_c(wszDbgText, L"???");
					}
					else
					{
						szDbgText[min(1023,nRead+1)] = 0;
						// CP_ACP differs from CP_OEMCP, thats why we need some overhead...
						MultiByteToWideChar(CP_ACP, 0, szDbgText, -1, wszDbgText, 1024);
					}
				}

				WideCharToMultiByte(CP_OEMCP, 0, wszDbgText, -1, szDbgText, 1024, 0, 0);

				#ifdef CRTPRINTF
				{
					_printf("{PID=%i.TID=%i} ", evt.dwProcessId,evt.dwThreadId, wszDbgText);
				}
				#else
				{
					_printf("{PID=%i.TID=%i} %s", evt.dwProcessId,evt.dwThreadId, szDbgText);
					int nLen = lstrlenA(szDbgText);

					if (nLen > 0 && szDbgText[nLen-1] != '\n')
						_printf("\n");
				}
				#endif
				
				dwContinueStatus = DBG_CONTINUE;
			}
			break;
		}

		// Продолжить отлаживаемый процесс
		ContinueDebugEvent(evt.dwProcessId, evt.dwThreadId, dwContinueStatus);
	}
	
	//if (hCOMDLG32)
	//	FreeLibrary(hCOMDLG32);
}
Пример #24
0
static int fork_and_ptraceme(RIO *io, int bits, const char *cmd) {
	PROCESS_INFORMATION pi;
        STARTUPINFO si = { sizeof (si) };
        DEBUG_EVENT de;
	int pid, tid;
	HANDLE th = INVALID_HANDLE_VALUE;
	if (!*cmd)
		return -1;
	setup_tokens ();

	char **argv = r_str_argv (cmd, NULL);
	// We need to build a command line with quoted argument and escaped quotes
	int cmd_len = 0;
	int i = 0;
	while (argv[i]) {
		char *current = argv[i];
		int quote_count = 0;
		while ((current = strchr (current, '"')))
			quote_count ++;
		cmd_len += strlen (argv[i]);
		cmd_len += quote_count; // The quotes will add one backslash each
		cmd_len += 2; // Add two enclosing quotes;
		i++;
	}
	cmd_len += i-1; // Add argc-1 spaces

	char *cmdline = malloc ((cmd_len + 1) * sizeof (char));
	int cmd_i = 0; // Next character to write in cmdline
	i = 0;
	while (argv[i]) {
		if (i != 0)
			cmdline[cmd_i++] = ' ';

		cmdline[cmd_i++] = '"';
		
		int arg_i = 0; // Index of current character in orginal argument
		while (argv[i][arg_i]) {
			char c = argv[i][arg_i];
			if (c == '"') {
				cmdline[cmd_i++] = '\\';
			}
			cmdline[cmd_i++] = c;
			arg_i++;
		}

		cmdline[cmd_i++] = '"';
		i++;
	}
	cmdline[cmd_i] = '\0';

        if (!CreateProcess (argv[0], cmdline,
                        NULL, NULL, FALSE,
                        CREATE_NEW_CONSOLE | DEBUG_ONLY_THIS_PROCESS,
                        NULL, NULL, &si, &pi)) {
                r_sys_perror ("CreateProcess");
                return -1;
        }
	free (cmdline);
	r_str_argv_free (argv);

        /* get process id and thread id */
        pid = pi.dwProcessId;
        tid = pi.dwThreadId;

#if 0
        /* load thread list */
	{
		HANDLE h;
		THREADENTRY32 te32;
		HANDLE WINAPI (*win32_openthread)(DWORD, BOOL, DWORD) = NULL;
		win32_openthread = (HANDLE WINAPI (*)(DWORD, BOOL, DWORD))
			GetProcAddress (GetModuleHandle ("kernel32"), "OpenThread");

		th = CreateToolhelp32Snapshot (TH32CS_SNAPTHREAD, pid);
		if (th == INVALID_HANDLE_VALUE || !Thread32First(th, &te32))
			r_sys_perror ("CreateToolhelp32Snapshot");

		do {
			if (te32.th32OwnerProcessID == pid) {
				h = win32_openthread (THREAD_ALL_ACCESS, 0, te32.th32ThreadID);
				if (h == NULL) r_sys_perror ("OpenThread");
				else eprintf ("HANDLE=%p\n", h);
			}
		} while (Thread32Next (th, &te32));
	}
#endif

#if 0
	// Access denied here :?
	if (ContinueDebugEvent (pid, tid, DBG_CONTINUE) == 0) {
		r_sys_perror ("ContinueDebugEvent");
		goto err_fork;
	}
#endif

        /* catch create process event */
        if (!WaitForDebugEvent (&de, 10000))
                goto err_fork;

        /* check if is a create process debug event */
        if (de.dwDebugEventCode != CREATE_PROCESS_DEBUG_EVENT) {
                eprintf ("exception code 0x%04x\n", (ut32)de.dwDebugEventCode);
                goto err_fork;
        }

	if (th != INVALID_HANDLE_VALUE)
		CloseHandle (th);

	eprintf ("PID=%d\n", pid);
	eprintf ("TID=%d\n", tid);
        return pid;

err_fork:
	eprintf ("ERRFORK\n");
        TerminateProcess (pi.hProcess, 1);
	if (th != INVALID_HANDLE_VALUE)
		CloseHandle (th);
        return -1;
}
Пример #25
0
static int
get_child_debug_event (struct target_waitstatus *ourstatus)
{
  ptid_t ptid;

  last_sig = TARGET_SIGNAL_0;
  ourstatus->kind = TARGET_WAITKIND_SPURIOUS;

  /* Check if GDB sent us an interrupt request.  */
  check_remote_input_interrupt_request ();

  if (soft_interrupt_requested)
    {
      soft_interrupt_requested = 0;
      fake_breakpoint_event ();
      goto gotevent;
    }

#ifndef _WIN32_WCE
  attaching = 0;
#else
  if (attaching)
    {
      /* WinCE doesn't set an initial breakpoint automatically.  To
	 stop the inferior, we flush all currently pending debug
	 events -- the thread list and the dll list are always
	 reported immediatelly without delay, then, we suspend all
	 threads and pretend we saw a trap at the current PC of the
	 main thread.

	 Contrary to desktop Windows, Windows CE *does* report the dll
	 names on LOAD_DLL_DEBUG_EVENTs resulting from a
	 DebugActiveProcess call.  This limits the way we can detect
	 if all the dlls have already been reported.  If we get a real
	 debug event before leaving attaching, the worst that will
	 happen is the user will see a spurious breakpoint.  */

      current_event.dwDebugEventCode = 0;
      if (!WaitForDebugEvent (&current_event, 0))
	{
	  OUTMSG2(("no attach events left\n"));
	  fake_breakpoint_event ();
	  attaching = 0;
	}
      else
	OUTMSG2(("got attach event\n"));
    }
  else
#endif
    {
      /* Keep the wait time low enough for confortable remote
	 interruption, but high enough so gdbserver doesn't become a
	 bottleneck.  */
      if (!WaitForDebugEvent (&current_event, 250))
        {
	  DWORD e  = GetLastError();

	  if (e == ERROR_PIPE_NOT_CONNECTED)
	    {
	      /* This will happen if the loader fails to succesfully
		 load the application, e.g., if the main executable
		 tries to pull in a non-existing export from a
		 DLL.  */
	      ourstatus->kind = TARGET_WAITKIND_EXITED;
	      ourstatus->value.integer = 1;
	      return 1;
	    }

	  return 0;
        }
    }

 gotevent:

  switch (current_event.dwDebugEventCode)
    {
    case CREATE_THREAD_DEBUG_EVENT:
      OUTMSG2 (("gdbserver: kernel event CREATE_THREAD_DEBUG_EVENT "
		"for pid=%d tid=%x)\n",
		(unsigned) current_event.dwProcessId,
		(unsigned) current_event.dwThreadId));

      /* Record the existence of this thread.  */
      child_add_thread (current_event.dwProcessId,
			current_event.dwThreadId,
			current_event.u.CreateThread.hThread,
			current_event.u.CreateThread.lpThreadLocalBase);
      break;

    case EXIT_THREAD_DEBUG_EVENT:
      OUTMSG2 (("gdbserver: kernel event EXIT_THREAD_DEBUG_EVENT "
		"for pid=%d tid=%x\n",
		(unsigned) current_event.dwProcessId,
		(unsigned) current_event.dwThreadId));
      child_delete_thread (current_event.dwProcessId,
			   current_event.dwThreadId);

      current_inferior = (struct thread_info *) all_threads.head;
      return 1;

    case CREATE_PROCESS_DEBUG_EVENT:
      OUTMSG2 (("gdbserver: kernel event CREATE_PROCESS_DEBUG_EVENT "
		"for pid=%d tid=%x\n",
		(unsigned) current_event.dwProcessId,
		(unsigned) current_event.dwThreadId));
      CloseHandle (current_event.u.CreateProcessInfo.hFile);

      current_process_handle = current_event.u.CreateProcessInfo.hProcess;
      main_thread_id = current_event.dwThreadId;

      ourstatus->kind = TARGET_WAITKIND_EXECD;
      ourstatus->value.execd_pathname = "Main executable";

      /* Add the main thread.  */
      child_add_thread (current_event.dwProcessId,
			main_thread_id,
			current_event.u.CreateProcessInfo.hThread,
			current_event.u.CreateProcessInfo.lpThreadLocalBase);

      ourstatus->value.related_pid = debug_event_ptid (&current_event);
#ifdef _WIN32_WCE
      if (!attaching)
	{
	  /* Windows CE doesn't set the initial breakpoint
	     automatically like the desktop versions of Windows do.
	     We add it explicitly here.	 It will be removed as soon as
	     it is hit.	 */
	  set_breakpoint_at ((CORE_ADDR) (long) current_event.u
			     .CreateProcessInfo.lpStartAddress,
			     auto_delete_breakpoint);
	}
#endif
      break;

    case EXIT_PROCESS_DEBUG_EVENT:
      OUTMSG2 (("gdbserver: kernel event EXIT_PROCESS_DEBUG_EVENT "
		"for pid=%d tid=%x\n",
		(unsigned) current_event.dwProcessId,
		(unsigned) current_event.dwThreadId));
      ourstatus->kind = TARGET_WAITKIND_EXITED;
      ourstatus->value.integer = current_event.u.ExitProcess.dwExitCode;
      child_continue (DBG_CONTINUE, -1);
      CloseHandle (current_process_handle);
      current_process_handle = NULL;
      break;

    case LOAD_DLL_DEBUG_EVENT:
      OUTMSG2 (("gdbserver: kernel event LOAD_DLL_DEBUG_EVENT "
		"for pid=%d tid=%x\n",
		(unsigned) current_event.dwProcessId,
		(unsigned) current_event.dwThreadId));
      CloseHandle (current_event.u.LoadDll.hFile);
      handle_load_dll ();

      ourstatus->kind = TARGET_WAITKIND_LOADED;
      ourstatus->value.sig = TARGET_SIGNAL_TRAP;
      break;

    case UNLOAD_DLL_DEBUG_EVENT:
      OUTMSG2 (("gdbserver: kernel event UNLOAD_DLL_DEBUG_EVENT "
		"for pid=%d tid=%x\n",
		(unsigned) current_event.dwProcessId,
		(unsigned) current_event.dwThreadId));
      handle_unload_dll ();
      ourstatus->kind = TARGET_WAITKIND_LOADED;
      ourstatus->value.sig = TARGET_SIGNAL_TRAP;
      break;

    case EXCEPTION_DEBUG_EVENT:
      OUTMSG2 (("gdbserver: kernel event EXCEPTION_DEBUG_EVENT "
		"for pid=%d tid=%x\n",
		(unsigned) current_event.dwProcessId,
		(unsigned) current_event.dwThreadId));
      handle_exception (ourstatus);
      break;

    case OUTPUT_DEBUG_STRING_EVENT:
      /* A message from the kernel (or Cygwin).  */
      OUTMSG2 (("gdbserver: kernel event OUTPUT_DEBUG_STRING_EVENT "
		"for pid=%d tid=%x\n",
		(unsigned) current_event.dwProcessId,
		(unsigned) current_event.dwThreadId));
      handle_output_debug_string (ourstatus);
      break;

    default:
      OUTMSG2 (("gdbserver: kernel event unknown "
		"for pid=%d tid=%x code=%ld\n",
		(unsigned) current_event.dwProcessId,
		(unsigned) current_event.dwThreadId,
		current_event.dwDebugEventCode));
      break;
    }

  ptid = debug_event_ptid (&current_event);
  current_inferior =
    (struct thread_info *) find_inferior_id (&all_threads, ptid);
  return 1;
}
Пример #26
0
static int fork_and_ptraceme(RIO *io, int bits, const char *cmd) {
	PROCESS_INFORMATION pi;
	STARTUPINFO si = { 0 } ;
	DEBUG_EVENT de;
	int pid, tid;
	HANDLE th = INVALID_HANDLE_VALUE;
	if (!*cmd) {
		return -1;
	}
	setup_tokens ();
	char *_cmd = io->args ? r_str_appendf (strdup (cmd), " %s", io->args) :
		strdup (cmd);
	char **argv = r_str_argv (_cmd, NULL);
	// We need to build a command line with quoted argument and escaped quotes
	int cmd_len = 0;
	int i = 0;

	si.cb = sizeof (si);
	while (argv[i]) {
		char *current = argv[i];
		int quote_count = 0;
		while ((current = strchr (current, '"'))) {
			quote_count ++;
		}
		cmd_len += strlen (argv[i]);
		cmd_len += quote_count; // The quotes will add one backslash each
		cmd_len += 2; // Add two enclosing quotes;
		i++;
	}
	cmd_len += i-1; // Add argc-1 spaces

	char *cmdline = malloc ((cmd_len + 1) * sizeof (char));
	int cmd_i = 0; // Next character to write in cmdline
	i = 0;
	while (argv[i]) {
		if (i != 0) {
			cmdline[cmd_i++] = ' ';
		}
		cmdline[cmd_i++] = '"';

		int arg_i = 0; // Index of current character in orginal argument
		while (argv[i][arg_i]) {
			char c = argv[i][arg_i];
			if (c == '"') {
				cmdline[cmd_i++] = '\\';
			}
			cmdline[cmd_i++] = c;
			arg_i++;
		}

		cmdline[cmd_i++] = '"';
		i++;
	}
	cmdline[cmd_i] = '\0';

	LPTSTR appname_ = r_sys_conv_utf8_to_utf16 (argv[0]);
	LPTSTR cmdline_ = r_sys_conv_utf8_to_utf16 (cmdline);
	if (!CreateProcess (appname_, cmdline_, NULL, NULL, FALSE,
						 CREATE_NEW_CONSOLE | DEBUG_ONLY_THIS_PROCESS,
						 NULL, NULL, &si, &pi)) {
		r_sys_perror ("fork_and_ptraceme/CreateProcess");
		free (appname_);
		free (cmdline_);
		return -1;
	}
	free (appname_);
	free (cmdline_);
	free (cmdline);
	r_str_argv_free (argv);
	/* get process id and thread id */
	pid = pi.dwProcessId;
	tid = pi.dwThreadId;

	/* catch create process event */
	if (!WaitForDebugEvent (&de, 10000)) goto err_fork;

	/* check if is a create process debug event */
	if (de.dwDebugEventCode != CREATE_PROCESS_DEBUG_EVENT) {
		eprintf ("exception code 0x%04x\n", (ut32)de.dwDebugEventCode);
		goto err_fork;
	}

	if (th != INVALID_HANDLE_VALUE) {
		CloseHandle (th);
	}
	eprintf ("Spawned new process with pid %d, tid = %d\n", pid, tid);
	winbase = (ut64)de.u.CreateProcessInfo.lpBaseOfImage;
	wintid = tid;
	return pid;

err_fork:
	eprintf ("ERRFORK\n");
	TerminateProcess (pi.hProcess, 1);
	if (th != INVALID_HANDLE_VALUE) CloseHandle (th);
	return -1;
}
Пример #27
0
void *Ploopgrab(LPVOID args)
{
    DEBUG_EVENT  dbg;
    DWORD cont = DBG_CONTINUE, size = 0;
    TCHAR pszFilename[MAX_PATH+1];
    DWORD64 mod;
    struct proc_uc *tmp = args;
    struct ps_prochandle *P = tmp->ps;
    int first_execp = 0;
    BOOL wow = 0;
    char *s;
    DWORD Options = SymGetOptions();

    if (DebugActiveProcess(P->pid) == 0) {
        dprintf( "failed to debug process (%d): %d\n", P->pid, GetLastError() );
        pthread_mutex_lock(&P->mutex);
        P->status = PS_STOP;
        P->flags = CREATE_FAILED;
        if (P->status == PS_STOP)
            pthread_cond_signal(&P->cond);
        pthread_mutex_unlock(&P->mutex);
        return NULL;
    }

    DebugSetProcessKillOnExit(FALSE);

    P->wstat = 0;
    P->exitcode = 0;
    P->event = CreateEvent(NULL,FALSE,FALSE,NULL);
    P->dll_load_order = 1;
    SymSetOptions(Options|SYMOPT_INCLUDE_32BIT_MODULES|SYMOPT_DEFERRED_LOADS|SYMOPT_DEBUG);

    while (1) {
        if (WaitForDebugEvent(&dbg, INFINITE) == 0) {
            return NULL;
        }

        cont = DBG_CONTINUE;
        pthread_mutex_lock(&P->mutex);

        switch (dbg.dwDebugEventCode) {
        case CREATE_PROCESS_DEBUG_EVENT:
            P->thandle = dbg.u.CreateProcessInfo.hThread;
            P->phandle = dbg.u.CreateProcessInfo.hProcess;
            if ((SymInitialize(P->phandle, 0, FALSE) == FALSE)) {
                dprintf("SymInitialize failed (%d): %d\n", P->pid, GetLastError());
                break;
            }

            s = GetFileNameFromHandle(dbg.u.CreateProcessInfo.hFile, pszFilename);
            addmodule(P, dbg.u.CreateProcessInfo.hFile, s, dbg.u.CreateProcessInfo.lpBaseOfImage, PE_TYPE_EXE, P->dll_load_order);
            size = GetFileSize(dbg.u.CreateProcessInfo.hFile, NULL);
            if (size == INVALID_FILE_SIZE) {
                size = 0;
            }

            if ((mod = SymLoadModuleEx(P->phandle,  dbg.u.CreateProcessInfo.hFile, s, NULL,
                                       (ULONG_PTR) dbg.u.CreateProcessInfo.lpBaseOfImage, size, NULL, 0)) == FALSE) {
                dprintf("SymLoadModule64 Failed for %s: %d\n", s, GetLastError());
                break;
            }

#if __amd64__
            if (Is32bitProcess(P->phandle)) {
                P->model = PR_MODEL_ILP32;
                wow = 1;
            } else
                P->model = PR_MODEL_ILP64;
#else
            P->model = PR_MODEL_ILP32;
#endif

            CloseHandle(dbg.u.CreateProcessInfo.hFile);
            P->status = PS_RUN;
            P->msg.type = 0;
            break;
        case CREATE_THREAD_DEBUG_EVENT:
            P->status = PS_RUN;
            P->msg.type = 0;
            break;
        case LOAD_DLL_DEBUG_EVENT:
            s = GetFileNameFromHandle(dbg.u.LoadDll.hFile, pszFilename);
            if (first_execp) {
                P->dll_load_order++;
            }
            addmodule(P, dbg.u.LoadDll.hFile, s, dbg.u.LoadDll.lpBaseOfDll, PE_TYPE_DLL, P->dll_load_order);
            size = GetFileSize(dbg.u.CreateProcessInfo.hFile, NULL);
            if (size == INVALID_FILE_SIZE) {
                size = 0;
            }
#if __amd64__
            /* Not tracing 64 bit dlls for 32 bit process */
            if (P->model == PR_MODEL_ILP32 && is64bitmodule(dbg.u.LoadDll.lpBaseOfDll, s)) {
                CloseHandle(dbg.u.LoadDll.hFile );
                break;
            }
#endif
            if ((mod = SymLoadModuleEx(P->phandle,  dbg.u.LoadDll.hFile, s, NULL,
                                       (ULONG_PTR) dbg.u.LoadDll.lpBaseOfDll, size, NULL, 0)) == FALSE) {
                dprintf("SymLoadModule64 failed for %s: %d\n", s, GetLastError());
                break;
            }

            CloseHandle(dbg.u.LoadDll.hFile );

            if (first_execp == 0) {
                P->status = PS_RUN;
                P->msg.type = RD_DLACTIVITY;
            } else {
                P->status = PS_STOP;
                P->msg.type = RD_DLACTIVITY;
            }
            break;
        case UNLOAD_DLL_DEBUG_EVENT:
            if (SymUnloadModule64(P->phandle, (ULONG_PTR) dbg.u.UnloadDll.lpBaseOfDll) ==  FALSE) {
                dprintf("SymUnloadModule64 failed-Imagebase %p: %d\n", dbg.u.UnloadDll.lpBaseOfDll, GetLastError());
                break;
            }
            delmodule(P, (ULONG64) dbg.u.UnloadDll.lpBaseOfDll);
            P->status = PS_RUN;
            P->msg.type = RD_DLACTIVITY;
            break;
        case EXIT_PROCESS_DEBUG_EVENT:
            P->exitcode = dbg.u.ExitProcess.dwExitCode;
            P->status = PS_UNDEAD;
            P->msg.type = RD_NONE;
            //SymCleanup(P->phandle);
            break;
        case EXIT_THREAD_DEBUG_EVENT:
            P->status = PS_RUN;
            P->msg.type = 0;
            break;
        case EXCEPTION_DEBUG_EVENT:
            switch(dbg.u.Exception.ExceptionRecord.ExceptionCode) {
            case EXCEPTION_BREAKPOINT:
                if (first_execp++ == 0) {
                    pthread_cond_signal(&P->cond);
                }
                P->status = PS_STOP;
                P->msg.type = 0;

                break;
            default:
                if (dbg.u.Exception.dwFirstChance == 0)
                    P->wstat = dbg.u.Exception.ExceptionRecord.ExceptionCode;
                P->status = PS_RUN;
                cont = DBG_EXCEPTION_NOT_HANDLED;
                break;
            }
            break;
        default:
            P->status = PS_RUN;
            dprintf("Debug Event not processed: %d\n", dbg.dwDebugEventCode);
            break;
        }

        if (P->status != PS_RUN)
            SetEvent(P->event);

        while (P->status == PS_STOP)
            pthread_cond_wait(&P->cond, &P->mutex);
        pthread_mutex_unlock(&P->mutex);

        ContinueDebugEvent(dbg.dwProcessId, dbg.dwThreadId, cont);
    }

}
Пример #28
0
bool CODebugger::run(unsigned int msec)
{
	DEBUG_EVENT	deDebugEvent;	//调试事件信息
	bool bResult = true;

	// 等待调试事件
	if(m_bActive && WaitForDebugEvent(&deDebugEvent, msec)) 
	{
		//处理调试事件
		switch(deDebugEvent.dwDebugEventCode)
		{ 
			//调试异常事件
		case EXCEPTION_DEBUG_EVENT:
			{
				bResult = OnDebugException(deDebugEvent);
				break;
			}

			//创建线程
		case CREATE_THREAD_DEBUG_EVENT: 	
			{
				AddThread(deDebugEvent.dwThreadId,
					deDebugEvent.u.CreateThread.hThread,
					(DWORD)deDebugEvent.u.CreateThread.lpStartAddress,
					(DWORD)deDebugEvent.u.CreateThread.lpThreadLocalBase);

				// call overloady
				D_CreateThread(&deDebugEvent);

				break;
			}

			//创建进程
		case CREATE_PROCESS_DEBUG_EVENT:
			{
				//m_hProcess = deDebugEvent.u.CreateProcessInfo.hProcess;
				//m_hThread = deDebugEvent.u.CreateProcessInfo.hThread;				

				//将主线程添加到线程链表
				DEBUGGER_THREAD* pDebuggerThread = AddThread(deDebugEvent.dwThreadId,deDebugEvent.u.CreateProcessInfo.hThread,0,0);
				pDebuggerThread->m_bIsMainThread = true;

				// call overloady
				D_CreateProcess(&deDebugEvent);

				// 关闭进程文件句柄
				if(deDebugEvent.u.CreateProcessInfo.hFile)
				{
					CloseHandle(deDebugEvent.u.CreateProcessInfo.hFile);
				}

				break;
			}

			//结束线程
		case EXIT_THREAD_DEBUG_EVENT: 		
			{
				RemoveThread(deDebugEvent.dwThreadId);

				// call overloady
				D_ExitThread(&deDebugEvent);

				break;
			}			

			//结束进程
		case EXIT_PROCESS_DEBUG_EVENT:	
			{
				if(exitfunc != NULL) 
				{					
					(*exitfunc)(&deDebugEvent);
				}				

				// call overloady
				D_ExitProcess(&deDebugEvent);

				break;
			}			

			//加载DLL
		case LOAD_DLL_DEBUG_EVENT: 		
			{				
				break;
			}			

			//卸载DLL
		case UNLOAD_DLL_DEBUG_EVENT: 		
			break;

			//输出调试字符串
		case OUTPUT_DEBUG_STRING_EVENT: 
			{
				// call overloady
				D_OutputDebugString(&deDebugEvent);

				break;
			}
		default:
			{
				bResult = false;
			}
		}

		DWORD dwContinueStatus;
		dwContinueStatus = bResult?DBG_CONTINUE:DBG_EXCEPTION_NOT_HANDLED;
		ContinueDebugEvent(deDebugEvent.dwProcessId, deDebugEvent.dwThreadId,dwContinueStatus);
	}
	else
	{
		return false;
	}

	return true;
}
Пример #29
0
int main(int argc, char* argv[])
{
    if ( argc != 2 )
    {
        printf("usage: %s crackme.exe \r\n", argv[0]);
        return -1;
    }

    // 保存文件名
    char *pszFileName = argv[1];

    // 启动信息
    STARTUPINFO si = { 0 };
    si.cb = sizeof(STARTUPINFO);
    GetStartupInfo(&si);

    // 进程信息
    PROCESS_INFORMATION pi = { 0 };

    // 创建被调试进程
    BOOL bRet = CreateProcess(pszFileName, 
                        NULL,
                        NULL,
                        NULL,
                        FALSE,
                        DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS,
                        NULL,
                        NULL,
                        &si,
                        &pi);

    if ( bRet == FALSE )
    {
        printf("CreateProcess Error \r\n");
        return -1;
    }

    DEBUG_EVENT de = { 0 };
    CONTEXT context = { 0 };
    // 保存原始的机器码
    BYTE bOldByte = 0;
    DWORD dwReadWriteNum = 0;

    // 保存正确密码使用
    char pszPassword[MAXBYTE] = { 0 };
    // 保存错误密码使用
    char pszErrorPass[MAXBYTE] = { 0 };

    while ( TRUE )
    {
        // 获取调试事件
        WaitForDebugEvent(&de, INFINITE);

        // 判断事件类型
        switch ( de.dwDebugEventCode )
        {
            // 创建进程时的调试事件
        case CREATE_PROCESS_DEBUG_EVENT:
            {
                // 读取欲设置INT3断点处的机器码
                // 方便后面恢复
                ReadProcessMemory(pi.hProcess,
                                (LPVOID)BP_VA,
                                (LPVOID)&bOldByte,
                                sizeof(BYTE),
                                &dwReadWriteNum);

                // 将INT3的机器码0xCC写入断点处
                WriteProcessMemory(pi.hProcess,
                                (LPVOID)BP_VA,
                                (LPVOID)&bInt3,
                                sizeof(BYTE),
                                &dwReadWriteNum);
        	    break;
            }
            // 产生异常时的调试事件
        case EXCEPTION_DEBUG_EVENT:
            {
                // 判断异常类型
                switch ( de.u.Exception.ExceptionRecord.ExceptionCode )
                {
                    // INT3类型的异常
                case EXCEPTION_BREAKPOINT:
                    {
                        // 获取线程环境
                        context.ContextFlags = CONTEXT_FULL;
                        GetThreadContext(pi.hThread, &context);

                        // 判断是否断在我们设置的断点位置处
                        if ( (BP_VA + 1) == context.Eip )
                        {
                            // 读取正确的密码
                            ReadProcessMemory(pi.hProcess,
                                        (LPVOID)context.Edx,
                                        (LPVOID)pszPassword,
                                        MAXBYTE,
                                        &dwReadWriteNum);
                            // 读取错误密码
                            ReadProcessMemory(pi.hProcess,
                                        (LPVOID)context.Ecx,
                                        (LPVOID)pszErrorPass,
                                        MAXBYTE,
                                        &dwReadWriteNum);
                            
                            printf("你输入的密码是: %s \r\n", pszErrorPass);
                            printf("正确的密码是: %s \r\n", pszPassword);

                            // 因为我们的指令执行了INT3因此被中断
                            // INT3的机器指令长度为一个字节
                            // 因此我们需要将EIP减一来修正EIP
                            // EIP是指令指针寄存器
                            // 其中保存着下条要执行指令的地址
                            context.Eip --;

                            // 修正原来该地址的机器码
                            WriteProcessMemory(pi.hProcess, 
                                        (LPVOID)BP_VA,
                                        (LPVOID)&bOldByte,
                                        sizeof(BYTE),
                                        &dwReadWriteNum);
                            // 设置当前的线程环境
                            SetThreadContext(pi.hThread, &context);
                        }
                        break;
                    }
                }
            }
        }
        
		ContinueDebugEvent(de.dwProcessId,de.dwThreadId,DBG_CONTINUE);
    }

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

	return 0;
}
Пример #30
0
/**
 * @brief 运行监视函数
 * 监视进程运行状态、时间、内存以及输出等信息
 *
 * @param hProcess 进程句柄
 * @param lim_time 时间限制
 * @param lim_memo 内存限制
 * @param lim_size 输出文件长度限制
 * @param cs 用于接收代码状态的引用
 * @return 若运行期间未出现异常则返回true,否则返回false
 */
bool CNBUTOJCore::WatchCode(const HANDLE hProcess, const __int64 lim_time, const SIZE_T lim_memo,
                            const DWORD lim_size, const char *outputFilename, CodeState &cs, const PROCESS_INFORMATION ProcInfo)
{
    DWORD                       maxMemo = 0;                    ///< 使用的内存
    __int64                     RunTime = -1;                   ///< 使用的时间
    DWORD                       nowSize;                        ///< 使用的输出大小
    DEBUG_EVENT                 DBE;                            ///< 调试信息结构体

    while(true)
    {
        /** 继续调试(时间是为了忽略断点的) */
        bool flag = WaitForDebugEvent(&DBE, lim_time + 200);
        if(!flag)
        {
            RunTime = _GetRunTime(hProcess) + lim_time + 200;
            return _ErrExit(hProcess, ProcInfo.dwProcessId, cs, TIME_LIMIT_EXCEEDED_2, RunTime, maxMemo);
        }

        /** 获取运行时间 */
        RunTime = _GetRunTime(hProcess);
        if(-1 == RunTime)
            return _ErrExit(hProcess, ProcInfo.dwProcessId, cs, SYSTEM_ERROR, RunTime, maxMemo, "Can't get running time.");

        /** 获取运行内存 */
        DWORD memo = _GetRunMemo(hProcess);
        if(-1 == memo) return _ErrExit(hProcess, ProcInfo.dwProcessId, cs, SYSTEM_ERROR, RunTime, maxMemo, "Can't get occupied memory.");
        else maxMemo = (memo > maxMemo) ? memo : maxMemo;

        /** 获取运行文件输出大小 */
        nowSize = _GetRunSize(outputFilename);

        /** 若超时 */
        if(RunTime > lim_time)
            return _ErrExit(hProcess, ProcInfo.dwProcessId, cs, TIME_LIMIT_EXCEEDED_1, RunTime, maxMemo);
        
        //cout << RunTime << " " << maxMemo << " " << nowSize << " " << DBE.dwDebugEventCode << endl;

        /** 若超内存 */
        if(maxMemo > lim_memo)
            return _ErrExit(hProcess, ProcInfo.dwProcessId, cs, MEMORY_LIMIT_EXCEEDED, RunTime, maxMemo);

        /** 若超输出 */
        //if(nowSize > lim_size)
        //    return _ErrExit(hProcess, ProcInfo.dwProcessId, cs, OUTPUT_LIMIT_EXCEEDED, RunTime, maxMemo);

        if(DBE.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)
        {
            ContinueDebugEvent(DBE.dwProcessId, DBE.dwThreadId, DBG_CONTINUE);
            if(DBE.u.CreateProcessInfo.hFile) CloseHandle(DBE.u.CreateProcessInfo.hFile);
            if(DBE.u.CreateProcessInfo.hProcess) CloseHandle(DBE.u.CreateProcessInfo.hProcess);
            if(DBE.u.CreateProcessInfo.hThread) CloseHandle(DBE.u.CreateProcessInfo.hThread);
            break;
        }
        else
        if(DBE.dwDebugEventCode == EXCEPTION_DEBUG_EVENT)
        {
            if(DBE.u.Exception.ExceptionRecord.ExceptionCode != 0x80000003)
            {
                //printf("0x%x\n", DBE.u.Exception.ExceptionRecord.ExceptionCode);
                /** 复制错误 */
                switch(DBE.u.Exception.ExceptionRecord.ExceptionCode)
                {
                case EXCEPTION_ACCESS_VIOLATION:
                    {
                        strcpy(cs.err_code, "ACCESS_VIOLATION");
                        break;
                    }

                case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
                    {
                        strcpy(cs.err_code, "ARRAY_BOUNDS_EXCEEDED");
                        break;
                    }

                case EXCEPTION_FLT_DENORMAL_OPERAND:
                    {
                        strcpy(cs.err_code, "FLOAT_DENORMAL_OPERAND");
                        break;
                    }

                case EXCEPTION_FLT_DIVIDE_BY_ZERO:
                    {
                        strcpy(cs.err_code, "FLOAT_DIVIDE_BY_ZERO");
                        break;
                    }

                case EXCEPTION_FLT_OVERFLOW:
                    {
                        strcpy(cs.err_code, "FLOAT_OVERFLOW");
                        break;
                    }

                case EXCEPTION_FLT_UNDERFLOW:
                    {
                        strcpy(cs.err_code, "FLOAT_UNDERFLOW");
                        break;
                    }

                case EXCEPTION_INT_DIVIDE_BY_ZERO:
                    {
                        strcpy(cs.err_code, "INTEGER_DIVIDE_BY_ZERO");
                        break;
                    }

                case EXCEPTION_INT_OVERFLOW:
                    {
                        strcpy(cs.err_code, "INTEGER_OVERFLOW");
                        break;
                    }

                case EXCEPTION_STACK_OVERFLOW:
                    {
                        strcpy(cs.err_code, "STACK_OVERFLOW");
                        break;
                    }

                default:
                    {
                        strcpy(cs.err_code, "OTHER_ERRORS");
                        break;
                    }
                }

                /** 关闭句柄,否则调试进程不能被结束 */
                if(DBE.u.CreateProcessInfo.hFile) CloseHandle(DBE.u.CreateProcessInfo.hFile);
                if(DBE.u.CreateProcessInfo.hProcess) CloseHandle(DBE.u.CreateProcessInfo.hProcess);
                if(DBE.u.CreateProcessInfo.hThread) CloseHandle(DBE.u.CreateProcessInfo.hThread);
                return _ErrExit(hProcess, ProcInfo.dwProcessId, cs, RUNTIME_ERROR, RunTime, maxMemo);
            }
        }

        /** 继续调试 */
        ContinueDebugEvent(DBE.dwProcessId, DBE.dwThreadId, DBG_CONTINUE);
        if(DBE.u.CreateProcessInfo.hFile) CloseHandle(DBE.u.CreateProcessInfo.hFile);
        if(DBE.u.CreateProcessInfo.hProcess) CloseHandle(DBE.u.CreateProcessInfo.hProcess);
        if(DBE.u.CreateProcessInfo.hThread) CloseHandle(DBE.u.CreateProcessInfo.hThread);
    }

    cs.exe_time = RunTime;
    cs.exe_memory = maxMemo;

    return true;
}