Background
If you are a penetration tester or red teamer, you might have run into the
situation that you have gotten access to a Linux machine or container (either
compromising it or by having been given white-box test access to the system in
order to test the defense-in-depth mechanisms). Now wouldn’t it be useful for
further exploration or post-exploitation if you had tmux
on that machine? Or
socat
? Or strace
? Or gdb
? Or frida
? Or r2
? Or $tool_of_your_choice
? What do you usually
do? You go for static binaries, either compiling them yourself, which might
turn out to be fiddly, or you trust a random person on the internet who was
kind enough to compile it for you.
Let me present an alternative: Nix. In case you did
not hear about it, it is a purely functional package manager (and also the
corresponding functional language to define those packages). One of the very
useful things about it is that it will built self-contained packages which
include all the dependencies that are needed to run it. So you could just build
your favourite tool using Nix (which has a lot of packages readily
available)
and copy it to the compromised machine, right? Well, unfortunately,
Nix binaries and the corresponding shared libraries by default live under
/nix
, which will probably not exist and not be writable in the likely case that you are not root
.
I read in the past that it is possible (but not encouraged, because you loose
the possibility to make use of the binary cache Nix provides for you) to change
that directory. So I set out to build a Nix that lives under /tmp
(or
optionally under /var/tmp
or some other directory you have write access to)
so one could just copy binaries to a location of ones choice
and then execute nearly anything. It turned out a bit more tricky than expected
but I managed. \o/.
So let me introduce a dockerized version of that work (if you want to do
the same manually, just look through the Dockerfile
to see what I do) which
enables you to compile arbitrary Nix packages and bundle them up into a tarball
which contains everything that is needed to run that binary from /tmp/nix
.
Quick start usage
$ git clone https://git.alech.de/alech/tmpnix
$ cd tmpnix
$ docker build base -t tmpnix-base
$ docker build bootstrapped -t tmpnix
$ docker volume create tmpnix
$ docker run tmpnix search '.*strace.*'
$ docker run --mount source=tmpnix,destination=/tmp/nix tmpnix build nixpkgs.strace
After finishing to build, the script will tell you how to copy the tar-ball containing the build result and all of its run-time dependencies from the container. Once you copied the tarball from the container, use tar xjf <tarball> -C /
to unpack with /
as a destination.
Future work
Since this might be also super-useful to help with building cross-compiled binaries for e.g. ARM/Android/etc. and Nix already supports this, the next step is to add support for that. First manual attempts looks like this is feasible but some work in figuring out the correct runtime dependencies is still needed. Also, maybe a little web interface that lets you search for packages, build them and download the built tarballs might be added. We’ll see.