Beispiel #1
0
func (t *Thread) resume() error {
	t.running = true
	var res C.WINBOOL
	t.dbp.execPtraceFunc(func() {
		//TODO: Note that we are ignoring the thread we were asked to continue and are continuing the
		//thread that we last broke on.
		res = C.ContinueDebugEvent(C.DWORD(t.dbp.Pid), C.DWORD(t.ID), C.DBG_CONTINUE)
	})
	if res == C.FALSE {
		return fmt.Errorf("could not ContinueDebugEvent.")
	}
	return nil
}
Beispiel #2
0
func (dbp *Process) waitForDebugEvent() (threadID, exitCode int, err error) {
	var debugEvent C.DEBUG_EVENT
	for {
		// Wait for a debug event...
		res := C.WaitForDebugEvent(&debugEvent, C.INFINITE)
		if res == C.FALSE {
			return 0, 0, fmt.Errorf("could not WaitForDebugEvent")
		}

		// ... handle each event kind ...
		unionPtr := unsafe.Pointer(&debugEvent.u[0])
		switch debugEvent.dwDebugEventCode {
		case C.CREATE_PROCESS_DEBUG_EVENT:
			debugInfo := (*C.CREATE_PROCESS_DEBUG_INFO)(unionPtr)
			hFile := debugInfo.hFile
			if hFile != C.HANDLE(uintptr(0)) /* NULL */ && hFile != C.HANDLE(uintptr(0xFFFFFFFFFFFFFFFF)) /* INVALID_HANDLE_VALUE */ {
				res = C.CloseHandle(hFile)
				if res == C.FALSE {
					return 0, 0, fmt.Errorf("could not close create process file handle")
				}
			}
			dbp.os.hProcess = sys.Handle(debugInfo.hProcess)
			_, err = dbp.addThread(sys.Handle(debugInfo.hThread), int(debugEvent.dwThreadId), false)
			if err != nil {
				return 0, 0, err
			}
			break
		case C.CREATE_THREAD_DEBUG_EVENT:
			debugInfo := (*C.CREATE_THREAD_DEBUG_INFO)(unionPtr)
			_, err = dbp.addThread(sys.Handle(debugInfo.hThread), int(debugEvent.dwThreadId), false)
			if err != nil {
				return 0, 0, err
			}
			break
		case C.EXIT_THREAD_DEBUG_EVENT:
			delete(dbp.Threads, int(debugEvent.dwThreadId))
			break
		case C.OUTPUT_DEBUG_STRING_EVENT:
			//TODO: Handle debug output strings
			break
		case C.LOAD_DLL_DEBUG_EVENT:
			debugInfo := (*C.LOAD_DLL_DEBUG_INFO)(unionPtr)
			hFile := debugInfo.hFile
			if hFile != C.HANDLE(uintptr(0)) /* NULL */ && hFile != C.HANDLE(uintptr(0xFFFFFFFFFFFFFFFF)) /* INVALID_HANDLE_VALUE */ {
				res = C.CloseHandle(hFile)
				if res == C.FALSE {
					return 0, 0, fmt.Errorf("could not close DLL load file handle")
				}
			}
			break
		case C.UNLOAD_DLL_DEBUG_EVENT:
			break
		case C.RIP_EVENT:
			break
		case C.EXCEPTION_DEBUG_EVENT:
			tid := int(debugEvent.dwThreadId)
			dbp.os.breakThread = tid
			return tid, 0, nil
		case C.EXIT_PROCESS_DEBUG_EVENT:
			debugInfo := (*C.EXIT_PROCESS_DEBUG_INFO)(unionPtr)
			return 0, int(debugInfo.dwExitCode), nil
		default:
			return 0, 0, fmt.Errorf("unknown debug event code: %d", debugEvent.dwDebugEventCode)
		}

		// .. and then continue unless we received an event that indicated we should break into debugger.
		res = C.ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, C.DBG_CONTINUE)
		if res == C.WINBOOL(0) {
			return 0, 0, fmt.Errorf("could not ContinueDebugEvent")
		}
	}
}
Beispiel #3
0
func (t *Thread) singleStep() error {
	var context C.CONTEXT
	context.ContextFlags = C.CONTEXT_ALL

	// Set the processor TRAP flag
	res := C.GetThreadContext(C.HANDLE(t.os.hThread), &context)
	if res == C.FALSE {
		return fmt.Errorf("could not GetThreadContext")
	}

	context.EFlags |= 0x100

	res = C.SetThreadContext(C.HANDLE(t.os.hThread), &context)
	if res == C.FALSE {
		return fmt.Errorf("could not SetThreadContext")
	}

	// Suspend all threads except this one
	for _, thread := range t.dbp.Threads {
		if thread.ID == t.ID {
			continue
		}
		res := C.SuspendThread(C.HANDLE(thread.os.hThread))
		if res == C.DWORD(0xFFFFFFFF) {
			return fmt.Errorf("could not suspend thread: %d", thread.ID)
		}
	}

	// Continue and wait for the step to complete
	t.dbp.execPtraceFunc(func() {
		res = C.ContinueDebugEvent(C.DWORD(t.dbp.Pid), C.DWORD(t.ID), C.DBG_CONTINUE)
	})
	if res == C.FALSE {
		return fmt.Errorf("could not ContinueDebugEvent.")
	}
	_, err := t.dbp.trapWait(0)
	if err != nil {
		return err
	}

	// Resume all threads except this one
	for _, thread := range t.dbp.Threads {
		if thread.ID == t.ID {
			continue
		}
		res := C.ResumeThread(C.HANDLE(thread.os.hThread))
		if res == C.DWORD(0xFFFFFFFF) {
			return fmt.Errorf("ould not resume thread: %d", thread.ID)
		}
	}

	// Unset the processor TRAP flag
	res = C.GetThreadContext(C.HANDLE(t.os.hThread), &context)
	if res == C.FALSE {
		return fmt.Errorf("could not GetThreadContext")
	}

	context.EFlags &= ^C.DWORD(0x100)

	res = C.SetThreadContext(C.HANDLE(t.os.hThread), &context)
	if res == C.FALSE {
		return fmt.Errorf("could not SetThreadContext")
	}

	return nil
}