feat(ssh-capture): LD_PRELOAD shim to zero inotifywait argv

The kmsg-watch (inotifywait) process was the last honest giveaway in
`ps aux` — its watch paths and event flags betrayed the honeypot. The
argv_zap.so shim hooks __libc_start_main, heap-copies argv for the real
main, then memsets the contiguous argv[1..] region to NUL so the kernel's
cmdline reader returns just argv[0].

gcc is installed and purged in the same Docker layer to keep the image
slim. The shim also calls prctl(PR_SET_NAME) so /proc/self/comm mirrors
the argv[0] disguise.
This commit is contained in:
2026-04-18 01:52:30 -04:00
parent e356829234
commit f462835373
4 changed files with 100 additions and 1 deletions

View File

@@ -78,6 +78,18 @@ COPY entrypoint.sh /entrypoint.sh
# `journal-relay` and inotifywait is invoked through a symlink named
# `kmsg-watch` — both names blend in with normal udev/journal daemons.
COPY capture.sh /usr/libexec/udev/journal-relay
# argv_zap.so: LD_PRELOAD shim that blanks argv[1..] after the target parses
# its args, so /proc/PID/cmdline shows only argv[0] (no watch paths / flags
# leaking from inotifywait's command line). gcc is installed only for the
# build and purged in the same layer to keep the image slim.
COPY argv_zap.c /tmp/argv_zap.c
RUN apt-get update && apt-get install -y --no-install-recommends gcc libc6-dev \
&& gcc -O2 -fPIC -shared -o /usr/lib/argv_zap.so /tmp/argv_zap.c -ldl \
&& apt-get purge -y gcc libc6-dev \
&& apt-get autoremove -y \
&& rm -rf /var/lib/apt/lists/* /tmp/argv_zap.c
RUN mkdir -p /usr/libexec/udev \
&& chmod +x /entrypoint.sh /usr/libexec/udev/journal-relay \
&& ln -sf /usr/bin/inotifywait /usr/libexec/udev/kmsg-watch