new plugins system
This commit is contained in:
@@ -5,7 +5,7 @@ package plugins
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
"runtime"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
@@ -15,59 +15,96 @@ func loadNativePlugin(data []byte) (NativePlugin, error) {
|
||||
return nil, errors.New("empty plugin binary")
|
||||
}
|
||||
|
||||
mm, err := LoadMemoryModule(data)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("pe load: %w", err)
|
||||
type initResult struct {
|
||||
dp *dllPlugin
|
||||
err error
|
||||
}
|
||||
ch := make(chan initResult, 1)
|
||||
|
||||
if err := mm.CallEntryPoint(dllProcessAttach); err != nil {
|
||||
mm.Free()
|
||||
return nil, fmt.Errorf("DllMain init: %w", err)
|
||||
}
|
||||
go func() {
|
||||
runtime.LockOSThread()
|
||||
|
||||
onLoad, err := mm.GetExport("PluginOnLoad")
|
||||
if err != nil {
|
||||
mm.Free()
|
||||
return nil, err
|
||||
}
|
||||
onEvent, err := mm.GetExport("PluginOnEvent")
|
||||
if err != nil {
|
||||
mm.Free()
|
||||
return nil, err
|
||||
}
|
||||
onUnload, err := mm.GetExport("PluginOnUnload")
|
||||
if err != nil {
|
||||
mm.Free()
|
||||
return nil, err
|
||||
}
|
||||
mm, err := LoadMemoryModule(data)
|
||||
if err != nil {
|
||||
ch <- initResult{err: fmt.Errorf("pe load: %w", err)}
|
||||
runtime.UnlockOSThread()
|
||||
return
|
||||
}
|
||||
|
||||
setCallback, _ := mm.GetExport("PluginSetCallback")
|
||||
if err := mm.CallEntryPoint(dllProcessAttach); err != nil {
|
||||
mm.Free()
|
||||
ch <- initResult{err: fmt.Errorf("DllMain init: %w", err)}
|
||||
runtime.UnlockOSThread()
|
||||
return
|
||||
}
|
||||
|
||||
runtime := "go"
|
||||
if getRuntimeAddr, err := mm.GetExport("PluginGetRuntime"); err == nil {
|
||||
ret, _, _ := syscall.SyscallN(getRuntimeAddr)
|
||||
if ret != 0 {
|
||||
var buf [32]byte
|
||||
for i := range buf {
|
||||
b := *(*byte)(unsafe.Pointer(ret + uintptr(i)))
|
||||
if b == 0 {
|
||||
runtime = string(buf[:i])
|
||||
break
|
||||
onLoad, err := mm.GetExport("PluginOnLoad")
|
||||
if err != nil {
|
||||
mm.Free()
|
||||
ch <- initResult{err: err}
|
||||
runtime.UnlockOSThread()
|
||||
return
|
||||
}
|
||||
onEvent, err := mm.GetExport("PluginOnEvent")
|
||||
if err != nil {
|
||||
mm.Free()
|
||||
ch <- initResult{err: err}
|
||||
runtime.UnlockOSThread()
|
||||
return
|
||||
}
|
||||
onUnload, err := mm.GetExport("PluginOnUnload")
|
||||
if err != nil {
|
||||
mm.Free()
|
||||
ch <- initResult{err: err}
|
||||
runtime.UnlockOSThread()
|
||||
return
|
||||
}
|
||||
|
||||
setCallback, _ := mm.GetExport("PluginSetCallback")
|
||||
|
||||
rt := "go"
|
||||
if getRuntimeAddr, err := mm.GetExport("PluginGetRuntime"); err == nil {
|
||||
ret, _, _ := syscall.SyscallN(getRuntimeAddr)
|
||||
if ret != 0 {
|
||||
var buf [32]byte
|
||||
for i := range buf {
|
||||
b := *(*byte)(unsafe.Pointer(ret + uintptr(i)))
|
||||
if b == 0 {
|
||||
rt = string(buf[:i])
|
||||
break
|
||||
}
|
||||
buf[i] = b
|
||||
}
|
||||
buf[i] = b
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dp := &dllPlugin{
|
||||
mem: mm,
|
||||
onLoadAddr: onLoad,
|
||||
onEventAddr: onEvent,
|
||||
onUnloadAddr: onUnload,
|
||||
setCallbackAddr: setCallback,
|
||||
pluginRuntime: runtime,
|
||||
dp := &dllPlugin{
|
||||
mem: mm,
|
||||
onLoadAddr: onLoad,
|
||||
onEventAddr: onEvent,
|
||||
onUnloadAddr: onUnload,
|
||||
setCallbackAddr: setCallback,
|
||||
pluginRuntime: rt,
|
||||
workCh: make(chan pluginWork),
|
||||
}
|
||||
|
||||
ch <- initResult{dp: dp}
|
||||
|
||||
dp.workerLoop()
|
||||
|
||||
runtime.UnlockOSThread()
|
||||
}()
|
||||
|
||||
res := <-ch
|
||||
if res.err != nil {
|
||||
return nil, res.err
|
||||
}
|
||||
return dp, nil
|
||||
return res.dp, nil
|
||||
}
|
||||
|
||||
type pluginWork struct {
|
||||
fn func() error
|
||||
done chan error
|
||||
}
|
||||
|
||||
type dllPlugin struct {
|
||||
@@ -78,76 +115,94 @@ type dllPlugin struct {
|
||||
setCallbackAddr uintptr
|
||||
callbackHandle uintptr // prevent GC of the callback closure
|
||||
pluginRuntime string // "go", "c", "cpp", etc.
|
||||
mu sync.Mutex
|
||||
workCh chan pluginWork
|
||||
}
|
||||
|
||||
func (p *dllPlugin) workerLoop() {
|
||||
for w := range p.workCh {
|
||||
w.done <- w.fn()
|
||||
}
|
||||
}
|
||||
|
||||
func (p *dllPlugin) runOnWorker(fn func() error) error {
|
||||
done := make(chan error, 1)
|
||||
p.workCh <- pluginWork{fn: fn, done: done}
|
||||
return <-done
|
||||
}
|
||||
|
||||
func (p *dllPlugin) Load(send func(string, []byte), hostInfo []byte) error {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
return p.runOnWorker(func() error {
|
||||
// Create a stdcall callback the DLL can invoke to send events to the host.
|
||||
cb := syscall.NewCallback(func(eventPtr, eventLen, payloadPtr, payloadLen uintptr) uintptr {
|
||||
event := make([]byte, eventLen)
|
||||
if eventLen > 0 {
|
||||
copy(event, unsafe.Slice((*byte)(unsafe.Pointer(eventPtr)), eventLen))
|
||||
}
|
||||
payload := make([]byte, payloadLen)
|
||||
if payloadLen > 0 {
|
||||
copy(payload, unsafe.Slice((*byte)(unsafe.Pointer(payloadPtr)), payloadLen))
|
||||
}
|
||||
send(string(event), payload)
|
||||
return 0
|
||||
})
|
||||
p.callbackHandle = cb
|
||||
|
||||
// Create a stdcall callback the DLL can invoke to send events to the host.
|
||||
cb := syscall.NewCallback(func(eventPtr, eventLen, payloadPtr, payloadLen uintptr) uintptr {
|
||||
event := make([]byte, eventLen)
|
||||
if eventLen > 0 {
|
||||
copy(event, unsafe.Slice((*byte)(unsafe.Pointer(eventPtr)), eventLen))
|
||||
if p.setCallbackAddr != 0 {
|
||||
syscall.SyscallN(p.setCallbackAddr, cb)
|
||||
}
|
||||
payload := make([]byte, payloadLen)
|
||||
if payloadLen > 0 {
|
||||
copy(payload, unsafe.Slice((*byte)(unsafe.Pointer(payloadPtr)), payloadLen))
|
||||
|
||||
var infoPtr uintptr
|
||||
infoLen := uintptr(len(hostInfo))
|
||||
if len(hostInfo) > 0 {
|
||||
infoPtr = uintptr(unsafe.Pointer(&hostInfo[0]))
|
||||
}
|
||||
send(string(event), payload)
|
||||
return 0
|
||||
ret, _, _ := syscall.SyscallN(p.onLoadAddr, infoPtr, infoLen, cb)
|
||||
if int32(ret) != 0 {
|
||||
return errors.New("PluginOnLoad returned non-zero")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
p.callbackHandle = cb
|
||||
|
||||
if p.setCallbackAddr != 0 {
|
||||
syscall.SyscallN(p.setCallbackAddr, cb)
|
||||
}
|
||||
|
||||
var infoPtr uintptr
|
||||
infoLen := uintptr(len(hostInfo))
|
||||
if len(hostInfo) > 0 {
|
||||
infoPtr = uintptr(unsafe.Pointer(&hostInfo[0]))
|
||||
}
|
||||
ret, _, _ := syscall.SyscallN(p.onLoadAddr, infoPtr, infoLen, cb)
|
||||
if int32(ret) != 0 {
|
||||
return errors.New("PluginOnLoad returned non-zero")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *dllPlugin) Event(event string, payload []byte) error {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
|
||||
eventBytes := []byte(event)
|
||||
var eventPtr, payloadPtr uintptr
|
||||
eventLen := uintptr(len(eventBytes))
|
||||
payloadLen := uintptr(len(payload))
|
||||
if len(eventBytes) > 0 {
|
||||
eventPtr = uintptr(unsafe.Pointer(&eventBytes[0]))
|
||||
}
|
||||
if len(payload) > 0 {
|
||||
payloadPtr = uintptr(unsafe.Pointer(&payload[0]))
|
||||
}
|
||||
payloadCopy := make([]byte, len(payload))
|
||||
copy(payloadCopy, payload)
|
||||
|
||||
ret, _, _ := syscall.SyscallN(p.onEventAddr, eventPtr, eventLen, payloadPtr, payloadLen)
|
||||
if int32(ret) != 0 {
|
||||
return errors.New("PluginOnEvent returned non-zero")
|
||||
}
|
||||
go func() {
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
|
||||
cleanup := p.mem.SetupThreadTLS()
|
||||
defer cleanup()
|
||||
|
||||
var eventPtr, payloadPtr uintptr
|
||||
eventLen := uintptr(len(eventBytes))
|
||||
payloadLen := uintptr(len(payloadCopy))
|
||||
if len(eventBytes) > 0 {
|
||||
eventPtr = uintptr(unsafe.Pointer(&eventBytes[0]))
|
||||
}
|
||||
if len(payloadCopy) > 0 {
|
||||
payloadPtr = uintptr(unsafe.Pointer(&payloadCopy[0]))
|
||||
}
|
||||
|
||||
syscall.SyscallN(p.onEventAddr, eventPtr, eventLen, payloadPtr, payloadLen)
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *dllPlugin) Unload() {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
if p.onUnloadAddr != 0 {
|
||||
syscall.SyscallN(p.onUnloadAddr)
|
||||
}
|
||||
_ = p.runOnWorker(func() error {
|
||||
if p.onUnloadAddr != 0 {
|
||||
syscall.SyscallN(p.onUnloadAddr)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (p *dllPlugin) Close() error {
|
||||
p.Unload()
|
||||
close(p.workCh)
|
||||
if p.pluginRuntime != "go" {
|
||||
if p.mem != nil {
|
||||
p.mem.Free()
|
||||
|
||||
@@ -11,6 +11,8 @@ import (
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
func currentTEB() uintptr
|
||||
|
||||
const (
|
||||
imageDOSSignature = 0x5A4D // "MZ"
|
||||
imageNTSignature = 0x00004550 // "PE\0\0"
|
||||
@@ -123,14 +125,18 @@ type imageTLSDirectory64 struct {
|
||||
}
|
||||
|
||||
type MemoryModule struct {
|
||||
base uintptr
|
||||
size uintptr
|
||||
entryPoint uintptr
|
||||
exports map[string]uintptr
|
||||
importDLLs []windows.Handle
|
||||
initialized bool
|
||||
tlsIndex uint32
|
||||
tlsData uintptr
|
||||
base uintptr
|
||||
size uintptr
|
||||
entryPoint uintptr
|
||||
exports map[string]uintptr
|
||||
importDLLs []windows.Handle
|
||||
initialized bool
|
||||
tlsIndex uint32
|
||||
tlsData uintptr
|
||||
tlsArrayAlloc uintptr // our VirtualAlloc'd ThreadLocalStoragePointer array
|
||||
tlsTemplSrc uintptr // PE template raw data start (for copying to new threads)
|
||||
tlsTemplSize uintptr // dataSize (template bytes to copy)
|
||||
tlsTotalSize uintptr // dataSize + zeroFill (total allocation per thread)
|
||||
}
|
||||
|
||||
func LoadMemoryModule(data []byte) (*MemoryModule, error) {
|
||||
@@ -293,8 +299,8 @@ func (mm *MemoryModule) Free() {
|
||||
if mm.tlsIndex != 0xFFFFFFFF {
|
||||
if mm.tlsData != 0 {
|
||||
_ = windows.VirtualFree(mm.tlsData, 0, windows.MEM_RELEASE)
|
||||
mm.tlsData = 0
|
||||
}
|
||||
procTlsFree.Call(uintptr(mm.tlsIndex))
|
||||
}
|
||||
for _, h := range mm.importDLLs {
|
||||
_ = windows.FreeLibrary(h)
|
||||
@@ -431,30 +437,78 @@ func (mm *MemoryModule) setupTLS(reason uint32) {
|
||||
|
||||
tls := (*imageTLSDirectory64)(unsafe.Pointer(mm.base + uintptr(tlsDir.VirtualAddress)))
|
||||
|
||||
idx, _, _ := procTlsAlloc.Call()
|
||||
if idx == 0xFFFFFFFF {
|
||||
return
|
||||
}
|
||||
mm.tlsIndex = uint32(idx)
|
||||
|
||||
if tls.AddressOfIndex != 0 {
|
||||
*(*uint32)(unsafe.Pointer(uintptr(tls.AddressOfIndex))) = mm.tlsIndex
|
||||
}
|
||||
|
||||
dataSize := uintptr(tls.EndAddressOfRawData - tls.StartAddressOfRawData)
|
||||
totalSize := dataSize + uintptr(tls.SizeOfZeroFill)
|
||||
|
||||
var tlsData uintptr
|
||||
if totalSize > 0 {
|
||||
tlsData, err := windows.VirtualAlloc(0, totalSize,
|
||||
var err error
|
||||
tlsData, err = windows.VirtualAlloc(0, totalSize,
|
||||
windows.MEM_RESERVE|windows.MEM_COMMIT, windows.PAGE_READWRITE)
|
||||
if err == nil && tlsData != 0 {
|
||||
if dataSize > 0 {
|
||||
copyMem(tlsData, (*byte)(unsafe.Pointer(uintptr(tls.StartAddressOfRawData))), dataSize)
|
||||
}
|
||||
procTlsSetValue.Call(uintptr(mm.tlsIndex), tlsData)
|
||||
mm.tlsData = tlsData
|
||||
if err != nil || tlsData == 0 {
|
||||
return
|
||||
}
|
||||
if dataSize > 0 {
|
||||
copyMem(tlsData, (*byte)(unsafe.Pointer(uintptr(tls.StartAddressOfRawData))), dataSize)
|
||||
}
|
||||
}
|
||||
|
||||
tebAddr := currentTEB()
|
||||
tlsArrayField := (*uintptr)(unsafe.Pointer(tebAddr + 0x58)) // ThreadLocalStoragePointer
|
||||
oldArray := *tlsArrayField
|
||||
|
||||
var newIndex uint32
|
||||
ptrSize := unsafe.Sizeof(uintptr(0))
|
||||
|
||||
if oldArray == 0 {
|
||||
newArray, err := windows.VirtualAlloc(0, ptrSize,
|
||||
windows.MEM_RESERVE|windows.MEM_COMMIT, windows.PAGE_READWRITE)
|
||||
if err != nil || newArray == 0 {
|
||||
if tlsData != 0 {
|
||||
_ = windows.VirtualFree(tlsData, 0, windows.MEM_RELEASE)
|
||||
}
|
||||
return
|
||||
}
|
||||
*(*uintptr)(unsafe.Pointer(newArray)) = tlsData
|
||||
*tlsArrayField = newArray
|
||||
newIndex = 0
|
||||
mm.tlsArrayAlloc = newArray
|
||||
} else {
|
||||
var count uint32
|
||||
for count = 0; count < 256; count++ {
|
||||
entry := *(*uintptr)(unsafe.Pointer(oldArray + uintptr(count)*ptrSize))
|
||||
if entry == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
newSize := uintptr(count+1) * ptrSize
|
||||
newArray, err := windows.VirtualAlloc(0, newSize,
|
||||
windows.MEM_RESERVE|windows.MEM_COMMIT, windows.PAGE_READWRITE)
|
||||
if err != nil || newArray == 0 {
|
||||
if tlsData != 0 {
|
||||
_ = windows.VirtualFree(tlsData, 0, windows.MEM_RELEASE)
|
||||
}
|
||||
return
|
||||
}
|
||||
if count > 0 {
|
||||
copyMem(newArray, (*byte)(unsafe.Pointer(oldArray)), uintptr(count)*ptrSize)
|
||||
}
|
||||
*(*uintptr)(unsafe.Pointer(newArray + uintptr(count)*ptrSize)) = tlsData
|
||||
*tlsArrayField = newArray
|
||||
newIndex = count
|
||||
mm.tlsArrayAlloc = newArray
|
||||
}
|
||||
|
||||
if tls.AddressOfIndex != 0 {
|
||||
*(*uint32)(unsafe.Pointer(uintptr(tls.AddressOfIndex))) = newIndex
|
||||
}
|
||||
|
||||
mm.tlsIndex = newIndex
|
||||
mm.tlsData = tlsData
|
||||
mm.tlsTemplSrc = uintptr(tls.StartAddressOfRawData)
|
||||
mm.tlsTemplSize = dataSize
|
||||
mm.tlsTotalSize = totalSize
|
||||
|
||||
if tls.AddressOfCallBacks != 0 {
|
||||
cbAddr := uintptr(tls.AddressOfCallBacks)
|
||||
for {
|
||||
@@ -468,6 +522,61 @@ func (mm *MemoryModule) setupTLS(reason uint32) {
|
||||
}
|
||||
}
|
||||
|
||||
func (mm *MemoryModule) SetupThreadTLS() func() {
|
||||
if mm.tlsIndex == 0xFFFFFFFF || mm.tlsTotalSize == 0 {
|
||||
return func() {}
|
||||
}
|
||||
|
||||
tlsData, err := windows.VirtualAlloc(0, mm.tlsTotalSize,
|
||||
windows.MEM_RESERVE|windows.MEM_COMMIT, windows.PAGE_READWRITE)
|
||||
if err != nil || tlsData == 0 {
|
||||
return func() {}
|
||||
}
|
||||
if mm.tlsTemplSize > 0 {
|
||||
copyMem(tlsData, (*byte)(unsafe.Pointer(mm.tlsTemplSrc)), mm.tlsTemplSize)
|
||||
}
|
||||
|
||||
ptrSize := unsafe.Sizeof(uintptr(0))
|
||||
tebAddr := currentTEB()
|
||||
tlsArrayField := (*uintptr)(unsafe.Pointer(tebAddr + 0x58))
|
||||
oldArray := *tlsArrayField
|
||||
|
||||
var newArray uintptr
|
||||
if oldArray == 0 {
|
||||
arrSize := uintptr(mm.tlsIndex+1) * ptrSize
|
||||
newArray, err = windows.VirtualAlloc(0, arrSize,
|
||||
windows.MEM_RESERVE|windows.MEM_COMMIT, windows.PAGE_READWRITE)
|
||||
if err != nil || newArray == 0 {
|
||||
_ = windows.VirtualFree(tlsData, 0, windows.MEM_RELEASE)
|
||||
return func() {}
|
||||
}
|
||||
*(*uintptr)(unsafe.Pointer(newArray + uintptr(mm.tlsIndex)*ptrSize)) = tlsData
|
||||
*tlsArrayField = newArray
|
||||
} else {
|
||||
needed := uintptr(mm.tlsIndex+1) * ptrSize
|
||||
newArray, err = windows.VirtualAlloc(0, needed,
|
||||
windows.MEM_RESERVE|windows.MEM_COMMIT, windows.PAGE_READWRITE)
|
||||
if err != nil || newArray == 0 {
|
||||
_ = windows.VirtualFree(tlsData, 0, windows.MEM_RELEASE)
|
||||
return func() {}
|
||||
}
|
||||
copyMem(newArray, (*byte)(unsafe.Pointer(oldArray)), needed)
|
||||
*(*uintptr)(unsafe.Pointer(newArray + uintptr(mm.tlsIndex)*ptrSize)) = tlsData
|
||||
*tlsArrayField = newArray
|
||||
}
|
||||
|
||||
return func() {
|
||||
_ = windows.VirtualFree(tlsData, 0, windows.MEM_RELEASE)
|
||||
if newArray != 0 {
|
||||
*(*uintptr)(unsafe.Pointer(newArray + uintptr(mm.tlsIndex)*ptrSize)) = 0
|
||||
_ = windows.VirtualFree(newArray, 0, windows.MEM_RELEASE)
|
||||
}
|
||||
tebNow := currentTEB()
|
||||
field := (*uintptr)(unsafe.Pointer(tebNow + 0x58))
|
||||
*field = oldArray
|
||||
}
|
||||
}
|
||||
|
||||
func peString(addr uintptr) string {
|
||||
var buf []byte
|
||||
for i := 0; i < 4096; i++ { // safety limit
|
||||
@@ -480,45 +589,42 @@ func peString(addr uintptr) string {
|
||||
return string(buf)
|
||||
}
|
||||
|
||||
var (
|
||||
modKernel32 = windows.NewLazySystemDLL("kernel32.dll")
|
||||
procGetProcAddr = modKernel32.NewProc("GetProcAddress")
|
||||
procTlsAlloc = modKernel32.NewProc("TlsAlloc")
|
||||
procTlsSetValue = modKernel32.NewProc("TlsSetValue")
|
||||
procTlsFree = modKernel32.NewProc("TlsFree")
|
||||
)
|
||||
|
||||
func getProcByOrdinal(module windows.Handle, ordinal uint16) (uintptr, error) {
|
||||
r, _, err := procGetProcAddr.Call(uintptr(module), uintptr(ordinal))
|
||||
if r == 0 {
|
||||
return 0, fmt.Errorf("GetProcAddress ordinal %d: %w", ordinal, err)
|
||||
func copyMem(dst uintptr, src *byte, size uintptr) {
|
||||
for i := uintptr(0); i < size; i++ {
|
||||
*(*byte)(unsafe.Pointer(dst + i)) = *(*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(src)) + i))
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func sectionProtection(chars uint32) uint32 {
|
||||
exec := chars&imageSCNMemExecute != 0
|
||||
read := chars&imageSCNMemRead != 0
|
||||
write := chars&imageSCNMemWrite != 0
|
||||
r := chars&imageSCNMemRead != 0
|
||||
w := chars&imageSCNMemWrite != 0
|
||||
x := chars&imageSCNMemExecute != 0
|
||||
|
||||
switch {
|
||||
case exec && write:
|
||||
case x && w:
|
||||
return windows.PAGE_EXECUTE_READWRITE
|
||||
case exec && read:
|
||||
case x && r:
|
||||
return windows.PAGE_EXECUTE_READ
|
||||
case exec:
|
||||
case x:
|
||||
return windows.PAGE_EXECUTE
|
||||
case write:
|
||||
case w:
|
||||
return windows.PAGE_READWRITE
|
||||
case read:
|
||||
case r:
|
||||
return windows.PAGE_READONLY
|
||||
default:
|
||||
return windows.PAGE_NOACCESS
|
||||
}
|
||||
}
|
||||
|
||||
func copyMem(dst uintptr, src *byte, size uintptr) {
|
||||
dstSlice := unsafe.Slice((*byte)(unsafe.Pointer(dst)), size)
|
||||
srcSlice := unsafe.Slice(src, size)
|
||||
copy(dstSlice, srcSlice)
|
||||
var (
|
||||
modKernel32 = windows.NewLazySystemDLL("kernel32.dll")
|
||||
procGetProcAddr = modKernel32.NewProc("GetProcAddress")
|
||||
)
|
||||
|
||||
func getProcByOrdinal(module windows.Handle, ordinal uint16) (uintptr, error) {
|
||||
r, _, err := procGetProcAddr.Call(uintptr(module), uintptr(ordinal))
|
||||
if r == 0 {
|
||||
return 0, fmt.Errorf("pe: GetProcAddress ordinal %d: %w", ordinal, err)
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
#include "textflag.h"
|
||||
|
||||
// func currentTEB() uintptr
|
||||
TEXT ·currentTEB(SB),NOSPLIT,$0-8
|
||||
// mov rax, gs:[0x30] — read the TEB self-pointer
|
||||
BYTE $0x65; BYTE $0x48; BYTE $0x8B; BYTE $0x04; BYTE $0x25
|
||||
LONG $0x00000030
|
||||
MOVQ AX, ret+0(FP)
|
||||
RET
|
||||
Reference in New Issue
Block a user