Skip to content

Instantly share code, notes, and snippets.

@niallnsec
Created April 29, 2018 15:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save niallnsec/1ffc71faa8d1f6a9ceaf27492ceadb8c to your computer and use it in GitHub Desktop.
Save niallnsec/1ffc71faa8d1f6a9ceaf27492ceadb8c to your computer and use it in GitHub Desktop.
package main
import (
"errors"
"fmt"
"log"
"strings"
"syscall"
"unsafe"
)
var (
modkernel32 = syscall.NewLazyDLL("kernel32.dll")
procReadProcessMemory = modkernel32.NewProc("ReadProcessMemory")
procGetProcessId = modkernel32.NewProc("GetProcessId")
modntdll = syscall.NewLazyDLL("ntdll.dll")
procNtQueryInformationProcess = modntdll.NewProc("NtQueryInformationProcess")
errNoSuchProcess = errors.New("no such process")
)
type (
UNICODE_STRING struct {
Length uint16
MaxLangth uint16
Buffer uintptr
}
WindowsProcess struct {
hProcess *syscall.Handle
processID uint32
pProcessID uint32
processName string
}
PROCESS_BASIC_INFORMATION struct {
ExitStatus uintptr
PebBaseAddress uintptr
AffinityMask uintptr
BasePriority uintptr
UniqueProcessId uintptr
InheritedFromUniqueProcessId uintptr
}
)
func main() {
hProcess, err := getProcessHandle("Notepad.exe", syscall.PROCESS_QUERY_INFORMATION|8|16)
if err != nil {
panic(err.Error())
}
wp := NewWindowsProcess(*hProcess)
pid, err := wp.ProcessID()
if err != nil {
panic(err.Error())
}
fmt.Printf("PID: %d\n", pid)
var pbi PROCESS_BASIC_INFORMATION
var retLen uint32
err = NtQueryInformationProcess(*hProcess, 0, &pbi, unsafe.Sizeof(pbi), &retLen)
if err != nil {
panic(err.Error())
}
fmt.Printf("Base Addr: %x\n", pbi.PebBaseAddress)
fmt.Printf("ProcID: %x\n", pbi.UniqueProcessId)
var procParams uint64
var br uint32
err = ReadProcessMemory(*hProcess, pbi.PebBaseAddress+32, uintptr(unsafe.Pointer(&procParams)), unsafe.Sizeof(procParams), uintptr(unsafe.Pointer(&br)))
if err != nil {
panic(err.Error())
}
fmt.Printf("Params: %x\n", procParams)
var pCmdLine UNICODE_STRING
err = ReadProcessMemory(*hProcess, uintptr(procParams+112), uintptr(unsafe.Pointer(&pCmdLine)), unsafe.Sizeof(pCmdLine), uintptr(unsafe.Pointer(&br)))
if err != nil {
panic(err.Error())
}
fmt.Printf("CMD Line: %x\n", pCmdLine.Buffer)
fmt.Printf("L HProc: %x\n", *hProcess)
fmt.Printf("L PBuffer: %x\n", pCmdLine.Buffer)
fmt.Printf("L BLength: %x\n", pCmdLine.Length)
var sparameter = make([]uint16, pCmdLine.Length/2, pCmdLine.Length/2)
err = ReadProcessMemory(*hProcess, pCmdLine.Buffer, uintptr(unsafe.Pointer(&sparameter[0])), uintptr(pCmdLine.Length), uintptr(unsafe.Pointer(&br)))
if err != nil {
panic(err.Error())
}
sCmdLine := syscall.UTF16ToString(sparameter)
ssCmdLine, err := pCmdLine.StringRemote(hProcess)
if err != nil {
panic(err.Error())
}
fmt.Printf("CMD Line: %s\n", sCmdLine)
fmt.Printf("CMD Line: %s\n", ssCmdLine)
syscall.CloseHandle(*hProcess)
}
func (us UNICODE_STRING) StringRemote(hProcess *syscall.Handle) (string, error) {
var br uint32
fmt.Printf("R HProc: %x\n", *hProcess)
fmt.Printf("R PBuffer: %x\n", us.Buffer)
fmt.Printf("R BLength: %x\n", us.Length)
//fmt.Println(br)
var sparameter = make([]uint16, us.Length/2, us.Length/2)
err := ReadProcessMemory(*hProcess, us.Buffer, uintptr(unsafe.Pointer(&sparameter[0])), uintptr(us.Length), uintptr(unsafe.Pointer(&br)))
if err != nil {
return "", err
}
s := syscall.UTF16ToString(sparameter)
return s, nil
}
func NewWindowsProcess(hProc syscall.Handle) *WindowsProcess {
return &WindowsProcess{
hProcess: &hProc,
}
}
func (wp *WindowsProcess) ProcessID() (uint32, error) {
if wp.processID == 0 {
pid, err := GetProcessId(*wp.hProcess)
if pid == 0 {
return 0, err
}
wp.processID = pid
}
return wp.processID, nil
}
func NtQueryInformationProcess(ProcessHandle syscall.Handle, ProcessInformationClass uint32,
ProcessInformation *PROCESS_BASIC_INFORMATION, ProcessInformationLength uintptr, ReturnLength *uint32) error {
r1, _, e1 := syscall.Syscall6(procNtQueryInformationProcess.Addr(), 5, uintptr(ProcessHandle),
uintptr(ProcessInformationClass), uintptr(unsafe.Pointer(ProcessInformation)), ProcessInformationLength,
uintptr(unsafe.Pointer(ReturnLength)), 0)
if r1 != 0 {
fmt.Println(r1)
return errors.New(e1.Error())
}
return nil
}
func GetProcessId(hProcess syscall.Handle) (uint32, error) {
r1, _, e1 := syscall.Syscall(procGetProcessId.Addr(), 1, uintptr(hProcess), 0, 0)
if r1 == 0 {
return 0, errors.New(e1.Error())
}
return uint32(r1), nil
}
func ReadProcessMemory(hProcess syscall.Handle, lpBaseAddress uintptr, lpBuffer uintptr, nSize uintptr,
lpNumberOfBytesRead uintptr) error {
r1, _, e1 := syscall.Syscall6(procReadProcessMemory.Addr(), 5, uintptr(hProcess), lpBaseAddress,
lpBuffer, nSize, lpNumberOfBytesRead, 0)
if r1 == 0 {
return errors.New(e1.Error())
}
return nil
}
func getProcessHandle(pName string, access int) (*syscall.Handle, error) {
hSnapshot, err := syscall.CreateToolhelp32Snapshot(syscall.TH32CS_SNAPPROCESS, 0)
if err != nil {
rerr := fmt.Errorf("error creating process snapshot: %s", err.Error())
log.Printf(rerr.Error())
return nil, rerr
}
var proc syscall.ProcessEntry32
proc.Size = uint32(unsafe.Sizeof(proc))
err = syscall.Process32First(hSnapshot, &proc)
if err != nil {
rerr := fmt.Errorf("error reading process snapshot: %s", err.Error())
log.Printf(rerr.Error())
return nil, rerr
}
pName = strings.ToLower(pName)
for {
sexe := syscall.UTF16ToString(proc.ExeFile[:])
if strings.ToLower(sexe) == pName {
hProcess, err := syscall.OpenProcess(uint32(access), false, proc.ProcessID)
if err != nil {
rerr := fmt.Errorf("error opening process: %s", err.Error())
log.Printf(rerr.Error())
return nil, rerr
}
return &hProcess, nil
}
err = syscall.Process32Next(hSnapshot, &proc)
if err != nil {
if err.Error() == "There are no more files." {
break
}
return nil, err
}
}
log.Printf(errNoSuchProcess.Error())
return nil, errNoSuchProcess
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment