12
12
import sys
13
13
import os
14
14
15
+ from typing import List , Optional
16
+
15
17
READELF_CMD = os .getenv ('READELF' , '/usr/bin/readelf' )
16
18
OBJDUMP_CMD = os .getenv ('OBJDUMP' , '/usr/bin/objdump' )
17
19
OTOOL_CMD = os .getenv ('OTOOL' , '/usr/bin/otool' )
18
20
19
- def run_command (command ):
21
+ def run_command (command ) -> str :
20
22
p = subprocess .run (command , stdout = subprocess .PIPE , check = True , universal_newlines = True )
21
23
return p .stdout
22
24
23
- def check_ELF_PIE (executable ):
25
+ def check_ELF_PIE (executable ) -> bool :
24
26
'''
25
27
Check for position independent executable (PIE), allowing for address space randomization.
26
28
'''
27
29
stdout = run_command ([READELF_CMD , '-h' , '-W' , executable ])
28
30
29
31
ok = False
30
32
for line in stdout .splitlines ():
31
- line = line .split ()
32
- if len (line )>= 2 and line [0 ] == 'Type:' and line [1 ] == 'DYN' :
33
+ tokens = line .split ()
34
+ if len (line )>= 2 and tokens [0 ] == 'Type:' and tokens [1 ] == 'DYN' :
33
35
ok = True
34
36
return ok
35
37
@@ -60,7 +62,7 @@ def get_ELF_program_headers(executable):
60
62
count += 1
61
63
return headers
62
64
63
- def check_ELF_NX (executable ):
65
+ def check_ELF_NX (executable ) -> bool :
64
66
'''
65
67
Check that no sections are writable and executable (including the stack)
66
68
'''
@@ -73,7 +75,7 @@ def check_ELF_NX(executable):
73
75
have_wx = True
74
76
return have_gnu_stack and not have_wx
75
77
76
- def check_ELF_RELRO (executable ):
78
+ def check_ELF_RELRO (executable ) -> bool :
77
79
'''
78
80
Check for read-only relocations.
79
81
GNU_RELRO program header must exist
@@ -99,7 +101,7 @@ def check_ELF_RELRO(executable):
99
101
have_bindnow = True
100
102
return have_gnu_relro and have_bindnow
101
103
102
- def check_ELF_Canary (executable ):
104
+ def check_ELF_Canary (executable ) -> bool :
103
105
'''
104
106
Check for use of stack canary
105
107
'''
@@ -126,14 +128,14 @@ def get_PE_dll_characteristics(executable) -> int:
126
128
IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE = 0x0040
127
129
IMAGE_DLL_CHARACTERISTICS_NX_COMPAT = 0x0100
128
130
129
- def check_PE_DYNAMIC_BASE (executable ):
131
+ def check_PE_DYNAMIC_BASE (executable ) -> bool :
130
132
'''PIE: DllCharacteristics bit 0x40 signifies dynamicbase (ASLR)'''
131
133
bits = get_PE_dll_characteristics (executable )
132
134
return (bits & IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE ) == IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE
133
135
134
136
# Must support high-entropy 64-bit address space layout randomization
135
137
# in addition to DYNAMIC_BASE to have secure ASLR.
136
- def check_PE_HIGH_ENTROPY_VA (executable ):
138
+ def check_PE_HIGH_ENTROPY_VA (executable ) -> bool :
137
139
'''PIE: DllCharacteristics bit 0x20 signifies high-entropy ASLR'''
138
140
bits = get_PE_dll_characteristics (executable )
139
141
return (bits & IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA ) == IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA
@@ -147,12 +149,12 @@ def check_PE_RELOC_SECTION(executable) -> bool:
147
149
return True
148
150
return False
149
151
150
- def check_PE_NX (executable ):
152
+ def check_PE_NX (executable ) -> bool :
151
153
'''NX: DllCharacteristics bit 0x100 signifies nxcompat (DEP)'''
152
154
bits = get_PE_dll_characteristics (executable )
153
155
return (bits & IMAGE_DLL_CHARACTERISTICS_NX_COMPAT ) == IMAGE_DLL_CHARACTERISTICS_NX_COMPAT
154
156
155
- def get_MACHO_executable_flags (executable ):
157
+ def get_MACHO_executable_flags (executable ) -> List [ str ] :
156
158
stdout = run_command ([OTOOL_CMD , '-vh' , executable ])
157
159
158
160
flags = []
@@ -240,7 +242,7 @@ def check_MACHO_Canary(executable) -> bool:
240
242
]
241
243
}
242
244
243
- def identify_executable (executable ):
245
+ def identify_executable (executable ) -> Optional [ str ] :
244
246
with open (filename , 'rb' ) as f :
245
247
magic = f .read (4 )
246
248
if magic .startswith (b'MZ' ):
0 commit comments