Why?
You want to evade detection post compromise of a host, and hide your process as something innocuous when someone inspects /proc
or ps
.
When?
You're host is Linux, and your executable is in C, or a language with FFI support.
How?
There are two classes of data to spoof:
- The contents of
/proc/pid/cmdline
. This is what shows up withps -f
. - The contents of
/proc/pid/comm
and the first line of/proc/pid/status
. This is what shows up withps
without-f
.
In nim
import os
proc NimMain() {.cdecl, importc.}
proc syscall(number: clong): clong
{.importc, varargs, header: "sys/syscall.h".}
var NR_PRCTL
{.importc: "__NR_prctl", header: "unistd.h".}: int
var PR_SET_NAME
{.importc: "PR_SET_NAME", header: "sys/prctl.h".}: int
proc main(argc: int, argv: cstringArray, envp: cstringArray): int
{.cdecl, exportc.} =
NimMain()
const FAKE_COMMAND = "spoofed"
# handles /proc/pid/comm and /proc/pid/status
discard syscall(NR_PRCTL, PR_SET_NAME, cstring(FAKE_COMMAND))
# handles /proc/pid/cmdline
let totalLength = len(argv[0])
var i = 0
for ch in FAKE_COMMAND:
argv[0][i] = FAKE_COMMAND[i]
i += 1
argv[0][i] = '\x00'
for j in i .. totalLength:
argv[0][j] = '\x00'
sleep(60000)
- Note that you'll need to compile this with
--nomain
. - Note that as argc and envp is consecutive in memory this means that a longer
FAKE_COMMAND
than the actualargv[0]
means we overwrite the contents of/proc/pid/environ
. To work around this, ensure your executable has a longer name than the what you want to spoof as.
Top comments (0)