diff options
| author | Cyrille Bagard <nocbos@gmail.com> | 2018-12-27 22:35:39 (GMT) | 
|---|---|---|
| committer | Cyrille Bagard <nocbos@gmail.com> | 2018-12-27 22:35:39 (GMT) | 
| commit | 865f6d87f3bce7f569343382c3dfd1bc68dcacee (patch) | |
| tree | 64869be2c5e7ad9285829b48ba7f7b446d73e3ec | |
| parent | d33e8935c5186ab2459dfa6c9340396377524fb1 (diff) | |
Displayed mitigations for Elf files using a new Python plugin.
| -rw-r--r-- | configure.ac | 1 | ||||
| -rw-r--r-- | plugins/python/Makefile.am | 2 | ||||
| -rw-r--r-- | plugins/python/checksec/Makefile.am | 9 | ||||
| -rw-r--r-- | plugins/python/checksec/__init__.py | 4 | ||||
| -rw-r--r-- | plugins/python/checksec/mitigations.py | 135 | ||||
| -rw-r--r-- | plugins/python/checksec/plugin.py | 39 | 
6 files changed, 189 insertions, 1 deletions
diff --git a/configure.ac b/configure.ac index 3943a2f..b514ea5 100644 --- a/configure.ac +++ b/configure.ac @@ -394,6 +394,7 @@ AC_CONFIG_FILES([Makefile                   plugins/pychrysalide/mangling/Makefile                   plugins/python/Makefile                   plugins/python/apkfiles/Makefile +                 plugins/python/checksec/Makefile                   plugins/readdex/Makefile                   plugins/readelf/Makefile                   plugins/readmc/Makefile diff --git a/plugins/python/Makefile.am b/plugins/python/Makefile.am index efbb704..1560913 100644 --- a/plugins/python/Makefile.am +++ b/plugins/python/Makefile.am @@ -1,2 +1,2 @@ -SUBDIRS = apkfiles +SUBDIRS = apkfiles checksec diff --git a/plugins/python/checksec/Makefile.am b/plugins/python/checksec/Makefile.am new file mode 100644 index 0000000..eecee28 --- /dev/null +++ b/plugins/python/checksec/Makefile.am @@ -0,0 +1,9 @@ + +checksecdir = $(pluginsdatadir)/python/checksec + +checksec_DATA = 							\ +	__init__.py								\ +	mitigations.py							\ +	plugin.py + +EXTRA_DIST = $(checksec_DATA) diff --git a/plugins/python/checksec/__init__.py b/plugins/python/checksec/__init__.py new file mode 100644 index 0000000..691b58d --- /dev/null +++ b/plugins/python/checksec/__init__.py @@ -0,0 +1,4 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +from checksec.plugin import CheckSec as AutoLoad diff --git a/plugins/python/checksec/mitigations.py b/plugins/python/checksec/mitigations.py new file mode 100644 index 0000000..1539fa7 --- /dev/null +++ b/plugins/python/checksec/mitigations.py @@ -0,0 +1,135 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +from pychrysalide.format.elf import ElfFormat + + +class ElfMitigations(): + +    def __init__(self, fmt): +        """Look for mitigations in a loaded Elf format.""" + +        self._fmt = fmt + +        self._nx = self._get_nx_status() + +        self._pie = self._get_pie_status() + +        self._relro = self._get_reloc_status() + +        self._canary = self._get_canary_status() + + +    def _get_nx_status(self): +        """Find information about the stack status.""" + +        # Cf. https://wiki.gentoo.org/wiki/Hardened/GNU_stack_quickstart +        # ...#Causes_of_executable_stack_markings + +        # -Wl,-z,execstack / -Wl,-z,noexecstack + +        stack = self._fmt.find_program_by_type(ElfFormat.PT_GNU_STACK) + +        status = stack is None or stack.p_flags & ElfFormat.PF_X + +        return 'No' if status else 'Yes' + + +    def _get_pie_status(self): +        """Check for taking advantage of ASLR.""" + +        # Cf. https://stackoverflow.com/questions/2463150/what-is-the-fpie-option-for-position-independent-executables-in-gcc-and-ld/5030518#5030518 + +        # -pie -fPIE + +        hdr = self._fmt.get_header() + +        status = hdr.e_type == ElfFormat.ET_DYN + +        return 'Yes' if status else 'No' + + +    def _get_reloc_status(self): +        """Track protections for the GOT.""" + +        # Cf. https://wiki.debian.org/Hardening +        # ...#DEB_BUILD_HARDENING_RELRO_.28ld_-z_relro.29 + +        # -Wl,-z,relro / -Wl,-z,now + +        prgm = self._fmt.find_program_by_type(ElfFormat.PT_GNU_RELRO) + +        entry = self._fmt.find_dynamic_item_by_type(ElfFormat.DT_BIND_NOW) + +        if prgm is None and entry is None: +            status = 'No' + +        elif not(prgm is None) and entry is None: +            status = 'Partial' + +        elif prgm is None and not(entry is None): +            status = 'Full' + +        else: +            status = 'Unknown' + +        return status + + +    def _get_canary_status(self): +        """Look for a canary as stack protection.""" + +        # Cf. https://outflux.net/blog/archives/2014*01/24/fstack-protector-strong/ + +        # -fno-stack-protector / -fstack-protector / -fstack-protector-all / -fstack-protector-strong + +        sym = self._fmt.find_symbol_by_label('__stack_chk_fail@plt') + +        status = sym is None + +        return 'No' if status else 'Yes' + + +    def __str__(self): +        """Output a mitigation summary.""" + +        desc = fmt.content.describe(True) + ':' + +        desc += '\n' + +        desc += '-' * (len(desc) - 1) + +        desc += '\n' + +        desc += 'NX: %s' % self._nx + +        desc += '\n' + +        desc += 'PIE: %s' % self._pie + +        desc += '\n' + +        desc += 'RelRO: %s' % self._relro + +        desc += '\n' + +        desc += 'Canary: %s' % self._canary + +        return desc + + +if __name__ == '__main__': + +    from pychrysalide.features import * +    import sys + +    cnt = FileContent(sys.argv[1]) +    fmt = ElfFormat(cnt) + +    binary = LoadedBinary(fmt) + +    status = binary.analyze_and_wait() + +    if status : +        m = ElfMitigations(binary.format) +        print(m) diff --git a/plugins/python/checksec/plugin.py b/plugins/python/checksec/plugin.py new file mode 100644 index 0000000..6efb9b5 --- /dev/null +++ b/plugins/python/checksec/plugin.py @@ -0,0 +1,39 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +from .mitigations import ElfMitigations +from pychrysalide import PluginModule +from pychrysalide.core import log_message, LMT_INFO +from pychrysalide.format.elf import ElfFormat + + +class CheckSec(PluginModule): +    """Check for Elf mititgations.""" + +    def get_interface(self): +        """Provide the full plugin description.""" + +        desc = { + +            'name' : 'CheckSec', +            'desc' : 'Output the exploit mitigations compiled with a loaded binary', +            'version' : '0.1', + +            'actions' : [ PluginModule.PGA_FORMAT_POST_ANALYSIS_ENDED ] + +        } + +        return desc + + +    def handle_format_analysis(self, action, format, gid, status): +        """Get notified at the end of format analysis.""" + +        if type(format) == ElfFormat: + +            m = ElfMitigations(format) + +            msg = 'Elf mitigations: NX: <b>%s</b>  PIE: <b>%s</b>  RelRO: <b>%s</b>  Canary: <b>%s</b>' \ +                  % (m._nx, m._pie, m._relro, m._canary) + +            self.log_message(LMT_INFO, msg)  | 
