Skip to content

Instantly share code, notes, and snippets.

@romainthomas
Created October 30, 2022 19:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save romainthomas/5898cd2c64b01b29270d9cad6787c1ff to your computer and use it in GitHub Desktop.
Save romainthomas/5898cd2c64b01b29270d9cad6787c1ff to your computer and use it in GitHub Desktop.
"""
Trick on the ELF format to complete classical obfuscation
It can be integrated as follows:
add_custom_command(TARGET native-lib
POST_BUILD COMMENT "Full binary strip"
COMMAND ${CMAKE_STRIP} --discard-all --discard-locals --strip-all --strip-unneeded $<TARGET_FILE:native-lib>
POST_BUILD COMMENT "Patching with LIEF"
COMMAND /usr/bin/env python /home/romain/dev/open-obfuscator/demo/break.py $<TARGET_FILE:native-lib> $<TARGET_FILE:native-lib>
)
"""
import sys
import lief
import random
LIB_SYM_POOL = "/usr/lib/libLLVM.so"
LIB = lief.parse(LIB_SYM_POOL)
pool_names = [s.name for s in LIB.exported_symbols]
print(f"Pool size: {len(pool_names)}")
def swap(target: lief.ELF.Binary, lhs: str, rhs: str):
lhs_section = target.get_section(lhs)
rhs_section = target.get_section(rhs)
if lhs_section is None or rhs_section is None:
print(f"Can't find {lhs} or {rhs}")
return
backup = lhs_section.offset, lhs_section.virtual_address, lhs_section.size, lhs_section.name
lhs_section.offset = rhs_section.offset
lhs_section.virtual_address = rhs_section.virtual_address
lhs_section.size = rhs_section.size
lhs_section.name = rhs_section.name
rhs_section.offset = backup[0]
rhs_section.virtual_address = backup[1]
rhs_section.size = backup[2]
rhs_section.name = backup[3]
def shuffle(target: lief.ELF.Binary, name):
section = target.get_section(name)
if section is None:
print(f"Can't find {name}")
return
section_content = list(section.content)
random.shuffle(section_content)
section.content = section_content
inpath = sys.argv[1]
outpath = sys.argv[2]
target: lief.ELF.Binary = lief.parse(inpath)
export_table = {s.value for s in target.exported_symbols}
text = target.get_section(".text")
for f in target.functions:
if f.address in export_table:
continue
name = random.choice(pool_names)
pool_names.remove(name)
target.add_exported_function(f.address + 3, name)
shuffle(target, ".eh_frame")
shuffle(target, ".eh_frame_hdr")
shuffle(target, ".gcc_except_table")
swap(target, ".got", ".plt")
swap(target, ".rodata", ".rela.plt")
swap(target, ".data.rel.ro", ".got")
swap(target, ".text", ".eh_frame")
dynsym: lief.ELF.Section = target.get_section(".dynsym").as_frame()
sizeof_sym = dynsym.entry_size
dynsym.size = 10 * sizeof_sym
target.write(outpath)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment