|
|
@ -12,6 +12,10 @@ from typing import List
|
|
|
|
|
|
|
|
|
|
|
|
import lief #type:ignore
|
|
|
|
import lief #type:ignore
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# temporary constant, to be replaced with lief.ELF.ARCH.RISCV
|
|
|
|
|
|
|
|
# https://github.com/lief-project/LIEF/pull/562
|
|
|
|
|
|
|
|
LIEF_ELF_ARCH_RISCV = lief.ELF.ARCH(243)
|
|
|
|
|
|
|
|
|
|
|
|
def check_ELF_RELRO(binary) -> bool:
|
|
|
|
def check_ELF_RELRO(binary) -> bool:
|
|
|
|
'''
|
|
|
|
'''
|
|
|
|
Check for read-only relocations.
|
|
|
|
Check for read-only relocations.
|
|
|
@ -178,24 +182,24 @@ def check_control_flow(binary) -> bool:
|
|
|
|
return True
|
|
|
|
return True
|
|
|
|
return False
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BASE_ELF = [
|
|
|
|
CHECKS = {
|
|
|
|
|
|
|
|
lief.EXE_FORMATS.ELF: [
|
|
|
|
|
|
|
|
('PIE', check_PIE),
|
|
|
|
('PIE', check_PIE),
|
|
|
|
('NX', check_NX),
|
|
|
|
('NX', check_NX),
|
|
|
|
('RELRO', check_ELF_RELRO),
|
|
|
|
('RELRO', check_ELF_RELRO),
|
|
|
|
('Canary', check_ELF_Canary),
|
|
|
|
('Canary', check_ELF_Canary),
|
|
|
|
('separate_code', check_ELF_separate_code),
|
|
|
|
('separate_code', check_ELF_separate_code),
|
|
|
|
],
|
|
|
|
]
|
|
|
|
lief.EXE_FORMATS.PE: [
|
|
|
|
|
|
|
|
|
|
|
|
BASE_PE = [
|
|
|
|
('PIE', check_PIE),
|
|
|
|
('PIE', check_PIE),
|
|
|
|
('DYNAMIC_BASE', check_PE_DYNAMIC_BASE),
|
|
|
|
('DYNAMIC_BASE', check_PE_DYNAMIC_BASE),
|
|
|
|
('HIGH_ENTROPY_VA', check_PE_HIGH_ENTROPY_VA),
|
|
|
|
('HIGH_ENTROPY_VA', check_PE_HIGH_ENTROPY_VA),
|
|
|
|
('NX', check_NX),
|
|
|
|
('NX', check_NX),
|
|
|
|
('RELOC_SECTION', check_PE_RELOC_SECTION),
|
|
|
|
('RELOC_SECTION', check_PE_RELOC_SECTION),
|
|
|
|
('CONTROL_FLOW', check_PE_control_flow),
|
|
|
|
('CONTROL_FLOW', check_PE_control_flow),
|
|
|
|
],
|
|
|
|
]
|
|
|
|
lief.EXE_FORMATS.MACHO: [
|
|
|
|
|
|
|
|
|
|
|
|
BASE_MACHO = [
|
|
|
|
('PIE', check_PIE),
|
|
|
|
('PIE', check_PIE),
|
|
|
|
('NOUNDEFS', check_MACHO_NOUNDEFS),
|
|
|
|
('NOUNDEFS', check_MACHO_NOUNDEFS),
|
|
|
|
('NX', check_NX),
|
|
|
|
('NX', check_NX),
|
|
|
@ -203,6 +207,21 @@ lief.EXE_FORMATS.MACHO: [
|
|
|
|
('Canary', check_MACHO_Canary),
|
|
|
|
('Canary', check_MACHO_Canary),
|
|
|
|
('CONTROL_FLOW', check_control_flow),
|
|
|
|
('CONTROL_FLOW', check_control_flow),
|
|
|
|
]
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CHECKS = {
|
|
|
|
|
|
|
|
lief.EXE_FORMATS.ELF: {
|
|
|
|
|
|
|
|
lief.ARCHITECTURES.X86: BASE_ELF,
|
|
|
|
|
|
|
|
lief.ARCHITECTURES.ARM: BASE_ELF,
|
|
|
|
|
|
|
|
lief.ARCHITECTURES.ARM64: BASE_ELF,
|
|
|
|
|
|
|
|
lief.ARCHITECTURES.PPC: BASE_ELF,
|
|
|
|
|
|
|
|
LIEF_ELF_ARCH_RISCV: BASE_ELF,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
lief.EXE_FORMATS.PE: {
|
|
|
|
|
|
|
|
lief.ARCHITECTURES.X86: BASE_PE,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
lief.EXE_FORMATS.MACHO: {
|
|
|
|
|
|
|
|
lief.ARCHITECTURES.X86: BASE_MACHO,
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
if __name__ == '__main__':
|
|
|
@ -211,13 +230,24 @@ if __name__ == '__main__':
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
binary = lief.parse(filename)
|
|
|
|
binary = lief.parse(filename)
|
|
|
|
etype = binary.format
|
|
|
|
etype = binary.format
|
|
|
|
|
|
|
|
arch = binary.abstract.header.architecture
|
|
|
|
|
|
|
|
binary.concrete
|
|
|
|
|
|
|
|
|
|
|
|
if etype == lief.EXE_FORMATS.UNKNOWN:
|
|
|
|
if etype == lief.EXE_FORMATS.UNKNOWN:
|
|
|
|
print(f'{filename}: unknown executable format')
|
|
|
|
print(f'{filename}: unknown executable format')
|
|
|
|
retval = 1
|
|
|
|
retval = 1
|
|
|
|
continue
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if arch == lief.ARCHITECTURES.NONE:
|
|
|
|
|
|
|
|
if binary.header.machine_type == LIEF_ELF_ARCH_RISCV:
|
|
|
|
|
|
|
|
arch = LIEF_ELF_ARCH_RISCV
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
print(f'{filename}: unknown architecture')
|
|
|
|
|
|
|
|
retval = 1
|
|
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
|
|
failed: List[str] = []
|
|
|
|
failed: List[str] = []
|
|
|
|
for (name, func) in CHECKS[etype]:
|
|
|
|
for (name, func) in CHECKS[etype][arch]:
|
|
|
|
if not func(binary):
|
|
|
|
if not func(binary):
|
|
|
|
failed.append(name)
|
|
|
|
failed.append(name)
|
|
|
|
if failed:
|
|
|
|
if failed:
|
|
|
|