def data_directories(interface): result = [] localisation = interface.lang.data_directory_tab[2] data_directory = interface.exeFile.optional_header['dataDirectory'] for i in range( int(interface.exeFile.optional_header['numberOfRvaAndSizes'][1])): if localisation[i] is not None: result.append( '{num:0>2}){0:>16} [{1:>10}] RVA [size] of {2}\n'.format( hex_from_bytes(data_directory[i][0]), hex_from_bytes(data_directory[i][1]), localisation[i], num=i + 1)) return "".join(result)
def __str__(self): localisation = self.lang.section_headers_tab[1] sections = self.exeFile.section_headers if len(self.args) == 0: args = range(0, int(self.exeFile.file_header['numberOfSections'][1])) elif len(self.args) == 2: args = range(self.args[0] - 1, self.args[1]) else: args = list(map(lambda x: x - 1, self.args)) result = [] for section_number in args: if (section_number > int( self.exeFile.file_header['numberOfSections'][1]) or section_number < 0): continue if section_number >= len(sections): break temp = [f'SECTION HEADER #{section_number + 1}'] for line_index, line in enumerate(sections[section_number]): field = sections[section_number][line] if line != 'name': field = hex_from_bytes(field) temp.append(f'{field:>12} {localisation[line_index]}') result.extend(temp) result.append('') return '\n'.join(result)
def make_table(self): # TODO: Rewrite filling section_headers table horizontal = count_positions(self.parent_.lang.section_headers_tab[1]) vertical = len(self.parent_.exe_file.section_headers) table = QTableWidget(vertical, horizontal) table.setEditTriggers(QAbstractItemView.NoEditTriggers) # Edit headers table.verticalHeader().setVisible(False) table.setHorizontalHeaderLabels( self.parent_.lang.section_headers_tab[1]) table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) for i in range(horizontal): (table.horizontalHeaderItem(i).setToolTip( table.horizontalHeaderItem(i).text())) # Filling data v_pos = 0 for section in self.parent_.exe_file.section_headers: h_pos = 0 for item in section.values(): table.setItem( v_pos, h_pos, QTableWidgetItem( hex_from_bytes(item) if item[0] != '.' else item)) table.item(v_pos, h_pos).setToolTip( str(int.from_bytes(item, 'little') ) if item[0] != '.' else item) h_pos += 1 v_pos += 1 return table
def __str__(self): optional_header_lang = self.lang.headers_info[1]['optional_header'] result = [f'{optional_header_lang[0].upper()}:\n'] optional_header_lang = optional_header_lang[2] # print(self.exeFile.optional_header) for key in self.exeFile.optional_header: if key == 'dataDirectory' or optional_header_lang[key] is None: continue val = self.exeFile.optional_header[key] interpreted_value = val[1] if key == 'subsystem': interpreted_value = '| ' + ( optional_header_lang[key][1][int(interpreted_value)] if int(interpreted_value) in optional_header_lang[key][1] else optional_header_lang[key][2]) field_name = optional_header_lang[key][0] elif key == 'dllCharacteristics': flags = interpreted_value interpreted_value = [''] names = optional_header_lang['dllCharacteristics'][1] for _id in range(len(flags)): if flags[_id] and names[_id] is not None: interpreted_value.append('\t\t\t{}'.format(names[_id])) interpreted_value = "\n".join(interpreted_value) field_name = optional_header_lang[key][0] else: interpreted_value = f'| {interpreted_value}' field_name = optional_header_lang[key] result.append('{0:>16} | {1:<30} {2}'.format( hex_from_bytes(val[0]), field_name, interpreted_value)) result.append(data_directories(self)) return "\n".join(result)
def __str__(self): file_header_lang = self.lang.headers_info[1]['file_header'] result = [f'{file_header_lang[0].upper()}:\n'] for key in self.exeFile.file_header: val = self.exeFile.file_header[key] interpreted_value = val[1] if key == 'creatingTime': creating_time = file_header_lang[2][ 'creatingTime'][1] if isinstance( file_header_lang[2]['creatingTime'], tuple) else val[2] interpreted_value = interpreted_value(creating_time) if key == 'characteristics': flags = interpreted_value interpreted_value = [''] characteristics = file_header_lang[2]['characteristics'][1] for (id_, flag) in enumerate(flags): if flag and characteristics[id_] is not None: interpreted_value.append('\t\t\t{}'.format( characteristics[id_])) interpreted_value = "\n".join(interpreted_value) else: interpreted_value = '| ' + interpreted_value key_name = (file_header_lang[2][key][0] if isinstance( file_header_lang[2][key], tuple) else file_header_lang[2][key]) result.append('{0:>16} | {1:<30} {2}'.format( hex_from_bytes(val[0]), key_name, interpreted_value)) return "\n".join(result)
def parse_export_table(self): """Parse export table if it exists. Parameters: parent - exeFile object that executes this function""" # if not isinstance(parent, ExeFile): # raise TypeError("parent object may be only ExeFile class") address, size = map(lambda x: int.from_bytes(x, 'little'), self.parent.optional_header['dataDirectory'][0]) if address == 0: return None address = self.parent.rva_to_raw(address)[1] with open(self.parent.path, 'rb') as f: f.seek(address) data = f.read(40) export_table = { 'characteristics': hex_from_bytes(data[:4]), 'timeDateStamp': hex_from_bytes(data[4:8]), 'version': (str(int.from_bytes(data[8:10], 'little')) + '.' + str(int.from_bytes(data[10:12], 'little'))), 'name': self.parent.rva_to_raw(data[12:16])[1], 'base': int.from_bytes(data[16:20], 'little'), 'numberOfFunctions': int.from_bytes(data[20:24], 'little'), 'numberOfNames': int.from_bytes(data[24:28], 'little'), 'addressesOfFunctions': self.parent.rva_to_raw(data[28:32])[1], 'addressesOfNames': self.parent.rva_to_raw(data[32:36])[1], 'addressesOfNameOrdinals': self.parent.rva_to_raw(data[36:40])[1] } export_table['name'] = get_line(f, export_table['name']) # Parsing names of functions f.seek(export_table['addressesOfNames'], 0) array_data = f.read(export_table['numberOfNames'] * 4) export_table['names'] = parse_data_to_array( array_data, 4, lambda x: get_line(f, self.parent.rva_to_raw(x)[1])) # Parsing ordinals f.seek(export_table['addressesOfNameOrdinals']) array_data = f.read(export_table['numberOfNames'] * 2) export_table['nameOrdinals'] = parse_data_to_array( array_data, 2, lambda x: int.from_bytes(x, 'little') + 1) # Parsing names of functions # TODO: Difference RVA (see documentation) f.seek(export_table['addressesOfFunctions']) array_data = f.read(export_table['numberOfFunctions'] * 4) export_table['addressesOfFunctions'] = parse_data_to_array( array_data, 4, lambda x: hex_from_bytes(x)) return export_table
def test_OnCommonData(self): expected = '0x0ABB' actual = common_funcs.hex_from_bytes(b'\xBB\x0A') self.assertEqual(expected, actual)
def test_ThrowsOnWrongDataTypes(self): with self.assertRaises(TypeError): common_funcs.hex_from_bytes(123)
def test_OnEmptyString(self): expected = "" actual = common_funcs.hex_from_bytes(b"") self.assertEqual(expected, actual)