diffing-with-bindiff/comp.py

169 lines
6.4 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# ВНИМАНИЕ: работает с двумя бинарниками, !!!!! собранными под x64 !!!!!
import subprocess
import os, time
# Для работы с IDA
from exetoi64 import make_i64
#
# Для работы с excel
from openpyxl import Workbook
from openpyxl.styles import Font, PatternFill
#
def main():
# Задается вручную
ida_path = r"C:\Users\user\Desktop\IDA Pro 7.7.220118 (Windows) (x86,x64,ARM64)\ida64.exe"
bindiff_path = r"C:\tools\BinDiff\bin\bindiff.exe"
exe_dir = r"C:\tools\ffmpeg"
#
# Создание .i64 из .exe файлов
start = time.perf_counter()
exe_list = find_exe_in_dir(exe_dir)
for exe_path in exe_list:
make_i64(ida_path, exe_path, exe_path + '.i64')
#
# Создание файлов экспорта, получение файлов сравнений
create_exports(bindiff_path, exe_dir, exe_dir)
compare_exports(bindiff_path, exe_dir)
#
# Получение имени файла с результатом сравнения
exe_1_name = os.path.basename(exe_list[0])
exe_2_name = os.path.basename(exe_list[1])
result_file_name = fr'{exe_dir}\{exe_1_name}_vs_{exe_2_name}.results'
#
# Формирую список с инфой о сравнении функций
compare_functions_info = parse_bindiff_log(result_file_name)
#
# Подсчет времени
elapsed = time.perf_counter() - start
print(f"Elapsed \033[92m{elapsed} sec\033[0m")
#
# Выгрузка
output_path = "output.xlsx"
create_excel_from_bindiff_log(compare_functions_info,
output_path,
exe_1_name,
exe_2_name,
elapsed)
#
def create_excel_from_bindiff_log(compare_functions_info,
output_file,
exe_1_name,
exe_2_name,
elapsed):
wb = Workbook()
ws = wb.active
ws.title = "BinDiff Results"
# Заголовки столбцов
headers = [
f'Address in {exe_1_name}',
f'Address in {exe_2_name}',
#'Match Type',
'Similarity',
#'Confidence',
#'Basic Block Similarity',
#'Flags',
#'Additional Flags',
'Matching Algorithm',
f'{exe_1_name}',
f'{exe_2_name}',
f'Matches: {len(compare_functions_info)}',
f'Elapsed: {elapsed:.2f} sec',
' '
]
ws.append(headers)
bold_font = Font(bold=True) # Стиль с жирным шрифтом
for cell in ws[1]: # ws[1] обращается к первой строке (заголовкам)
cell.font = bold_font # Применяет стиль к каждой ячейке
# Окраска ячеек с общей информацией
green_fill = PatternFill(start_color="90EE00", end_color="90EE00", fill_type="solid")
light_green_fill = PatternFill(start_color="90EE90", end_color="90EE90", fill_type="solid")
ws['G1'].fill = green_fill
ws['H1'].fill = light_green_fill
# Добавляю данные
for result in compare_functions_info:
row = [
result['addr1'],
result['addr2'],
#result['match_type'],
result['similarity'],
#result['confidence'],
#result['bb_similarity'],
#result['flags'],
#result['additional_flags'],
result['matching_algorithm'],
result['name1'],
result['name2'],
' '
]
ws.append(row)
wb.save(output_file)
def parse_bindiff_log(log_file):
results = []
with open(log_file, 'r') as f:
for line in f:
fields = line.strip().split('\t')
# в логе который создает bindiff по каждой функции 11 полей
if len(fields) == 11:
result = {
'addr1': fields[0], # адрес функции в первом бинаре
'addr2': fields[1], # адрес во втором
'match_type': fields[2], # тип совпадения
'similarity': fields[3], # сходство
'confidence': fields[4], # уверенность (на сколько bindiff уверен в правильности сопоставления)
'bb_similarity': fields[5], # сходство базовых блоков (показывает, насколько похожи базовые блоки внутри функции)
'flags': fields[6], # дополнительная информация
'additional_flags': fields[7], # дополнительная информация
'matching_algorithm': fields[8].replace("function: ", ""), # описание метода, который был использован для сопоставления функций
'name1': fields[9].strip('"'), # имя функции в первом бинаре
'name2': fields[10].strip('"') # имя во втором бинаре
}
results.append(result)
return results
def find_exe_in_dir(directory):
exe_files = []
for root, _, files in os.walk(directory):
for file in files:
if file.endswith(".exe"):
exe_files.append(os.path.join(root, file))
return exe_files
def create_exports(bindiff_path, idb_dir, bindiff_exports_dir):
cmd = f"{bindiff_path} --export {idb_dir} --output_dir {bindiff_exports_dir}"
print('Creating export files...', end=' ')
try:
subprocess.run(cmd, capture_output=True, check=True)
print('\033[92mSuccess!\033[0m')
except subprocess.CalledProcessError as e:
print(f"\033[91mError during export: {e}\033[0m")
def compare_exports(bindiff_path, bindiff_exports_dir):
cmd = f"{bindiff_path} {bindiff_exports_dir} --output_format log"
print('Comparing...', end=' ')
try:
subprocess.run(cmd, capture_output=True, check=True)
print('\033[92mSuccess!\033[0m')
except subprocess.CalledProcessError as e:
print(f"\033[91mError during comparing: {e}\033[0m")
if __name__ == "__main__":
main()