blob: f054fac4efa656eb738bc2e64c17cc2e76f97d17 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
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.ElfProgramHeaderType.PT_GNU_STACK)
status = stack is None or stack.p_flags & ElfFormat.ElfProgramHeaderFlags.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.ElfHeaderType.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.ElfProgramHeaderType.PT_GNU_RELRO)
entry = self._fmt.find_dynamic_item_by_type(ElfFormat.ElfSectionHeaderFlags.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)
|