kvs/инструменты/kvsd_data.py

243 lines
11 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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": "р", "r9d": "р", "r10d": "р10д", "r11d": "р11д",
"r12d": "р12д", "r13d": "р13д", "r14d": "р14д", "r15d": "р15д",
"ax": "аикс", "cx": "сикс", "dx": "дикс", "bx": "бикс",
"sp": "эсп", "bp": "бипи", "si": "эс", "di": "ди",
"r8w": "р", "r9w": "р", "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}"