Skip to content

Instantly share code, notes, and snippets.

@moyix
Created September 2, 2022 16:12
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save moyix/2154125d0cb9947ec0525fb49449fab7 to your computer and use it in GitHub Desktop.
Save moyix/2154125d0cb9947ec0525fb49449fab7 to your computer and use it in GitHub Desktop.
A faster check to see if a binary has a constructor that enables FTZ/DAZ that just does byte matching
import sys
import mmap
from elftools.elf.elffile import ELFFile, ELFError
import struct
set_fast_math_code = bytes.fromhex('0fae5c24fc814c24fc408000000fae5424fcc3')
def load_bytes_from_elf(bindata, elf, vaddr, size):
try:
paddr = next(iter(elf.address_offsets(vaddr)))
except StopIteration:
return None
return bindata[paddr:paddr+size]
def check_for_ffast_math(elf, bindata, addr):
# +4 because we may have an endbr64 instruction (f30f1efa) in the prologue
code = load_bytes_from_elf(bindata, elf, addr, len(set_fast_math_code)+4)
if code is None:
return False
return set_fast_math_code in code
for filename in sys.argv[1:]:
print(f"{filename} ", end="", flush=True)
try:
elf = ELFFile(open(filename,'rb'))
except ELFError:
print("is not an ELF file")
continue
if (arch := elf.get_machine_arch()) != 'x64':
print(f"is {arch} not x64")
continue
bindata = mmap.mmap(elf.stream.fileno(), 0, access=mmap.ACCESS_READ)
s = elf.get_section_by_name('.init_array')
if s is not None and (ia_data := s.data()):
constructors = struct.unpack(f'<{len(ia_data)//8}Q', ia_data)
else:
constructors = []
i = len(constructors)
print(f"({i} constructor{'s'[:i^1]}) ", end="", flush=True)
for addr in constructors:
if check_for_ffast_math(elf, bindata, addr):
print(f"contains ffast-math constructor at {hex(addr)}")
break
else:
print("is clean")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment