sigsleeper is a tool for setting up sleeper code in Linux.
What do you mean by "sleeper code"?
Sleeper code would be code that sits unseen on a target system. In this case, sigsleeper hides its payload inside of a legitimate process on Linux. It does this by injecting the payload into a target process and setting it up as a signal handler. The payload can be either shellcode or commands to execute. The payload is then run anytime a "trigger" signal is received. sigsleeper can also be used to hijack an existing signal handler, running the original signal handler after the completion of the payload.
What are signals and signal handlers?
A signal handler is a piece of code that is run anytime a process receives a signal. Signals are a mechanism used to notify processes of any number of events. Normally, this is an asynchronous notification from the kernel. (The signal can originate from another process, such as kill, but are delivered through the kernel.)
As an example, let's look at SIGINT. This is a normal signal that is used to tell a process it has been "interrupted", such as by a "ctrl-c". The signal handler in this case is a default handler called SIG_DFL (which in this case will terminate the process). Using a custom signal handler to intercept SIGINT is not unheard of. A programmer may want to do that to ensure that the process has time to properly clean up after itself before exiting. The function that performs that cleanup would be the custom signal handler.
What's the use-case for sigsleeper?
sigsleeper would be used during the post-exploitation phase of a pentest for setting up a persistence mechanism.
Is this a rootkit?
Not exactly. It demonstrates the sort of userland rootkit that is possible. This tool, taken with some others from my repositories, and a bit of creativity, could be used as the basis of a Linux userland rootkit.
Where can I learn more about signals in Linux?
There are a couple of places that can give guidance on this topic:
- The signal (7) man page is a good start. This will give you a reasonable high-level overview.
- Chapter 10 from Stevens & Rago's "Advanced Programming in the UNIX Environment (3rd Edition)" covers signals in depth. I cannot recommend this book highly enough.
Finally, both the above links describe signals as they work in theory. To understand the dirty details of implementation, you really have to go source diving. From the Linux kernel source, read:
- kernel/signal.c
- arch/x86/kernel/signal.c
And from the glibc source, read:
- sysdeps/posix/signal.c
- sysdeps/unix/sysv/linux/x86_64/sigaction.c
What Architectures / OSs will this run on?
Currently, sigsleeper will only run on x86_64 Linux. Because it uses the Linux ptrace interface to inject assembly language syscalls into a target process, nothing here is portable. That said, check out my other project, ptrace_do. If I get around to supporting ptrace_do for other architectures, then porting sigsleeper shouldn't be too hard.
Usage: sigsleeper [-s SIGNAL] [-o] [-f] [-e COMMAND] [-d] PID
-s SIGNAL : Use SIGNAL as the trigger. Signal name, short name, or number are all accepted. (SIGUSR1 is the default).
-o : Invoke the original signal handler after running our payload.
-f : Add fork() shellcode so that the payload runs in a child process, ensuring the original process does not block.
-e COMMAND : Use exec() shellcode to launch COMMAND for the payload instead of reading from stdin.
: This option requires that COMMAND have an absolute path.
-d : Display debug output.
As an example, we will embed a call to '/bin/echo Hello world!' into the shell we are logged into. We can then trigger it by using the kill command to send SIGUSR1 to our current shell.
empty@monkey:~$ sigsleeper -f -e '/bin/echo Hello world!' $$
empty@monkey:~$ kill -USR1 $$
empty@monkey:~$ Hello world!
To help with the heavy lifting, I've written a supporting library that is needed by sigsleeper:
- ptrace_do: A ptrace library for easy syscall injection in Linux.
git clone https://github.com/emptymonkey/ptrace_do.git
cd ptrace_do
make
cd ..
git clone https://github.com/emptymonkey/sigsleeper.git
cd sigsleeper
make