Ejemplo n.º 1
0
def get_elf_info(filepath_name):
    print_green(filepath_name)
    with open(filepath_name, 'rb') as f:
        elf = ELFFile(f)
    print_green(elf)
    print_blue(vars(elf))
    print_green("{0}".format(elf.header))
    print_red('--')

    # set data of pandas
    df = pd.DataFrame(columns=[
        "malware", "VirtualAddress", "ResourceSize", "DebugSize", "IATSize"
    ])

    # get file path
    PATH = path_HOME + u'/tool/pylib/doc2vec_testcode/bin_data/*'
    files = glob.glob(PATH)
    print_yelow(PATH)
    print_yelow(files)

    print_red('--')

    # extruct elf information from path's files for feature engieering
    for file in files:
        with open(file, 'rb') as f:
            data = ELFFile(f)
            if 0:
                print_green(data)
                print_blue(data._file_stringtable_section)
                print_purple(vars(data._file_stringtable_section))
                print_blue(data.structs)
            print_purple(vars(data.structs))
            print_blue(data.structs.Elf_addr)

            print_green(data.address_offsets(data, 0))
Ejemplo n.º 2
0
def _locate_parameter(library, disas, start_idx, target_register, mem_tag):
    retval = None
    idx = start_idx
    while idx > 0:
        idx -= 1
        earlier_insn = disas[idx]
        _, written = earlier_insn.regs_access()
        if target_register not in written:
            continue
        elif earlier_insn.id != capstone.x86_const.X86_INS_LEA:
            break
        # Here we know it was a <lea ..., %rsi>, and these
        # accesses will mostly be RIP-relative on x86_64 so we only support
        # <lea xxx(%rip), %rsi> for now.
        _, val = list(earlier_insn.operands)
        if val.type == mem_tag and val.value.mem.base == capstone.x86.X86_REG_RIP:
            straddr = earlier_insn.address + val.value.mem.disp + earlier_insn.size
            elffile = ELFFile(library.fd)
            stroff = next(elffile.address_offsets(straddr))
            strval = parse_cstring_from_stream(library.fd, stroff)
            retval = strval.decode('utf-8')
            break
    return retval
Ejemplo n.º 3
0
class ParsedElf:
    def __init__(self, file):
        self.file = file
        self.elf = ELFFile(file)

        self.is_dynamic = len(self.segment_by_type("PT_DYNAMIC")) != 0
        if not self.is_dynamic:
            return

        self.segments = list(self.elf.iter_segments())
        self.sections = list(self.elf.iter_sections())

        self.dynamic = only(self.segment_by_type("PT_DYNAMIC"))
        self.is_rela = self.tag("DT_PLTREL") == 7

        self.dynstr = self.read_section("DT_STRTAB", "DT_STRSZ")
        if self.is_rela:
            self.reldyn = self.read_section("DT_RELA", "DT_RELASZ")
            self.relstruct = self.elf.structs.Elf_Rela
        else:
            self.reldyn = self.read_section("DT_REL", "DT_RELSZ")
            self.relstruct = self.elf.structs.Elf_Rel
        self.reldyn_relocations = parse(self.reldyn, self.relstruct)

        self.relplt = self.read_section("DT_JMPREL", "DT_PLTRELSZ")
        self.relplt_relocations = parse(self.relplt, self.relstruct)

        self.symbols_count = max([
            relocation.r_info_sym
            for relocation in self.reldyn_relocations + self.relplt_relocations
        ]) + 1

        self.dynsym = self.read_section("DT_SYMTAB", "DT_SYMENT",
                                        self.symbols_count)
        self.symbols = parse(self.dynsym, self.elf.structs.Elf_Sym)

        self.gnuversion = self.read_section("DT_VERSYM",
                                            scale=self.symbols_count * 2)
        self.gnuversion_indices = self.parse_ints(self.gnuversion, 2)

        if self.has_tag("DT_VERNEED"):
            self.verneeds = []
            verneed_count = self.tag("DT_VERNEEDNUM")
            self.seek_address(self.tag("DT_VERNEED"))
            verneed_position = self.current_position()

            verneed_struct = self.elf.structs.Elf_Verneed
            vernaux_struct = self.elf.structs.Elf_Vernaux

            for _ in range(verneed_count):
                verneed = self.read_struct(verneed_struct)

                vernauxs = []
                vernaux_position = verneed_position + verneed.vn_aux
                self.file.seek(vernaux_position)
                for _ in range(verneed.vn_cnt):
                    vernaux = self.read_struct(vernaux_struct)
                    vernauxs.append(vernaux)

                    vernaux_position += vernaux.vna_next
                    self.file.seek(vernaux_position)

                self.verneeds.append((verneed, vernauxs))

                verneed_position += verneed.vn_next
                self.file.seek(verneed_position)

    def serialize_verneeds(self, list):
        stream = BytesIO()
        verneed_struct = self.elf.structs.Elf_Verneed
        vernaux_struct = self.elf.structs.Elf_Vernaux

        verneed_position = 0
        for verneed in list:
            stream.write(verneed_struct.build(verneed[0]))

            vernaux_position = verneed_position + verneed[0].vn_aux
            for vernaux in verneed[1]:
                stream.seek(vernaux_position)
                stream.write(vernaux_struct.build(vernaux))
                vernaux_position += vernaux.vna_next

            verneed_position += verneed[0].vn_next
            stream.seek(verneed_position)

        return stream.getvalue()

    def parse_ints(self, buffer, size):
        assert len(buffer) % size == 0
        size_map = {1: "B", 2: "H", 4: "I", 8: "Q"}
        if self.elf.little_endian:
            format = "<" + size_map[size]
        else:
            format = ">" + size_map[size]
        return [
            struct.unpack(format, chunk)[0] for chunk in chunks(buffer, size)
        ]

    def serialize_ints(self, list, size):
        size_map = {1: "B", 2: "H", 4: "I", 8: "Q"}
        if self.elf.little_endian:
            format = "<" + size_map[size]
        else:
            format = ">" + size_map[size]
        return b"".join([struct.pack(format, number) for number in list])

    def current_position(self):
        return self.file.tell()

    def read_struct(self, struct):
        buffer = self.file.read(struct.sizeof())
        assert len(buffer) == struct.sizeof()
        return only(parse(buffer, struct))

    def read_section(self, address_tag, size_tag=None, scale=1):
        if size_tag is not None:
            if not self.has_tag(size_tag):
                return bytes()
            else:
                size = self.tag(size_tag) * scale
        else:
            size = scale

        if self.has_tag(address_tag):
            return self.read_address(self.tag(address_tag), size)
        else:
            return bytes()

    def seek_address(self, address):
        self.file.seek(only(self.elf.address_offsets(address)))

    def read_address(self, address, size):
        self.seek_address(address)
        result = self.file.read(size)
        assert len(result) == size
        return result

    def segment_by_type(self, type):
        return [
            segment for segment in self.elf.iter_segments()
            if segment.header.p_type == type
        ]

    def dt_by_tag(self, search):
        return [
            tag for tag in self.dynamic.iter_tags()
            if tag.entry.d_tag == search
        ]

    def tag(self, tag):
        return only(self.dt_by_tag(tag)).entry.d_val

    def has_tag(self, tag):
        return len(self.dt_by_tag(tag)) != 0
Ejemplo n.º 4
0
def main():
    parser = argparse.ArgumentParser(
        description="Rewrite portions of .dynstr.")
    parser.add_argument("elf_path",
                        metavar="ELF",
                        help="path to the ELF file.")
    parser.add_argument("search", metavar="SEARCH", help="string to search.")
    parser.add_argument("replace", metavar="REPLACE", help="replacement.")
    parser.add_argument(
        "padding",
        metavar="PADDING",
        nargs="?",
        default="\x00",
        help="padding (default NUL).",
    )
    args = parser.parse_args()

    fail = False
    if len(args.replace) > len(args.search):
        fail = True

    if len(args.replace) < len(args.search):
        args.replace = args.replace + args.padding * (len(args.search) -
                                                      len(args.replace))

    args.replace = args.replace.encode("ascii")
    args.search = args.search.encode("ascii")

    with open(args.elf_path, "rb+") as elf_file:
        elf = ELFFile(elf_file)
        dynamic = unique_or_none([
            segment for segment in elf.iter_segments()
            if type(segment) is DynamicSegment
        ])

        if dynamic is None:
            log("Not a dynamic executable")
            return 0

        address = unique_or_none([
            tag.entry.d_val for tag in dynamic.iter_tags()
            if tag.entry.d_tag == "DT_STRTAB"
        ])

        offset = None
        if address:
            offset = unique_or_none(list(elf.address_offsets(address)))

        size = unique_or_none([
            tag.entry.d_val for tag in dynamic.iter_tags()
            if tag.entry.d_tag == "DT_STRSZ"
        ])

        if offset is None or size is None:
            log("DT_STRTAB not found")
            return 0

        elf_file.seek(offset)
        original = elf_file.read(size)

        new = original.replace(args.search, args.replace)
        if new != original:
            if fail:
                log("Search string is shorter than replacement.")
                return 1
            log("Patching")
            elf_file.seek(offset)
            elf_file.write(new)
        else:
            log("Nothing to patch")

    return 0
Ejemplo n.º 5
0
#!/usr/bin/python3.6

from elftools.elf.elffile import ELFFile
import subprocess
import binascii


with open('../task/task', 'rb') as f:
    #-- Get address of encrypted flag --#
    elf = ELFFile(f)
    symtab = elf.get_section_by_name('.symtab')
    target = symtab.get_symbol_by_name('C')[0].entry.st_value
    target = next(elf.address_offsets(target))

    #-- Read encrypted flag --#
    f.seek(target)
    target = f.read(64)

    #-- Decrypt == Encrypt --#
    out = subprocess.check_output('../task/task', input=target, stderr=subprocess.STDOUT)
    out = b''.join([l[len(b'[=] '):] for l in out.split(b'\n') if l.startswith(b'[=] ')])
    out = out.replace(b'0x', b'').replace(b' ', b'').replace(b',', b'')
    out = binascii.a2b_hex(out).rstrip(b'\0').decode('ascii')
    print(f'[+] Flag: {out}')
Ejemplo n.º 6
0
class ELFReader(object):
    def __init__(self, binary):
        self.fd = io.BytesIO(binary)
        self.elf = ELFFile(self.fd)
        self.arch = self.elf.get_machine_arch()
        if self.arch == "x64":
            self.cs = Cs(CS_ARCH_X86, CS_MODE_64)
        elif self.arch == "x86":
            self.cs = Cs(CS_ARCH_X86, CS_MODE_32)
        else:
            raise Exception("unknown arch")
        self.cs.detail = True
        self.vaddr = 0

    def vseek(self, addr):
        fileoff = list(self.elf.address_offsets(addr))[0]
        self.fd.seek(fileoff, os.SEEK_SET)
        self.vaddr = addr

    def vread(self, length):
        data = self.fd.read(length)
        self.vaddr += len(data)
        return data

    def vreadInstr(self):
        stream = self.fd.read(32)
        try:
            disas = list(self.cs.disasm(stream, self.vaddr, 1))[0]
        except Exception:
            print("Cannot decode:", stream, hex(self.vaddr))
        self.vseek(self.vaddr + disas.size)
        return Instruction(disas)

    def vreadCSInstr(self):
        stream = self.fd.read(32)
        try:
            disas = list(self.cs.disasm(stream, self.vaddr, 1))[0]
        except Exception:
            print("Cannot decode:", stream, hex(self.vaddr))
        self.vseek(self.vaddr + disas.size)
        return disas

    def get_symbol(self, symbolName):
        symtab = self.elf.get_section_by_name(".symtab")
        if not symtab or not isinstance(symtab, SymbolTableSection):
            return
        for i in range(symtab.num_symbols()):
            symbol = symtab.get_symbol(i)
            if symbol.name != symbolName: continue
            return symbol["st_value"]

    def get_section(self, name):
        # for i in range(self.elf.num_sections()): print(self.elf.get_section(i).name)
        return self.elf.get_section_by_name(name)

    def iter_symbols(self):
        for tableName in (".symtab", ".dynsym"):
            symtab = self.elf.get_section_by_name(tableName)
            if symtab and isinstance(symtab, SymbolTableSection):
                for symbol in symtab.iter_symbols():
                    # print(symbol.name, symbol["st_info"], symbol["st_value"])
                    if symbol["st_value"] == 0:
                        continue
                    if symbol["st_info"]["type"] == "STT_FUNC":
                        yield symbol["st_value"], symbol.name, "function"
                    if symbol["st_info"]["type"] == "STT_OBJECT":
                        yield symbol["st_value"], symbol.name, "object"