aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2019-08-05 15:15:15 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2019-08-05 15:15:15 +0200
commit9af5e654239ed87f1ec56524083733f333cde2f4 (patch)
tree906319a4c14749edceff7ba804ed82bc448dd441
parentgo.mod: operate like a normal go module (diff)
downloadwireguard-windows-9af5e654239ed87f1ec56524083733f333cde2f4.tar.xz
wireguard-windows-9af5e654239ed87f1ec56524083733f333cde2f4.zip
Fully cooked peb testjd/fullycooked-peb
-rw-r--r--elevate/shellexecute.go27
-rw-r--r--elevate/syscall_windows.go23
-rw-r--r--elevate/zsyscall_windows.go14
3 files changed, 37 insertions, 27 deletions
diff --git a/elevate/shellexecute.go b/elevate/shellexecute.go
index d784a2ed..4c213216 100644
--- a/elevate/shellexecute.go
+++ b/elevate/shellexecute.go
@@ -25,10 +25,6 @@ const (
/* We could use the undocumented LdrFindEntryForAddress function instead, but that's undocumented, and we're trying
* to be as rock-solid as possible here. */
func findCurrentDataTableEntry() (entry *cLDR_DATA_TABLE_ENTRY, err error) {
- ourBase, err := getModuleHandle(nil) /* This is the same as peb->ImageBaseAddress, but that member is undocumented. */
- if err != nil {
- return
- }
peb := rtlGetCurrentPeb()
if peb == nil || peb.Ldr == nil {
err = windows.ERROR_INVALID_ADDRESS
@@ -36,7 +32,7 @@ func findCurrentDataTableEntry() (entry *cLDR_DATA_TABLE_ENTRY, err error) {
}
for cur := peb.Ldr.InMemoryOrderModuleList.Flink; cur != &peb.Ldr.InMemoryOrderModuleList; cur = cur.Flink {
entry = (*cLDR_DATA_TABLE_ENTRY)(unsafe.Pointer(uintptr(unsafe.Pointer(cur)) - unsafe.Offsetof(cLDR_DATA_TABLE_ENTRY{}.InMemoryOrderLinks)))
- if entry.DllBase == ourBase {
+ if entry.DllBase == peb.ImageBaseAddress {
return
}
}
@@ -91,20 +87,37 @@ func ShellExecute(program string, arguments string, directory string, show int32
return
}
}
+
dataTableEntry, err := findCurrentDataTableEntry()
if err != nil {
return
}
+ processParameters := rtlGetCurrentPeb().ProcessParameters
+ fullDllName := dataTableEntry.FullDllName.Buffer
+ baseDllName := dataTableEntry.BaseDllName.Buffer
+ imagePathName := processParameters.ImagePathName.Buffer
+ dllPath := processParameters.DllPath.Buffer
+ commandLine := processParameters.CommandLine.Buffer
+
var windowsDirectory [windows.MAX_PATH]uint16
if _, err = getWindowsDirectory(&windowsDirectory[0], windows.MAX_PATH); err != nil {
return
}
- originalPath := dataTableEntry.FullDllName.Buffer
explorerPath := windows.StringToUTF16Ptr(filepath.Join(windows.UTF16ToString(windowsDirectory[:]), "explorer.exe"))
+ explorerName := windows.StringToUTF16Ptr("explorer.exe")
rtlInitUnicodeString(&dataTableEntry.FullDllName, explorerPath)
+ rtlInitUnicodeString(&processParameters.ImagePathName, explorerPath)
+ rtlInitUnicodeString(&processParameters.DllPath, explorerPath)
+ rtlInitUnicodeString(&dataTableEntry.BaseDllName, explorerName)
+ rtlInitUnicodeString(&processParameters.CommandLine, explorerName)
defer func() {
- rtlInitUnicodeString(&dataTableEntry.FullDllName, originalPath)
+ rtlInitUnicodeString(&processParameters.CommandLine, commandLine)
+ rtlInitUnicodeString(&dataTableEntry.BaseDllName, baseDllName)
+ rtlInitUnicodeString(&processParameters.DllPath, dllPath)
+ rtlInitUnicodeString(&processParameters.ImagePathName, imagePathName)
+ rtlInitUnicodeString(&dataTableEntry.FullDllName, fullDllName)
runtime.KeepAlive(explorerPath)
+ runtime.KeepAlive(explorerName)
}()
if err = coInitializeEx(0, cCOINIT_APARTMENTTHREADED); err == nil {
diff --git a/elevate/syscall_windows.go b/elevate/syscall_windows.go
index c7def8fa..3da3bca9 100644
--- a/elevate/syscall_windows.go
+++ b/elevate/syscall_windows.go
@@ -32,11 +32,13 @@ type cLIST_ENTRY struct {
* engineered, but the below shows only the documented and therefore stable fields from Microsoft's winternl.h header */
type cLDR_DATA_TABLE_ENTRY struct {
- Reserved1 [2]uintptr
+ InLoadOrderLinks cLIST_ENTRY
InMemoryOrderLinks cLIST_ENTRY
- Reserved2 [2]uintptr
+ InInitializationOrderLinks cLIST_ENTRY
DllBase uintptr
- Reserved3 [2]uintptr
+ EntryPoint uintptr
+ SizeOfImage uint32
+ BaseDllName cUNICODE_STRING
FullDllName cUNICODE_STRING
Reserved4 [8]byte
Reserved5 [3]uintptr
@@ -50,13 +52,23 @@ type cPEB_LDR_DATA struct {
InMemoryOrderModuleList cLIST_ENTRY
}
+type cRTL_USER_PROCESS_PARAMETERS struct {
+ Reserved1 [16]byte
+ Reserved2 [8]uintptr
+ DllPath cUNICODE_STRING
+ ImagePathName cUNICODE_STRING
+ CommandLine cUNICODE_STRING
+
+}
+
type cPEB struct {
Reserved1 [2]byte
BeingDebugged byte
Reserved2 [1]byte
- Reserved3 [2]uintptr
+ Reserved3 [1]uintptr
+ ImageBaseAddress uintptr
Ldr *cPEB_LDR_DATA
- ProcessParameters uintptr
+ ProcessParameters *cRTL_USER_PROCESS_PARAMETERS
Reserved4 [3]uintptr
AtlThunkSListPtr uintptr
Reserved5 uintptr
@@ -77,7 +89,6 @@ const (
cCOINIT_APARTMENTTHREADED = 2
)
-//sys getModuleHandle(moduleName *uint16) (moduleHandle uintptr, err error) [failretval==0] = kernel32.GetModuleHandleW
//sys getWindowsDirectory(windowsDirectory *uint16, inLen uint32) (outLen uint32, err error) [failretval==0] = kernel32.GetWindowsDirectoryW
//sys rtlInitUnicodeString(destinationString *cUNICODE_STRING, sourceString *uint16) = ntdll.RtlInitUnicodeString
diff --git a/elevate/zsyscall_windows.go b/elevate/zsyscall_windows.go
index a3c5400d..8f7a5a8a 100644
--- a/elevate/zsyscall_windows.go
+++ b/elevate/zsyscall_windows.go
@@ -41,7 +41,6 @@ var (
modntdll = windows.NewLazySystemDLL("ntdll.dll")
modole32 = windows.NewLazySystemDLL("ole32.dll")
- procGetModuleHandleW = modkernel32.NewProc("GetModuleHandleW")
procGetWindowsDirectoryW = modkernel32.NewProc("GetWindowsDirectoryW")
procRtlInitUnicodeString = modntdll.NewProc("RtlInitUnicodeString")
procRtlGetCurrentPeb = modntdll.NewProc("RtlGetCurrentPeb")
@@ -50,19 +49,6 @@ var (
procCoGetObject = modole32.NewProc("CoGetObject")
)
-func getModuleHandle(moduleName *uint16) (moduleHandle uintptr, err error) {
- r0, _, e1 := syscall.Syscall(procGetModuleHandleW.Addr(), 1, uintptr(unsafe.Pointer(moduleName)), 0, 0)
- moduleHandle = uintptr(r0)
- if moduleHandle == 0 {
- if e1 != 0 {
- err = errnoErr(e1)
- } else {
- err = syscall.EINVAL
- }
- }
- return
-}
-
func getWindowsDirectory(windowsDirectory *uint16, inLen uint32) (outLen uint32, err error) {
r0, _, e1 := syscall.Syscall(procGetWindowsDirectoryW.Addr(), 2, uintptr(unsafe.Pointer(windowsDirectory)), uintptr(inLen), 0)
outLen = uint32(r0)