Add memory obfuscation and ps-hidden process detection

This commit is contained in:
Luna 2026-06-13 03:55:09 -07:00
parent cb334c0c94
commit 893409b549
17 changed files with 353 additions and 26 deletions

View file

@ -18,6 +18,9 @@ class TestDiffCores(unittest.TestCase):
def test_no_hidden_pids_when_views_agree(self):
self.assertEqual(rootcheck.find_hidden_pids({1, 2}, {1, 2}), set())
def test_ps_hidden_pids_are_proc_minus_ps(self):
self.assertEqual(rootcheck.find_ps_hidden_pids({1, 2, 3}, {1, 3}), {2})
def test_hidden_modules_live_in_sys_but_not_proc(self):
self.assertEqual(
rootcheck.find_hidden_modules({"ext4", "nf_tables"},
@ -108,7 +111,7 @@ class TestRunIntegration(unittest.TestCase):
for name in ("proc_pids", "alive_pids", "proc_modules",
"sys_live_modules", "procnet_listen_ports",
"procnet_udp_ports", "procnet_raw_protocols",
"procnet_protocol_kinds",
"procnet_protocol_kinds", "ps_pids", "proc_pid_exists",
"promiscuous_interfaces", "module_taints", "kernel_taint"):
self._saved[name] = getattr(rootcheck, name)
@ -125,12 +128,15 @@ class TestRunIntegration(unittest.TestCase):
rootcheck.procnet_udp_ports = lambda: views.get("procnet_udp_ports", set())
rootcheck.procnet_raw_protocols = lambda: views.get("procnet_raw_protocols", set())
rootcheck.procnet_protocol_kinds = lambda: views.get("procnet_protocol_kinds", set())
rootcheck.ps_pids = lambda: views.get("ps_pids", set())
rootcheck.proc_pid_exists = lambda pid: pid in views.get("existing_pids", set())
rootcheck.promiscuous_interfaces = lambda: views.get("promisc", [])
rootcheck.module_taints = lambda: views.get("module_taints", {})
rootcheck.kernel_taint = lambda: views.get("kernel_taint", 0)
def test_clean_system_yields_nothing(self):
self._patch(proc_pids={1, 2}, alive_pids={1, 2},
ps_pids={1, 2}, existing_pids={1, 2},
proc_modules={"ext4"}, sys_live_modules={"ext4"})
state = SystemState(sockets=[])
self.assertEqual(list(rootcheck.run(self.cfg, state)), [])
@ -138,6 +144,7 @@ class TestRunIntegration(unittest.TestCase):
def test_hidden_module_and_port_and_promisc(self):
self._patch(
proc_pids={1}, alive_pids={1},
ps_pids={1}, existing_pids={1},
proc_modules={"ext4"}, sys_live_modules={"ext4", "diamorphine"},
procnet_ports={22, 31337}, procnet_udp_ports={53, 4444},
procnet_raw_protocols={1, 58},
@ -167,9 +174,21 @@ class TestRunIntegration(unittest.TestCase):
self.assertIn("promiscuous_interface", alerts)
self.assertEqual(alerts["promiscuous_interface"].sid, rootcheck.SID_PROMISC)
def test_process_visible_in_proc_but_missing_from_ps_alerts(self):
self._patch(
proc_pids={1, 4242}, alive_pids={1, 4242},
ps_pids={1}, existing_pids={1, 4242},
proc_modules={"ext4"}, sys_live_modules={"ext4"})
alerts = {a.signature: a for a in rootcheck.run(self.cfg, SystemState(sockets=[]))}
self.assertIn("rootkit_ps_hidden_process", alerts)
self.assertEqual(alerts["rootkit_ps_hidden_process"].sid,
rootcheck.SID_PS_HIDDEN_PROCESS)
self.assertEqual(alerts["rootkit_ps_hidden_process"].pids, (4242,))
def test_tainted_module_and_kernel_taint(self):
self._patch(
proc_pids={1}, alive_pids={1},
ps_pids={1}, existing_pids={1},
proc_modules={"ext4", "vendor_gpu"},
sys_live_modules={"ext4", "vendor_gpu"},
module_taints={"vendor_gpu": "OE"},
@ -185,6 +204,7 @@ class TestRunIntegration(unittest.TestCase):
self.cfg.rootcheck_module_allow = ("vendor_gpu",)
self._patch(
proc_pids={1}, alive_pids={1},
ps_pids={1}, existing_pids={1},
proc_modules={"vendor_gpu"}, sys_live_modules={"vendor_gpu"},
module_taints={"vendor_gpu": "OE"})
alerts = {a.signature: a for a in rootcheck.run(self.cfg, SystemState(sockets=[]))}