update send packet to be compatible with win 11 24h2
This commit is contained in:
@@ -21,28 +21,32 @@ const (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
sendPacketStubBase = []byte{
|
sendPacketStubBase = []byte{
|
||||||
0x48, 0x89, 0xC8,
|
0xF3, 0x0F, 0x1E, 0xFA,
|
||||||
0x49, 0x89, 0xC0,
|
0x53,
|
||||||
0x48, 0x83, 0xEC, 0x28,
|
0x48, 0x89, 0xCB,
|
||||||
0x48, 0x8B, 0x48, 0x08,
|
0x48, 0x83, 0xEC, 0x20,
|
||||||
0x48, 0x8B, 0x50, 0x10,
|
0x48, 0x8B, 0x03,
|
||||||
0x48, 0x8B, 0x00,
|
0x48, 0x8B, 0x4B, 0x08,
|
||||||
|
0x48, 0x8B, 0x53, 0x10,
|
||||||
|
0x45, 0x33, 0xC0,
|
||||||
0xFF, 0xD0,
|
0xFF, 0xD0,
|
||||||
0x41, 0xC7, 0x40, 0x18,
|
0xC7, 0x43, 0x18, 0x01, 0x00, 0x00, 0x00,
|
||||||
0x01, 0x00, 0x00, 0x00,
|
|
||||||
0xB8, 0x01, 0x00, 0x00, 0x00,
|
0xB8, 0x01, 0x00, 0x00, 0x00,
|
||||||
0x48, 0x83, 0xC4, 0x28,
|
0x48, 0x83, 0xC4, 0x20,
|
||||||
|
0x5B,
|
||||||
0xC3,
|
0xC3,
|
||||||
}
|
}
|
||||||
|
|
||||||
kernel32 = windows.NewLazySystemDLL("kernel32.dll")
|
kernel32 = windows.NewLazySystemDLL("kernel32.dll")
|
||||||
procVirtualAllocEx = kernel32.NewProc("VirtualAllocEx")
|
procVirtualAllocEx = kernel32.NewProc("VirtualAllocEx")
|
||||||
procVirtualFreeEx = kernel32.NewProc("VirtualFreeEx")
|
procVirtualFreeEx = kernel32.NewProc("VirtualFreeEx")
|
||||||
procQueueUserAPC = kernel32.NewProc("QueueUserAPC")
|
procQueueUserAPC = kernel32.NewProc("QueueUserAPC")
|
||||||
procSuspendThread = kernel32.NewProc("SuspendThread")
|
procSuspendThread = kernel32.NewProc("SuspendThread")
|
||||||
procResumeThread = kernel32.NewProc("ResumeThread")
|
procResumeThread = kernel32.NewProc("ResumeThread")
|
||||||
procGetExitCodeThread = kernel32.NewProc("GetExitCodeThread")
|
procGetExitCodeThread = kernel32.NewProc("GetExitCodeThread")
|
||||||
procGetThreadTimes = kernel32.NewProc("GetThreadTimes")
|
procGetThreadTimes = kernel32.NewProc("GetThreadTimes")
|
||||||
|
procVirtualProtectEx = kernel32.NewProc("VirtualProtectEx")
|
||||||
|
procSetProcessValidCallTargets = kernel32.NewProc("SetProcessValidCallTargets")
|
||||||
|
|
||||||
d2gsCachedFn uintptr
|
d2gsCachedFn uintptr
|
||||||
d2gsCacheMu sync.RWMutex
|
d2gsCacheMu sync.RWMutex
|
||||||
@@ -67,6 +71,8 @@ const (
|
|||||||
sendPacketMetaSize = 32
|
sendPacketMetaSize = 32
|
||||||
|
|
||||||
threadStillActive = 259
|
threadStillActive = 259
|
||||||
|
|
||||||
|
cfgCallTargetValid = 0x1
|
||||||
)
|
)
|
||||||
|
|
||||||
type sendPacketState struct {
|
type sendPacketState struct {
|
||||||
@@ -84,6 +90,11 @@ type sendPacketState struct {
|
|||||||
leakedBuffers []uintptr
|
leakedBuffers []uintptr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type cfgCallTargetInfo struct {
|
||||||
|
Offset uintptr
|
||||||
|
Flags uintptr
|
||||||
|
}
|
||||||
|
|
||||||
func findPatternOffset(memory []byte, pattern, mask string) int {
|
func findPatternOffset(memory []byte, pattern, mask string) int {
|
||||||
if len(pattern) != len(mask) {
|
if len(pattern) != len(mask) {
|
||||||
return -1
|
return -1
|
||||||
@@ -157,6 +168,16 @@ func (s *sendPacketState) ensureStub(handle windows.Handle) error {
|
|||||||
return fmt.Errorf("write remote stub: %w", err)
|
return fmt.Errorf("write remote stub: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := markCallTargetValid(handle, addr, stubSize); err != nil {
|
||||||
|
virtualFreeEx(handle, addr)
|
||||||
|
return fmt.Errorf("register call target: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := virtualProtectEx(handle, addr, stubSize, windows.PAGE_EXECUTE_READ); err != nil {
|
||||||
|
virtualFreeEx(handle, addr)
|
||||||
|
return fmt.Errorf("set stub protection: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
s.stub = addr
|
s.stub = addr
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -631,3 +652,69 @@ func virtualFreeEx(handle windows.Handle, address uintptr) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
func markCallTargetValid(handle windows.Handle, address uintptr, size uintptr) error {
|
||||||
|
if err := procSetProcessValidCallTargets.Find(); err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if address == 0 {
|
||||||
|
return errors.New("attempt to register null call target")
|
||||||
|
}
|
||||||
|
|
||||||
|
regionSize := alignUp(size, 0x1000)
|
||||||
|
info := cfgCallTargetInfo{
|
||||||
|
Offset: 0,
|
||||||
|
Flags: cfgCallTargetValid,
|
||||||
|
}
|
||||||
|
|
||||||
|
ret, _, err := procSetProcessValidCallTargets.Call(
|
||||||
|
uintptr(handle),
|
||||||
|
address,
|
||||||
|
regionSize,
|
||||||
|
1,
|
||||||
|
uintptr(unsafe.Pointer(&info)),
|
||||||
|
)
|
||||||
|
if ret == 0 {
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("SetProcessValidCallTargets: %w", err)
|
||||||
|
}
|
||||||
|
return errors.New("SetProcessValidCallTargets failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func alignUp(value, alignment uintptr) uintptr {
|
||||||
|
if alignment == 0 {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
mask := alignment - 1
|
||||||
|
return (value + mask) &^ mask
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user