aboutsummaryrefslogtreecommitdiffstats
path: root/tun
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2021-10-16 22:49:38 -0600
committerJason A. Donenfeld <Jason@zx2c4.com>2021-10-16 22:49:38 -0600
commitba9e364dab402cfc104eb00669f7fdfd9259559e (patch)
tree8da1081c32cdcf8a1592d6853b2dad4463cdd260 /tun
parentglobal: remove old-style build tags (diff)
downloadwireguard-go-ba9e364dab402cfc104eb00669f7fdfd9259559e.tar.xz
wireguard-go-ba9e364dab402cfc104eb00669f7fdfd9259559e.zip
wintun: remove memmod option for dll loading
Only wireguard-windows used this, and it's moving to wgnt exclusively. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to 'tun')
-rw-r--r--tun/wintun/dll_fromfile_windows.go54
-rw-r--r--tun/wintun/dll_fromrsrc_windows.go61
-rw-r--r--tun/wintun/dll_windows.go39
-rw-r--r--tun/wintun/memmod/memmod_windows.go693
-rw-r--r--tun/wintun/memmod/memmod_windows_32.go16
-rw-r--r--tun/wintun/memmod/memmod_windows_386.go8
-rw-r--r--tun/wintun/memmod/memmod_windows_64.go36
-rw-r--r--tun/wintun/memmod/memmod_windows_amd64.go8
-rw-r--r--tun/wintun/memmod/memmod_windows_arm.go8
-rw-r--r--tun/wintun/memmod/memmod_windows_arm64.go8
-rw-r--r--tun/wintun/memmod/syscall_windows.go398
-rw-r--r--tun/wintun/memmod/syscall_windows_32.go96
-rw-r--r--tun/wintun/memmod/syscall_windows_64.go95
13 files changed, 39 insertions, 1481 deletions
diff --git a/tun/wintun/dll_fromfile_windows.go b/tun/wintun/dll_fromfile_windows.go
deleted file mode 100644
index 3a1cece..0000000
--- a/tun/wintun/dll_fromfile_windows.go
+++ /dev/null
@@ -1,54 +0,0 @@
-//go:build !load_wintun_from_rsrc
-
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
- */
-
-package wintun
-
-import (
- "fmt"
- "sync"
- "sync/atomic"
- "unsafe"
-
- "golang.org/x/sys/windows"
-)
-
-type lazyDLL struct {
- Name string
- mu sync.Mutex
- module windows.Handle
- onLoad func(d *lazyDLL)
-}
-
-func (d *lazyDLL) Load() error {
- if atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&d.module))) != nil {
- return nil
- }
- d.mu.Lock()
- defer d.mu.Unlock()
- if d.module != 0 {
- return nil
- }
-
- const (
- LOAD_LIBRARY_SEARCH_APPLICATION_DIR = 0x00000200
- LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800
- )
- module, err := windows.LoadLibraryEx(d.Name, 0, LOAD_LIBRARY_SEARCH_APPLICATION_DIR|LOAD_LIBRARY_SEARCH_SYSTEM32)
- if err != nil {
- return fmt.Errorf("Unable to load library: %w", err)
- }
-
- atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&d.module)), unsafe.Pointer(module))
- if d.onLoad != nil {
- d.onLoad(d)
- }
- return nil
-}
-
-func (p *lazyProc) nameToAddr() (uintptr, error) {
- return windows.GetProcAddress(p.dll.module, p.Name)
-}
diff --git a/tun/wintun/dll_fromrsrc_windows.go b/tun/wintun/dll_fromrsrc_windows.go
deleted file mode 100644
index 0f43097..0000000
--- a/tun/wintun/dll_fromrsrc_windows.go
+++ /dev/null
@@ -1,61 +0,0 @@
-//go:build load_wintun_from_rsrc
-
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
- */
-
-package wintun
-
-import (
- "fmt"
- "sync"
- "sync/atomic"
- "unsafe"
-
- "golang.org/x/sys/windows"
-
- "golang.zx2c4.com/wireguard/tun/wintun/memmod"
-)
-
-type lazyDLL struct {
- Name string
- mu sync.Mutex
- module *memmod.Module
- onLoad func(d *lazyDLL)
-}
-
-func (d *lazyDLL) Load() error {
- if atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&d.module))) != nil {
- return nil
- }
- d.mu.Lock()
- defer d.mu.Unlock()
- if d.module != nil {
- return nil
- }
-
- const ourModule windows.Handle = 0
- resInfo, err := windows.FindResource(ourModule, d.Name, windows.RT_RCDATA)
- if err != nil {
- return fmt.Errorf("Unable to find \"%v\" RCDATA resource: %w", d.Name, err)
- }
- data, err := windows.LoadResourceData(ourModule, resInfo)
- if err != nil {
- return fmt.Errorf("Unable to load resource: %w", err)
- }
- module, err := memmod.LoadLibrary(data)
- if err != nil {
- return fmt.Errorf("Unable to load library: %w", err)
- }
-
- atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&d.module)), unsafe.Pointer(module))
- if d.onLoad != nil {
- d.onLoad(d)
- }
- return nil
-}
-
-func (p *lazyProc) nameToAddr() (uintptr, error) {
- return p.dll.module.ProcAddressByName(p.Name)
-}
diff --git a/tun/wintun/dll_windows.go b/tun/wintun/dll_windows.go
index 1ecd6d0..c96e4a7 100644
--- a/tun/wintun/dll_windows.go
+++ b/tun/wintun/dll_windows.go
@@ -10,6 +10,8 @@ import (
"sync"
"sync/atomic"
"unsafe"
+
+ "golang.org/x/sys/windows"
)
func newLazyDLL(name string, onLoad func(d *lazyDLL)) *lazyDLL {
@@ -57,3 +59,40 @@ func (p *lazyProc) Addr() uintptr {
}
return p.addr
}
+
+type lazyDLL struct {
+ Name string
+ mu sync.Mutex
+ module windows.Handle
+ onLoad func(d *lazyDLL)
+}
+
+func (d *lazyDLL) Load() error {
+ if atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&d.module))) != nil {
+ return nil
+ }
+ d.mu.Lock()
+ defer d.mu.Unlock()
+ if d.module != 0 {
+ return nil
+ }
+
+ const (
+ LOAD_LIBRARY_SEARCH_APPLICATION_DIR = 0x00000200
+ LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800
+ )
+ module, err := windows.LoadLibraryEx(d.Name, 0, LOAD_LIBRARY_SEARCH_APPLICATION_DIR|LOAD_LIBRARY_SEARCH_SYSTEM32)
+ if err != nil {
+ return fmt.Errorf("Unable to load library: %w", err)
+ }
+
+ atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&d.module)), unsafe.Pointer(module))
+ if d.onLoad != nil {
+ d.onLoad(d)
+ }
+ return nil
+}
+
+func (p *lazyProc) nameToAddr() (uintptr, error) {
+ return windows.GetProcAddress(p.dll.module, p.Name)
+}
diff --git a/tun/wintun/memmod/memmod_windows.go b/tun/wintun/memmod/memmod_windows.go
deleted file mode 100644
index da6ff9a..0000000
--- a/tun/wintun/memmod/memmod_windows.go
+++ /dev/null
@@ -1,693 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2017-2021 WireGuard LLC. All Rights Reserved.
- */
-
-package memmod
-
-import (
- "errors"
- "fmt"
- "strings"
- "sync"
- "syscall"
- "unsafe"
-
- "golang.org/x/sys/windows"
-)
-
-type addressList struct {
- next *addressList
- address uintptr
-}
-
-func (head *addressList) free() {
- for node := head; node != nil; node = node.next {
- windows.VirtualFree(node.address, 0, windows.MEM_RELEASE)
- }
-}
-
-type Module struct {
- headers *IMAGE_NT_HEADERS
- codeBase uintptr
- modules []windows.Handle
- initialized bool
- isDLL bool
- isRelocated bool
- nameExports map[string]uint16
- entry uintptr
- blockedMemory *addressList
-}
-
-func (module *Module) headerDirectory(idx int) *IMAGE_DATA_DIRECTORY {
- return &module.headers.OptionalHeader.DataDirectory[idx]
-}
-
-func (module *Module) copySections(address uintptr, size uintptr, oldHeaders *IMAGE_NT_HEADERS) error {
- sections := module.headers.Sections()
- for i := range sections {
- if sections[i].SizeOfRawData == 0 {
- // Section doesn't contain data in the dll itself, but may define uninitialized data.
- sectionSize := oldHeaders.OptionalHeader.SectionAlignment
- if sectionSize == 0 {
- continue
- }
- dest, err := windows.VirtualAlloc(module.codeBase+uintptr(sections[i].VirtualAddress),
- uintptr(sectionSize),
- windows.MEM_COMMIT,
- windows.PAGE_READWRITE)
- if err != nil {
- return fmt.Errorf("Error allocating section: %w", err)
- }
-
- // Always use position from file to support alignments smaller than page size (allocation above will align to page size).
- dest = module.codeBase + uintptr(sections[i].VirtualAddress)
- // NOTE: On 64bit systems we truncate to 32bit here but expand again later when "PhysicalAddress" is used.
- sections[i].SetPhysicalAddress((uint32)(dest & 0xffffffff))
- dst := unsafe.Slice((*byte)(a2p(dest)), sectionSize)
- for j := range dst {
- dst[j] = 0
- }
- continue
- }
-
- if size < uintptr(sections[i].PointerToRawData+sections[i].SizeOfRawData) {
- return errors.New("Incomplete section")
- }
-
- // Commit memory block and copy data from dll.
- dest, err := windows.VirtualAlloc(module.codeBase+uintptr(sections[i].VirtualAddress),
- uintptr(sections[i].SizeOfRawData),
- windows.MEM_COMMIT,
- windows.PAGE_READWRITE)
- if err != nil {
- return fmt.Errorf("Error allocating memory block: %w", err)
- }
-
- // Always use position from file to support alignments smaller than page size (allocation above will align to page size).
- memcpy(
- module.codeBase+uintptr(sections[i].VirtualAddress),
- address+uintptr(sections[i].PointerToRawData),
- uintptr(sections[i].SizeOfRawData))
- // NOTE: On 64bit systems we truncate to 32bit here but expand again later when "PhysicalAddress" is used.
- sections[i].SetPhysicalAddress((uint32)(dest & 0xffffffff))
- }
-
- return nil
-}
-
-func (module *Module) realSectionSize(section *IMAGE_SECTION_HEADER) uintptr {
- size := section.SizeOfRawData
- if size != 0 {
- return uintptr(size)
- }
- if (section.Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) != 0 {
- return uintptr(module.headers.OptionalHeader.SizeOfInitializedData)
- }
- if (section.Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) != 0 {
- return uintptr(module.headers.OptionalHeader.SizeOfUninitializedData)
- }
- return 0
-}
-
-type sectionFinalizeData struct {
- address uintptr
- alignedAddress uintptr
- size uintptr
- characteristics uint32
- last bool
-}
-
-func (module *Module) finalizeSection(sectionData *sectionFinalizeData) error {
- if sectionData.size == 0 {
- return nil
- }
-
- if (sectionData.characteristics & IMAGE_SCN_MEM_DISCARDABLE) != 0 {
- // Section is not needed any more and can safely be freed.
- if sectionData.address == sectionData.alignedAddress &&
- (sectionData.last ||
- (sectionData.size%uintptr(module.headers.OptionalHeader.SectionAlignment)) == 0) {
- // Only allowed to decommit whole pages.
- windows.VirtualFree(sectionData.address, sectionData.size, windows.MEM_DECOMMIT)
- }
- return nil
- }
-
- // determine protection flags based on characteristics
- var ProtectionFlags = [8]uint32{
- windows.PAGE_NOACCESS, // not writeable, not readable, not executable
- windows.PAGE_EXECUTE, // not writeable, not readable, executable
- windows.PAGE_READONLY, // not writeable, readable, not executable
- windows.PAGE_EXECUTE_READ, // not writeable, readable, executable
- windows.PAGE_WRITECOPY, // writeable, not readable, not executable
- windows.PAGE_EXECUTE_WRITECOPY, // writeable, not readable, executable
- windows.PAGE_READWRITE, // writeable, readable, not executable
- windows.PAGE_EXECUTE_READWRITE, // writeable, readable, executable
- }
- protect := ProtectionFlags[sectionData.characteristics>>29]
- if (sectionData.characteristics & IMAGE_SCN_MEM_NOT_CACHED) != 0 {
- protect |= windows.PAGE_NOCACHE
- }
-
- // Change memory access flags.
- var oldProtect uint32
- err := windows.VirtualProtect(sectionData.address, sectionData.size, protect, &oldProtect)
- if err != nil {
- return fmt.Errorf("Error protecting memory page: %w", err)
- }
-
- return nil
-}
-
-var rtlAddFunctionTable = windows.NewLazySystemDLL("ntdll.dll").NewProc("RtlAddFunctionTable")
-
-func (module *Module) registerExceptionHandlers() {
- directory := module.headerDirectory(IMAGE_DIRECTORY_ENTRY_EXCEPTION)
- if directory.Size == 0 || directory.VirtualAddress == 0 {
- return
- }
- rtlAddFunctionTable.Call(module.codeBase+uintptr(directory.VirtualAddress), uintptr(directory.Size)/unsafe.Sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY{}), module.codeBase)
-}
-
-func (module *Module) finalizeSections() error {
- sections := module.headers.Sections()
- imageOffset := module.headers.OptionalHeader.imageOffset()
- sectionData := sectionFinalizeData{}
- sectionData.address = uintptr(sections[0].PhysicalAddress()) | imageOffset
- sectionData.alignedAddress = alignDown(sectionData.address, uintptr(module.headers.OptionalHeader.SectionAlignment))
- sectionData.size = module.realSectionSize(&sections[0])
- sections[0].SetVirtualSize(uint32(sectionData.size))
- sectionData.characteristics = sections[0].Characteristics
-
- // Loop through all sections and change access flags.
- for i := uint16(1); i < module.headers.FileHeader.NumberOfSections; i++ {
- sectionAddress := uintptr(sections[i].PhysicalAddress()) | imageOffset
- alignedAddress := alignDown(sectionAddress, uintptr(module.headers.OptionalHeader.SectionAlignment))
- sectionSize := module.realSectionSize(&sections[i])
- sections[i].SetVirtualSize(uint32(sectionSize))
- // Combine access flags of all sections that share a page.
- // TODO: We currently share flags of a trailing large section with the page of a first small section. This should be optimized.
- if sectionData.alignedAddress == alignedAddress || sectionData.address+sectionData.size > alignedAddress {
- // Section shares page with previous.
- if (sections[i].Characteristics&IMAGE_SCN_MEM_DISCARDABLE) == 0 || (sectionData.characteristics&IMAGE_SCN_MEM_DISCARDABLE) == 0 {
- sectionData.characteristics = (sectionData.characteristics | sections[i].Characteristics) &^ IMAGE_SCN_MEM_DISCARDABLE
- } else {
- sectionData.characteristics |= sections[i].Characteristics
- }
- sectionData.size = sectionAddress + sectionSize - sectionData.address
- continue
- }
-
- err := module.finalizeSection(&sectionData)
- if err != nil {
- return fmt.Errorf("Error finalizing section: %w", err)
- }
- sectionData.address = sectionAddress
- sectionData.alignedAddress = alignedAddress
- sectionData.size = sectionSize
- sectionData.characteristics = sections[i].Characteristics
- }
- sectionData.last = true
- err := module.finalizeSection(&sectionData)
- if err != nil {
- return fmt.Errorf("Error finalizing section: %w", err)
- }
- return nil
-}
-
-func (module *Module) executeTLS() {
- directory := module.headerDirectory(IMAGE_DIRECTORY_ENTRY_TLS)
- if directory.VirtualAddress == 0 {
- return
- }
-
- tls := (*IMAGE_TLS_DIRECTORY)(a2p(module.codeBase + uintptr(directory.VirtualAddress)))
- callback := tls.AddressOfCallbacks
- if callback != 0 {
- for {
- f := *(*uintptr)(a2p(callback))
- if f == 0 {
- break
- }
- syscall.Syscall(f, 3, module.codeBase, uintptr(DLL_PROCESS_ATTACH), uintptr(0))
- callback += unsafe.Sizeof(f)
- }
- }
-}
-
-func (module *Module) performBaseRelocation(delta uintptr) (relocated bool, err error) {
- directory := module.headerDirectory(IMAGE_DIRECTORY_ENTRY_BASERELOC)
- if directory.Size == 0 {
- return delta == 0, nil
- }
-
- relocationHdr := (*IMAGE_BASE_RELOCATION)(a2p(module.codeBase + uintptr(directory.VirtualAddress)))
- for relocationHdr.VirtualAddress > 0 {
- dest := module.codeBase + uintptr(relocationHdr.VirtualAddress)
-
- relInfos := unsafe.Slice(
- (*uint16)(a2p(uintptr(unsafe.Pointer(relocationHdr))+unsafe.Sizeof(*relocationHdr))),
- (uintptr(relocationHdr.SizeOfBlock)-unsafe.Sizeof(*relocationHdr))/unsafe.Sizeof(uint16(0)))
- for _, relInfo := range relInfos {
- // The upper 4 bits define the type of relocation.
- relType := relInfo >> 12
- // The lower 12 bits define the offset.
- relOffset := uintptr(relInfo & 0xfff)
-
- switch relType {
- case IMAGE_REL_BASED_ABSOLUTE:
- // Skip relocation.
-
- case IMAGE_REL_BASED_LOW:
- *(*uint16)(a2p(dest + relOffset)) += uint16(delta & 0xffff)
- break
-
- case IMAGE_REL_BASED_HIGH:
- *(*uint16)(a2p(dest + relOffset)) += uint16(uint32(delta) >> 16)
- break
-
- case IMAGE_REL_BASED_HIGHLOW:
- *(*uint32)(a2p(dest + relOffset)) += uint32(delta)
-
- case IMAGE_REL_BASED_DIR64:
- *(*uint64)(a2p(dest + relOffset)) += uint64(delta)
-
- case IMAGE_REL_BASED_THUMB_MOV32:
- inst := *(*uint32)(a2p(dest + relOffset))
- imm16 := ((inst << 1) & 0x0800) + ((inst << 12) & 0xf000) +
- ((inst >> 20) & 0x0700) + ((inst >> 16) & 0x00ff)
- if (inst & 0x8000fbf0) != 0x0000f240 {
- return false, fmt.Errorf("Wrong Thumb2 instruction %08x, expected MOVW", inst)
- }
- imm16 += uint32(delta) & 0xffff
- hiDelta := (uint32(delta&0xffff0000) >> 16) + ((imm16 & 0xffff0000) >> 16)
- *(*uint32)(a2p(dest + relOffset)) = (inst & 0x8f00fbf0) + ((imm16 >> 1) & 0x0400) +
- ((imm16 >> 12) & 0x000f) +
- ((imm16 << 20) & 0x70000000) +
- ((imm16 << 16) & 0xff0000)
- if hiDelta != 0 {
- inst = *(*uint32)(a2p(dest + relOffset + 4))
- imm16 = ((inst << 1) & 0x0800) + ((inst << 12) & 0xf000) +
- ((inst >> 20) & 0x0700) + ((inst >> 16) & 0x00ff)
- if (inst & 0x8000fbf0) != 0x0000f2c0 {
- return false, fmt.Errorf("Wrong Thumb2 instruction %08x, expected MOVT", inst)
- }
- imm16 += hiDelta
- if imm16 > 0xffff {
- return false, fmt.Errorf("Resulting immediate value won't fit: %08x", imm16)
- }
- *(*uint32)(a2p(dest + relOffset + 4)) = (inst & 0x8f00fbf0) +
- ((imm16 >> 1) & 0x0400) +
- ((imm16 >> 12) & 0x000f) +
- ((imm16 << 20) & 0x70000000) +
- ((imm16 << 16) & 0xff0000)
- }
-
- default:
- return false, fmt.Errorf("Unsupported relocation: %v", relType)
- }
- }
-
- // Advance to next relocation block.
- relocationHdr = (*IMAGE_BASE_RELOCATION)(a2p(uintptr(unsafe.Pointer(relocationHdr)) + uintptr(relocationHdr.SizeOfBlock)))
- }
- return true, nil
-}
-
-func (module *Module) buildImportTable() error {
- directory := module.headerDirectory(IMAGE_DIRECTORY_ENTRY_IMPORT)
- if directory.Size == 0 {
- return nil
- }
-
- module.modules = make([]windows.Handle, 0, 16)
- importDesc := (*IMAGE_IMPORT_DESCRIPTOR)(a2p(module.codeBase + uintptr(directory.VirtualAddress)))
- for importDesc.Name != 0 {
- handle, err := windows.LoadLibraryEx(windows.BytePtrToString((*byte)(a2p(module.codeBase+uintptr(importDesc.Name)))), 0, windows.LOAD_LIBRARY_SEARCH_SYSTEM32)
- if err != nil {
- return fmt.Errorf("Error loading module: %w", err)
- }
- var thunkRef, funcRef *uintptr
- if importDesc.OriginalFirstThunk() != 0 {
- thunkRef = (*uintptr)(a2p(module.codeBase + uintptr(importDesc.OriginalFirstThunk())))
- funcRef = (*uintptr)(a2p(module.codeBase + uintptr(importDesc.FirstThunk)))
- } else {
- // No hint table.
- thunkRef = (*uintptr)(a2p(module.codeBase + uintptr(importDesc.FirstThunk)))
- funcRef = (*uintptr)(a2p(module.codeBase + uintptr(importDesc.FirstThunk)))
- }
- for *thunkRef != 0 {
- if IMAGE_SNAP_BY_ORDINAL(*thunkRef) {
- *funcRef, err = windows.GetProcAddressByOrdinal(handle, IMAGE_ORDINAL(*thunkRef))
- } else {
- thunkData := (*IMAGE_IMPORT_BY_NAME)(a2p(module.codeBase + *thunkRef))
- *funcRef, err = windows.GetProcAddress(handle, windows.BytePtrToString(&thunkData.Name[0]))
- }
- if err != nil {
- windows.FreeLibrary(handle)
- return fmt.Errorf("Error getting function address: %w", err)
- }
- thunkRef = (*uintptr)(a2p(uintptr(unsafe.Pointer(thunkRef)) + unsafe.Sizeof(*thunkRef)))
- funcRef = (*uintptr)(a2p(uintptr(unsafe.Pointer(funcRef)) + unsafe.Sizeof(*funcRef)))
- }
- module.modules = append(module.modules, handle)
- importDesc = (*IMAGE_IMPORT_DESCRIPTOR)(a2p(uintptr(unsafe.Pointer(importDesc)) + unsafe.Sizeof(*importDesc)))
- }
- return nil
-}
-
-func (module *Module) buildNameExports() error {
- directory := module.headerDirectory(IMAGE_DIRECTORY_ENTRY_EXPORT)
- if directory.Size == 0 {
- return errors.New("No export table found")
- }
- exports := (*IMAGE_EXPORT_DIRECTORY)(a2p(module.codeBase + uintptr(directory.VirtualAddress)))
- if exports.NumberOfNames == 0 || exports.NumberOfFunctions == 0 {
- return errors.New("No functions exported")
- }
- if exports.NumberOfNames == 0 {
- return errors.New("No functions exported by name")
- }
- nameRefs := unsafe.Slice((*uint32)(a2p(module.codeBase+uintptr(exports.AddressOfNames))), exports.NumberOfNames)
- ordinals := unsafe.Slice((*uint16)(a2p(module.codeBase+uintptr(exports.AddressOfNameOrdinals))), exports.NumberOfNames)
- module.nameExports = make(map[string]uint16)
- for i := range nameRefs {
- nameArray := windows.BytePtrToString((*byte)(a2p(module.codeBase + uintptr(nameRefs[i]))))
- module.nameExports[nameArray] = ordinals[i]
- }
- return nil
-}
-
-type addressRange struct {
- start uintptr
- end uintptr
-}
-
-var loadedAddressRanges []addressRange
-var loadedAddressRangesMu sync.RWMutex
-var haveHookedRtlPcToFileHeader sync.Once
-var hookRtlPcToFileHeaderResult error
-
-func hookRtlPcToFileHeader() error {
- var kernelBase windows.Handle
- err := windows.GetModuleHandleEx(windows.GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, windows.StringToUTF16Ptr("kernelbase.dll"), &kernelBase)
- if err != nil {
- return err
- }
- imageBase := unsafe.Pointer(kernelBase)
- dosHeader := (*IMAGE_DOS_HEADER)(imageBase)
- ntHeaders := (*IMAGE_NT_HEADERS)(unsafe.Add(imageBase, dosHeader.E_lfanew))
- importsDirectory := ntHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
- importDescriptor := (*IMAGE_IMPORT_DESCRIPTOR)(unsafe.Add(imageBase, importsDirectory.VirtualAddress))
- for ; importDescriptor.Name != 0; importDescriptor = (*IMAGE_IMPORT_DESCRIPTOR)(unsafe.Add(unsafe.Pointer(importDescriptor), unsafe.Sizeof(*importDescriptor))) {
- libraryName := windows.BytePtrToString((*byte)(unsafe.Add(imageBase, importDescriptor.Name)))
- if strings.EqualFold(libraryName, "ntdll.dll") {
- break
- }
- }
- if importDescriptor.Name == 0 {
- return errors.New("ntdll.dll not found")
- }
- originalThunk := (*uintptr)(unsafe.Add(imageBase, importDescriptor.OriginalFirstThunk()))
- thunk := (*uintptr)(unsafe.Add(imageBase, importDescriptor.FirstThunk))
- for ; *originalThunk != 0; originalThunk = (*uintptr)(unsafe.Add(unsafe.Pointer(originalThunk), unsafe.Sizeof(*originalThunk))) {
- if *originalThunk&IMAGE_ORDINAL_FLAG == 0 {
- function := (*IMAGE_IMPORT_BY_NAME)(unsafe.Add(imageBase, *originalThunk))
- name := windows.BytePtrToString(&function.Name[0])
- if name == "RtlPcToFileHeader" {
- break
- }
- }
- thunk = (*uintptr)(unsafe.Add(unsafe.Pointer(thunk), unsafe.Sizeof(*thunk)))
- }
- if *originalThunk == 0 {
- return errors.New("RtlPcToFileHeader not found")
- }
- var oldProtect uint32
- err = windows.VirtualProtect(uintptr(unsafe.Pointer(thunk)), unsafe.Sizeof(*thunk), windows.PAGE_READWRITE, &oldProtect)
- if err != nil {
- return err
- }
- originalRtlPcToFileHeader := *thunk
- *thunk = windows.NewCallback(func(pcValue uintptr, baseOfImage *uintptr) uintptr {
- loadedAddressRangesMu.RLock()
- for i := range loadedAddressRanges {
- if pcValue >= loadedAddressRanges[i].start && pcValue < loadedAddressRanges[i].end {
- pcValue = *thunk
- break
- }
- }
- loadedAddressRangesMu.RUnlock()
- ret, _, _ := syscall.Syscall(originalRtlPcToFileHeader, 2, pcValue, uintptr(unsafe.Pointer(baseOfImage)), 0)
- return ret
- })
- err = windows.VirtualProtect(uintptr(unsafe.Pointer(thunk)), unsafe.Sizeof(*thunk), oldProtect, &oldProtect)
- if err != nil {
- return err
- }
- return nil
-}
-
-// LoadLibrary loads module image to memory.
-func LoadLibrary(data []byte) (module *Module, err error) {
- addr := uintptr(unsafe.Pointer(&data[0]))
- size := uintptr(len(data))
- if size < unsafe.Sizeof(IMAGE_DOS_HEADER{}) {
- return nil, errors.New("Incomplete IMAGE_DOS_HEADER")
- }
- dosHeader := (*IMAGE_DOS_HEADER)(a2p(addr))
- if dosHeader.E_magic != IMAGE_DOS_SIGNATURE {
- return nil, fmt.Errorf("Not an MS-DOS binary (provided: %x, expected: %x)", dosHeader.E_magic, IMAGE_DOS_SIGNATURE)
- }
- if (size < uintptr(dosHeader.E_lfanew)+unsafe.Sizeof(IMAGE_NT_HEADERS{})) {
- return nil, errors.New("Incomplete IMAGE_NT_HEADERS")
- }
- oldHeader := (*IMAGE_NT_HEADERS)(a2p(addr + uintptr(dosHeader.E_lfanew)))
- if oldHeader.Signature != IMAGE_NT_SIGNATURE {
- return nil, fmt.Errorf("Not an NT binary (provided: %x, expected: %x)", oldHeader.Signature, IMAGE_NT_SIGNATURE)
- }
- if oldHeader.FileHeader.Machine != imageFileProcess {
- return nil, fmt.Errorf("Foreign platform (provided: %x, expected: %x)", oldHeader.FileHeader.Machine, imageFileProcess)
- }
- if (oldHeader.OptionalHeader.SectionAlignment & 1) != 0 {
- return nil, errors.New("Unaligned section")
- }
- lastSectionEnd := uintptr(0)
- sections := oldHeader.Sections()
- optionalSectionSize := oldHeader.OptionalHeader.SectionAlignment
- for i := range sections {
- var endOfSection uintptr
- if sections[i].SizeOfRawData == 0 {
- // Section without data in the DLL
- endOfSection = uintptr(sections[i].VirtualAddress) + uintptr(optionalSectionSize)
- } else {
- endOfSection = uintptr(sections[i].VirtualAddress) + uintptr(sections[i].SizeOfRawData)
- }
- if endOfSection > lastSectionEnd {
- lastSectionEnd = endOfSection
- }
- }
- alignedImageSize := alignUp(uintptr(oldHeader.OptionalHeader.SizeOfImage), uintptr(oldHeader.OptionalHeader.SectionAlignment))
- if alignedImageSize != alignUp(lastSectionEnd, uintptr(oldHeader.OptionalHeader.SectionAlignment)) {
- return nil, errors.New("Section is not page-aligned")
- }
-
- module = &Module{isDLL: (oldHeader.FileHeader.Characteristics & IMAGE_FILE_DLL) != 0}
- defer func() {
- if err != nil {
- module.Free()
- module = nil
- }
- }()
-
- // Reserve memory for image of library.
- // TODO: Is it correct to commit the complete memory region at once? Calling DllEntry raises an exception if we don't.
- module.codeBase, err = windows.VirtualAlloc(oldHeader.OptionalHeader.ImageBase,
- alignedImageSize,
- windows.MEM_RESERVE|windows.MEM_COMMIT,
- windows.PAGE_READWRITE)
- if err != nil {
- // Try to allocate memory at arbitrary position.
- module.codeBase, err = windows.VirtualAlloc(0,
- alignedImageSize,
- windows.MEM_RESERVE|windows.MEM_COMMIT,
- windows.PAGE_READWRITE)
- if err != nil {
- err = fmt.Errorf("Error allocating code: %w", err)
- return
- }
- }
- err = module.check4GBBoundaries(alignedImageSize)
- if err != nil {
- err = fmt.Errorf("Error reallocating code: %w", err)
- return
- }
-
- if size < uintptr(oldHeader.OptionalHeader.SizeOfHeaders) {
- err = errors.New("Incomplete headers")
- return
- }
- // Commit memory for headers.
- headers, err := windows.VirtualAlloc(module.codeBase,
- uintptr(oldHeader.OptionalHeader.SizeOfHeaders),
- windows.MEM_COMMIT,
- windows.PAGE_READWRITE)
- if err != nil {
- err = fmt.Errorf("Error allocating headers: %w", err)
- return
- }
- // Copy PE header to code.
- memcpy(headers, addr, uintptr(oldHeader.OptionalHeader.SizeOfHeaders))
- module.headers = (*IMAGE_NT_HEADERS)(a2p(headers + uintptr(dosHeader.E_lfanew)))
-
- // Update position.
- module.headers.OptionalHeader.ImageBase = module.codeBase
-
- // Copy sections from DLL file block to new memory location.
- err = module.copySections(addr, size, oldHeader)
- if err != nil {
- err = fmt.Errorf("Error copying sections: %w", err)
- return
- }
-
- // Adjust base address of imported data.
- locationDelta := module.headers.OptionalHeader.ImageBase - oldHeader.OptionalHeader.ImageBase
- if locationDelta != 0 {
- module.isRelocated, err = module.performBaseRelocation(locationDelta)
- if err != nil {
- err = fmt.Errorf("Error relocating module: %w", err)
- return
- }
- } else {
- module.isRelocated = true
- }
-
- // Load required dlls and adjust function table of imports.
- err = module.buildImportTable()
- if err != nil {
- err = fmt.Errorf("Error building import table: %w", err)
- return
- }
-
- // Mark memory pages depending on section headers and release sections that are marked as "discardable".
- err = module.finalizeSections()
- if err != nil {
- err = fmt.Errorf("Error finalizing sections: %w", err)
- return
- }
-
- // Register exception tables, if they exist.
- module.registerExceptionHandlers()
-
- // Register function PCs.
- loadedAddressRangesMu.Lock()
- loadedAddressRanges = append(loadedAddressRanges, addressRange{module.codeBase, module.codeBase + alignedImageSize})
- loadedAddressRangesMu.Unlock()
- haveHookedRtlPcToFileHeader.Do(func() {
- hookRtlPcToFileHeaderResult = hookRtlPcToFileHeader()
- })
- err = hookRtlPcToFileHeaderResult
- if err != nil {
- return
- }
-
- // TLS callbacks are executed BEFORE the main loading.
- module.executeTLS()
-
- // Get entry point of loaded module.
- if module.headers.OptionalHeader.AddressOfEntryPoint != 0 {
- module.entry = module.codeBase + uintptr(module.headers.OptionalHeader.AddressOfEntryPoint)
- if module.isDLL {
- // Notify library about attaching to process.
- r0, _, _ := syscall.Syscall(module.entry, 3, module.codeBase, uintptr(DLL_PROCESS_ATTACH), 0)
- successful := r0 != 0
- if !successful {
- err = windows.ERROR_DLL_INIT_FAILED
- return
- }
- module.initialized = true
- }
- }
-
- module.buildNameExports()
- return
-}
-
-// Free releases module resources and unloads it.
-func (module *Module) Free() {
- if module.initialized {
- // Notify library about detaching from process.
- syscall.Syscall(module.entry, 3, module.codeBase, uintptr(DLL_PROCESS_DETACH), 0)
- module.initialized = false
- }
- if module.modules != nil {
- // Free previously opened libraries.
- for _, handle := range module.modules {
- windows.FreeLibrary(handle)
- }
- module.modules = nil
- }
- if module.codeBase != 0 {
- windows.VirtualFree(module.codeBase, 0, windows.MEM_RELEASE)
- module.codeBase = 0
- }
- if module.blockedMemory != nil {
- module.blockedMemory.free()
- module.blockedMemory = nil
- }
-}
-
-// ProcAddressByName returns function address by exported name.
-func (module *Module) ProcAddressByName(name string) (uintptr, error) {
- directory := module.headerDirectory(IMAGE_DIRECTORY_ENTRY_EXPORT)
- if directory.Size == 0 {
- return 0, errors.New("No export table found")
- }
- exports := (*IMAGE_EXPORT_DIRECTORY)(a2p(module.codeBase + uintptr(directory.VirtualAddress)))
- if module.nameExports == nil {
- return 0, errors.New("No functions exported by name")
- }
- if idx, ok := module.nameExports[name]; ok {
- if uint32(idx) > exports.NumberOfFunctions {
- return 0, errors.New("Ordinal number too high")
- }
- // AddressOfFunctions contains the RVAs to the "real" functions.
- return module.codeBase + uintptr(*(*uint32)(a2p(module.codeBase + uintptr(exports.AddressOfFunctions) + uintptr(idx)*4))), nil
- }
- return 0, errors.New("Function not found by name")
-}
-
-// ProcAddressByOrdinal returns function address by exported ordinal.
-func (module *Module) ProcAddressByOrdinal(ordinal uint16) (uintptr, error) {
- directory := module.headerDirectory(IMAGE_DIRECTORY_ENTRY_EXPORT)
- if directory.Size == 0 {
- return 0, errors.New("No export table found")
- }
- exports := (*IMAGE_EXPORT_DIRECTORY)(a2p(module.codeBase + uintptr(directory.VirtualAddress)))
- if uint32(ordinal) < exports.Base {
- return 0, errors.New("Ordinal number too low")
- }
- idx := ordinal - uint16(exports.Base)
- if uint32(idx) > exports.NumberOfFunctions {
- return 0, errors.New("Ordinal number too high")
- }
- // AddressOfFunctions contains the RVAs to the "real" functions.
- return module.codeBase + uintptr(*(*uint32)(a2p(module.codeBase + uintptr(exports.AddressOfFunctions) + uintptr(idx)*4))), nil
-}
-
-func alignDown(value, alignment uintptr) uintptr {
- return value & ^(alignment - 1)
-}
-
-func alignUp(value, alignment uintptr) uintptr {
- return (value + alignment - 1) & ^(alignment - 1)
-}
-
-func a2p(addr uintptr) unsafe.Pointer {
- return unsafe.Pointer(addr)
-}
-
-func memcpy(dst, src, size uintptr) {
- copy(unsafe.Slice((*byte)(a2p(dst)), size), unsafe.Slice((*byte)(a2p(src)), size))
-}
diff --git a/tun/wintun/memmod/memmod_windows_32.go b/tun/wintun/memmod/memmod_windows_32.go
deleted file mode 100644
index 50e6feb..0000000
--- a/tun/wintun/memmod/memmod_windows_32.go
+++ /dev/null
@@ -1,16 +0,0 @@
-//go:build (windows && 386) || (windows && arm)
-
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2017-2021 WireGuard LLC. All Rights Reserved.
- */
-
-package memmod
-
-func (opthdr *IMAGE_OPTIONAL_HEADER) imageOffset() uintptr {
- return 0
-}
-
-func (module *Module) check4GBBoundaries(alignedImageSize uintptr) (err error) {
- return
-}
diff --git a/tun/wintun/memmod/memmod_windows_386.go b/tun/wintun/memmod/memmod_windows_386.go
deleted file mode 100644
index 475c5c5..0000000
--- a/tun/wintun/memmod/memmod_windows_386.go
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2017-2021 WireGuard LLC. All Rights Reserved.
- */
-
-package memmod
-
-const imageFileProcess = IMAGE_FILE_MACHINE_I386
diff --git a/tun/wintun/memmod/memmod_windows_64.go b/tun/wintun/memmod/memmod_windows_64.go
deleted file mode 100644
index a53851c..0000000
--- a/tun/wintun/memmod/memmod_windows_64.go
+++ /dev/null
@@ -1,36 +0,0 @@
-//go:build (windows && amd64) || (windows && arm64)
-
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2017-2021 WireGuard LLC. All Rights Reserved.
- */
-
-package memmod
-
-import (
- "fmt"
-
- "golang.org/x/sys/windows"
-)
-
-func (opthdr *IMAGE_OPTIONAL_HEADER) imageOffset() uintptr {
- return uintptr(opthdr.ImageBase & 0xffffffff00000000)
-}
-
-func (module *Module) check4GBBoundaries(alignedImageSize uintptr) (err error) {
- for (module.codeBase >> 32) < ((module.codeBase + alignedImageSize) >> 32) {
- node := &addressList{
- next: module.blockedMemory,
- address: module.codeBase,
- }
- module.blockedMemory = node
- module.codeBase, err = windows.VirtualAlloc(0,
- alignedImageSize,
- windows.MEM_RESERVE|windows.MEM_COMMIT,
- windows.PAGE_READWRITE)
- if err != nil {
- return fmt.Errorf("Error allocating memory block: %w", err)
- }
- }
- return
-}
diff --git a/tun/wintun/memmod/memmod_windows_amd64.go b/tun/wintun/memmod/memmod_windows_amd64.go
deleted file mode 100644
index a021a63..0000000
--- a/tun/wintun/memmod/memmod_windows_amd64.go
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2017-2021 WireGuard LLC. All Rights Reserved.
- */
-
-package memmod
-
-const imageFileProcess = IMAGE_FILE_MACHINE_AMD64
diff --git a/tun/wintun/memmod/memmod_windows_arm.go b/tun/wintun/memmod/memmod_windows_arm.go
deleted file mode 100644
index 4637a01..0000000
--- a/tun/wintun/memmod/memmod_windows_arm.go
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2017-2021 WireGuard LLC. All Rights Reserved.
- */
-
-package memmod
-
-const imageFileProcess = IMAGE_FILE_MACHINE_ARMNT
diff --git a/tun/wintun/memmod/memmod_windows_arm64.go b/tun/wintun/memmod/memmod_windows_arm64.go
deleted file mode 100644
index b8f1259..0000000
--- a/tun/wintun/memmod/memmod_windows_arm64.go
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2017-2021 WireGuard LLC. All Rights Reserved.
- */
-
-package memmod
-
-const imageFileProcess = IMAGE_FILE_MACHINE_ARM64
diff --git a/tun/wintun/memmod/syscall_windows.go b/tun/wintun/memmod/syscall_windows.go
deleted file mode 100644
index a111f92..0000000
--- a/tun/wintun/memmod/syscall_windows.go
+++ /dev/null
@@ -1,398 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2017-2021 WireGuard LLC. All Rights Reserved.
- */
-
-package memmod
-
-import "unsafe"
-
-const (
- IMAGE_DOS_SIGNATURE = 0x5A4D // MZ
- IMAGE_OS2_SIGNATURE = 0x454E // NE
- IMAGE_OS2_SIGNATURE_LE = 0x454C // LE
- IMAGE_VXD_SIGNATURE = 0x454C // LE
- IMAGE_NT_SIGNATURE = 0x00004550 // PE00
-)
-
-// DOS .EXE header
-type IMAGE_DOS_HEADER struct {
- E_magic uint16 // Magic number
- E_cblp uint16 // Bytes on last page of file
- E_cp uint16 // Pages in file
- E_crlc uint16 // Relocations
- E_cparhdr uint16 // Size of header in paragraphs
- E_minalloc uint16 // Minimum extra paragraphs needed
- E_maxalloc uint16 // Maximum extra paragraphs needed
- E_ss uint16 // Initial (relative) SS value
- E_sp uint16 // Initial SP value
- E_csum uint16 // Checksum
- E_ip uint16 // Initial IP value
- E_cs uint16 // Initial (relative) CS value
- E_lfarlc uint16 // File address of relocation table
- E_ovno uint16 // Overlay number
- E_res [4]uint16 // Reserved words
- E_oemid uint16 // OEM identifier (for e_oeminfo)
- E_oeminfo uint16 // OEM information; e_oemid specific
- E_res2 [10]uint16 // Reserved words
- E_lfanew int32 // File address of new exe header
-}
-
-// File header format
-type IMAGE_FILE_HEADER struct {
- Machine uint16
- NumberOfSections uint16
- TimeDateStamp uint32
- PointerToSymbolTable uint32
- NumberOfSymbols uint32
- SizeOfOptionalHeader uint16
- Characteristics uint16
-}
-
-const (
- IMAGE_SIZEOF_FILE_HEADER = 20
-
- IMAGE_FILE_RELOCS_STRIPPED = 0x0001 // Relocation info stripped from file.
- IMAGE_FILE_EXECUTABLE_IMAGE = 0x0002 // File is executable (i.e. no unresolved external references).
- IMAGE_FILE_LINE_NUMS_STRIPPED = 0x0004 // Line nunbers stripped from file.
- IMAGE_FILE_LOCAL_SYMS_STRIPPED = 0x0008 // Local symbols stripped from file.
- IMAGE_FILE_AGGRESIVE_WS_TRIM = 0x0010 // Aggressively trim working set
- IMAGE_FILE_LARGE_ADDRESS_AWARE = 0x0020 // App can handle >2gb addresses
- IMAGE_FILE_BYTES_REVERSED_LO = 0x0080 // Bytes of machine word are reversed.
- IMAGE_FILE_32BIT_MACHINE = 0x0100 // 32 bit word machine.
- IMAGE_FILE_DEBUG_STRIPPED = 0x0200 // Debugging info stripped from file in .DBG file
- IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP = 0x0400 // If Image is on removable media, copy and run from the swap file.
- IMAGE_FILE_NET_RUN_FROM_SWAP = 0x0800 // If Image is on Net, copy and run from the swap file.
- IMAGE_FILE_SYSTEM = 0x1000 // System File.
- IMAGE_FILE_DLL = 0x2000 // File is a DLL.
- IMAGE_FILE_UP_SYSTEM_ONLY = 0x4000 // File should only be run on a UP machine
- IMAGE_FILE_BYTES_REVERSED_HI = 0x8000 // Bytes of machine word are reversed.
-
- IMAGE_FILE_MACHINE_UNKNOWN = 0
- IMAGE_FILE_MACHINE_TARGET_HOST = 0x0001 // Useful for indicating we want to interact with the host and not a WoW guest.
- IMAGE_FILE_MACHINE_I386 = 0x014c // Intel 386.
- IMAGE_FILE_MACHINE_R3000 = 0x0162 // MIPS little-endian, 0x160 big-endian
- IMAGE_FILE_MACHINE_R4000 = 0x0166 // MIPS little-endian
- IMAGE_FILE_MACHINE_R10000 = 0x0168 // MIPS little-endian
- IMAGE_FILE_MACHINE_WCEMIPSV2 = 0x0169 // MIPS little-endian WCE v2
- IMAGE_FILE_MACHINE_ALPHA = 0x0184 // Alpha_AXP
- IMAGE_FILE_MACHINE_SH3 = 0x01a2 // SH3 little-endian
- IMAGE_FILE_MACHINE_SH3DSP = 0x01a3
- IMAGE_FILE_MACHINE_SH3E = 0x01a4 // SH3E little-endian
- IMAGE_FILE_MACHINE_SH4 = 0x01a6 // SH4 little-endian
- IMAGE_FILE_MACHINE_SH5 = 0x01a8 // SH5
- IMAGE_FILE_MACHINE_ARM = 0x01c0 // ARM Little-Endian
- IMAGE_FILE_MACHINE_THUMB = 0x01c2 // ARM Thumb/Thumb-2 Little-Endian
- IMAGE_FILE_MACHINE_ARMNT = 0x01c4 // ARM Thumb-2 Little-Endian
- IMAGE_FILE_MACHINE_AM33 = 0x01d3
- IMAGE_FILE_MACHINE_POWERPC = 0x01F0 // IBM PowerPC Little-Endian
- IMAGE_FILE_MACHINE_POWERPCFP = 0x01f1
- IMAGE_FILE_MACHINE_IA64 = 0x0200 // Intel 64
- IMAGE_FILE_MACHINE_MIPS16 = 0x0266 // MIPS
- IMAGE_FILE_MACHINE_ALPHA64 = 0x0284 // ALPHA64
- IMAGE_FILE_MACHINE_MIPSFPU = 0x0366 // MIPS
- IMAGE_FILE_MACHINE_MIPSFPU16 = 0x0466 // MIPS
- IMAGE_FILE_MACHINE_AXP64 = IMAGE_FILE_MACHINE_ALPHA64
- IMAGE_FILE_MACHINE_TRICORE = 0x0520 // Infineon
- IMAGE_FILE_MACHINE_CEF = 0x0CEF
- IMAGE_FILE_MACHINE_EBC = 0x0EBC // EFI Byte Code
- IMAGE_FILE_MACHINE_AMD64 = 0x8664 // AMD64 (K8)
- IMAGE_FILE_MACHINE_M32R = 0x9041 // M32R little-endian
- IMAGE_FILE_MACHINE_ARM64 = 0xAA64 // ARM64 Little-Endian
- IMAGE_FILE_MACHINE_CEE = 0xC0EE
-)
-
-// Directory format
-type IMAGE_DATA_DIRECTORY struct {
- VirtualAddress uint32
- Size uint32
-}
-
-const IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16
-
-type IMAGE_NT_HEADERS struct {
- Signature uint32
- FileHeader IMAGE_FILE_HEADER
- OptionalHeader IMAGE_OPTIONAL_HEADER
-}
-
-func (ntheader *IMAGE_NT_HEADERS) Sections() []IMAGE_SECTION_HEADER {
- return (*[0xffff]IMAGE_SECTION_HEADER)(unsafe.Pointer(
- (uintptr)(unsafe.Pointer(ntheader)) +
- unsafe.Offsetof(ntheader.OptionalHeader) +
- uintptr(ntheader.FileHeader.SizeOfOptionalHeader)))[:ntheader.FileHeader.NumberOfSections]
-}
-
-const (
- IMAGE_DIRECTORY_ENTRY_EXPORT = 0 // Export Directory
- IMAGE_DIRECTORY_ENTRY_IMPORT = 1 // Import Directory
- IMAGE_DIRECTORY_ENTRY_RESOURCE = 2 // Resource Directory
- IMAGE_DIRECTORY_ENTRY_EXCEPTION = 3 // Exception Directory
- IMAGE_DIRECTORY_ENTRY_SECURITY = 4 // Security Directory
- IMAGE_DIRECTORY_ENTRY_BASERELOC = 5 // Base Relocation Table
- IMAGE_DIRECTORY_ENTRY_DEBUG = 6 // Debug Directory
- IMAGE_DIRECTORY_ENTRY_COPYRIGHT = 7 // (X86 usage)
- IMAGE_DIRECTORY_ENTRY_ARCHITECTURE = 7 // Architecture Specific Data
- IMAGE_DIRECTORY_ENTRY_GLOBALPTR = 8 // RVA of GP
- IMAGE_DIRECTORY_ENTRY_TLS = 9 // TLS Directory
- IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG = 10 // Load Configuration Directory
- IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT = 11 // Bound Import Directory in headers
- IMAGE_DIRECTORY_ENTRY_IAT = 12 // Import Address Table
- IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT = 13 // Delay Load Import Descriptors
- IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR = 14 // COM Runtime descriptor
-)
-
-const IMAGE_SIZEOF_SHORT_NAME = 8
-
-// Section header format
-type IMAGE_SECTION_HEADER struct {
- Name [IMAGE_SIZEOF_SHORT_NAME]byte
- physicalAddressOrVirtualSize uint32
- VirtualAddress uint32
- SizeOfRawData uint32
- PointerToRawData uint32
- PointerToRelocations uint32
- PointerToLinenumbers uint32
- NumberOfRelocations uint16
- NumberOfLinenumbers uint16
- Characteristics uint32
-}
-
-func (ishdr *IMAGE_SECTION_HEADER) PhysicalAddress() uint32 {
- return ishdr.physicalAddressOrVirtualSize
-}
-
-func (ishdr *IMAGE_SECTION_HEADER) SetPhysicalAddress(addr uint32) {
- ishdr.physicalAddressOrVirtualSize = addr
-}
-
-func (ishdr *IMAGE_SECTION_HEADER) VirtualSize() uint32 {
- return ishdr.physicalAddressOrVirtualSize
-}
-
-func (ishdr *IMAGE_SECTION_HEADER) SetVirtualSize(addr uint32) {
- ishdr.physicalAddressOrVirtualSize = addr
-}
-
-const (
- // Dll characteristics.
- IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA = 0x0020
- IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE = 0x0040
- IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY = 0x0080
- IMAGE_DLL_CHARACTERISTICS_NX_COMPAT = 0x0100
- IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION = 0x0200
- IMAGE_DLL_CHARACTERISTICS_NO_SEH = 0x0400
- IMAGE_DLL_CHARACTERISTICS_NO_BIND = 0x0800
- IMAGE_DLL_CHARACTERISTICS_APPCONTAINER = 0x1000
- IMAGE_DLL_CHARACTERISTICS_WDM_DRIVER = 0x2000
- IMAGE_DLL_CHARACTERISTICS_GUARD_CF = 0x4000
- IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE = 0x8000
-)
-
-const (
- // Section characteristics.
- IMAGE_SCN_TYPE_REG = 0x00000000 // Reserved.
- IMAGE_SCN_TYPE_DSECT = 0x00000001 // Reserved.
- IMAGE_SCN_TYPE_NOLOAD = 0x00000002 // Reserved.
- IMAGE_SCN_TYPE_GROUP = 0x00000004 // Reserved.
- IMAGE_SCN_TYPE_NO_PAD = 0x00000008 // Reserved.
- IMAGE_SCN_TYPE_COPY = 0x00000010 // Reserved.
-
- IMAGE_SCN_CNT_CODE = 0x00000020 // Section contains code.
- IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040 // Section contains initialized data.
- IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080 // Section contains uninitialized data.
-
- IMAGE_SCN_LNK_OTHER = 0x00000100 // Reserved.
- IMAGE_SCN_LNK_INFO = 0x00000200 // Section contains comments or some other type of information.
- IMAGE_SCN_TYPE_OVER = 0x00000400 // Reserved.
- IMAGE_SCN_LNK_REMOVE = 0x00000800 // Section contents will not become part of image.
- IMAGE_SCN_LNK_COMDAT = 0x00001000 // Section contents comdat.
- IMAGE_SCN_MEM_PROTECTED = 0x00004000 // Obsolete.
- IMAGE_SCN_NO_DEFER_SPEC_EXC = 0x00004000 // Reset speculative exceptions handling bits in the TLB entries for this section.
- IMAGE_SCN_GPREL = 0x00008000 // Section content can be accessed relative to GP
- IMAGE_SCN_MEM_FARDATA = 0x00008000
- IMAGE_SCN_MEM_SYSHEAP = 0x00010000 // Obsolete.
- IMAGE_SCN_MEM_PURGEABLE = 0x00020000
- IMAGE_SCN_MEM_16BIT = 0x00020000
- IMAGE_SCN_MEM_LOCKED = 0x00040000
- IMAGE_SCN_MEM_PRELOAD = 0x00080000
-
- IMAGE_SCN_ALIGN_1BYTES = 0x00100000 //
- IMAGE_SCN_ALIGN_2BYTES = 0x00200000 //
- IMAGE_SCN_ALIGN_4BYTES = 0x00300000 //
- IMAGE_SCN_ALIGN_8BYTES = 0x00400000 //
- IMAGE_SCN_ALIGN_16BYTES = 0x00500000 // Default alignment if no others are specified.
- IMAGE_SCN_ALIGN_32BYTES = 0x00600000 //
- IMAGE_SCN_ALIGN_64BYTES = 0x00700000 //
- IMAGE_SCN_ALIGN_128BYTES = 0x00800000 //
- IMAGE_SCN_ALIGN_256BYTES = 0x00900000 //
- IMAGE_SCN_ALIGN_512BYTES = 0x00A00000 //
- IMAGE_SCN_ALIGN_1024BYTES = 0x00B00000 //
- IMAGE_SCN_ALIGN_2048BYTES = 0x00C00000 //
- IMAGE_SCN_ALIGN_4096BYTES = 0x00D00000 //
- IMAGE_SCN_ALIGN_8192BYTES = 0x00E00000 //
- IMAGE_SCN_ALIGN_MASK = 0x00F00000
-
- IMAGE_SCN_LNK_NRELOC_OVFL = 0x01000000 // Section contains extended relocations.
- IMAGE_SCN_MEM_DISCARDABLE = 0x02000000 // Section can be discarded.
- IMAGE_SCN_MEM_NOT_CACHED = 0x04000000 // Section is not cachable.
- IMAGE_SCN_MEM_NOT_PAGED = 0x08000000 // Section is not pageable.
- IMAGE_SCN_MEM_SHARED = 0x10000000 // Section is shareable.
- IMAGE_SCN_MEM_EXECUTE = 0x20000000 // Section is executable.
- IMAGE_SCN_MEM_READ = 0x40000000 // Section is readable.
- IMAGE_SCN_MEM_WRITE = 0x80000000 // Section is writeable.
-
- // TLS Characteristic Flags
- IMAGE_SCN_SCALE_INDEX = 0x00000001 // Tls index is scaled.
-)
-
-// Based relocation format
-type IMAGE_BASE_RELOCATION struct {
- VirtualAddress uint32
- SizeOfBlock uint32
-}
-
-const (
- IMAGE_REL_BASED_ABSOLUTE = 0
- IMAGE_REL_BASED_HIGH = 1
- IMAGE_REL_BASED_LOW = 2
- IMAGE_REL_BASED_HIGHLOW = 3
- IMAGE_REL_BASED_HIGHADJ = 4
- IMAGE_REL_BASED_MACHINE_SPECIFIC_5 = 5
- IMAGE_REL_BASED_RESERVED = 6
- IMAGE_REL_BASED_MACHINE_SPECIFIC_7 = 7
- IMAGE_REL_BASED_MACHINE_SPECIFIC_8 = 8
- IMAGE_REL_BASED_MACHINE_SPECIFIC_9 = 9
- IMAGE_REL_BASED_DIR64 = 10
-
- IMAGE_REL_BASED_IA64_IMM64 = 9
-
- IMAGE_REL_BASED_MIPS_JMPADDR = 5
- IMAGE_REL_BASED_MIPS_JMPADDR16 = 9
-
- IMAGE_REL_BASED_ARM_MOV32 = 5
- IMAGE_REL_BASED_THUMB_MOV32 = 7
-)
-
-// Export Format
-type IMAGE_EXPORT_DIRECTORY struct {
- Characteristics uint32
- TimeDateStamp uint32
- MajorVersion uint16
- MinorVersion uint16
- Name uint32
- Base uint32
- NumberOfFunctions uint32
- NumberOfNames uint32
- AddressOfFunctions uint32 // RVA from base of image
- AddressOfNames uint32 // RVA from base of image
- AddressOfNameOrdinals uint32 // RVA from base of image
-}
-
-type IMAGE_IMPORT_BY_NAME struct {
- Hint uint16
- Name [1]byte
-}
-
-func IMAGE_ORDINAL(ordinal uintptr) uintptr {
- return ordinal & 0xffff
-}
-
-func IMAGE_SNAP_BY_ORDINAL(ordinal uintptr) bool {
- return (ordinal & IMAGE_ORDINAL_FLAG) != 0
-}
-
-// Thread Local Storage
-type IMAGE_TLS_DIRECTORY struct {
- StartAddressOfRawData uintptr
- EndAddressOfRawData uintptr
- AddressOfIndex uintptr // PDWORD
- AddressOfCallbacks uintptr // PIMAGE_TLS_CALLBACK *;
- SizeOfZeroFill uint32
- Characteristics uint32
-}
-
-type IMAGE_IMPORT_DESCRIPTOR struct {
- characteristicsOrOriginalFirstThunk uint32 // 0 for terminating null import descriptor
- // RVA to original unbound IAT (PIMAGE_THUNK_DATA)
- TimeDateStamp uint32 // 0 if not bound,
- // -1 if bound, and real date\time stamp
- // in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND)
- // O.W. date/time stamp of DLL bound to (Old BIND)
- ForwarderChain uint32 // -1 if no forwarders
- Name uint32
- FirstThunk uint32 // RVA to IAT (if bound this IAT has actual addresses)
-}
-
-func (imgimpdesc *IMAGE_IMPORT_DESCRIPTOR) Characteristics() uint32 {
- return imgimpdesc.characteristicsOrOriginalFirstThunk
-}
-
-func (imgimpdesc *IMAGE_IMPORT_DESCRIPTOR) OriginalFirstThunk() uint32 {
- return imgimpdesc.characteristicsOrOriginalFirstThunk
-}
-
-type IMAGE_DELAYLOAD_DESCRIPTOR struct {
- Attributes uint32
- DllNameRVA uint32
- ModuleHandleRVA uint32
- ImportAddressTableRVA uint32
- ImportNameTableRVA uint32
- BoundImportAddressTableRVA uint32
- UnloadInformationTableRVA uint32
- TimeDateStamp uint32
-}
-
-type IMAGE_LOAD_CONFIG_CODE_INTEGRITY struct {
- Flags uint16
- Catalog uint16
- CatalogOffset uint32
- Reserved uint32
-}
-
-const (
- IMAGE_GUARD_CF_INSTRUMENTED = 0x00000100
- IMAGE_GUARD_CFW_INSTRUMENTED = 0x00000200
- IMAGE_GUARD_CF_FUNCTION_TABLE_PRESENT = 0x00000400
- IMAGE_GUARD_SECURITY_COOKIE_UNUSED = 0x00000800
- IMAGE_GUARD_PROTECT_DELAYLOAD_IAT = 0x00001000
- IMAGE_GUARD_DELAYLOAD_IAT_IN_ITS_OWN_SECTION = 0x00002000
- IMAGE_GUARD_CF_EXPORT_SUPPRESSION_INFO_PRESENT = 0x00004000
- IMAGE_GUARD_CF_ENABLE_EXPORT_SUPPRESSION = 0x00008000
- IMAGE_GUARD_CF_LONGJUMP_TABLE_PRESENT = 0x00010000
- IMAGE_GUARD_RF_INSTRUMENTED = 0x00020000
- IMAGE_GUARD_RF_ENABLE = 0x00040000
- IMAGE_GUARD_RF_STRICT = 0x00080000
- IMAGE_GUARD_RETPOLINE_PRESENT = 0x00100000
- IMAGE_GUARD_EH_CONTINUATION_TABLE_PRESENT = 0x00400000
- IMAGE_GUARD_XFG_ENABLED = 0x00800000
- IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_MASK = 0xF0000000
- IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_SHIFT = 28
-)
-
-type IMAGE_RUNTIME_FUNCTION_ENTRY struct {
- BeginAddress uint32
- EndAddress uint32
- UnwindInfoAddress uint32
-}
-
-const (
- DLL_PROCESS_ATTACH = 1
- DLL_THREAD_ATTACH = 2
- DLL_THREAD_DETACH = 3
- DLL_PROCESS_DETACH = 0
-)
-
-type SYSTEM_INFO struct {
- ProcessorArchitecture uint16
- Reserved uint16
- PageSize uint32
- MinimumApplicationAddress uintptr
- MaximumApplicationAddress uintptr
- ActiveProcessorMask uintptr
- NumberOfProcessors uint32
- ProcessorType uint32
- AllocationGranularity uint32
- ProcessorLevel uint16
- ProcessorRevision uint16
-}
diff --git a/tun/wintun/memmod/syscall_windows_32.go b/tun/wintun/memmod/syscall_windows_32.go
deleted file mode 100644
index f036ecb..0000000
--- a/tun/wintun/memmod/syscall_windows_32.go
+++ /dev/null
@@ -1,96 +0,0 @@
-//go:build (windows && 386) || (windows && arm)
-
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2017-2021 WireGuard LLC. All Rights Reserved.
- */
-
-package memmod
-
-// Optional header format
-type IMAGE_OPTIONAL_HEADER struct {
- Magic uint16
- MajorLinkerVersion uint8
- MinorLinkerVersion uint8
- SizeOfCode uint32
- SizeOfInitializedData uint32
- SizeOfUninitializedData uint32
- AddressOfEntryPoint uint32
- BaseOfCode uint32
- BaseOfData uint32
- ImageBase uintptr
- SectionAlignment uint32
- FileAlignment uint32
- MajorOperatingSystemVersion uint16
- MinorOperatingSystemVersion uint16
- MajorImageVersion uint16
- MinorImageVersion uint16
- MajorSubsystemVersion uint16
- MinorSubsystemVersion uint16
- Win32VersionValue uint32
- SizeOfImage uint32
- SizeOfHeaders uint32
- CheckSum uint32
- Subsystem uint16
- DllCharacteristics uint16
- SizeOfStackReserve uintptr
- SizeOfStackCommit uintptr
- SizeOfHeapReserve uintptr
- SizeOfHeapCommit uintptr
- LoaderFlags uint32
- NumberOfRvaAndSizes uint32
- DataDirectory [IMAGE_NUMBEROF_DIRECTORY_ENTRIES]IMAGE_DATA_DIRECTORY
-}
-
-const IMAGE_ORDINAL_FLAG uintptr = 0x80000000
-
-type IMAGE_LOAD_CONFIG_DIRECTORY struct {
- Size uint32
- TimeDateStamp uint32
- MajorVersion uint16
- MinorVersion uint16
- GlobalFlagsClear uint32
- GlobalFlagsSet uint32
- CriticalSectionDefaultTimeout uint32
- DeCommitFreeBlockThreshold uint32
- DeCommitTotalFreeThreshold uint32
- LockPrefixTable uint32
- MaximumAllocationSize uint32
- VirtualMemoryThreshold uint32
- ProcessHeapFlags uint32
- ProcessAffinityMask uint32
- CSDVersion uint16
- DependentLoadFlags uint16
- EditList uint32
- SecurityCookie uint32
- SEHandlerTable uint32
- SEHandlerCount uint32
- GuardCFCheckFunctionPointer uint32
- GuardCFDispatchFunctionPointer uint32
- GuardCFFunctionTable uint32
- GuardCFFunctionCount uint32
- GuardFlags uint32
- CodeIntegrity IMAGE_LOAD_CONFIG_CODE_INTEGRITY
- GuardAddressTakenIatEntryTable uint32
- GuardAddressTakenIatEntryCount uint32
- GuardLongJumpTargetTable uint32
- GuardLongJumpTargetCount uint32
- DynamicValueRelocTable uint32
- CHPEMetadataPointer uint32
- GuardRFFailureRoutine uint32
- GuardRFFailureRoutineFunctionPointer uint32
- DynamicValueRelocTableOffset uint32
- DynamicValueRelocTableSection uint16
- Reserved2 uint16
- GuardRFVerifyStackPointerFunctionPointer uint32
- HotPatchTableOffset uint32
- Reserved3 uint32
- EnclaveConfigurationPointer uint32
- VolatileMetadataPointer uint32
- GuardEHContinuationTable uint32
- GuardEHContinuationCount uint32
- GuardXFGCheckFunctionPointer uint32
- GuardXFGDispatchFunctionPointer uint32
- GuardXFGTableDispatchFunctionPointer uint32
- CastGuardOsDeterminedFailureMode uint32
-}
diff --git a/tun/wintun/memmod/syscall_windows_64.go b/tun/wintun/memmod/syscall_windows_64.go
deleted file mode 100644
index 6f2c039..0000000
--- a/tun/wintun/memmod/syscall_windows_64.go
+++ /dev/null
@@ -1,95 +0,0 @@
-//go:build (windows && amd64) || (windows && arm64)
-
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2017-2021 WireGuard LLC. All Rights Reserved.
- */
-
-package memmod
-
-// Optional header format
-type IMAGE_OPTIONAL_HEADER struct {
- Magic uint16
- MajorLinkerVersion uint8
- MinorLinkerVersion uint8
- SizeOfCode uint32
- SizeOfInitializedData uint32
- SizeOfUninitializedData uint32
- AddressOfEntryPoint uint32
- BaseOfCode uint32
- ImageBase uintptr
- SectionAlignment uint32
- FileAlignment uint32
- MajorOperatingSystemVersion uint16
- MinorOperatingSystemVersion uint16
- MajorImageVersion uint16
- MinorImageVersion uint16
- MajorSubsystemVersion uint16
- MinorSubsystemVersion uint16
- Win32VersionValue uint32
- SizeOfImage uint32
- SizeOfHeaders uint32
- CheckSum uint32
- Subsystem uint16
- DllCharacteristics uint16
- SizeOfStackReserve uintptr
- SizeOfStackCommit uintptr
- SizeOfHeapReserve uintptr
- SizeOfHeapCommit uintptr
- LoaderFlags uint32
- NumberOfRvaAndSizes uint32
- DataDirectory [IMAGE_NUMBEROF_DIRECTORY_ENTRIES]IMAGE_DATA_DIRECTORY
-}
-
-const IMAGE_ORDINAL_FLAG uintptr = 0x8000000000000000
-
-type IMAGE_LOAD_CONFIG_DIRECTORY struct {
- Size uint32
- TimeDateStamp uint32
- MajorVersion uint16
- MinorVersion uint16
- GlobalFlagsClear uint32
- GlobalFlagsSet uint32
- CriticalSectionDefaultTimeout uint32
- DeCommitFreeBlockThreshold uint64
- DeCommitTotalFreeThreshold uint64
- LockPrefixTable uint64
- MaximumAllocationSize uint64
- VirtualMemoryThreshold uint64
- ProcessAffinityMask uint64
- ProcessHeapFlags uint32
- CSDVersion uint16
- DependentLoadFlags uint16
- EditList uint64
- SecurityCookie uint64
- SEHandlerTable uint64
- SEHandlerCount uint64
- GuardCFCheckFunctionPointer uint64
- GuardCFDispatchFunctionPointer uint64
- GuardCFFunctionTable uint64
- GuardCFFunctionCount uint64
- GuardFlags uint32
- CodeIntegrity IMAGE_LOAD_CONFIG_CODE_INTEGRITY
- GuardAddressTakenIatEntryTable uint64
- GuardAddressTakenIatEntryCount uint64
- GuardLongJumpTargetTable uint64
- GuardLongJumpTargetCount uint64
- DynamicValueRelocTable uint64
- CHPEMetadataPointer uint64
- GuardRFFailureRoutine uint64
- GuardRFFailureRoutineFunctionPointer uint64
- DynamicValueRelocTableOffset uint32
- DynamicValueRelocTableSection uint16
- Reserved2 uint16
- GuardRFVerifyStackPointerFunctionPointer uint64
- HotPatchTableOffset uint32
- Reserved3 uint32
- EnclaveConfigurationPointer uint64
- VolatileMetadataPointer uint64
- GuardEHContinuationTable uint64
- GuardEHContinuationCount uint64
- GuardXFGCheckFunctionPointer uint64
- GuardXFGDispatchFunctionPointer uint64
- GuardXFGTableDispatchFunctionPointer uint64
- CastGuardOsDeterminedFailureMode uint64
-}