Skip to content

Commit 7c82da4

Browse files
committed
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).
1 parent 5d4c70d commit 7c82da4

File tree

3 files changed

+20
-2
lines changed

3 files changed

+20
-2
lines changed

volatility3/framework/layers/intel.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,11 @@ def _mask(value: int, high_bit: int, low_bit: int) -> int:
110110
def _page_is_valid(entry: int) -> bool:
111111
"""Returns whether a particular page is valid based on its entry."""
112112
return bool(entry & 1)
113+
114+
@staticmethod
115+
def _page_is_dirty(entry: int) -> bool:
116+
"""Returns whether a particular page is dirty based on its entry."""
117+
return bool(entry & (1<<6))
113118

114119
def canonicalize(self, addr: int) -> int:
115120
"""Canonicalizes an address by performing an appropiate sign extension on the higher addresses"""
@@ -259,6 +264,10 @@ def is_valid(self, offset: int, length: int = 1) -> bool:
259264
except exceptions.InvalidAddressException:
260265
return False
261266

267+
def is_dirty(self, offset: int) -> bool:
268+
"""Returns whether the page at offset is marked dirty"""
269+
return self._page_is_dirty(self._translate_entry(offset)[0])
270+
262271
def mapping(
263272
self, offset: int, length: int, ignore_errors: bool = False
264273
) -> Iterable[Tuple[int, int, int, int, str]]:

volatility3/framework/plugins/linux/malfind.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ def _list_injections(self, task):
4747
proc_layer = self.context.layers[proc_layer_name]
4848

4949
for vma in task.mm.get_vma_iter():
50-
if vma.is_suspicious() and vma.get_name(self.context, task) != "[vdso]":
50+
if vma.is_suspicious(proc_layer) and vma.get_name(self.context, task) != "[vdso]":
5151
data = proc_layer.read(vma.vm_start, 64, pad=True)
5252
yield vma, data
5353

volatility3/framework/symbols/linux/extensions/__init__.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -578,7 +578,7 @@ def get_name(self, context, task):
578578
return fname
579579

580580
# used by malfind
581-
def is_suspicious(self):
581+
def is_suspicious(self, proclayer):
582582
ret = False
583583

584584
flags_str = self.get_protection()
@@ -587,6 +587,15 @@ def is_suspicious(self):
587587
ret = True
588588
elif flags_str == "r-x" and self.vm_file.dereference().vol.offset == 0:
589589
ret = True
590+
elif "x" in flags_str:
591+
for i in range(self.vm_start,self.vm_end,constants.linux.PAGE_SHIFT):
592+
try:
593+
if proclayer.is_dirty(i):
594+
vollog.warning(f"Found malicious (dirty+exec) page at {hex(i)} !")
595+
ret = True
596+
break
597+
except (exceptions.PagedInvalidAddressException, exceptions.InvalidAddressException):
598+
pass
590599
return ret
591600

592601

0 commit comments

Comments
 (0)