diff options
Diffstat (limited to 'plugins/python/checksec/mitigations.py')
-rw-r--r-- | plugins/python/checksec/mitigations.py | 135 |
1 files changed, 135 insertions, 0 deletions
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) |