Skip to content

Commit 5a8f907

Browse files
committed
scripts: add CONTROL_FLOW to ELF security checks
1 parent e13f8f7 commit 5a8f907

File tree

2 files changed

+49
-13
lines changed

2 files changed

+49
-13
lines changed

contrib/devtools/security-check.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,17 @@ def check_ELF_separate_code(binary):
111111
return False
112112
return True
113113

114+
def check_ELF_control_flow(binary) -> bool:
115+
'''
116+
Check for control flow instrumentation
117+
'''
118+
main = binary.get_function_address('main')
119+
content = binary.get_content_from_virtual_address(main, 4, lief.Binary.VA_TYPES.AUTO)
120+
121+
if content == [243, 15, 30, 250]: # endbr64
122+
return True
123+
return False
124+
114125
def check_PE_DYNAMIC_BASE(binary) -> bool:
115126
'''PIE: DllCharacteristics bit 0x40 signifies dynamicbase (ASLR)'''
116127
return lief.PE.DLL_CHARACTERISTICS.DYNAMIC_BASE in binary.optional_header.dll_characteristics_lists
@@ -210,7 +221,7 @@ def check_MACHO_control_flow(binary) -> bool:
210221

211222
CHECKS = {
212223
lief.EXE_FORMATS.ELF: {
213-
lief.ARCHITECTURES.X86: BASE_ELF,
224+
lief.ARCHITECTURES.X86: BASE_ELF + [('CONTROL_FLOW', check_ELF_control_flow)],
214225
lief.ARCHITECTURES.ARM: BASE_ELF,
215226
lief.ARCHITECTURES.ARM64: BASE_ELF,
216227
lief.ARCHITECTURES.PPC: BASE_ELF,

contrib/devtools/test-security-check.py

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
'''
66
Test script for security-check.py
77
'''
8+
import lief #type:ignore
89
import os
910
import subprocess
1011
from typing import List
@@ -41,25 +42,49 @@ def call_security_check(cc, source, executable, options):
4142
p = subprocess.run(['./contrib/devtools/security-check.py',executable], stdout=subprocess.PIPE, universal_newlines=True)
4243
return (p.returncode, p.stdout.rstrip())
4344

45+
def get_arch(cc, source, executable):
46+
subprocess.run([*cc, source, '-o', executable], check=True)
47+
binary = lief.parse(executable)
48+
arch = binary.abstract.header.architecture
49+
os.remove(executable)
50+
return arch
51+
4452
class TestSecurityChecks(unittest.TestCase):
4553
def test_ELF(self):
4654
source = 'test1.c'
4755
executable = 'test1'
4856
cc = determine_wellknown_cmd('CC', 'gcc')
4957
write_testcode(source)
58+
arch = get_arch(cc, source, executable)
5059

51-
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-zexecstack','-fno-stack-protector','-Wl,-znorelro','-no-pie','-fno-PIE', '-Wl,-z,separate-code']),
52-
(1, executable+': failed PIE NX RELRO Canary'))
53-
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fno-stack-protector','-Wl,-znorelro','-no-pie','-fno-PIE', '-Wl,-z,separate-code']),
54-
(1, executable+': failed PIE RELRO Canary'))
55-
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fstack-protector-all','-Wl,-znorelro','-no-pie','-fno-PIE', '-Wl,-z,separate-code']),
56-
(1, executable+': failed PIE RELRO'))
57-
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fstack-protector-all','-Wl,-znorelro','-pie','-fPIE', '-Wl,-z,separate-code']),
58-
(1, executable+': failed RELRO'))
59-
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fstack-protector-all','-Wl,-zrelro','-Wl,-z,now','-pie','-fPIE', '-Wl,-z,noseparate-code']),
60-
(1, executable+': failed separate_code'))
61-
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fstack-protector-all','-Wl,-zrelro','-Wl,-z,now','-pie','-fPIE', '-Wl,-z,separate-code']),
62-
(0, ''))
60+
if arch == lief.ARCHITECTURES.X86:
61+
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-zexecstack','-fno-stack-protector','-Wl,-znorelro','-no-pie','-fno-PIE', '-Wl,-z,separate-code']),
62+
(1, executable+': failed PIE NX RELRO Canary CONTROL_FLOW'))
63+
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fno-stack-protector','-Wl,-znorelro','-no-pie','-fno-PIE', '-Wl,-z,separate-code']),
64+
(1, executable+': failed PIE RELRO Canary CONTROL_FLOW'))
65+
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fstack-protector-all','-Wl,-znorelro','-no-pie','-fno-PIE', '-Wl,-z,separate-code']),
66+
(1, executable+': failed PIE RELRO CONTROL_FLOW'))
67+
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fstack-protector-all','-Wl,-znorelro','-pie','-fPIE', '-Wl,-z,separate-code']),
68+
(1, executable+': failed RELRO CONTROL_FLOW'))
69+
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fstack-protector-all','-Wl,-zrelro','-Wl,-z,now','-pie','-fPIE', '-Wl,-z,noseparate-code']),
70+
(1, executable+': failed separate_code CONTROL_FLOW'))
71+
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fstack-protector-all','-Wl,-zrelro','-Wl,-z,now','-pie','-fPIE', '-Wl,-z,separate-code']),
72+
(1, executable+': failed CONTROL_FLOW'))
73+
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fstack-protector-all','-Wl,-zrelro','-Wl,-z,now','-pie','-fPIE', '-Wl,-z,separate-code', '-fcf-protection=full']),
74+
(0, ''))
75+
else:
76+
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-zexecstack','-fno-stack-protector','-Wl,-znorelro','-no-pie','-fno-PIE', '-Wl,-z,separate-code']),
77+
(1, executable+': failed PIE NX RELRO Canary'))
78+
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fno-stack-protector','-Wl,-znorelro','-no-pie','-fno-PIE', '-Wl,-z,separate-code']),
79+
(1, executable+': failed PIE RELRO Canary'))
80+
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fstack-protector-all','-Wl,-znorelro','-no-pie','-fno-PIE', '-Wl,-z,separate-code']),
81+
(1, executable+': failed PIE RELRO'))
82+
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fstack-protector-all','-Wl,-znorelro','-pie','-fPIE', '-Wl,-z,separate-code']),
83+
(1, executable+': failed RELRO'))
84+
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fstack-protector-all','-Wl,-zrelro','-Wl,-z,now','-pie','-fPIE', '-Wl,-z,noseparate-code']),
85+
(1, executable+': failed separate_code'))
86+
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fstack-protector-all','-Wl,-zrelro','-Wl,-z,now','-pie','-fPIE', '-Wl,-z,separate-code']),
87+
(0, ''))
6388

6489
clean_files(source, executable)
6590

0 commit comments

Comments
 (0)