{ "cells": [ { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "# Custom Backend Loader\n", "\n", "If you want to load the disassembled binaries made by a tool that is not yet supported by QBinDiff you can implement your own backend loader.\n", "\n", "You have to provide an implementation for all the classes that are found in `src/qbindiff/loader/backend/abstract.py`:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "import networkx\n", "from collections.abc import Iterator\n", "\n", "from qbindiff.loader.backend import (\n", " AbstractOperandBackend,\n", " AbstractInstructionBackend,\n", " AbstractBasicBlockBackend,\n", " AbstractFunctionBackend,\n", " AbstractProgramBackend\n", ")\n", "from qbindiff.loader import Structure\n", "from qbindiff.loader.types import ReferenceType, ReferenceTarget, FunctionType\n", "from qbindiff.types import Addr\n", "\n", "class CustomOperandBackend(AbstractOperandBackend):\n", "\n", " def __str__(self) -> str:\n", " raise NotImplementedError()\n", "\n", " @property\n", " def immutable_value(self) -> int | None:\n", " raise NotImplementedError()\n", "\n", " @property\n", " def type(self) -> int:\n", " raise NotImplementedError()\n", "\n", " def is_immutable(self) -> bool:\n", " raise NotImplementedError()\n", "\n", "class CustomInstructionBackend(AbstractInstructionBackend):\n", "\n", " @property\n", " def addr(self) -> Addr:\n", " raise NotImplementedError()\n", "\n", " @property\n", " def mnemonic(self) -> str:\n", " raise NotImplementedError()\n", "\n", " @property\n", " def references(self) -> dict[ReferenceType, list[ReferenceTarget]]:\n", " raise NotImplementedError()\n", "\n", " @property\n", " def operands(self) -> Iterator[AbstractOperandBackend]:\n", " raise NotImplementedError()\n", "\n", " @property\n", " def groups(self) -> list[int]:\n", " raise NotImplementedError()\n", "\n", " @property\n", " def id(self) -> int:\n", " raise NotImplementedError()\n", "\n", " @property\n", " def comment(self) -> str:\n", " raise NotImplementedError()\n", "\n", " @property\n", " def bytes(self) -> bytes:\n", " raise NotImplementedError()\n", "\n", "class CustomBasicBlockBackend(AbstractBasicBlockBackend):\n", "\n", " @property\n", " def addr(self) -> Addr:\n", " raise NotImplementedError()\n", "\n", " @property\n", " def instructions(self) -> Iterator[AbstractInstructionBackend]:\n", " raise NotImplementedError()\n", "\n", "class CustomFunctionBackend(AbstractFunctionBackend):\n", "\n", " @property\n", " def basic_blocks(self) -> Iterator[AbstractBasicBlockBackend]:\n", " raise NotImplementedError()\n", "\n", " @property\n", " def addr(self) -> Addr:\n", " raise NotImplementedError()\n", "\n", " @property\n", " def graph(self) -> networkx.DiGraph:\n", " raise NotImplementedError()\n", "\n", " @property\n", " def parents(self) -> set[Addr]:\n", " raise NotImplementedError()\n", "\n", " @property\n", " def children(self) -> set[Addr]:\n", " raise NotImplementedError()\n", "\n", " @property\n", " def type(self) -> FunctionType:\n", " raise NotImplementedError()\n", "\n", " @property\n", " def name(self) -> str:\n", " raise NotImplementedError()\n", "\n", "class CustomProgramBackend(AbstractProgramBackend):\n", "\n", " @property\n", " def functions(self) -> Iterator[AbstractFunctionBackend]:\n", " raise NotImplementedError()\n", "\n", " @property\n", " def name(self) -> str:\n", " raise NotImplementedError()\n", "\n", " @property\n", " def structures(self) -> list[Structure]:\n", " raise NotImplementedError()\n", "\n", " @property\n", " def callgraph(self) -> networkx.DiGraph:\n", " raise NotImplementedError()\n", "\n", " @property\n", " def fun_names(self) -> dict[str, Addr]:\n", " raise NotImplementedError()\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Most of the methods are self-explanatory but if you want to know more look at the docstring in the file `src/qbindiff/loader/backend/abstract.py`\n", "or at the python help." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on class AbstractProgramBackend in module qbindiff.loader.backend.abstract:\n", "\n", "class AbstractProgramBackend(builtins.object)\n", " | This is an abstract class and should not be used as is.\n", " | It represents a generic backend loader for a Program\n", " | \n", " | Readonly properties defined here:\n", " | \n", " | callgraph\n", " | The callgraph of the program.\n", " | \n", " | exec_path\n", " | Returns the executable path\n", " | \n", " | fun_names\n", " | Returns a dictionary with function name as key and the function address as value.\n", " | \n", " | functions\n", " | Returns an iterator over backend function objects.\n", " | \n", " | name\n", " | The name of the program.\n", " | \n", " | structures\n", " | Returns the list of structures defined in program.\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data descriptors defined here:\n", " | \n", " | __dict__\n", " | dictionary for instance variables (if defined)\n", " | \n", " | __weakref__\n", " | list of weak references to the object (if defined)\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes defined here:\n", " | \n", " | __abstractmethods__ = frozenset({'callgraph', 'exec_path', 'fun_names'...\n", "\n" ] } ], "source": [ "from qbindiff.loader.backend import AbstractProgramBackend\n", "\n", "help(AbstractProgramBackend)" ] } ], "metadata": { "kernelspec": { "display_name": "venv", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.5" }, "orig_nbformat": 4 }, "nbformat": 4, "nbformat_minor": 2 }