func DetachNotifyHandler(hwnd uint32) { key := uintptr(hwnd) if _, exists := notifyHandlers[key]; exists { C.HTMLayoutSetCallback(C.HWND(C.HANDLE(key)), nil, nil) delete(notifyHandlers, key) } }
func RootElement(hwnd uint32) *Element { var handle HELEMENT = BAD_HELEMENT if ret := C.HTMLayoutGetRootElement(C.HWND(C.HANDLE(uintptr(hwnd))), (*C.HELEMENT)(&handle)); ret != HLDOM_OK { domPanic(ret, "Failed to get root element") } return NewElementFromHandle(handle) }
func (dbp *Process) requestManualStop() error { res := C.DebugBreakProcess(C.HANDLE(dbp.os.hProcess)) if res == C.FALSE { return fmt.Errorf("failed to break process %d", dbp.Pid) } return nil }
// Load html contents into window func LoadHtml(hwnd uint32, data []byte, baseUrl string) error { if len(data) > 0 { if ok := C.HTMLayoutLoadHtmlEx(C.HWND(C.HANDLE(uintptr(hwnd))), (*C.BYTE)(&data[0]), C.UINT(len(data)), (*C.WCHAR)(stringToUtf16Ptr(baseUrl))); ok == 0 { return errors.New("HTMLayoutLoadHtmlEx failed") } } return nil }
// SetPC sets the RIP register to the value specified by `pc`. func (r *Regs) SetPC(thread *Thread, pc uint64) error { var context C.CONTEXT context.ContextFlags = C.CONTEXT_ALL res := C.GetThreadContext(C.HANDLE(thread.os.hThread), &context) if res == C.FALSE { return fmt.Errorf("could not GetThreadContext") } context.Rip = C.DWORD64(pc) res = C.SetThreadContext(C.HANDLE(thread.os.hThread), &context) if res == C.FALSE { return fmt.Errorf("could not SetThreadContext") } return nil }
func FocusedElement(hwnd uint32) *Element { var handle HELEMENT = BAD_HELEMENT if ret := C.HTMLayoutGetFocusElement(C.HWND(C.HANDLE(uintptr(hwnd))), (*C.HELEMENT)(&handle)); ret != HLDOM_OK { domPanic(ret, "Failed to get focus element") } if handle != BAD_HELEMENT { return NewElementFromHandle(handle) } return nil }
func DetachWindowEventHandler(hwnd uint32) { key := uintptr(hwnd) if handler, exists := windowEventHandlers[hwnd]; exists { tag := uintptr(unsafe.Pointer(handler)) if ret := C.HTMLayoutWindowDetachEventHandler(C.HWND(C.HANDLE(key)), (*[0]byte)(unsafe.Pointer(goElementProc)), C.LPVOID(tag)); ret != HLDOM_OK { domPanic(ret, "Failed to detach event handler from window") } delete(windowEventHandlers, hwnd) } }
func newHandle(c *Config) (handle syscall.Handle, err error) { handle, err = syscall.CreateFile( syscall.StringToUTF16Ptr(c.Address), syscall.GENERIC_READ|syscall.GENERIC_WRITE, 0, // mode nil, // security syscall.OPEN_EXISTING, // create mode 0, // attributes 0) // templates if err != nil { return } defer func() { if err != nil { syscall.CloseHandle(handle) } }() var dcb C.DCB dcb.BaudRate = C.DWORD(c.BaudRate) // Data bits if c.DataBits == 0 { dcb.ByteSize = 8 } else { dcb.ByteSize = C.BYTE(c.DataBits) } // Stop bits switch c.StopBits { case 0, 1: // Default is one stop bit. dcb.StopBits = C.ONESTOPBIT case 2: dcb.StopBits = C.TWOSTOPBITS default: err = fmt.Errorf("serial: unsupported stop bits %v", c.StopBits) return } // Parity switch c.Parity { case "", "E": // Default parity mode is Even. dcb.Parity = C.EVENPARITY case "O": dcb.Parity = C.ODDPARITY case "N": dcb.Parity = C.NOPARITY default: err = fmt.Errorf("serial: unsupported parity %v", c.Parity) return } if C.SetCommState(C.HANDLE(handle), &dcb) == 0 { err = fmt.Errorf("serial: could not set device state: %v", syscall.GetLastError()) return } return }
func registers(thread *Thread) (Registers, error) { var context C.CONTEXT context.ContextFlags = C.CONTEXT_ALL res := C.GetThreadContext(C.HANDLE(thread.os.hThread), &context) if res == C.FALSE { return nil, fmt.Errorf("failed to read ThreadContext") } var threadInfo C.THREAD_BASIC_INFORMATION res = C.thread_basic_information(C.HANDLE(thread.os.hThread), &threadInfo) if res == C.FALSE { return nil, fmt.Errorf("failed to get thread_basic_information") } tls := uintptr(threadInfo.TebBaseAddress) regs := &Regs{ rax: uint64(context.Rax), rbx: uint64(context.Rbx), rcx: uint64(context.Rcx), rdx: uint64(context.Rdx), rdi: uint64(context.Rdi), rsi: uint64(context.Rsi), rbp: uint64(context.Rbp), rsp: uint64(context.Rsp), r8: uint64(context.R8), r9: uint64(context.R9), r10: uint64(context.R10), r11: uint64(context.R11), r12: uint64(context.R12), r13: uint64(context.R13), r14: uint64(context.R14), r15: uint64(context.R15), rip: uint64(context.Rip), eflags: uint64(context.EFlags), cs: uint64(context.SegCs), fs: uint64(context.SegFs), gs: uint64(context.SegGs), tls: uint64(tls), } return regs, nil }
func AttachWindowEventHandler(hwnd uint32, handler *EventHandler) { key := uintptr(hwnd) tag := uintptr(unsafe.Pointer(handler)) if _, exists := windowEventHandlers[hwnd]; exists { if ret := C.HTMLayoutWindowDetachEventHandler(C.HWND(C.HANDLE(key)), (*[0]byte)(unsafe.Pointer(goElementProc)), C.LPVOID(tag)); ret != HLDOM_OK { domPanic(ret, "Failed to detach event handler from window before adding the new one") } } // Overwrite if it exists windowEventHandlers[hwnd] = handler // Don't let the caller disable ATTACH/DETACH events, otherwise we // won't know when to throw out our event handler object subscription := handler.Subscription() subscription &= ^uint32(DISABLE_INITIALIZATION & 0xffffffff) if ret := C.HTMLayoutWindowAttachEventHandler(C.HWND(C.HANDLE(key)), (*[0]byte)(unsafe.Pointer(goElementProc)), C.LPVOID(tag), C.UINT(subscription)); ret != HLDOM_OK { domPanic(ret, "Failed to attach event handler to window") } }
func (t *Thread) writeMemory(addr uintptr, data []byte) (int, error) { var ( vmData = C.LPCVOID(unsafe.Pointer(&data[0])) vmAddr = C.LPVOID(addr) length = C.SIZE_T(len(data)) count C.SIZE_T ) ret := C.WriteProcessMemory(C.HANDLE(t.dbp.os.hProcess), vmAddr, vmData, length, &count) if ret == C.FALSE { return int(count), fmt.Errorf("could not write memory") } return int(count), nil }
// Kill kills the process. func (dbp *Process) Kill() error { if dbp.exited { return nil } if !dbp.Threads[dbp.Pid].Stopped() { return errors.New("process must be stopped in order to kill it") } // TODO: Should not have to ignore failures here, // but some tests appear to Kill twice causing // this to fail on second attempt. _ = C.TerminateProcess(C.HANDLE(dbp.os.hProcess), 1) dbp.exited = true return nil }
func (t *Thread) readMemory(addr uintptr, size int) ([]byte, error) { if size == 0 { return nil, nil } var ( buf = make([]byte, size) vmData = C.LPVOID(unsafe.Pointer(&buf[0])) vmAddr = C.LPCVOID(addr) length = C.SIZE_T(size) count C.SIZE_T ) ret := C.ReadProcessMemory(C.HANDLE(t.dbp.os.hProcess), vmAddr, vmData, length, &count) if ret == C.FALSE { return nil, fmt.Errorf("could not read memory") } return buf, nil }
func registers(thread *Thread) (Registers, error) { var context C.CONTEXT context.ContextFlags = C.CONTEXT_ALL res := C.GetThreadContext(C.HANDLE(thread.os.hThread), &context) if res == C.FALSE { return nil, fmt.Errorf("failed to read ThreadContext") } var threadInfo _THREAD_BASIC_INFORMATION status := _NtQueryInformationThread(syscall.Handle(thread.os.hThread), _ThreadBasicInformation, uintptr(unsafe.Pointer(&threadInfo)), uint32(unsafe.Sizeof(threadInfo)), nil) if !_NT_SUCCESS(status) { return nil, fmt.Errorf("failed to get thread_basic_information") } regs := &Regs{ rax: uint64(context.Rax), rbx: uint64(context.Rbx), rcx: uint64(context.Rcx), rdx: uint64(context.Rdx), rdi: uint64(context.Rdi), rsi: uint64(context.Rsi), rbp: uint64(context.Rbp), rsp: uint64(context.Rsp), r8: uint64(context.R8), r9: uint64(context.R9), r10: uint64(context.R10), r11: uint64(context.R11), r12: uint64(context.R12), r13: uint64(context.R13), r14: uint64(context.R14), r15: uint64(context.R15), rip: uint64(context.Rip), eflags: uint64(context.EFlags), cs: uint64(context.SegCs), fs: uint64(context.SegFs), gs: uint64(context.SegGs), tls: uint64(threadInfo.TebBaseAddress), } return regs, nil }
// Open connects to the given serial port. func (p *port) Open(c *Config) (err error) { handle, err := newHandle(c) if err != nil { return } // Read and write timeout if c.Timeout > 0 { timeout := C.DWORD(c.Timeout.Nanoseconds() / 1E6) var timeouts C.COMMTIMEOUTS // wait until a byte arrived or time out timeouts.ReadIntervalTimeout = C.MAXDWORD timeouts.ReadTotalTimeoutMultiplier = C.MAXDWORD timeouts.ReadTotalTimeoutConstant = timeout timeouts.WriteTotalTimeoutMultiplier = 0 timeouts.WriteTotalTimeoutConstant = timeout if C.SetCommTimeouts(C.HANDLE(handle), &timeouts) == 0 { err = fmt.Errorf("serial: could not set timeout: %v", syscall.GetLastError()) syscall.CloseHandle(handle) return } } p.handle = handle return }
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") } } }
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 }
func main() { handle, err := syscall.CreateFile(syscall.StringToUTF16Ptr(port), syscall.GENERIC_READ|syscall.GENERIC_WRITE, 0, // mode nil, // security syscall.OPEN_EXISTING, // no creating new 0, 0) if err != nil { fmt.Print(err) return } fmt.Printf("handle created %d\n", handle) defer syscall.CloseHandle(handle) var dcb C.DCB dcb.BaudRate = 9600 dcb.ByteSize = 8 dcb.StopBits = C.ONESTOPBIT dcb.Parity = C.NOPARITY if C.SetCommState(C.HANDLE(handle), &dcb) == 0 { fmt.Printf("set comm state error %v\n", syscall.GetLastError()) return } fmt.Printf("set comm state succeed\n") var timeouts C.COMMTIMEOUTS // time-out between charactor for receiving (ms) timeouts.ReadIntervalTimeout = 1000 timeouts.ReadTotalTimeoutMultiplier = 0 timeouts.ReadTotalTimeoutConstant = 1000 timeouts.WriteTotalTimeoutMultiplier = 0 timeouts.WriteTotalTimeoutConstant = 1000 if C.SetCommTimeouts(C.HANDLE(handle), &timeouts) == 0 { fmt.Printf("set comm timeouts error %v\n", syscall.GetLastError()) return } fmt.Printf("set comm timeouts succeed\n") var n uint32 data := []byte("abc") err = syscall.WriteFile(handle, data, &n, nil) if err != nil { fmt.Println(err) return } fmt.Printf("write file succeed\n") fmt.Printf("Press Enter when ready for reading...") reader := bufio.NewReader(os.Stdin) _, _ = reader.ReadString('\n') data = make([]byte, 512) err = syscall.ReadFile(handle, data, &n, nil) if err != nil { fmt.Println(err) return } fmt.Printf("received data %v:\n", n) fmt.Printf("%x\n", data[:n]) fmt.Printf("closed\n") }
// Main htmlayout wndproc func ProcNoDefault(hwnd, msg uint32, wparam, lparam uintptr) (uintptr, bool) { var handled C.BOOL = 0 var result C.LRESULT = C.HTMLayoutProcND(C.HWND(C.HANDLE(uintptr(hwnd))), C.UINT(msg), C.WPARAM(wparam), C.LPARAM(lparam), &handled) return uintptr(result), handled != 0 }
// Load resource (file or url) into window func LoadResource(hwnd uint32, uri string) error { if ok := C.HTMLayoutLoadFile(C.HWND(C.HANDLE(uintptr(hwnd))), (*C.WCHAR)(stringToUtf16Ptr(uri))); ok == 0 { return errors.New("HTMLayoutLoadFile failed") } return nil }
func AttachNotifyHandler(hwnd uint32, handler *NotifyHandler) { key := uintptr(hwnd) // Overwrite if it exists notifyHandlers[key] = handler C.HTMLayoutSetCallback(C.HWND(C.HANDLE(key)), (*[0]byte)(unsafe.Pointer(goNotifyProc)), C.LPVOID(key)) }
// Call this from your NotifyHandler.HandleLoadData method if you want htmlayout to // process the data right away so you don't have to provide a buffer in the NmhlLoadData structure. func DataReady(hwnd uint32, uri *uint16, data []byte) bool { return C.HTMLayoutDataReady(C.HWND(C.HANDLE(uintptr(hwnd))), (*C.WCHAR)(uri), (*C.BYTE)(&data[0]), C.DWORD(len(data))) != 0 }