check IoC of dirty bit in PTEs from executable VMAs.

this can for example detect code injected using ptrace().
this can also detect injected code that was reset to the original code (malware uninstalled before memory dump happened).
This commit is contained in:
xabrouck
2023-08-14 11:53:14 +02:00
parent 5d4c70d517
commit 7c82da4f50
3 changed files with 20 additions and 2 deletions
+9
View File
@@ -110,6 +110,11 @@ class Intel(linear.LinearlyMappedLayer):
def _page_is_valid(entry: int) -> bool:
"""Returns whether a particular page is valid based on its entry."""
return bool(entry & 1)
@staticmethod
def _page_is_dirty(entry: int) -> bool:
"""Returns whether a particular page is dirty based on its entry."""
return bool(entry & (1<<6))
def canonicalize(self, addr: int) -> int:
"""Canonicalizes an address by performing an appropiate sign extension on the higher addresses"""
@@ -259,6 +264,10 @@ class Intel(linear.LinearlyMappedLayer):
except exceptions.InvalidAddressException:
return False
def is_dirty(self, offset: int) -> bool:
"""Returns whether the page at offset is marked dirty"""
return self._page_is_dirty(self._translate_entry(offset)[0])
def mapping(
self, offset: int, length: int, ignore_errors: bool = False
) -> Iterable[Tuple[int, int, int, int, str]]:
@@ -47,7 +47,7 @@ class Malfind(interfaces.plugins.PluginInterface):
proc_layer = self.context.layers[proc_layer_name]
for vma in task.mm.get_vma_iter():
if vma.is_suspicious() and vma.get_name(self.context, task) != "[vdso]":
if vma.is_suspicious(proc_layer) and vma.get_name(self.context, task) != "[vdso]":
data = proc_layer.read(vma.vm_start, 64, pad=True)
yield vma, data
@@ -578,7 +578,7 @@ class vm_area_struct(objects.StructType):
return fname
# used by malfind
def is_suspicious(self):
def is_suspicious(self, proclayer):
ret = False
flags_str = self.get_protection()
@@ -587,6 +587,15 @@ class vm_area_struct(objects.StructType):
ret = True
elif flags_str == "r-x" and self.vm_file.dereference().vol.offset == 0:
ret = True
elif "x" in flags_str:
for i in range(self.vm_start,self.vm_end,constants.linux.PAGE_SHIFT):
try:
if proclayer.is_dirty(i):
vollog.warning(f"Found malicious (dirty+exec) page at {hex(i)} !")
ret = True
break
except (exceptions.PagedInvalidAddressException, exceptions.InvalidAddressException):
pass
return ret