Example #1
0
def test_MACHO_lib_ecpg(assertion):
    macho_lib = open(__dir__ + 'libecpg.6.5.dylib', 'rb').read()
    e = MACHO(macho_lib)
    macho_lib_hash = hashlib.md5(macho_lib).hexdigest()
    d = e.pack()
    assertion(macho_lib_hash,
              hashlib.md5(d).hexdigest(),
              'Packing after reading postgresql library')
    d = ('\n'.join([_ for l in e.load for _ in l.otool()])).encode('latin1')
    assertion('df729c8806748bba93ef960787036d37',
              hashlib.md5(d).hexdigest(),
              'Otool-like output including section size "past end of file"')
    d = ('\n'.join([_ for l in e.load
                    for _ in l.otool(llvm=7)])).encode('latin1')
    assertion(
        '7038d70ea2d7caf8b4a2adc3c9c01ef9',
        hashlib.md5(d).hexdigest(),
        'Otool-like output including section size "past end of file", llvm version 7'
    )
    assertion(
        e.symbols[1].otool(),
        'execute.c                           NO_SECT         0x4  D 0x00000000 0000',
        'Display symbol with N_STAB type')
def test_MACHO_lib_system(assertion):
    macho_lib = open(__dir__ + 'libSystem.B.dylib', 'rb').read()
    e = MACHO(macho_lib)
    macho_lib_hash = hashlib.md5(macho_lib).hexdigest()
    d = e.pack()
    assertion(macho_lib_hash,
              hashlib.md5(d).hexdigest(), 'Packing after reading libSystem')
    bind_s = [
        _ for a in e.arch for _ in a.sect
        if getattr(_, 'type', None) in ('rebase_', 'export_')
    ]
    d = ('\n'.join([str(_) for s in bind_s for _ in s.info])).encode('latin1')
    assertion('81bc735570cb8f78099579fcf6a29f65',
              hashlib.md5(d).hexdigest(),
              'dyldinfo-like output for rebase and export (libSystem)')
    bind_s = [
        _ for a in e.arch for _ in a.sect
        if getattr(_, 'type', None) == 'rebase_'
    ]
    d = ('\n'.join([str(_) for s in bind_s for _ in s])).encode('latin1')
    assertion('c71cebc604ba70bfd348a3e08f7ea20c',
              hashlib.md5(d).hexdigest(),
              'dyldinfo-like output for rebase opcodes (libSystem)')
Example #3
0
def test_MACHO_ios_lyonmetro(assertion):
    global log_history
    macho_ios = open(__dir__ + 'LyonMetro', 'rb').read()
    e = MACHO(macho_ios)
    assertion([
        ('warn',
         ('Some encrypted text is not parsed with the section headers of LC_SEGMENT(__TEXT)',
          ), {}),
        ('warn',
         ('parse_dynamic_symbols() can only be used with x86 architectures, not %s',
          12), {}),
        ('warn', ('Part of the file was not parsed: %d bytes', 3908), {})
    ], log_history, 'Parsing LyonMetro iOS app (logs)')
    log_history = []
    macho_ios_hash = hashlib.md5(macho_ios).hexdigest()
    d = e.pack()
    assertion(macho_ios_hash,
              hashlib.md5(d).hexdigest(),
              'Packing after reading iOS application LyonMetro')
    assertion(e.entrypoint, 0x2f50, 'Entrypoint in iOS application LyonMetro')
    d = ('\n'.join([_ for l in e.load for _ in l.otool()])).encode('latin1')
    assertion('7bac82cc00b5cce2cb96344d678508e5',
              hashlib.md5(d).hexdigest(),
              'Otool-like output including LC_VERSION_MIN_IPHONEOS')
Example #4
0
def test_MACHO_minimal(assertion):
    global log_history
    # Simple tests of object creation
    e = MACHO(struct.pack("<I", macho.MH_MAGIC))
    assertion([('warn', (
        'parse_dynamic_symbols() can only be used with x86 architectures, not %s',
        0), {})], log_history,
              'Parsing a minimal data, with Mach-O magic number only (logs)')
    log_history = []
    assertion(e.entrypoint, -1, 'No entrypoint in a truncated Mach-O header')
    assertion([('error', ('Not a unique loader with entrypoint: []', ), {})],
              log_history, 'No entrypoint in a truncated Mach-O header (logs)')
    log_history = []
    d = e.pack()
    assertion('37b830a1776346543c72ff53fbbe2b4a',
              hashlib.md5(d).hexdigest(),
              'Parsing a minimal data, with Mach-O magic number only')
Example #5
0
def test_COFF_ckermit(assertion):
    # C-Kermit binary for OSF1
    out_osf1 = open(__dir__+'/binary_input/cku200.dec-osf-1.3a', 'rb').read()
    e = Coff(out_osf1)
    d = repr(e.OSF1Symbols).encode('latin1')
    assertion('c7df867846612e6fc1c52a8042f706cc',
              hashlib.md5(d).hexdigest(),
              'Display OSF/1 Symbols')
    # C-Kermit binary for Clipper CLIX
    e = Coff(open(__dir__+'/binary_input/cku196.clix-3.1', 'rb').read())
    # C-Kermit binary for Apollo
    e = Coff(open(__dir__+'/binary_input/cku193a05.apollo-sr10-s5r3', 'rb').read())
    # C-Kermit XCOFF32 binary for AIX
    e = Coff(open(__dir__+'/binary_input/cku190.rs6aix32c-3.2.4', 'rb').read())
    # C-Kermit eCOFF32 binary for MIPS, big endian
    e = Coff(open(__dir__+'/binary_input/cku192.irix40', 'rb').read())
    # C-Kermit eCOFF32 binary for MIPS, little endian
    e = Coff(open(__dir__+'/binary_input/cku192.ultrix43c-mips3', 'rb').read())
Example #6
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)')
Example #7
0
def test_PE_manipulate(assertion):
    global log_history
    pe_mingw = open(__dir__+'/binary_input/pe_mingw.exe', 'rb').read()
    e = PE(pe_mingw)
    # Packed file is not identical :-(
    # Are missing:
    # - the data between the end of DOS header and the start of PE header
    # - the padding after the list of sections, before the first section
    # - many parts of directories
    d = e.pack()
    assertion('2f08b8315c4e0a30d51a8decf104345c',
              hashlib.md5(d).hexdigest(),
              'Packing after reading pe_mingw.exe')
    d = PE(d).pack()
    assertion('2f08b8315c4e0a30d51a8decf104345c',
              hashlib.md5(d).hexdigest(),
              'Packing after reading pe_mingw.exe; fix point')
    d = e.SHList.display().encode('latin1')
    assertion('ba631f3f172712b6526e284269c1ecbb',
              hashlib.md5(d).hexdigest(),
              'Display Sections from PE')
    d = e.Symbols.display().encode('latin1')
    assertion('1ee89dc3dc2104190734747d148b7511',
              hashlib.md5(d).hexdigest(),
              'Display COFF Symbols')
    assertion('__gnu_exception_handler@4',
              e.Symbols.getbyindex(2).name,
              'Get symbol by index, found')
    assertion(None,
              e.Symbols.getbyindex(2000),
              'Get symbol by index, not existing')
    d = e.getsectionbyname('.text').pack()
    assertion('ad0d51a670cb6cd2015499840ffefb8f',
              hashlib.md5(d).hexdigest(),
              'Get existing section by name')
    d = e.getsectionbyoff(0x400+0x100).pack()
    assertion('ad0d51a670cb6cd2015499840ffefb8f',
              hashlib.md5(d).hexdigest(),
              'Get existing section by offset')
    d = e.getsectionbyvad(0x400000+0x1000+0x100).pack()
    assertion('ad0d51a670cb6cd2015499840ffefb8f',
              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.getsectionbyoff(0x80000)
    assertion(None, d, 'Get non-existing section by offset')
    d = e.getsectionbyvad(0x1000)
    assertion(None, d, 'Get non-existing section by address')
    d = e[0x100:0x120]
    assertion('6b8897a89909959320f8adfc1d81c9ee',
              hashlib.md5(d).hexdigest(),
              'Extract chunk from raw data')
    assertion(True,
              e.virt.is_addr_in(0x401000),
              'Address in mapped virtual memory')
    assertion(False,
              e.virt.is_addr_in(0x201000),
              'Address not in mapped virtual memory')
    d = e.virt[0x401000]
    assertion('4c614360da93c0a041b22e537de151eb',
              hashlib.md5(d).hexdigest(),
              'Extract byte from mapped memory, in a section')
    d = e.virt[0x400100]
    assertion('93b885adfe0da089cdf634904fd59f71',
              hashlib.md5(d).hexdigest(),
              'Extract byte from mapped memory, in no section')
    d = e.virt[0x400100:0x400120]
    assertion('6b8897a89909959320f8adfc1d81c9ee',
              hashlib.md5(d).hexdigest(),
              'Extract chunk from mapped memory, in headers')
    d = e.virt[0x401000:0x401020]
    assertion('21ac18c2564a3b408b31aae0af19d502',
              hashlib.md5(d).hexdigest(),
              'Extract chunk from mapped memory, in a section')
    d = e.virt[0x100:0x200] # One null byte
    assertion([('warn', ('unknown rva address! -3fff00',), {})],
              log_history,
              'Extract chunk from non-mapped memory (logs)')
    log_history = []
    assertion('93b885adfe0da089cdf634904fd59f71',
              hashlib.md5(d).hexdigest(),
              'Extract chunk from non-mapped memory')
    assertion(e.virt[0x401000:0x401020],
              e.virt(0x401000,0x401020),
              'Extract chunk from mapped memory, old API')
    e[0x100:0x120] = e[0x100:0x120]
    d = e.pack()
    assertion('2f08b8315c4e0a30d51a8decf104345c',
              hashlib.md5(d).hexdigest(),
              'Writing in raw data')
    e.rva.set(0x1100, e.virt[0x401100:0x401120])
    d = e.pack()
    assertion('2f08b8315c4e0a30d51a8decf104345c',
              hashlib.md5(d).hexdigest(),
              'Writing at RVA')
    e.virt[0x401100:0x401120] = e.virt[0x401100:0x401120]
    d = e.pack()
    assertion('2f08b8315c4e0a30d51a8decf104345c',
              hashlib.md5(d).hexdigest(),
              'Writing in memory (interval)')
    e.virt[0x401100] = e.virt[0x401100:0x401120]
    d = e.pack()
    assertion('2f08b8315c4e0a30d51a8decf104345c',
              hashlib.md5(d).hexdigest(),
              'Writing in memory (address)')
    e.virt[0x400100:0x400120] = e.virt[0x400100:0x400120]
    assertion([('warn', ('Cannot write at RVA %s', slice(256, 288, None)), {})],
              log_history,
              'Writing at invalid RVA (logs)')
    log_history = []
    assertion(0x468e71, len(e.virt), 'Max virtual address')
    assertion([('warn', ('__len__ deprecated',), {})],
              log_history,
              '__len__ deprectated (logs)')
    log_history = []
    # Find leave; ret
    assertion(0x401294,
              e.virt.find(struct.pack('BB', 0xc9, 0xc3)),
              'Find pattern (from the start)')
    assertion(0x4014B4,
              e.virt.rfind(struct.pack('BB', 0xc9, 0xc3)),
              'Find pattern (from the end)')
    e.SHList.align_sections()
    d = e.pack()
    assertion('2f08b8315c4e0a30d51a8decf104345c',
              hashlib.md5(d).hexdigest(),
              'Align sections')
    # Remove Bound Import directory
    # Usually, its content is not stored in any section... that's
    # a future version of elfesteem will need to manage this
    # specific directory in a specific way.
    e.NThdr.optentries[pe.DIRECTORY_ENTRY_BOUND_IMPORT].rva = 0
    e.NThdr.optentries[pe.DIRECTORY_ENTRY_BOUND_IMPORT].size = 0
    # Create new sections with all zero content
    s_redir = e.SHList.add_section(name = "redir", size = 0x1000)
    s_test  = e.SHList.add_section(name = "test",  size = 0x1000)
    s_rel   = e.SHList.add_section(name = "rel",   size = 0x5000)
    d = e.pack()
    assertion('439f6c698d3d5238d88c5ccef99761e2',
              hashlib.md5(d).hexdigest(),
              'Adding sections')
    d = PE(d).pack()
    assertion('439f6c698d3d5238d88c5ccef99761e2',
              hashlib.md5(d).hexdigest(),
              'Adding sections; fix point')
    e = PE(pe_mingw)
    # Delete the last sections => OK
    for _ in range(2):
        del e.SHList._array[-1]
        e.SHList._size -= 40
        e.COFFhdr.numberofsections -= 1
    # Add two Descriptors in the Import Directory
    e.DirImport.add_dlldesc(
          [({"name":"kernel32.dll",
             "firstthunk":s_test.addr},
            ["CreateFileA",
             "SetFilePointer",
             "WriteFile",
             "CloseHandle",
             ]
            ),
           ({"name":"USER32.dll",
             "firstthunk":None},
            ["SetDlgItemInt",
             "GetMenu",
             "HideCaret",
             ]
            )
           ]
          )
    s_myimp = e.SHList.add_section(name="myimp", rawsize=len(e.DirImport))
    e.DirImport.set_rva(s_myimp.addr)
    assertion(0x4050a8,
              e.DirImport.get_funcvirt('KERNEL32.dll','ExitProcess'),
              'Import ExitProcess')
    assertion(None,
              e.DirImport.get_funcvirt(None,'LoadStringW'),
              'Import LoadStringW')
    assertion(None,
              e.DirExport.get_funcvirt('SetUserGeoID'),
              'Export SetUserGeoID')
    d = e.pack()
    assertion('8a3a1c8c9aa2db211e1d34c7efbb8473',
              hashlib.md5(d).hexdigest(),
              'Adding new imports')
    d = PE(d).pack()
    assertion([('warn', ('Section %d size %#x not aligned to %#x', 5, 294, 512), {})],
              log_history,
              'Adding new imports (logs)')
    log_history = []
    assertion('8a3a1c8c9aa2db211e1d34c7efbb8473',
              hashlib.md5(d).hexdigest(),
              'Adding new imports; fix point')
    # Add an export
    if e.DirExport.expdesc is None:
        e.DirExport.create(['coco'])
    assertion(0x40703e,
              e.DirExport.get_funcvirt('coco'),
              'Export: get_funcvirt')
    # 'eval' avoids warnings with python2.3
    assertion({1: eval("0xdeedc0fe"), 'coco': eval("0xdeedc0fe")},
              e.export_funcs(),
              'Export: export_funcs')
    d = e.pack()
    assertion('47a864481296d88f908126fb822ded59',
              hashlib.md5(d).hexdigest(),
              'Adding new exports')
    d = PE(d).pack()
    assertion([('warn', ('Section %d size %#x not aligned to %#x', 5, 294, 512), {})],
              log_history,
              'Adding new exports (logs)')
    log_history = []
    assertion('47a864481296d88f908126fb822ded59',
              hashlib.md5(d).hexdigest(),
              'Adding new exports; fix point')
    # Add a new Descriptor in the Import Directory
    e.DirImport.add_dlldesc([ ({"name":"MyDLL.dll"}, ["MyFunc"]) ])
    e.DirImport.set_rva(None)
    assertion('47a864481296d88f908126fb822ded59',
              hashlib.md5(d).hexdigest(),
              'Adding imports, no specified section')
Example #8
0
def test_PE_empty64(assertion):
    e = PE(wsize=64)
    d = e.pack()
    assertion('863bf62f521b0cad3209e42cff959eed',
              hashlib.md5(d).hexdigest(),
              'Creation of a standard empty PE+')
Example #9
0
def test_PE_ange(assertion):
    global log_history
    # Parse some ill-formed PE made by Ange Albertini
    e = PE(open(__dir__+'/binary_input/Ange/resourceloop.exe', 'rb').read())
    assertion([('warn', ('Resource tree too deep',), {})]*212,
              log_history,
              'Ange/resourceloop.exe (logs)')
    log_history = []
    e = PE(open(__dir__+'/binary_input/Ange/namedresource.exe', 'rb').read())
    assertion([],
              log_history,
              'Ange/namedresource.exe (logs)')
    e = PE(open(__dir__+'/binary_input/Ange/weirdsord.exe', 'rb').read())
    assertion([('warn', ('Section %d offset %#x not aligned to %#x', 0, 513, 16384), {}), ('warn', ('Section %d size %#x not aligned to %#x', 0, 270, 16384), {})],
              log_history,
              'Ange/weirdsord.exe (logs)')
    log_history = []
    e = PE(open(__dir__+'/binary_input/Ange/nosectionW7.exe', 'rb').read())
    assertion([('warn', ('Number of rva %d does not match sizeofoptionalheader %d', 16, 0), {})],
              log_history,
              'Ange/nosectionW7.exe (logs)')
    log_history = []
    e = PE(open(__dir__+'/binary_input/Ange/imports_relocW7.exe', 'rb').read())
    assertion([],
              log_history,
              'Ange/imports_relocW7.exe (logs)')
    e = PE(open(__dir__+'/binary_input/Ange/imports_tinyXP.exe', 'rb').read())
    assertion([],
              log_history,
              'Ange/imports_tinyXP.exe (logs)')
    e = PE(open(__dir__+'/binary_input/Ange/bottomsecttbl.exe', 'rb').read())
    assertion([('warn', ('Number of rva %d does not match sizeofoptionalheader %d', 16, 696), {})],
              log_history,
              'Ange/bottomsecttbl.exe (logs)')
    log_history = []
    e = PE(open(__dir__+'/binary_input/Ange/delayfake.exe', 'rb').read())
    assertion([],
              log_history,
              'Ange/delayfake.exe (logs)')
    e = PE(open(__dir__+'/binary_input/Ange/exportobf.exe', 'rb').read())
    assertion([],
              log_history,
              'Ange/exportobf.exe (logs)')
    e = PE(open(__dir__+'/binary_input/Ange/dllbound-ld.exe', 'rb').read())
    assertion([],
              log_history,
              'Ange/dllbound-ld.exe (logs)')
    e = PE(open(__dir__+'/binary_input/Ange/d_tiny.dll', 'rb').read())
    assertion([('warn', ('Opthdr magic %#x', 31074), {}),
               ('warn', ('Number of rva %d does not match sizeofoptionalheader %d', 0, 13864), {}),
               ('warn', ('Windows 8 needs at least 13 directories, %d found', 0), {}),
               ('warn', ('Too many symbols: %d', 541413408), {}),
               ('warn', ('File too short for StrTable -0x61746127 != 0x0',), {})],
              log_history,
              'Ange/d_tiny.dll (logs)')
    log_history = []
    e = PE(open(__dir__+'/binary_input/Ange/dllfw.dll', 'rb').read())
    assertion([],
              log_history,
              'Ange/dllfw.dll (logs)')
    e = PE(open(__dir__+'/binary_input/Ange/tinydllXP.dll', 'rb').read())
    assertion([('warn', ('Number of rva %d does not match sizeofoptionalheader %d', 0, 0), {}),
               ('warn', ('Windows 8 needs at least 13 directories, %d found', 0), {}),
               ('warn', ('File too short for StrTable 0x55 != 0xc258016a',), {})],
              log_history,
              'Ange/tinydllXP.dll (logs)')
    log_history = []
    e = PE(open(__dir__+'/binary_input/Ange/resourceloop.exe', 'rb').read())
    log_history = []
    d = e.DirRes.display().encode('latin1')
    assertion('98701be30b09759a64340e5245e48195',
              hashlib.md5(d).hexdigest(),
              'Display Directory RESOURCE that is too deep')