Пример #1
0
def get_funcs_exe_source(c_file, filename):
    """Get function defined in @c_file"""
    with open(c_file) as fdesc:
        data = fdesc.read()
    funcs = []
    for match in match_C.finditer(data):
        funcs.append(match.groups()[0])
    funcs = list(name for name in set(funcs) if name not in whitelist_funcs)

    # Find corresponding binary offset
    to_check = []
    with open(filename) as fdesc:
        elf = ELF(fdesc.read())

    symbols = {}
    for name, symb in elf.getsectionbyname(".symtab").symbols.iteritems():
        offset = symb.value
        if name.startswith("__"):
            name = name[2:]
        symbols.setdefault(name, set()).add(offset)
        if name in funcs:
            if name.startswith(custom_tag):
                ## Custom tags can be used to write equivalent functions like
                ## 'my_strlen' for a custom strlen
                name = name[len(custom_tag):]
            to_check.append((offset, name))
    return to_check, symbols
Пример #2
0
def get_funcs_exe_source(c_file, filename):
    """Get function defined in @c_file"""
    with open(c_file) as fdesc:
        data = fdesc.read()
    funcs = []
    for match in match_C.finditer(data):
        funcs.append(match.groups()[0])
    funcs = list(name for name in set(funcs) if name not in whitelist_funcs)

    # Find corresponding binary offset
    to_check = []
    with open(filename) as fdesc:
        elf = ELF(fdesc.read())

    symbols = {}
    for name, symb in elf.getsectionbyname(".symtab").symbols.iteritems():
        offset = symb.value
        if name.startswith("__"):
            name = name[2:]
        symbols.setdefault(name, set()).add(offset)
        if name in funcs:
            if name.startswith(custom_tag):
                ## Custom tags can be used to write equivalent functions like
                ## 'my_strlen' for a custom strlen
                name = name[len(custom_tag):]
            to_check.append((offset, name))
    return to_check, symbols
Пример #3
0
def test_ELF_small64(assertion):
    elf64_small = open(__dir__+'/binary_input/elf64_small.out', 'rb').read()
    assertion('dc21d928bb6a3a0fa59b17fafe803d50',
              hashlib.md5(elf64_small).hexdigest(),
              'Reading elf64_small.out')
    e = ELF(elf64_small)
    d = e.pack()
    assertion('dc21d928bb6a3a0fa59b17fafe803d50',
              hashlib.md5(d).hexdigest(),
              'Packing after reading elf64_small.out')
    # Packed file is identical :-)
    d = e.sh.readelf_display().encode('latin1')
    assertion('6d4aa86afdbf612430cb699987bc22b9',
              hashlib.md5(d).hexdigest(),
              'Display Section Headers (readelf, 64bit)')
    d = e.getsectionbyname('.symtab').readelf_display().encode('latin1')
    assertion('452e64fb0f2dad5c0e44d83e57b9d82b',
              hashlib.md5(d).hexdigest(),
              'Display Symbol Table (elf64)')
    d = e.getsectionbyname('.rela.dyn').readelf_display().encode('latin1')
    assertion('650cf3f99117d39d63fae73232e09acf',
              hashlib.md5(d).hexdigest(),
              'Display Reloc Table (elf64)')
Пример #4
0
def test_ELF_group(assertion):
    elf_group = open(__dir__+'/binary_input/elf_cpp.o', 'rb').read()
    assertion('57fed5de9474bc0600173a1db5ee6327',
              hashlib.md5(elf_group).hexdigest(),
              'Reading elf_cpp.o')
    e = ELF(elf_group)
    d = e.pack()
    assertion('57fed5de9474bc0600173a1db5ee6327',
              hashlib.md5(d).hexdigest(),
              'Packing after reading elf_cpp.o')
    # Packed file is identical :-)
    d = e.getsectionbyname('.group').readelf_display().encode('latin1')
    assertion('5c80b11a64a32e7aaee8ef378da4ccef',
              hashlib.md5(d).hexdigest(),
              'Display Group Section')
Пример #5
0
def test_ELF_small32(assertion):
    global log_history
    elf_small = open(__dir__+'/binary_input/elf_small.out', 'rb').read()
    assertion('d5284d5f438e25ef5502a0c1de97d84f',
              hashlib.md5(elf_small).hexdigest(),
              'Reading elf_small.out')
    e = ELF(elf_small)
    d = e.pack()
    assertion('d5284d5f438e25ef5502a0c1de97d84f',
              hashlib.md5(d).hexdigest(),
              'Packing after reading elf_small.out')
    # Packed file is identical :-)
    d = repr(e.ph).encode('latin1')
    assertion('ab4b1e52e7532789592878872910a2a1',
              hashlib.md5(d).hexdigest(),
              'Display Program Headers')
    d = repr(e.sh).encode('latin1')
    assertion('ddf01165114eb70bd27910e4c5b03c09',
              hashlib.md5(d).hexdigest(),
              'Display Section Headers (repr)')
    d = e.sh.readelf_display().encode('latin1')
    assertion('08da11fa164d7013561db398c068ac71',
              hashlib.md5(d).hexdigest(),
              'Display Section Headers (readelf)')
    d = e.getsectionbyname('.symtab').readelf_display().encode('latin1')
    assertion('943434f4cde658b1659b7d8db39d9e60',
              hashlib.md5(d).hexdigest(),
              'Display Symbol Table')
    assertion('    49: 0804a01c     0 NOTYPE  GLOBAL DEFAULT  ABS _edata',
              e.getsectionbyname('.symtab')['_edata'].readelf_display(),
              'Get symbol by name, found')
    assertion('     2: 00000000     0 FUNC    GLOBAL DEFAULT  UND __stack_chk_fail',
              e.getsectionbyname('.dynsym')[2].readelf_display(),
              'Get symbol by index, found')
    d = e.getsectionbytype(elf.SHT_SYMTAB).pack()
    assertion('4ed5a808faff1ca7c6a766ae45ebf377',
              hashlib.md5(d).hexdigest(),
              'Get existing section by type')
    d = e.getsectionbyname('.text').pack()
    assertion('7149c6e4b8baaab8beebfeb818585638',
              hashlib.md5(d).hexdigest(),
              'Get existing section by name')
    d = e.getsectionbyvad(0x080483d0+0x100).pack()
    assertion('7149c6e4b8baaab8beebfeb818585638',
              hashlib.md5(d).hexdigest(),
              'Get existing section by address')
    d = e.getsectionbyname('no_sect')
    assertion(None, d, 'Get non-existing section by name')
    d = e.getsectionbyvad(0x1000)
    assertion(None, d, 'Get non-existing section by address')
    d = e[0x100:0x120]
    assertion('5e94f899265a799826a46ec86a293e16',
              hashlib.md5(d).hexdigest(),
              'Extract chunk from raw data')
    assertion(e[0x100:0x120],
              e._content[0x100:0x120],
              'Extract chunk from raw data, deprecated API')
    assertion(True,
              e.virt.is_addr_in(0x080483d0),
              'Address in mapped virtual memory')
    assertion(False,
              e.virt.is_addr_in(0x08048000),
              'Address not in mapped virtual memory')
    d = e.virt[0x080483d0:0x080483e0]
    assertion('9d225ebfd0f9562b74b17c5a4653dc6f',
              hashlib.md5(d).hexdigest(),
              'Extract chunk from mapped memory, in a section')
    try:
        d = e.virt[0x08040000:0x08040020]
        assertion(0,1, 'Extract chunk from non-mapped memory')
    except ValueError:
        pass
    assertion(e.virt[0x080483d0:0x080483e0],
              e.virt(0x080483d0,0x080483e0),
              'Extract chunk from mapped memory, old API')
    e.virt[0x080483d0:0x080483e0] = e.virt[0x080483d0:0x080483e0]
    d = e.pack()
    assertion('d5284d5f438e25ef5502a0c1de97d84f',
              hashlib.md5(d).hexdigest(),
              'Writing in memory (interval)')
    e.virt[0x080483d0] = e.virt[0x080483d0:0x080483e0]
    d = e.pack()
    assertion('d5284d5f438e25ef5502a0c1de97d84f',
              hashlib.md5(d).hexdigest(),
              'Writing in memory (address)')
    assertion(0x804a028, len(e.virt), 'Max virtual address')
    assertion([('warn', ('__len__ deprecated',), {})],
              log_history,
              '__len__ deprecated (logs)')
    log_history = []
    # Find leave; ret
    assertion(0x8048481,
              e.virt.find(struct.pack('BB', 0xc9, 0xc3)),
              'Find pattern (existing)')
    assertion(-1,
              e.virt.find(struct.pack('BBBB', 1,2,3,4)),
              'Find pattern (not existing)')
Пример #6
0
def run_test():
    ko = []
    def assertion(target, value, message):
        if target != value: ko.append(message)
    import struct
    assertion('f71dbe52628a3f83a77ab494817525c6',
              hashlib.md5(struct.pack('BBBB',116,111,116,111)).hexdigest(),
              'MD5')
    from elfesteem.elf_init import ELF, log
    from elfesteem import elf
    # Remove warnings
    import logging
    log.setLevel(logging.ERROR)
    e = ELF()
    d = e.pack()
    assertion('0ddf18391c150850c72257b3f3caa67b',
              hashlib.md5(d).hexdigest(),
              'Creation of a standard empty ELF')
    d = ELF(d).pack()
    assertion('0ddf18391c150850c72257b3f3caa67b',
              hashlib.md5(d).hexdigest(),
              'Creation of a standard empty ELF; fix point')
    assertion(True,
              e.has_relocatable_sections(),
              'Standard empty ELF is relocatable')
    elf_small = open(__dir__+'/binary_input/elf_small.out', 'rb').read()
    assertion('d5284d5f438e25ef5502a0c1de97d84f',
              hashlib.md5(elf_small).hexdigest(),
              'Reading elf_small.out')
    e = ELF(
        e_type    = elf.ET_REL, # Default value
        e_machine = elf.EM_386, # Default value
        sections = ['.text', '.text.startup', '.group',
                    '.data', '.rodata.str1.4', '.rodata.cst4',
                    '.bss', '.eh_frame', '.comment', '.note.GNU-stack',
                    ],
        relocs = ['.text'], # These sections will have relocs
        )
    d = e.pack()
    assertion('dc3f17080d002ba0bfb3aec9f3bec8b2',
              hashlib.md5(d).hexdigest(),
              'Creation of an ELF with a given list of sections')
    try:
        e = ELF(open(__dir__+'/binary_input/README.txt', 'rb').read())
        ko.append('Not an ELF')
    except ValueError:
        pass
    e = ELF(elf_small)
    d = e.pack()
    assertion('d5284d5f438e25ef5502a0c1de97d84f',
              hashlib.md5(d).hexdigest(),
              'Packing after reading elf_small.out')
    # Packed file is identical :-)
    d = repr(e.ph).encode('latin1')
    assertion('ab4b1e52e7532789592878872910a2a1',
              hashlib.md5(d).hexdigest(),
              'Display Program Headers')
    d = repr(e.sh).encode('latin1')
    assertion('ddf01165114eb70bd27910e4c5b03c09',
              hashlib.md5(d).hexdigest(),
              'Display Section Headers (repr)')
    d = e.sh.readelf_display().encode('latin1')
    assertion('08da11fa164d7013561db398c068ac71',
              hashlib.md5(d).hexdigest(),
              'Display Section Headers (readelf)')
    d = e.getsectionbyname('.symtab').readelf_display().encode('latin1')
    assertion('067a9f91e9a33693dffca1e1ff3de023',
              hashlib.md5(d).hexdigest(),
              'Display Symbol Table')
    assertion('000049: 0804a01c    0 NOTYPE  GLOBAL DEFAULT  ABS _edata',
              e.getsectionbyname('.symtab')['_edata'].readelf_display(),
              'Get symbol by name, found')
    assertion('000002: 00000000    0 FUNC    GLOBAL DEFAULT  UND __stack_chk_fail',
              e.getsectionbyname('.dynsym')[2].readelf_display(),
              'Get symbol by index, found')
    d = e.getsectionbyname('.text').pack()
    assertion('7149c6e4b8baaab8beebfeb818585638',
              hashlib.md5(d).hexdigest(),
              'Get existing section by name')
    d = e.getsectionbyvad(0x080483d0+0x100).pack()
    assertion('7149c6e4b8baaab8beebfeb818585638',
              hashlib.md5(d).hexdigest(),
              'Get existing section by address')
    d = e.getsectionbyname('no_sect')
    assertion(None, d, 'Get non-existing section by name')
    d = e.getsectionbyvad(0x1000)
    assertion(None, d, 'Get non-existing section by address')
    d = e[0x100:0x120]
    assertion('5e94f899265a799826a46ec86a293e16',
              hashlib.md5(d).hexdigest(),
              'Extract chunk from raw data')
    assertion(e[0x100:0x120],
              e._content[0x100:0x120],
              'Extract chunk from raw data, deprecated API')
    assertion(True,
              e.virt.is_addr_in(0x080483d0),
              'Address in mapped virtual memory')
    assertion(False,
              e.virt.is_addr_in(0x08048000),
              'Address not in mapped virtual memory')
    d = e.virt[0x080483d0:0x080483e0]
    assertion('9d225ebfd0f9562b74b17c5a4653dc6f',
              hashlib.md5(d).hexdigest(),
              'Extract chunk from mapped memory, in a section')
    try:
        d = e.virt[0x08040000:0x08040020]
        ko.append('Extract chunk from non-mapped memory')
    except ValueError:
        pass
    assertion(e.virt[0x080483d0:0x080483e0],
              e.virt(0x080483d0,0x080483e0),
              'Extract chunk from mapped memory, old API')
    e.virt[0x080483d0:0x080483e0] = e.virt[0x080483d0:0x080483e0]
    d = e.pack()
    assertion('d5284d5f438e25ef5502a0c1de97d84f',
              hashlib.md5(d).hexdigest(),
              'Writing in memory')
    # Warning: __len__ deprecated
    assertion(0x804a028, len(e.virt), 'Max virtual address')
    # Find leave; ret
    assertion(0x8048481,
              e.virt.find(struct.pack('BB', 0xc9, 0xc3)),
              'Find pattern (existing)')
    assertion(-1,
              e.virt.find(struct.pack('BBBB', 1,2,3,4)),
              'Find pattern (not existing)')
    elf64_small = open(__dir__+'/binary_input/elf64_small.out', 'rb').read()
    assertion('dc21d928bb6a3a0fa59b17fafe803d50',
              hashlib.md5(elf64_small).hexdigest(),
              'Reading elf64_small.out')
    e = ELF(elf64_small)
    d = e.pack()
    assertion('dc21d928bb6a3a0fa59b17fafe803d50',
              hashlib.md5(d).hexdigest(),
              'Packing after reading elf64_small.out')
    # Packed file is identical :-)
    d = e.sh.readelf_display().encode('latin1')
    assertion('6d4aa86afdbf612430cb699987bc22b9',
              hashlib.md5(d).hexdigest(),
              'Display Section Headers (readelf, 64bit)')
    d = e.getsectionbyname('.symtab').readelf_display().encode('latin1')
    assertion('f51c09394daa3d77a872d514b7fac72d',
              hashlib.md5(d).hexdigest(),
              'Display Symbol Table (elf64)')
    d = e.getsectionbyname('.rela.dyn').readelf_display().encode('latin1')
    assertion('650cf3f99117d39d63fae73232e09acf',
              hashlib.md5(d).hexdigest(),
              'Display Reloc Table (elf64)')
    elf_group = open(__dir__+'/binary_input/elf_cpp.o', 'rb').read()
    assertion('57fed5de9474bc0600173a1db5ee6327',
              hashlib.md5(elf_group).hexdigest(),
              'Reading elf_cpp.o')
    e = ELF(elf_group)
    d = e.pack()
    assertion('57fed5de9474bc0600173a1db5ee6327',
              hashlib.md5(d).hexdigest(),
              'Packing after reading elf_cpp.o')
    # Packed file is identical :-)
    d = e.getsectionbyname('.group').readelf_display().encode('latin1')
    assertion('5c80b11a64a32e7aaee8ef378da4ccef',
              hashlib.md5(d).hexdigest(),
              'Display Group Section')
    elf_tmp320c6x = open(__dir__+'/binary_input/notle-tesla-dsp.xe64T', 'rb').read()
    assertion('fb83ed8d809f394e70f5d84d0c8e593f',
              hashlib.md5(elf_tmp320c6x).hexdigest(),
              'Reading notle-tesla-dsp.xe64T')
    e = ELF(elf_tmp320c6x)
    d = e.pack()
    assertion('fb83ed8d809f394e70f5d84d0c8e593f',
              hashlib.md5(d).hexdigest(),
              'Packing after reading notle-tesla-dsp.xe64T')
    # Packed file is identical :-)
    d = e.sh.readelf_display().encode('latin1')
    assertion('ecf169c765d29175177528e24601f1be',
              hashlib.md5(d).hexdigest(),
              'Display Section Headers (TMP320C6x)')
    return ko
Пример #7
0
def test_find(args):

    custom_tag = "my_"
    whitelist_funcs = ["main"]

    # Compil tests
    log_info("Remove old files")
    os.system("make clean")
    log_info("Compile C files")
    status = os.system("make")

    # Find test names
    c_files = []

    for cur_dir, sub_dir, files in os.walk("."):
        c_files += [x for x in files if x.endswith(".c")]

    log_info("Found:\n\t- " + "\n\t- ".join(c_files))

    m = re.compile("\w+[ \*]+(\w+)\(.*\)")
    for c_file in c_files:
        # Get function defined in the source
        with open(c_file) as fdesc:
            data = fdesc.read()
        filename = c_file[:-2]
        log_info(" %s:" % filename)
        funcs = []
        for p in m.finditer(data):
            funcs.append(p.groups()[0])
        funcs = list(x for x in set(funcs) if x not in whitelist_funcs)

        # Find corresponding binary offset
        to_check = []
        with open(filename) as fdesc:
            elf = ELF(fdesc.read())

        symbols = {}
        for name, symb in elf.getsectionbyname(".symtab").symbols.iteritems():
            offset = symb.value
            if name.startswith("__"):
                name = name[2:]
            symbols.setdefault(name, set()).add(offset)
            if name in funcs:
                if name.startswith(custom_tag):
                    ## Custom tags can be used to write equivalent functions like
                    ## 'my_strlen' for a custom strlen
                    name = name[len(custom_tag):]
                to_check.append((offset, name))

        print "\n".join("0x%08x: %s" % (addr, funcname)
                        for (addr, funcname) in to_check)

        # Launch Sibyl
        log_info("Launch Sibyl")
        options = ["-j", "gcc", "-i", "5", "-b", "ABIStdCall_x86_32"]
        if not args.arch_heuristic:
            options += ["-a", "x86_32"]

        cmd = ["sibyl", "find"] + options + [filename]
        if not args.func_heuristic:
            cmd += [hex(addr) for addr, f in to_check]
        print " ".join(cmd)
        sibyl = subprocess.Popen(cmd,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE)

        # Parse result
        found = []
        stdout, stderr = sibyl.communicate()
        for line in stdout.split("\n"):
            if not line:
                continue
            addr, func = line.split(" : ")
            found.append((int(addr, 16), func))

        if sibyl.returncode:
            log_error("Process exits with a %d code" % sibyl.returncode)
            print stderr
            exit(sibyl.returncode)

        log_info("Evaluate results")
        i = 0

        for element in found:
            if element not in to_check:
                offset, name = element
                if offset in symbols.get(name, []):
                    # Present in symtab but not in C source file
                    print "[+] Additionnal found: %s (@0x%08x)" % (name,
                                                                   offset)
                else:
                    alt_names = [
                        aname for aname, offsets in symbols.iteritems()
                        if offset in offsets
                    ]
                    log_error("Bad found: %s (@0x%08x -> '%s')" %
                              (name, offset, ",".join(alt_names)))
            else:
                i += 1
        for element in to_check:
            if element not in found:
                log_error("Unable to find: %s (@0x%08x)" %
                          (element[1], element[0]))

        log_success("Found %d/%d correct elements" % (i, len(to_check)))

    log_info("Remove old files")
    os.system("make clean")
Пример #8
0
    with open(c_file) as fdesc:
        data = fdesc.read()
    filename = c_file[:-2]
    print "[+] %s:" % filename
    funcs = []
    for p in m.finditer(data):
        funcs.append(p.groups()[0])
    funcs = list(x for x in set(funcs) if x not in whitelist_funcs)

    # Find corresponding binary offset
    to_check = []
    with open(filename) as fdesc:
        elf = ELF(fdesc.read())

    symbols = {}
    for name, symb in elf.getsectionbyname(".symtab").symbols.iteritems():
        offset = symb.value
        if name.startswith("__"):
            name = name[2:]
        symbols.setdefault(name, set()).add(offset)
        if name in funcs:
            if name.startswith(custom_tag):
                ## Custom tags can be used to write equivalent functions like
                ## 'my_strlen' for a custom strlen
                name = name[len(custom_tag):]
            to_check.append((offset, name))

    print "\n".join("0x%08x: %s" % (addr, funcname)
                    for (addr, funcname) in to_check)

    # Launch Sibyl