hypno
hypno copied to clipboard
Support injecting into containers in linux
Can check if the target process has a different /proc/<pid>/task/<pid>/ns/mnt
. If it does, create the shared library in /proc/pid/root
instead in the current filesystem. Python's tempfile module doesn't support searching for a tempdir in a different filesystem, and it caches it for the whole process once it's found. So maybe we can create a subprocess, nsenter the target filesystem, and then continue normally. Alternatively, just copy the logic in tempfile
or assume that /tmp
is writable.
Hi, I think this sounds really useful.
I think there may also need to be a change to the pyinjector.inject(...)
API. Currently it checks that the shared library exists before injecting.
A couple of ideas came to mind already but neither are too satisfying:
pyinjector
could relativize the path when it sees that it starts with /proc/<pid>/root
pyinjector.inject(123, '/proc/123/root/path/to/lib.so')
# ->
injector.inject(b'/path/to/lib.so')
Or it could double check /proc/<pid>/root
when the path is not initially found
pyinjector.inject(123, '/path/to/lib.so')
# ->
if ... and not os.path.isfile('/proc/123/root/path/to/lib.so'):
raise ...
Hmmm how about just always using /proc/pid/root
both for the shared library tmpdir in hypno and for the existence check in pyinjector?
Ahh, you mean NamedTemporaryFile(..., dir=f'/proc/{pid}/root')
instead of NamedTemporaryFile(..., dir=f'/proc/{pid}/root/tmp')
? I think it's quite common to mount /
as readonly. I think it's less common to not have /tmp
mounted read/write. But maybe I've misunderstood.
...
I was thinking over this some more this morning and I think I've perhaps come up with a clearer API for pyinjector
def inject(pid: int, library_path: AnyStr, uninject: bool = False,
process_root: AnyStr = "") -> int:
...
which would be called, in those examples, like so
injector.inject(b'/path/to/lib.so', process_root=b'/proc/123/root')
This has the advantage that it extends generally to any kind of chroot jail and that pyinjector doesn't have to bake in any knowledge about Linux's /proc
filesystem.
The caller is responsible for making it clear at what path they expect the target process to see the library.
In hypno I just meant that it's possible to always look for a tempdir in the target process' fs using /proc/pid/root
, regardless if it's the same or not as /
.
In pyinjector, I like your suggestion, but I think that it'd also be useful to always check for existence of the shared library in the target process' fs (again using /proc/pid/root
) by default. The additional argument you suggested could still be used to override this default behavior.