wintun: load wintun.dll from RCDATA resource
Signed-off-by: Simon Rozman <simon@rozman.si> Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
		
							parent
							
								
									3e08b8aee0
								
							
						
					
					
						commit
						65e03a9182
					
				
							
								
								
									
										2
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.mod
									
									
									
									
									
								
							@ -5,6 +5,6 @@ go 1.13
 | 
				
			|||||||
require (
 | 
					require (
 | 
				
			||||||
	golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79
 | 
						golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79
 | 
				
			||||||
	golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5
 | 
						golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5
 | 
				
			||||||
	golang.org/x/sys v0.0.0-20201027130517-9d1ec526b7bf
 | 
						golang.org/x/sys v0.0.0-20201107080550-4d91cf3a1aaf
 | 
				
			||||||
	golang.org/x/text v0.3.2
 | 
						golang.org/x/text v0.3.2
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.sum
									
									
									
									
									
								
							@ -9,6 +9,8 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
 | 
				
			|||||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
					golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20201027130517-9d1ec526b7bf h1:HmHgHRpqpvB74D7bjXkue6kkHJfOrKyYJtW6Sv4jpI4=
 | 
					golang.org/x/sys v0.0.0-20201027130517-9d1ec526b7bf h1:HmHgHRpqpvB74D7bjXkue6kkHJfOrKyYJtW6Sv4jpI4=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20201027130517-9d1ec526b7bf/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
					golang.org/x/sys v0.0.0-20201027130517-9d1ec526b7bf/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
				
			||||||
 | 
					golang.org/x/sys v0.0.0-20201107080550-4d91cf3a1aaf h1:kt3wY1Lu5MJAnKTfoMR52Cu4gwvna4VTzNOiT8tY73s=
 | 
				
			||||||
 | 
					golang.org/x/sys v0.0.0-20201107080550-4d91cf3a1aaf/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
				
			||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 | 
					golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 | 
				
			||||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
 | 
					golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
 | 
				
			||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 | 
					golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										97
									
								
								tun/wintun/dll_windows.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								tun/wintun/dll_windows.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,97 @@
 | 
				
			|||||||
 | 
					/* SPDX-License-Identifier: MIT
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2020 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"
 | 
				
			||||||
 | 
						"golang.zx2c4.com/wireguard/tun/wintun/resource"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type lazyDLL struct {
 | 
				
			||||||
 | 
						Name   string
 | 
				
			||||||
 | 
						mu     sync.Mutex
 | 
				
			||||||
 | 
						module *memmod.Module
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func newLazyDLL(name string) *lazyDLL {
 | 
				
			||||||
 | 
						return &lazyDLL{Name: name}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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 := resource.FindByName(ourModule, d.Name, resource.RT_RCDATA)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("Unable to find \"%v\" RCDATA resource: %v", d.Name, err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						data, err := resource.Load(ourModule, resInfo)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("Unable to load resource: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						module, err := memmod.LoadLibrary(data)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("Unable to load library: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&d.module)), unsafe.Pointer(module))
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (d *lazyDLL) NewProc(name string) *lazyProc {
 | 
				
			||||||
 | 
						return &lazyProc{dll: d, Name: name}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type lazyProc struct {
 | 
				
			||||||
 | 
						Name string
 | 
				
			||||||
 | 
						mu   sync.Mutex
 | 
				
			||||||
 | 
						dll  *lazyDLL
 | 
				
			||||||
 | 
						addr uintptr
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *lazyProc) Find() error {
 | 
				
			||||||
 | 
						if atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&p.addr))) != nil {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						p.mu.Lock()
 | 
				
			||||||
 | 
						defer p.mu.Unlock()
 | 
				
			||||||
 | 
						if p.addr != 0 {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err := p.dll.Load()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("Error loading %v DLL: %v", p.dll.Name, err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						addr, err := p.dll.module.ProcAddressByName(p.Name)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("Error getting %v address: %v", p.Name, err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&p.addr)), unsafe.Pointer(addr))
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *lazyProc) Addr() uintptr {
 | 
				
			||||||
 | 
						err := p.Find()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							panic(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return p.addr
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										620
									
								
								tun/wintun/memmod/memmod_windows.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										620
									
								
								tun/wintun/memmod/memmod_windows.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,620 @@
 | 
				
			|||||||
 | 
					/* SPDX-License-Identifier: MIT
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2020 WireGuard LLC. All Rights Reserved.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package memmod
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"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, old_headers *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 := old_headers.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: %v", 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))
 | 
				
			||||||
 | 
								var dst []byte
 | 
				
			||||||
 | 
								unsafeSlice(unsafe.Pointer(&dst), a2p(dest), int(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: %v", 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: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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])
 | 
				
			||||||
 | 
						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])
 | 
				
			||||||
 | 
							// 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: %v", 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: %v", 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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							var relInfos []uint16
 | 
				
			||||||
 | 
							unsafeSlice(
 | 
				
			||||||
 | 
								unsafe.Pointer(&relInfos),
 | 
				
			||||||
 | 
								a2p(uintptr(unsafe.Pointer(relocationHdr))+unsafe.Sizeof(*relocationHdr)),
 | 
				
			||||||
 | 
								int((uintptr(relocationHdr.SizeOfBlock)-unsafe.Sizeof(*relocationHdr))/unsafe.Sizeof(relInfos[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 !isBadReadPtr(uintptr(unsafe.Pointer(importDesc)), unsafe.Sizeof(*importDesc)) && importDesc.Name != 0 {
 | 
				
			||||||
 | 
							handle, err := loadLibraryA((*byte)(a2p(module.codeBase + uintptr(importDesc.Name))))
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return fmt.Errorf("Error loading module: %v", 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 = getProcAddress(handle, (*byte)(a2p(IMAGE_ORDINAL(*thunkRef))))
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									thunkData := (*IMAGE_IMPORT_BY_NAME)(a2p(module.codeBase + *thunkRef))
 | 
				
			||||||
 | 
									*funcRef, err = getProcAddress(handle, &thunkData.Name[0])
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									windows.FreeLibrary(handle)
 | 
				
			||||||
 | 
									return fmt.Errorf("Error getting function address: %v", 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")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var nameRefs []uint32
 | 
				
			||||||
 | 
						unsafeSlice(unsafe.Pointer(&nameRefs), a2p(module.codeBase+uintptr(exports.AddressOfNames)), int(exports.NumberOfNames))
 | 
				
			||||||
 | 
						var ordinals []uint16
 | 
				
			||||||
 | 
						unsafeSlice(unsafe.Pointer(&ordinals), a2p(module.codeBase+uintptr(exports.AddressOfNameOrdinals)), int(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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 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: %v", err)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						err = module.check4GBBoundaries(alignedImageSize)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							err = fmt.Errorf("Error reallocating code: %v", 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: %v", 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: %v", 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: %v", 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: %v", 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: %v", err)
 | 
				
			||||||
 | 
							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) {
 | 
				
			||||||
 | 
						var d, s []byte
 | 
				
			||||||
 | 
						unsafeSlice(unsafe.Pointer(&d), a2p(dst), int(size))
 | 
				
			||||||
 | 
						unsafeSlice(unsafe.Pointer(&s), a2p(src), int(size))
 | 
				
			||||||
 | 
						copy(d, s)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// unsafeSlice updates the slice slicePtr to be a slice
 | 
				
			||||||
 | 
					// referencing the provided data with its length & capacity set to
 | 
				
			||||||
 | 
					// lenCap.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// TODO: when Go 1.16 or Go 1.17 is the minimum supported version,
 | 
				
			||||||
 | 
					// update callers to use unsafe.Slice instead of this.
 | 
				
			||||||
 | 
					func unsafeSlice(slicePtr, data unsafe.Pointer, lenCap int) {
 | 
				
			||||||
 | 
						type sliceHeader struct {
 | 
				
			||||||
 | 
							Data unsafe.Pointer
 | 
				
			||||||
 | 
							Len  int
 | 
				
			||||||
 | 
							Cap  int
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						h := (*sliceHeader)(slicePtr)
 | 
				
			||||||
 | 
						h.Data = data
 | 
				
			||||||
 | 
						h.Len = lenCap
 | 
				
			||||||
 | 
						h.Cap = lenCap
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										16
									
								
								tun/wintun/memmod/memmod_windows_32.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								tun/wintun/memmod/memmod_windows_32.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					// +build 386 arm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* SPDX-License-Identifier: MIT
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2020 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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										8
									
								
								tun/wintun/memmod/memmod_windows_386.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								tun/wintun/memmod/memmod_windows_386.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					/* SPDX-License-Identifier: MIT
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2020 WireGuard LLC. All Rights Reserved.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package memmod
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const imageFileProcess = IMAGE_FILE_MACHINE_I386
 | 
				
			||||||
							
								
								
									
										36
									
								
								tun/wintun/memmod/memmod_windows_64.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								tun/wintun/memmod/memmod_windows_64.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					// +build amd64 arm64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* SPDX-License-Identifier: MIT
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2020 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: %v", err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										8
									
								
								tun/wintun/memmod/memmod_windows_amd64.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								tun/wintun/memmod/memmod_windows_amd64.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					/* SPDX-License-Identifier: MIT
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2020 WireGuard LLC. All Rights Reserved.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package memmod
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const imageFileProcess = IMAGE_FILE_MACHINE_AMD64
 | 
				
			||||||
							
								
								
									
										8
									
								
								tun/wintun/memmod/memmod_windows_arm.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								tun/wintun/memmod/memmod_windows_arm.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					/* SPDX-License-Identifier: MIT
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2020 WireGuard LLC. All Rights Reserved.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package memmod
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const imageFileProcess = IMAGE_FILE_MACHINE_ARMNT
 | 
				
			||||||
							
								
								
									
										8
									
								
								tun/wintun/memmod/memmod_windows_arm64.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								tun/wintun/memmod/memmod_windows_arm64.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					/* SPDX-License-Identifier: MIT
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2020 WireGuard LLC. All Rights Reserved.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package memmod
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const imageFileProcess = IMAGE_FILE_MACHINE_ARM64
 | 
				
			||||||
							
								
								
									
										8
									
								
								tun/wintun/memmod/mksyscall.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								tun/wintun/memmod/mksyscall.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					/* SPDX-License-Identifier: MIT
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2020 WireGuard LLC. All Rights Reserved.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package memmod
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go syscall_windows.go
 | 
				
			||||||
							
								
								
									
										343
									
								
								tun/wintun/memmod/syscall_windows.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										343
									
								
								tun/wintun/memmod/syscall_windows.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,343 @@
 | 
				
			|||||||
 | 
					/* SPDX-License-Identifier: MIT
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2020 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 (
 | 
				
			||||||
 | 
						// 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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						DLL_PROCESS_ATTACH = 1
 | 
				
			||||||
 | 
						DLL_THREAD_ATTACH  = 2
 | 
				
			||||||
 | 
						DLL_THREAD_DETACH  = 3
 | 
				
			||||||
 | 
						DLL_PROCESS_DETACH = 0
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//sys	loadLibraryA(libFileName *byte) (module windows.Handle, err error) = kernel32.LoadLibraryA
 | 
				
			||||||
 | 
					//sys	getProcAddress(module windows.Handle, procName *byte) (addr uintptr, err error) = kernel32.GetProcAddress
 | 
				
			||||||
 | 
					//sys	isBadReadPtr(addr uintptr, ucb uintptr) (ret bool) = kernel32.IsBadReadPtr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										45
									
								
								tun/wintun/memmod/syscall_windows_32.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								tun/wintun/memmod/syscall_windows_32.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,45 @@
 | 
				
			|||||||
 | 
					// +build 386 arm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* SPDX-License-Identifier: MIT
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2020 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
 | 
				
			||||||
							
								
								
									
										44
									
								
								tun/wintun/memmod/syscall_windows_64.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								tun/wintun/memmod/syscall_windows_64.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,44 @@
 | 
				
			|||||||
 | 
					// +build amd64 arm64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* SPDX-License-Identifier: MIT
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2020 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
 | 
				
			||||||
							
								
								
									
										70
									
								
								tun/wintun/memmod/zsyscall_windows.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								tun/wintun/memmod/zsyscall_windows.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,70 @@
 | 
				
			|||||||
 | 
					// Code generated by 'go generate'; DO NOT EDIT.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package memmod
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"syscall"
 | 
				
			||||||
 | 
						"unsafe"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"golang.org/x/sys/windows"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var _ unsafe.Pointer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Do the interface allocations only once for common
 | 
				
			||||||
 | 
					// Errno values.
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						errnoERROR_IO_PENDING = 997
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
 | 
				
			||||||
 | 
						errERROR_EINVAL     error = syscall.EINVAL
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// errnoErr returns common boxed Errno values, to prevent
 | 
				
			||||||
 | 
					// allocations at runtime.
 | 
				
			||||||
 | 
					func errnoErr(e syscall.Errno) error {
 | 
				
			||||||
 | 
						switch e {
 | 
				
			||||||
 | 
						case 0:
 | 
				
			||||||
 | 
							return errERROR_EINVAL
 | 
				
			||||||
 | 
						case errnoERROR_IO_PENDING:
 | 
				
			||||||
 | 
							return errERROR_IO_PENDING
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// TODO: add more here, after collecting data on the common
 | 
				
			||||||
 | 
						// error values see on Windows. (perhaps when running
 | 
				
			||||||
 | 
						// all.bat?)
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						procGetProcAddress = modkernel32.NewProc("GetProcAddress")
 | 
				
			||||||
 | 
						procIsBadReadPtr   = modkernel32.NewProc("IsBadReadPtr")
 | 
				
			||||||
 | 
						procLoadLibraryA   = modkernel32.NewProc("LoadLibraryA")
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getProcAddress(module windows.Handle, procName *byte) (addr uintptr, err error) {
 | 
				
			||||||
 | 
						r0, _, e1 := syscall.Syscall(procGetProcAddress.Addr(), 2, uintptr(module), uintptr(unsafe.Pointer(procName)), 0)
 | 
				
			||||||
 | 
						addr = uintptr(r0)
 | 
				
			||||||
 | 
						if addr == 0 {
 | 
				
			||||||
 | 
							err = errnoErr(e1)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func isBadReadPtr(addr uintptr, ucb uintptr) (ret bool) {
 | 
				
			||||||
 | 
						r0, _, _ := syscall.Syscall(procIsBadReadPtr.Addr(), 2, uintptr(addr), uintptr(ucb), 0)
 | 
				
			||||||
 | 
						ret = r0 != 0
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func loadLibraryA(libFileName *byte) (module windows.Handle, err error) {
 | 
				
			||||||
 | 
						r0, _, e1 := syscall.Syscall(procLoadLibraryA.Addr(), 1, uintptr(unsafe.Pointer(libFileName)), 0, 0)
 | 
				
			||||||
 | 
						module = windows.Handle(r0)
 | 
				
			||||||
 | 
						if module == 0 {
 | 
				
			||||||
 | 
							err = errnoErr(e1)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										8
									
								
								tun/wintun/resource/mksyscall.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								tun/wintun/resource/mksyscall.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					/* SPDX-License-Identifier: MIT
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2020 WireGuard LLC. All Rights Reserved.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package resource
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go resource_windows.go
 | 
				
			||||||
							
								
								
									
										143
									
								
								tun/wintun/resource/resource_windows.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								tun/wintun/resource/resource_windows.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,143 @@
 | 
				
			|||||||
 | 
					/* SPDX-License-Identifier: MIT
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2020 WireGuard LLC. All Rights Reserved.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package resource
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"unsafe"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"golang.org/x/sys/windows"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func MAKEINTRESOURCE(i uint16) *uint16 {
 | 
				
			||||||
 | 
						return (*uint16)(unsafe.Pointer(uintptr(i)))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Predefined Resource Types
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						VS_VERSION_INFO uint16 = 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						RT_CURSOR                                          = MAKEINTRESOURCE(1)
 | 
				
			||||||
 | 
						RT_BITMAP                                          = MAKEINTRESOURCE(2)
 | 
				
			||||||
 | 
						RT_ICON                                            = MAKEINTRESOURCE(3)
 | 
				
			||||||
 | 
						RT_MENU                                            = MAKEINTRESOURCE(4)
 | 
				
			||||||
 | 
						RT_DIALOG                                          = MAKEINTRESOURCE(5)
 | 
				
			||||||
 | 
						RT_STRING                                          = MAKEINTRESOURCE(6)
 | 
				
			||||||
 | 
						RT_FONTDIR                                         = MAKEINTRESOURCE(7)
 | 
				
			||||||
 | 
						RT_FONT                                            = MAKEINTRESOURCE(8)
 | 
				
			||||||
 | 
						RT_ACCELERATOR                                     = MAKEINTRESOURCE(9)
 | 
				
			||||||
 | 
						RT_RCDATA                                          = MAKEINTRESOURCE(10)
 | 
				
			||||||
 | 
						RT_MESSAGETABLE                                    = MAKEINTRESOURCE(11)
 | 
				
			||||||
 | 
						RT_GROUP_CURSOR                                    = MAKEINTRESOURCE(12)
 | 
				
			||||||
 | 
						RT_GROUP_ICON                                      = MAKEINTRESOURCE(14)
 | 
				
			||||||
 | 
						RT_VERSION                                         = MAKEINTRESOURCE(16)
 | 
				
			||||||
 | 
						RT_DLGINCLUDE                                      = MAKEINTRESOURCE(17)
 | 
				
			||||||
 | 
						RT_PLUGPLAY                                        = MAKEINTRESOURCE(19)
 | 
				
			||||||
 | 
						RT_VXD                                             = MAKEINTRESOURCE(20)
 | 
				
			||||||
 | 
						RT_ANICURSOR                                       = MAKEINTRESOURCE(21)
 | 
				
			||||||
 | 
						RT_ANIICON                                         = MAKEINTRESOURCE(22)
 | 
				
			||||||
 | 
						RT_HTML                                            = MAKEINTRESOURCE(23)
 | 
				
			||||||
 | 
						RT_MANIFEST                                        = MAKEINTRESOURCE(24)
 | 
				
			||||||
 | 
						CREATEPROCESS_MANIFEST_RESOURCE_ID                 = MAKEINTRESOURCE(1)
 | 
				
			||||||
 | 
						ISOLATIONAWARE_MANIFEST_RESOURCE_ID                = MAKEINTRESOURCE(2)
 | 
				
			||||||
 | 
						ISOLATIONAWARE_NOSTATICIMPORT_MANIFEST_RESOURCE_ID = MAKEINTRESOURCE(3)
 | 
				
			||||||
 | 
						ISOLATIONPOLICY_MANIFEST_RESOURCE_ID               = MAKEINTRESOURCE(4)
 | 
				
			||||||
 | 
						ISOLATIONPOLICY_BROWSER_MANIFEST_RESOURCE_ID       = MAKEINTRESOURCE(5)
 | 
				
			||||||
 | 
						MINIMUM_RESERVED_MANIFEST_RESOURCE_ID              = MAKEINTRESOURCE(1 /*inclusive*/)
 | 
				
			||||||
 | 
						MAXIMUM_RESERVED_MANIFEST_RESOURCE_ID              = MAKEINTRESOURCE(16 /*inclusive*/)
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//sys	findResource(module windows.Handle, name *uint16, resType *uint16) (resInfo windows.Handle, err error) = kernel32.FindResourceW
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func FindByID(module windows.Handle, id uint16, resType *uint16) (resInfo windows.Handle, err error) {
 | 
				
			||||||
 | 
						return findResource(module, MAKEINTRESOURCE(id), resType)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func FindByName(module windows.Handle, name string, resType *uint16) (resInfo windows.Handle, err error) {
 | 
				
			||||||
 | 
						var name16 *uint16
 | 
				
			||||||
 | 
						name16, err = windows.UTF16PtrFromString(name)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						resInfo, err = findResource(module, name16, resType)
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//sys	sizeofResource(module windows.Handle, resInfo windows.Handle) (size uint32, err error) = kernel32.SizeofResource
 | 
				
			||||||
 | 
					//sys	loadResource(module windows.Handle, resInfo windows.Handle) (resData windows.Handle, err error) = kernel32.LoadResource
 | 
				
			||||||
 | 
					//sys	lockResource(resData windows.Handle) (addr uintptr, err error) = kernel32.LockResource
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func Load(module, resInfo windows.Handle) (data []byte, err error) {
 | 
				
			||||||
 | 
						size, err := sizeofResource(module, resInfo)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							err = fmt.Errorf("Unable to size resource: %v", err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						resData, err := loadResource(module, resInfo)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							err = fmt.Errorf("Unable to load resource: %v", err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ptr, err := lockResource(resData)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							err = fmt.Errorf("Unable to lock resource: %v", err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						unsafeSlice(unsafe.Pointer(&data), unsafe.Pointer(ptr), int(size))
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type VS_FIXEDFILEINFO struct {
 | 
				
			||||||
 | 
						Signature        uint32
 | 
				
			||||||
 | 
						StrucVersion     uint32
 | 
				
			||||||
 | 
						FileVersionMS    uint32
 | 
				
			||||||
 | 
						FileVersionLS    uint32
 | 
				
			||||||
 | 
						ProductVersionMS uint32
 | 
				
			||||||
 | 
						ProductVersionLS uint32
 | 
				
			||||||
 | 
						FileFlagsMask    uint32
 | 
				
			||||||
 | 
						FileFlags        uint32
 | 
				
			||||||
 | 
						FileOS           uint32
 | 
				
			||||||
 | 
						FileType         uint32
 | 
				
			||||||
 | 
						FileSubtype      uint32
 | 
				
			||||||
 | 
						FileDateMS       uint32
 | 
				
			||||||
 | 
						FileDateLS       uint32
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//sys	verQueryValue(block *byte, section *uint16, value **byte, size *uint32) (err error) = version.VerQueryValueW
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func VerQueryRootValue(block []byte) (ffi *VS_FIXEDFILEINFO, err error) {
 | 
				
			||||||
 | 
						var data *byte
 | 
				
			||||||
 | 
						var size uint32
 | 
				
			||||||
 | 
						err = verQueryValue(&block[0], windows.StringToUTF16Ptr("\\"), &data, &size)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if uintptr(size) < unsafe.Sizeof(VS_FIXEDFILEINFO{}) {
 | 
				
			||||||
 | 
							err = errors.New("Incomplete VS_FIXEDFILEINFO")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ffi = (*VS_FIXEDFILEINFO)(unsafe.Pointer(data))
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// unsafeSlice updates the slice slicePtr to be a slice
 | 
				
			||||||
 | 
					// referencing the provided data with its length & capacity set to
 | 
				
			||||||
 | 
					// lenCap.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// TODO: when Go 1.16 or Go 1.17 is the minimum supported version,
 | 
				
			||||||
 | 
					// update callers to use unsafe.Slice instead of this.
 | 
				
			||||||
 | 
					func unsafeSlice(slicePtr, data unsafe.Pointer, lenCap int) {
 | 
				
			||||||
 | 
						type sliceHeader struct {
 | 
				
			||||||
 | 
							Data unsafe.Pointer
 | 
				
			||||||
 | 
							Len  int
 | 
				
			||||||
 | 
							Cap  int
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						h := (*sliceHeader)(slicePtr)
 | 
				
			||||||
 | 
						h.Data = data
 | 
				
			||||||
 | 
						h.Len = lenCap
 | 
				
			||||||
 | 
						h.Cap = lenCap
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										112
									
								
								tun/wintun/resource/zsyscall_windows.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								tun/wintun/resource/zsyscall_windows.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,112 @@
 | 
				
			|||||||
 | 
					// Code generated by 'go generate'; DO NOT EDIT.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package resource
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"syscall"
 | 
				
			||||||
 | 
						"unsafe"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"golang.org/x/sys/windows"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var _ unsafe.Pointer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Do the interface allocations only once for common
 | 
				
			||||||
 | 
					// Errno values.
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						errnoERROR_IO_PENDING = 997
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// errnoErr returns common boxed Errno values, to prevent
 | 
				
			||||||
 | 
					// allocations at runtime.
 | 
				
			||||||
 | 
					func errnoErr(e syscall.Errno) error {
 | 
				
			||||||
 | 
						switch e {
 | 
				
			||||||
 | 
						case 0:
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						case errnoERROR_IO_PENDING:
 | 
				
			||||||
 | 
							return errERROR_IO_PENDING
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// TODO: add more here, after collecting data on the common
 | 
				
			||||||
 | 
						// error values see on Windows. (perhaps when running
 | 
				
			||||||
 | 
						// all.bat?)
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
 | 
				
			||||||
 | 
						modversion  = windows.NewLazySystemDLL("version.dll")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						procFindResourceW  = modkernel32.NewProc("FindResourceW")
 | 
				
			||||||
 | 
						procSizeofResource = modkernel32.NewProc("SizeofResource")
 | 
				
			||||||
 | 
						procLoadResource   = modkernel32.NewProc("LoadResource")
 | 
				
			||||||
 | 
						procLockResource   = modkernel32.NewProc("LockResource")
 | 
				
			||||||
 | 
						procVerQueryValueW = modversion.NewProc("VerQueryValueW")
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func findResource(module windows.Handle, name *uint16, resType *uint16) (resInfo windows.Handle, err error) {
 | 
				
			||||||
 | 
						r0, _, e1 := syscall.Syscall(procFindResourceW.Addr(), 3, uintptr(module), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(resType)))
 | 
				
			||||||
 | 
						resInfo = windows.Handle(r0)
 | 
				
			||||||
 | 
						if resInfo == 0 {
 | 
				
			||||||
 | 
							if e1 != 0 {
 | 
				
			||||||
 | 
								err = errnoErr(e1)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								err = syscall.EINVAL
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func sizeofResource(module windows.Handle, resInfo windows.Handle) (size uint32, err error) {
 | 
				
			||||||
 | 
						r0, _, e1 := syscall.Syscall(procSizeofResource.Addr(), 2, uintptr(module), uintptr(resInfo), 0)
 | 
				
			||||||
 | 
						size = uint32(r0)
 | 
				
			||||||
 | 
						if size == 0 {
 | 
				
			||||||
 | 
							if e1 != 0 {
 | 
				
			||||||
 | 
								err = errnoErr(e1)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								err = syscall.EINVAL
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func loadResource(module windows.Handle, resInfo windows.Handle) (resData windows.Handle, err error) {
 | 
				
			||||||
 | 
						r0, _, e1 := syscall.Syscall(procLoadResource.Addr(), 2, uintptr(module), uintptr(resInfo), 0)
 | 
				
			||||||
 | 
						resData = windows.Handle(r0)
 | 
				
			||||||
 | 
						if resData == 0 {
 | 
				
			||||||
 | 
							if e1 != 0 {
 | 
				
			||||||
 | 
								err = errnoErr(e1)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								err = syscall.EINVAL
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func lockResource(resData windows.Handle) (addr uintptr, err error) {
 | 
				
			||||||
 | 
						r0, _, e1 := syscall.Syscall(procLockResource.Addr(), 1, uintptr(resData), 0, 0)
 | 
				
			||||||
 | 
						addr = uintptr(r0)
 | 
				
			||||||
 | 
						if addr == 0 {
 | 
				
			||||||
 | 
							if e1 != 0 {
 | 
				
			||||||
 | 
								err = errnoErr(e1)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								err = syscall.EINVAL
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func verQueryValue(block *byte, section *uint16, value **byte, size *uint32) (err error) {
 | 
				
			||||||
 | 
						r1, _, e1 := syscall.Syscall6(procVerQueryValueW.Addr(), 4, uintptr(unsafe.Pointer(block)), uintptr(unsafe.Pointer(section)), uintptr(unsafe.Pointer(value)), uintptr(unsafe.Pointer(size)), 0, 0)
 | 
				
			||||||
 | 
						if r1 == 0 {
 | 
				
			||||||
 | 
							if e1 != 0 {
 | 
				
			||||||
 | 
								err = errnoErr(e1)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								err = syscall.EINVAL
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -34,7 +34,7 @@ type Adapter struct {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
	modwintun = windows.NewLazyDLL("wintun.dll")
 | 
						modwintun = newLazyDLL("wintun.dll")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	procWintunCreateAdapter           = modwintun.NewProc("WintunCreateAdapter")
 | 
						procWintunCreateAdapter           = modwintun.NewProc("WintunCreateAdapter")
 | 
				
			||||||
	procWintunDeleteAdapter           = modwintun.NewProc("WintunDeleteAdapter")
 | 
						procWintunDeleteAdapter           = modwintun.NewProc("WintunDeleteAdapter")
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user