243 lines
11 KiB
Python
243 lines
11 KiB
Python
#!/usr/bin/env python3
|
||
# -*- coding: utf-8 -*-
|
||
|
||
"""
|
||
kvsd_data.py
|
||
Словари для дизассемблера КВС
|
||
Трансляция x86-64 мнемоник в кастомный синтаксис
|
||
"""
|
||
|
||
# === СЛОВАРЬ ТРАНСЛЯЦИИ МНЕМОНИК ===
|
||
MNEMONIC_TRANSLATION = {
|
||
"mov": "переместить",
|
||
"movzx": "переместить_с_нулями",
|
||
"movsx": "переместить_со_знаком",
|
||
"lea": "загрузить_адрес",
|
||
"add": "прибавить",
|
||
"sub": "вычесть",
|
||
"inc": "увеличить",
|
||
"dec": "уменьшить",
|
||
"mul": "умножить",
|
||
"div": "разделить",
|
||
"imul": "умножить_знаковое",
|
||
"idiv": "разделить_знаковое",
|
||
"neg": "отрицать",
|
||
"and": "и",
|
||
"or": "или",
|
||
"xor": "исключающее_или",
|
||
"not": "инвертировать",
|
||
"cmp": "сравнить",
|
||
"test": "проверить",
|
||
"jmp": "переход",
|
||
"je": "переход_если_равно",
|
||
"jz": "переход_если_ноль",
|
||
"jne": "переход_если_неравно",
|
||
"jnz": "переход_если_не_ноль",
|
||
"jl": "переход_если_меньше",
|
||
"jg": "переход_если_больше",
|
||
"jle": "переход_если_меньше_или_равно",
|
||
"jge": "переход_если_больше_или_равно",
|
||
"jc": "переход_если_перенос",
|
||
"jnc": "переход_если_нет_переноса",
|
||
"jo": "переход_если_переполнение",
|
||
"jno": "переход_если_нет_переполнения",
|
||
"js": "переход_если_знак",
|
||
"jns": "переход_если_нет_знака",
|
||
"jp": "переход_если_чётность",
|
||
"jnp": "переход_если_не_чётность",
|
||
"jbe": "переход_если_ниже_или_равно",
|
||
"ja": "переход_если_выше",
|
||
"call": "вызвать",
|
||
"ret": "вернуться",
|
||
"retn": "вернуться",
|
||
"push": "втолкнуть",
|
||
"pop": "вытолкнуть",
|
||
"pushf": "втолкнуть_флаги",
|
||
"popf": "вытолкнуть_флаги",
|
||
"shl": "сдвиг_влево",
|
||
"sal": "сдвиг_влево",
|
||
"shr": "сдвиг_вправо",
|
||
"sar": "сдвиг_арифметический_вправо",
|
||
"rol": "вращать_влево",
|
||
"ror": "вращать_вправо",
|
||
"rcl": "вращать_через_перенос_влево",
|
||
"rcr": "вращать_через_перенос_вправо",
|
||
"syscall": "вызов_системы",
|
||
"int": "прервать",
|
||
"sysenter": "войти_в_систему",
|
||
"hlt": "остановить",
|
||
"cpuid": "идентифицировать_процессор",
|
||
"rdtsc": "прочитать_счётчик",
|
||
"nop": "нет_операции",
|
||
"int3": "отладка",
|
||
"movsb": "переместить_байт",
|
||
"movsw": "переместить_слово",
|
||
"movsd": "переместить_двойное_слово",
|
||
"movsq": "переместить_квадрослово",
|
||
"cmpsb": "сравнить_байты",
|
||
"cmpsw": "сравнить_слова",
|
||
"scasb": "сканировать_байт",
|
||
"stosb": "сохранить_байт",
|
||
"stc": "установить_перенос",
|
||
"clc": "сбросить_перенос",
|
||
"std": "установить_направление",
|
||
"cld": "сбросить_направление",
|
||
"in": "ввод_байта",
|
||
"out": "вывод_байта",
|
||
"loop": "цикл",
|
||
"loope": "цикл_если_равно",
|
||
"loopne": "цикл_если_не_равно",
|
||
"xchg": "обменять",
|
||
}
|
||
|
||
# === СЛОВАРЬ ТРАНСЛЯЦИИ РЕГИСТРОВ ===
|
||
REGISTER_TRANSLATION = {
|
||
"rax": "раикс", "rcx": "рсикс", "rdx": "рдикс", "rbx": "рбикс",
|
||
"rsp": "рсипи", "rbp": "рбипи", "rsi": "рсиай", "rdi": "рдиай",
|
||
"r8": "р8", "r9": "р9", "r10": "р10", "r11": "р11",
|
||
"r12": "р12", "r13": "р13", "r14": "р14", "r15": "р15",
|
||
"eax": "еаикс", "ecx": "есикс", "edx": "едикс", "ebx": "ебикс",
|
||
"esp": "есипи", "ebp": "ебипи", "esi": "есиай", "edi": "едиай",
|
||
"r8d": "р8д", "r9d": "р9д", "r10d": "р10д", "r11d": "р11д",
|
||
"r12d": "р12д", "r13d": "р13д", "r14d": "р14д", "r15d": "р15д",
|
||
"ax": "аикс", "cx": "сикс", "dx": "дикс", "bx": "бикс",
|
||
"sp": "эсп", "bp": "бипи", "si": "эс", "di": "ди",
|
||
"r8w": "р8в", "r9w": "р9в", "r10w": "р10в", "r11w": "р11в",
|
||
"r12w": "р12в", "r13w": "р13в", "r14w": "р14в", "r15w": "р15в",
|
||
"al": "ал", "cl": "кл", "dl": "дл", "bl": "бл",
|
||
"spl": "спл", "bpl": "бпл", "sil": "сил", "dil": "дил",
|
||
"r8b": "р8б", "r9b": "р9б", "r10b": "р10б", "r11b": "р11б",
|
||
"r12b": "р12б", "r13b": "р13б", "r14b": "р14б", "r15b": "р15б",
|
||
"ah": "аш", "ch": "чш", "dh": "дш", "bh": "бш",
|
||
"rip": "рип", "rflags": "рфлаги",
|
||
}
|
||
|
||
|
||
def translate_mnemonic(mnemonic, operand_str="", instr_len=0):
|
||
"""
|
||
Переводит мнемонику x86-64 в кастомный синтаксис КВС.
|
||
|
||
Аргументы:
|
||
mnemonic (str): исходная мнемоника
|
||
operand_str (str): строка операндов (для определения short)
|
||
instr_len (int): длина инструкции в байтах (для определения коротких/длинных переходов)
|
||
"""
|
||
# Для JMP: определяем по наличию "short" в операндах
|
||
if mnemonic == "jmp" and "short" in operand_str:
|
||
return "короткий_переход"
|
||
|
||
# Для условных переходов: определяем по длине инструкции
|
||
if mnemonic in ["je", "jz", "jne", "jnz", "jl", "jg", "jle", "jge",
|
||
"jc", "jnc", "jo", "jno", "js", "jns", "jp", "jnp",
|
||
"jbe", "ja"]:
|
||
# Длина 2 байта = короткий переход (rel8)
|
||
if instr_len == 2:
|
||
translation = {
|
||
"je": "короткий_переход_если_равно",
|
||
"jz": "короткий_переход_если_ноль",
|
||
"jne": "короткий_переход_если_неравно",
|
||
"jnz": "короткий_переход_если_не_ноль",
|
||
"jl": "короткий_переход_если_меньше",
|
||
"jg": "короткий_переход_если_больше",
|
||
"jle": "короткий_переход_если_меньше_или_равно",
|
||
"jge": "короткий_переход_если_больше_или_равно",
|
||
"jc": "короткий_переход_если_перенос",
|
||
"jnc": "короткий_переход_если_нет_переноса",
|
||
"jo": "короткий_переход_если_переполнение",
|
||
"jno": "короткий_переход_если_нет_переполнения",
|
||
"js": "короткий_переход_если_знак",
|
||
"jns": "короткий_переход_если_нет_знака",
|
||
"jp": "короткий_переход_если_чётность",
|
||
"jnp": "короткий_переход_если_не_чётность",
|
||
"jbe": "короткий_переход_если_ниже_или_равно",
|
||
"ja": "короткий_переход_если_выше",
|
||
}
|
||
return translation.get(mnemonic, mnemonic)
|
||
# Длина 6 байт = длинный переход (rel32)
|
||
elif instr_len == 6:
|
||
translation = {
|
||
"je": "переход_если_равно",
|
||
"jz": "переход_если_ноль",
|
||
"jne": "переход_если_неравно",
|
||
"jnz": "переход_если_не_ноль",
|
||
"jl": "переход_если_меньше",
|
||
"jg": "переход_если_больше",
|
||
"jle": "переход_если_меньше_или_равно",
|
||
"jge": "переход_если_больше_или_равно",
|
||
"jc": "переход_если_перенос",
|
||
"jnc": "переход_если_нет_переноса",
|
||
"jo": "переход_если_переполнение",
|
||
"jno": "переход_если_нет_переполнения",
|
||
"js": "переход_если_знак",
|
||
"jns": "переход_если_нет_знака",
|
||
"jp": "переход_если_чётность",
|
||
"jnp": "переход_если_не_чётность",
|
||
"jbe": "переход_если_ниже_или_равно",
|
||
"ja": "переход_если_выше",
|
||
}
|
||
return translation.get(mnemonic, mnemonic)
|
||
|
||
return MNEMONIC_TRANSLATION.get(mnemonic, mnemonic)
|
||
|
||
|
||
def translate_operand(operand):
|
||
"""
|
||
Переводит операнд: заменяет все регистры на кастомные имена.
|
||
Также удаляет слово "short" из операндов.
|
||
"""
|
||
if not operand:
|
||
return operand
|
||
|
||
result = operand
|
||
|
||
# Удаляем "short" из операндов (для коротких переходов)
|
||
result = result.replace("short ", "")
|
||
result = result.replace(" short", "")
|
||
|
||
# Сортируем регистры по длине (от длинных к коротким)
|
||
sorted_regs = sorted(REGISTER_TRANSLATION.keys(), key=len, reverse=True)
|
||
|
||
for reg in sorted_regs:
|
||
trans_reg = REGISTER_TRANSLATION[reg]
|
||
for sep in ['', ' ', ',', '+', '-', '*', '/', '(', ')', '[', ']', ':', '&', '|']:
|
||
result = result.replace(reg + sep, trans_reg + sep)
|
||
result = result.replace(sep + reg, sep + trans_reg)
|
||
if result.startswith(reg):
|
||
result = trans_reg + result[len(reg):]
|
||
if result.endswith(reg):
|
||
result = result[:-len(reg)] + trans_reg
|
||
result = result.replace(reg, trans_reg)
|
||
|
||
return result
|
||
|
||
|
||
def translate_line(line):
|
||
"""
|
||
Переводит строку дизассемблера.
|
||
Формат: "00401000 48B80A0000000000 mov rax,0xa"
|
||
"""
|
||
if not line.strip():
|
||
return line
|
||
|
||
parts = line.split(maxsplit=2)
|
||
if len(parts) < 3:
|
||
return line
|
||
|
||
address = parts[0]
|
||
bytes_hex = parts[1]
|
||
rest = parts[2]
|
||
|
||
rest_parts = rest.split(maxsplit=1)
|
||
mnemonic = rest_parts[0]
|
||
operands = rest_parts[1] if len(rest_parts) > 1 else ""
|
||
|
||
# Вычисляем длину инструкции
|
||
instr_len = len(bytes_hex) // 2 if bytes_hex else 0
|
||
|
||
new_mnemonic = translate_mnemonic(mnemonic, operands, instr_len)
|
||
new_operands = translate_operand(operands)
|
||
|
||
if new_operands:
|
||
return f"{address} {bytes_hex} {new_mnemonic} {new_operands}"
|
||
else:
|
||
return f"{address} {bytes_hex} {new_mnemonic}" |