Skip to content

Commit

Permalink
DLL hijacking detection
Browse files Browse the repository at this point in the history
  • Loading branch information
pedrofdez26 committed Jul 13, 2022
1 parent 30c8a65 commit e0acb9c
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 16 deletions.
11 changes: 8 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

## Installation

In order to run the plugin, [Python 3](https://www.python.org/downloads/) (version 3.9 or greater) and [Volatility 3](https://github.com/volatilityfoundation/volatility3) have to be installed on the machine where *Modex* is going to be used. Also, the following Python packages have to be installed: *py-tlsh*, *tabulate*. Additionally, the *Modex* plugin depends on the *SimplePteEnumerator* plugin (file named *simple_pteenum.py* that can be found [here](https://github.com/f-block/volatility-plugins)). The *SimplePteEnumerator* plugin allows *Modex* to know which pages are mapped in a given range inside a particular process private address space, and to differentiate between private and shared pages.
In order to run the plugin, [Python 3](https://www.python.org/downloads/) (version 3.9 or greater) and [Volatility 3](https://github.com/volatilityfoundation/volatility3) have to be installed on the machine where *Modex* is going to be used. Also, the following Python packages have to be installed: *py-tlsh*, *tabulate*. Additionally, the *Modex* plugin depends on the *SimplePteEnumerator* plugin (file named *simple_pteenum.py* that can be found [here](https://github.com/f-block/volatility-plugins)). The *SimplePteEnumerator* plugin allows *Modex* to know which pages are mapped in a given range inside the private address space of a process, and to differentiate between private and shared pages.

After installing *Volatility 3*, the *modex.py* file in this repository and all the Python files present in [here](https://github.com/f-block/volatility-plugins) must be placed in the *volatility3/framework/plugins/windows* directory, which is inside the cloned *Volatility 3* repository.

Expand Down Expand Up @@ -52,8 +52,8 @@ python3 setup.py install
Here is how to use the *InterModex* tool:

```
usage: inter_modex.py [-h] [-a] [-d MEMORY_DUMPS_DIRECTORY] [-l {DEBUG,INFO,WARNING,ERROR,CRITICAL}] [-m MODULE] [-o MODEX_OUTPUTS_DIRECTORY] [-p] [-r] [-s SUM_PATH]
[-t VOLATILITY_PATH] [-v]
usage: inter_modex.py [-h] [-a] [-d MEMORY_DUMPS_DIRECTORY] [--detect] [-l {DEBUG,INFO,WARNING,ERROR,CRITICAL}] [-m MODULE] [-o MODEX_OUTPUTS_DIRECTORY] [-p] [-r]
[-s SUM_PATH] [-t VOLATILITY_PATH] [-v]
Extracts a module as complete as possible from multiple memory dumps
Expand All @@ -62,6 +62,7 @@ optional arguments:
-a, --dump-anomalies When there are different shared pages at the same offset, dump those pages
-d MEMORY_DUMPS_DIRECTORY, --memory-dumps-directory MEMORY_DUMPS_DIRECTORY
directory where the memory dumps are (the Modex plugin will be called)
--detect detect the presence of the DLL hijacking technique
-l {DEBUG,INFO,WARNING,ERROR,CRITICAL}, --log-level {DEBUG,INFO,WARNING,ERROR,CRITICAL}
logging level
-m MODULE, --module MODULE
Expand All @@ -86,6 +87,10 @@ python3 inter_modex.py --memory-dumps-directory MemoryDumpsDirectory --volatilit
```
Additionally, for *InterModex* to work, the *python3* command has to be a valid command in the command line (and also the *python2* command if you want to derelocate the extracted module with *SUM*). Finally, the outputs produced by the *InterModex* tool are very similar to the ones generated by *Modex*, and the *tests.py* file can also be used to check if an *InterModex* output is correct.

# DLL Hijacking Detection

In addition to extracting a module as complete as possible, *Modex* and *InterModex* can also be used to detect the *DLL hijacking* technique. For that, the *--detect* option must be supplied. When this option is provided, the output is a directory that contains a JSON file and a text file. The JSON file contains information about the detection, and the text file is a log file with details about the execution.

# License

[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
Expand Down
12 changes: 6 additions & 6 deletions inter_modex.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,8 @@ def convert_mapped_modules_from_json_to_objects(mapped_modules: List[Dict[str, A
return mapped_modules_converted


def detect_dll_proxying_across_several_memory_dumps(modex_detection_attempts: List[ModexDetectionAttempt],
output_directory: str, logger) -> None:
def detect_dll_hijacking_across_several_memory_dumps(modex_detection_attempts: List[ModexDetectionAttempt],
output_directory: str, logger) -> None:
detection_info: Dict[str, Any] = {}
mapped_modules: List[Module] = []
for modex_detection_attempt in modex_detection_attempts:
Expand All @@ -172,7 +172,7 @@ def detect_dll_proxying_across_several_memory_dumps(modex_detection_attempts: Li
else:
suspicious_processes[modex_detection_attempt.memory_dump_location].append(module.process_id)

detection_info['dll_proxying_detection_result'] = True if suspicious_processes else False
detection_info['dll_hijacking_detection_result'] = True if suspicious_processes else False
detection_info['suspicious_processes'] = suspicious_processes

detection_info_path: str = os.path.join(output_directory, get_detection_information_filename())
Expand All @@ -195,13 +195,13 @@ def perform_detection(modex_outputs_directory: str, output_directory: str, logge
mapped_modules: List[Module] = convert_mapped_modules_from_json_to_objects(detection_info['mapped_modules'])
modex_detection_attempts.append(
ModexDetectionAttempt(detection_info['memory_dump_location'], mapped_modules,
detection_info['dll_proxying_detection_result'],
detection_info['dll_hijacking_detection_result'],
detection_info['suspicious_processes']))
else:
logger.info(
f'\tThe Modex output {successful_modex_output} was considered successful, but the .json file does not exist, and it must exist for a Modex output to be successful. As a result, this output will not be considered in the detection process.')

detect_dll_proxying_across_several_memory_dumps(modex_detection_attempts, output_directory, logger)
detect_dll_hijacking_across_several_memory_dumps(modex_detection_attempts, output_directory, logger)


def perform_mixture(modex_outputs_directory: str, perform_derelocation: bool, sum_path: str, dump_anomalies: bool,
Expand Down Expand Up @@ -306,7 +306,7 @@ def validate_arguments() -> Dict[str, Any]:
help='directory where the memory dumps are (the Modex plugin will be called)')
arg_parser.add_argument('--detect',
action='store_true',
help='detect the presence of the DLL proxying technique')
help='detect the presence of the DLL hijacking technique')
arg_parser.add_argument('-l',
'--log-level',
choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'],
Expand Down
14 changes: 7 additions & 7 deletions modex.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,11 +297,11 @@ def get_detection_information_filename() -> str:

def log_detection_process_common_parts(logger) -> None:
logger.info(
f'\nThe --detect option was supplied to detect the presence of the DLL proxying technique. For more details check the {get_detection_information_filename()} file.')
f'\nThe --detect option was supplied to detect the presence of the DLL hijacking technique. For more details check the {get_detection_information_filename()} file.')


def detect_dll_proxying_inside_one_memory_dump(modules: List[Module], output_directory: str, memory_dump_location: str,
logger) -> List[str]:
def detect_dll_hijacking_inside_one_memory_dump(modules: List[Module], output_directory: str, memory_dump_location: str,
logger) -> List[str]:
mapped_modules_info: List[Dict[str, Any]] = []
for module in modules:
mapped_modules_info.append(module.get_information_for_metadata_file())
Expand All @@ -317,7 +317,7 @@ def detect_dll_proxying_inside_one_memory_dump(modules: List[Module], output_dir
if module.path.casefold() != most_common_path or module.size != most_common_size:
suspicious_modules.append(module)

detection_info['dll_proxying_detection_result'] = True if suspicious_modules else False
detection_info['dll_hijacking_detection_result'] = True if suspicious_modules else False

suspicious_processes: List[int] = []
for suspicious_module in suspicious_modules:
Expand Down Expand Up @@ -557,7 +557,7 @@ def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]
default=False,
optional=True),
requirements.BooleanRequirement(name='detect',
description="Detect the presence of the DLL proxying technique",
description="Detect the presence of the DLL hijacking technique",
default=False,
optional=True)
]
Expand Down Expand Up @@ -644,8 +644,8 @@ def run(self):
return renderers.TreeGrid([("Filename", str)], self._generator(files_finally_generated))

if is_detect_option_supplied:
files_finally_generated += detect_dll_proxying_inside_one_memory_dump(modules_to_mix, output_directory,
memory_dump_location, logger)
files_finally_generated += detect_dll_hijacking_inside_one_memory_dump(modules_to_mix, output_directory,
memory_dump_location, logger)
return renderers.TreeGrid([("Filename", str)], self._generator(files_finally_generated))

# Make sure that the modules can be mixed
Expand Down

0 comments on commit e0acb9c

Please sign in to comment.