secure v2
This commit is contained in:
@@ -38,14 +38,11 @@ var (
|
||||
}
|
||||
|
||||
kernel32 = windows.NewLazySystemDLL("kernel32.dll")
|
||||
procVirtualAllocEx = kernel32.NewProc("VirtualAllocEx")
|
||||
procVirtualFreeEx = kernel32.NewProc("VirtualFreeEx")
|
||||
procQueueUserAPC = kernel32.NewProc("QueueUserAPC")
|
||||
procSuspendThread = kernel32.NewProc("SuspendThread")
|
||||
procResumeThread = kernel32.NewProc("ResumeThread")
|
||||
procGetExitCodeThread = kernel32.NewProc("GetExitCodeThread")
|
||||
procGetThreadTimes = kernel32.NewProc("GetThreadTimes")
|
||||
procVirtualProtectEx = kernel32.NewProc("VirtualProtectEx")
|
||||
procSetProcessValidCallTargets = kernel32.NewProc("SetProcessValidCallTargets")
|
||||
procCreateRemoteThread = kernel32.NewProc("CreateRemoteThread")
|
||||
|
||||
@@ -143,7 +140,7 @@ func (s *sendPacketState) ensureHandle(pid uint32) (windows.Handle, error) {
|
||||
virtualFreeEx(s.handle, s.stub)
|
||||
}
|
||||
|
||||
windows.CloseHandle(s.handle)
|
||||
_ = ntCloseHandle(s.handle)
|
||||
s.handle = 0
|
||||
s.processPID = 0
|
||||
s.stub = 0
|
||||
@@ -153,7 +150,7 @@ func (s *sendPacketState) ensureHandle(pid uint32) (windows.Handle, error) {
|
||||
s.fn = 0
|
||||
}
|
||||
|
||||
h, err := windows.OpenProcess(sendPacketProcessAccess, false, pid)
|
||||
h, err := ntOpenProcess(pid, sendPacketProcessAccess)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("open process %d: %w", pid, err)
|
||||
}
|
||||
@@ -305,7 +302,7 @@ func (s *sendPacketState) Cleanup() error {
|
||||
|
||||
// Close thread handle - the main thread may change between games
|
||||
if s.thread != 0 {
|
||||
windows.CloseHandle(s.thread)
|
||||
_ = ntCloseHandle(s.thread)
|
||||
s.thread = 0
|
||||
s.threadID = 0
|
||||
}
|
||||
@@ -343,12 +340,12 @@ func (s *sendPacketState) ensureThreadHandle(p *Process) (windows.Handle, error)
|
||||
}
|
||||
}
|
||||
// Thread is invalid, close and reset
|
||||
windows.CloseHandle(s.thread)
|
||||
_ = ntCloseHandle(s.thread)
|
||||
s.thread = 0
|
||||
s.threadID = 0
|
||||
s.processPID = 0
|
||||
} else if s.thread != 0 && s.processPID != p.pid {
|
||||
windows.CloseHandle(s.thread)
|
||||
_ = ntCloseHandle(s.thread)
|
||||
s.thread = 0
|
||||
s.threadID = 0
|
||||
s.processPID = 0
|
||||
@@ -366,7 +363,7 @@ func (s *sendPacketState) ensureThreadHandle(p *Process) (windows.Handle, error)
|
||||
|
||||
// Validate the newly opened thread belongs to the correct process
|
||||
if err := validateThreadBelongsToProcess(handle, p.pid); err != nil {
|
||||
windows.CloseHandle(handle)
|
||||
_ = ntCloseHandle(handle)
|
||||
return 0, fmt.Errorf("thread %d validation failed: %w", threadID, err)
|
||||
}
|
||||
|
||||
@@ -509,7 +506,7 @@ func findMainThreadID(pid uint32) (uint32, error) {
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("CreateToolhelp32Snapshot: %w", err)
|
||||
}
|
||||
defer windows.CloseHandle(snapshot)
|
||||
defer ntCloseHandle(snapshot)
|
||||
|
||||
var entry windows.ThreadEntry32
|
||||
entry.Size = uint32(unsafe.Sizeof(entry))
|
||||
@@ -526,7 +523,7 @@ func findMainThreadID(pid uint32) (uint32, error) {
|
||||
thread, err := windows.OpenThread(sendPacketThreadAccess, false, entry.ThreadID)
|
||||
if err == nil {
|
||||
creationTime, err := getThreadCreationTime(thread)
|
||||
windows.CloseHandle(thread)
|
||||
_ = ntCloseHandle(thread)
|
||||
|
||||
if err == nil && creationTime < earliestCreationTime {
|
||||
earliestCreationTime = creationTime
|
||||
@@ -866,7 +863,7 @@ func (p *Process) waitForPacketCompletion(handle windows.Handle, state *sendPack
|
||||
select {
|
||||
case <-timeout:
|
||||
// Try to read status one last time before failing
|
||||
if err := windows.ReadProcessMemory(handle, state.meta+sendPacketStatusOffset, &statusBuf[0], 4, nil); err == nil {
|
||||
if err := ntReadProcessMemory(handle, state.meta+sendPacketStatusOffset, statusBuf[:]); err == nil {
|
||||
status := binary.LittleEndian.Uint32(statusBuf[:])
|
||||
if status == 1 {
|
||||
return nil
|
||||
@@ -874,7 +871,7 @@ func (p *Process) waitForPacketCompletion(handle windows.Handle, state *sendPack
|
||||
}
|
||||
return fmt.Errorf("packet send timeout: APC not processed within %dms", timeoutMs)
|
||||
case <-ticker.C:
|
||||
if err := windows.ReadProcessMemory(handle, state.meta+sendPacketStatusOffset, &statusBuf[0], 4, nil); err != nil {
|
||||
if err := ntReadProcessMemory(handle, state.meta+sendPacketStatusOffset, statusBuf[:]); err != nil {
|
||||
continue
|
||||
}
|
||||
status := binary.LittleEndian.Uint32(statusBuf[:])
|
||||
@@ -892,74 +889,26 @@ func writeRemoteMemory(handle windows.Handle, address uintptr, data []byte) erro
|
||||
if len(data) == 0 {
|
||||
return nil
|
||||
}
|
||||
return windows.WriteProcessMemory(handle, address, &data[0], uintptr(len(data)), nil)
|
||||
return ntWriteProcessMemory(handle, address, data)
|
||||
}
|
||||
|
||||
func virtualAllocEx(handle windows.Handle, size uintptr, protect uint32) (uintptr, error) {
|
||||
if size == 0 {
|
||||
return 0, errors.New("allocation size cannot be zero")
|
||||
}
|
||||
|
||||
addr, _, err := procVirtualAllocEx.Call(
|
||||
uintptr(handle),
|
||||
0,
|
||||
size,
|
||||
windows.MEM_COMMIT|windows.MEM_RESERVE,
|
||||
uintptr(protect),
|
||||
)
|
||||
if addr == 0 {
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return 0, errors.New("VirtualAllocEx failed")
|
||||
}
|
||||
return addr, nil
|
||||
return ntAllocateVirtualMemory(handle, size, windows.MEM_COMMIT|windows.MEM_RESERVE, protect)
|
||||
}
|
||||
|
||||
func virtualFreeEx(handle windows.Handle, address uintptr) error {
|
||||
if address == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
ret, _, err := procVirtualFreeEx.Call(
|
||||
uintptr(handle),
|
||||
address,
|
||||
0,
|
||||
windows.MEM_RELEASE,
|
||||
)
|
||||
if ret == 0 {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return errors.New("VirtualFreeEx failed")
|
||||
}
|
||||
return nil
|
||||
return ntFreeVirtualMemory(handle, address, windows.MEM_RELEASE)
|
||||
}
|
||||
|
||||
func virtualProtectEx(handle windows.Handle, address uintptr, size uintptr, protect uint32) error {
|
||||
if address == 0 || size == 0 {
|
||||
return errors.New("attempt to protect invalid region")
|
||||
}
|
||||
|
||||
if err := procVirtualProtectEx.Find(); err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var oldProtect uint32
|
||||
ret, _, err := procVirtualProtectEx.Call(
|
||||
uintptr(handle),
|
||||
address,
|
||||
size,
|
||||
uintptr(protect),
|
||||
uintptr(unsafe.Pointer(&oldProtect)),
|
||||
)
|
||||
if ret == 0 {
|
||||
if err != nil {
|
||||
return fmt.Errorf("VirtualProtectEx: %w", err)
|
||||
}
|
||||
return errors.New("VirtualProtectEx failed")
|
||||
}
|
||||
return nil
|
||||
_, err := ntProtectVirtualMemory(handle, address, size, protect)
|
||||
return err
|
||||
}
|
||||
|
||||
func markCallTargetValid(handle windows.Handle, address uintptr, size uintptr) error {
|
||||
|
||||
Reference in New Issue
Block a user