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:
@@ -322,6 +322,33 @@ def test_capture_script_uses_masked_inotify_bin():
|
||||
assert "kmsg-watch" in body
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# argv_zap LD_PRELOAD shim (hides inotifywait args from ps)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def test_argv_zap_source_shipped():
|
||||
ctx = get_service("ssh").dockerfile_context()
|
||||
src = ctx / "argv_zap.c"
|
||||
assert src.exists(), "argv_zap.c missing from SSH template context"
|
||||
body = src.read_text()
|
||||
assert "__libc_start_main" in body
|
||||
assert "PR_SET_NAME" in body
|
||||
|
||||
|
||||
def test_dockerfile_compiles_argv_zap():
|
||||
df = _dockerfile_text()
|
||||
assert "argv_zap.c" in df
|
||||
assert "argv_zap.so" in df
|
||||
# gcc must be installed AND purged in the same layer (image-size hygiene).
|
||||
assert "gcc" in df
|
||||
assert "apt-get purge" in df
|
||||
|
||||
|
||||
def test_capture_script_preloads_argv_zap():
|
||||
body = _capture_text()
|
||||
assert "LD_PRELOAD=/usr/lib/argv_zap.so" in body
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# File-catcher: compose_fragment volume
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user