-
-
Save romainthomas/5898cd2c64b01b29270d9cad6787c1ff to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
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