from pathlib import Path import logging import rzpipe import json class _RizinBase: def __init__(self, path: Path): rz_pipe = rzpipe.open(str(path.absolute())) for cmd in self.arch_cmds: rz_pipe.cmd(cmd) rz_pipe.cmd("aa") result = rz_pipe.cmd("pdj") rz_pipe.quit() self.disassembly = json.loads(result) def __repr__(self) -> str: return self.objdump def __len__(self) -> int: return len(self.disassembly) def __lt__(self, other): return len(self) < len(other) @property def objdump(self) -> str: if hasattr(self, "_objdump"): return self._objdump self._objdump = str() for each in self.disassembly: offset = each.get("offset") opcode = each.get("opcode") self._objdump += f"{offset:#02x}:\t{opcode}\n" return self._objdump @property def disasm(self) -> list: if hasattr(self, "_disasm"): return self._disasm self._disasm = list() for each in self.disassembly: offset = each.get("offset") opcode = each.get("opcode") if opcode: mnemonic = opcode.split(" ")[0] opcode = opcode.split(" ")[1:] else: mnemonic = None self._disasm.append([offset, mnemonic, opcode]) return self._disasm @property def rets(self) -> list: if hasattr(self, "_rets"): return self._rets self._rets = list() for each in self.disasm: _, mnemonic, _ = each if mnemonic and "ret" in mnemonic: self._rets.append(mnemonic) return self._rets @property def ret_rates(self) -> list: rates = dict() for mnemonic in set(self.rets): rates[mnemonic] = self.rets.count(mnemonic) _ret_rates = sorted( ((value, key) for (key, value) in rates.items()), reverse=True ) return _ret_rates @property def mnemonic_rates(self) -> list: mnemonics = list() for each in self.disasm: _, mnemonic, _ = each if mnemonic: mnemonics.append(mnemonic) rates = dict() for mnemonic in set(mnemonics): rates[mnemonic] = mnemonics.count(mnemonic) _mnemonic_rates = sorted( ((value, key) for (key, value) in rates.items()), reverse=True ) return _mnemonic_rates class x86_16(_RizinBase): arch_cmds = ["e asm.arch=x86", "e asm.bits=16"]