aboutsummaryrefslogtreecommitdiff
path: root/contrib/devtools
diff options
context:
space:
mode:
authorfanquake <fanquake@gmail.com>2021-04-07 09:38:00 +0800
committerfanquake <fanquake@gmail.com>2021-05-04 20:47:59 +0800
commita25b2e965c93fe2a46a2f8f1e7bdf5642d453511 (patch)
treec4cb7754aead90af3f31671d10e803c27f75ab05 /contrib/devtools
parent7e7eae7aa86ab95c44eed601f8c993285a256bbc (diff)
contrib: use LIEF for macOS security checks
Diffstat (limited to 'contrib/devtools')
-rwxr-xr-xcontrib/devtools/security-check.py54
1 files changed, 12 insertions, 42 deletions
diff --git a/contrib/devtools/security-check.py b/contrib/devtools/security-check.py
index 7a0761ad15..bc65d9a9be 100755
--- a/contrib/devtools/security-check.py
+++ b/contrib/devtools/security-check.py
@@ -6,17 +6,17 @@
Perform basic security checks on a series of executables.
Exit status will be 0 if successful, and the program will be silent.
Otherwise the exit status will be 1 and it will log which executables failed which checks.
-Needs `objdump` (for PE) and `otool` (for MACHO).
+Needs `objdump` (for PE).
'''
import subprocess
import sys
import os
from typing import List, Optional
+import lief
import pixie
OBJDUMP_CMD = os.getenv('OBJDUMP', '/usr/bin/objdump')
-OTOOL_CMD = os.getenv('OTOOL', '/usr/bin/otool')
def run_command(command) -> str:
p = subprocess.run(command, stdout=subprocess.PIPE, check=True, universal_newlines=True)
@@ -184,71 +184,41 @@ def check_PE_NX(executable) -> bool:
bits = get_PE_dll_characteristics(executable)
return (bits & IMAGE_DLL_CHARACTERISTICS_NX_COMPAT) == IMAGE_DLL_CHARACTERISTICS_NX_COMPAT
-def get_MACHO_executable_flags(executable) -> List[str]:
- stdout = run_command([OTOOL_CMD, '-vh', executable])
-
- flags: List[str] = []
- for line in stdout.splitlines():
- tokens = line.split()
- # filter first two header lines
- if 'magic' in tokens or 'Mach' in tokens:
- continue
- # filter ncmds and sizeofcmds values
- flags += [t for t in tokens if not t.isdigit()]
- return flags
-
def check_MACHO_PIE(executable) -> bool:
'''
Check for position independent executable (PIE), allowing for address space randomization.
'''
- flags = get_MACHO_executable_flags(executable)
- if 'PIE' in flags:
- return True
- return False
+ binary = lief.parse(executable)
+ return binary.is_pie
def check_MACHO_NOUNDEFS(executable) -> bool:
'''
Check for no undefined references.
'''
- flags = get_MACHO_executable_flags(executable)
- if 'NOUNDEFS' in flags:
- return True
- return False
+ binary = lief.parse(executable)
+ return binary.header.has(lief.MachO.HEADER_FLAGS.NOUNDEFS)
def check_MACHO_NX(executable) -> bool:
'''
Check for no stack execution
'''
- flags = get_MACHO_executable_flags(executable)
- if 'ALLOW_STACK_EXECUTION' in flags:
- return False
- return True
+ binary = lief.parse(executable)
+ return binary.has_nx
def check_MACHO_LAZY_BINDINGS(executable) -> bool:
'''
Check for no lazy bindings.
We don't use or check for MH_BINDATLOAD. See #18295.
'''
- stdout = run_command([OTOOL_CMD, '-l', executable])
-
- for line in stdout.splitlines():
- tokens = line.split()
- if 'lazy_bind_off' in tokens or 'lazy_bind_size' in tokens:
- if tokens[1] != '0':
- return False
- return True
+ binary = lief.parse(executable)
+ return binary.dyld_info.lazy_bind == (0,0)
def check_MACHO_Canary(executable) -> bool:
'''
Check for use of stack canary
'''
- stdout = run_command([OTOOL_CMD, '-Iv', executable])
-
- ok = False
- for line in stdout.splitlines():
- if '___stack_chk_fail' in line:
- ok = True
- return ok
+ binary = lief.parse(executable)
+ return binary.has_symbol('___stack_chk_fail')
CHECKS = {
'ELF': [