secure v2

This commit is contained in:
vietdungdev
2026-03-21 11:51:59 +07:00
parent 28062d1c04
commit 8173a628b2
3 changed files with 308 additions and 74 deletions

View File

@@ -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 {