예제 #1
0
def parse_delay_import_table(dd, sections, optional_header, data, offsets):
    if not dd or "delay_import_table" not in dd:
        return None, offsets
    base_rva, table_len = dd["delay_import_table"]["virtual_address"], dd["delay_import_table"]["length"]
    if not base_rva or not table_len:
        return None, offsets
    
    base = rva_to_offset(base_rva, sections)
    if not base or base + table_len > len(data):
        return None, offsets

    vals = {}
    entry_len = struct.calcsize(delay_import_table_str)
    current_offset = base
    while current_offset - base < table_len and current_offset + entry_len < len(data):
        val_data = struct.unpack(delay_import_table_str, data[current_offset:current_offset+entry_len])
        check = 0
        for v in val_data:
            if v != 0:
                check = 1; break
        if not check:
            break
        import_entry = {}
        for offset, elem in enumerate(delay_import_table_spec):
            import_entry[elem[0]] = val_data[offset]
        name_rva = import_entry["name_rva"]
        if not name_rva:
            continue
        name, offsets = rva_string_lookup(name_rva, sections, optional_header["image_base"], data, offsets)
        lookup_table_rva = import_entry["delay_import_name_table"]
        lookup_table_offset = rva_to_offset(lookup_table_rva, sections)
        function_names, offsets = parse_import_lookup_table(lookup_table_offset, lookup_table_rva, optional_header, sections, data, offsets)
        address_table_rva = import_entry["delay_import_address_table"]
        address_table_offset = rva_to_offset(address_table_rva, sections)
        #Delay imports only have addresses in the file at the lookup table.  The address table is populated on demand in the image.
        addresses, offsets = parse_import_address_table(lookup_table_offset, address_table_rva, optional_header, sections, data, offsets)

        import_entry["function_names"] = function_names        
        import_entry["addresses"] = addresses   

        if name:
            vals[name] = import_entry
        else:
            vals[current_offset] = import_entry
        offsets = build_delay_offset_strings(import_entry, current_offset, name, offsets)
        current_offset +=  entry_len
        
    return vals, offsets
예제 #2
0
def rva_string_lookup(rva, sections, image_base, data, offsets):
    if not rva:
        return None, offsets
    f_offset = rva_to_offset(rva, sections, image_base)
    if not f_offset:   
        return None, offsets
    string_end = data[f_offset:].find("\x00")
    offsets[f_offset] = [{"len":string_end, "string":"Import Name"}]
    return data[f_offset:f_offset+string_end], offsets
예제 #3
0
def parse_base_relocations(dd, sections, data, offsets):
    if not dd or "base_relocation_table" not in dd:
        return None, offsets
    base, table_len = dd["base_relocation_table"]["virtual_address"], dd["base_relocation_table"]["length"]
    if base == 0 and table_len == 0:
        return None, offsets
    entry_len = struct.calcsize(base_relocation_block_str)
    base = rva_to_offset(base, sections)
    if not base:
        return None, offsets
    offset = base
    relocations = []
    while offset - base < table_len and offset+entry_len < len(data):
        val_data = struct.unpack(base_relocation_block_str, data[offset:offset+entry_len])
        block = {}
        for n, elem in enumerate(base_relocation_block_spec):
            block[elem[0]] = val_data[n]
        
        o = offset
        for elem in base_relocation_block_spec:
            length = elem[1]
            s = "%s: %s (%s)"%(elem[0], block[elem[0]], elem[2])
            offsets[o].append({"len":length, "string":s})
            o += length
        
        rels = []
        s = block["block_size"]
        offset += entry_len
        s -= entry_len
        num_entries = s / struct.calcsize(base_relocation_str)
        rlen = struct.calcsize(base_relocation_str)
        for i in xrange(num_entries):
            if offset + rlen >= len(data):
                break
            type_offset = struct.unpack(base_relocation_str, data[offset:offset+rlen])
            type_val = (type_offset[0] & 0b1111000000000000) >> 12
            offset_val = type_offset[0] & 0b0000111111111111
            rels.append((type_val, offset_val))
            offsets[offset].append({"len":rlen, "string":"Type: %s, Offset: %s"%(type_val, offset_val)})
            offset += rlen
        block["relocations"] = rels
            
        relocations.append(block)
    
    return relocations, offsets
예제 #4
0
def parse_exports_directory_table(dd, sections, optional_header, data, offsets):
    if not dd or "export_table" not in dd:
        return None, offsets
    base_rva, table_len = dd["export_table"]["virtual_address"], dd["export_table"]["length"]
    if base_rva == 0 and table_len == 0:
        return None, offsets
    
    str_len = struct.calcsize(exports_directory_table_str)
    base = rva_to_offset(base_rva, sections)
    if not base or base + str_len >= len(data):
        return None, offsets
    
    vals = {}
    val_data = struct.unpack(exports_directory_table_str, data[base:base+str_len])
    for n, elem in enumerate(exports_directory_table_spec):
        vals[elem[0]] = val_data[n]
        
    build_exports_offset_strings(vals, base, offsets)
    
    base_rva = vals["export_address_table_rva"]
    base = rva_to_offset(base_rva, sections)   
    entry_len = struct.calcsize(exports_address_table_str)
    addresses = []
    for i in xrange(vals["address_table_entries"]):
        if not base or base + entry_len >= len(data):
            break
        address = struct.unpack(exports_address_table_str, data[base:base+entry_len])
        addresses.append(address[0])
        base += entry_len
    
    base_rva = vals["name_pointer_rva"]
    base = rva_to_offset(base_rva, sections)
    if not base:
        return None, offsets
    entry_len = struct.calcsize(exports_name_pointer_table_str)
    export_names = []
    for i in xrange(vals["number_of_name_pointers"]):
        if base + entry_len >= len(data):
            break
        name_ptr = struct.unpack(exports_name_pointer_table_str, data[base:base+entry_len])
        name, offsets = rva_string_lookup(name_ptr[0], sections, optional_header["image_base"], data, offsets)
        base += entry_len
        if name:
            export_names.append(name)
    
    base_rva = vals["ordinal_table_rva"]
    base = rva_to_offset(base_rva, sections)    
    entry_len = struct.calcsize(exports_ordinal_table_str)
    ords = []
    for i in xrange(vals["number_of_name_pointers"]):
        if not base or base + entry_len >= len(data):
            break
        ord = struct.unpack(exports_ordinal_table_str, data[base:base+entry_len])
        ords.append(ord[0])
        base += entry_len
    
    exports = {}
    
    for n, o in zip(export_names, ords):
        if o < len(addresses):
            exports[n] = {"ord":o, "address":addresses[o]}
       
    vals["export_names"] = exports
    return vals, offsets