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

@ -7,10 +7,10 @@ from enodia_sentinel.alert import Severity
from enodia_sentinel.config import Config
from enodia_sentinel.detectors import (
credential_access, deleted_exe, egress, input_snooper, ld_preload,
new_listener, new_suid, reverse_shell,
memory_obfuscation, new_listener, new_suid, reverse_shell,
stealth_network,
)
from enodia_sentinel.system import Socket, SystemState
from enodia_sentinel.system import MemoryMap, Socket, SystemState, parse_memory_maps
@dataclass
@ -26,6 +26,7 @@ class FakeProc:
uid: int = 0
cwd: str = "/"
fd_targets: dict = field(default_factory=dict)
memory_maps: list = field(default_factory=list)
def stdio_socket_inode(self):
return self._stdio_inode
@ -158,6 +159,61 @@ class TestStealthNetwork(unittest.TestCase):
self.assertEqual(list(stealth_network.detect(SystemState(sockets=[sock]), cfg())), [])
class TestMemoryObfuscation(unittest.TestCase):
def test_maps_parser_extracts_path(self):
text = "7f00-8000 rwxp 00000000 00:00 0 /memfd:stage (deleted)\n"
maps = parse_memory_maps(text)
self.assertEqual(maps[0].start, 0x7f00)
self.assertEqual(maps[0].end, 0x8000)
self.assertEqual(maps[0].perms, "rwxp")
self.assertEqual(maps[0].path, "/memfd:stage (deleted)")
def test_executable_memfd_alerts(self):
proc = FakeProc(
pid=350, comm="hoxha",
memory_maps=[MemoryMap(0x1000, 0x2000, "r-xp", "/memfd:stage (deleted)")],
)
alerts = list(memory_obfuscation.detect(SystemState(processes=[proc]), cfg()))
self.assertEqual(len(alerts), 1)
self.assertEqual(alerts[0].signature, "memory_obfuscation")
self.assertEqual(alerts[0].severity, Severity.CRITICAL)
def test_rwx_anonymous_alerts(self):
proc = FakeProc(
pid=351, comm="packer",
memory_maps=[MemoryMap(0x3000, 0x4000, "rwxp", "")],
)
alerts = list(memory_obfuscation.detect(SystemState(processes=[proc]), cfg()))
self.assertEqual(len(alerts), 1)
self.assertEqual(alerts[0].severity, Severity.HIGH)
def test_process_hiding_library_alerts(self):
proc = FakeProc(
pid=352, comm="bash",
memory_maps=[MemoryMap(0x5000, 0x6000, "r-xp", "/usr/lib/libhide.so")],
)
alerts = list(memory_obfuscation.detect(SystemState(processes=[proc]), cfg()))
self.assertEqual(len(alerts), 1)
self.assertEqual(alerts[0].signature, "process_hiding_library")
self.assertEqual(alerts[0].severity, Severity.CRITICAL)
def test_jit_allowlisted_comm_ignored(self):
proc = FakeProc(
pid=353, comm="node",
memory_maps=[MemoryMap(0x7000, 0x8000, "rwxp", "")],
)
self.assertEqual(list(memory_obfuscation.detect(SystemState(processes=[proc]), cfg())), [])
def test_hide_library_alerts_even_in_jit_allowlisted_comm(self):
proc = FakeProc(
pid=354, comm="node",
memory_maps=[MemoryMap(0x9000, 0xa000, "r-xp", "/tmp/libhide.so")],
)
alerts = list(memory_obfuscation.detect(SystemState(processes=[proc]), cfg()))
self.assertEqual(len(alerts), 1)
self.assertEqual(alerts[0].signature, "process_hiding_library")
class TestNewSuid(unittest.TestCase):
def test_new_in_writable_is_critical(self):
state = SystemState(