diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2021-10-16 22:49:38 -0600 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2021-10-16 22:49:38 -0600 |
commit | ba9e364dab402cfc104eb00669f7fdfd9259559e (patch) | |
tree | 8da1081c32cdcf8a1592d6853b2dad4463cdd260 | |
parent | dfd688b6aa7b044f7e7e0662288c66ee1d56e0e8 (diff) |
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>
-rw-r--r-- | tun/wintun/dll_fromfile_windows.go | 54 | ||||
-rw-r--r-- | tun/wintun/dll_fromrsrc_windows.go | 61 | ||||
-rw-r--r-- | tun/wintun/dll_windows.go | 39 | ||||
-rw-r--r-- | tun/wintun/memmod/memmod_windows.go | 693 | ||||
-rw-r--r-- | tun/wintun/memmod/memmod_windows_32.go | 16 | ||||
-rw-r--r-- | tun/wintun/memmod/memmod_windows_386.go | 8 | ||||
-rw-r--r-- | tun/wintun/memmod/memmod_windows_64.go | 36 | ||||
-rw-r--r-- | tun/wintun/memmod/memmod_windows_amd64.go | 8 | ||||
-rw-r--r-- | tun/wintun/memmod/memmod_windows_arm.go | 8 | ||||
-rw-r--r-- | tun/wintun/memmod/memmod_windows_arm64.go | 8 | ||||
-rw-r--r-- | tun/wintun/memmod/syscall_windows.go | 398 | ||||
-rw-r--r-- | tun/wintun/memmod/syscall_windows_32.go | 96 | ||||
-rw-r--r-- | tun/wintun/memmod/syscall_windows_64.go | 95 |
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(§ions[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(§ions[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(§ionData) - 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(§ionData) - 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 -} |