|
| 1 | +#!/usr/bin/env python3 |
| 2 | +# |
| 3 | +# Cross Platform and Multi Architecture Advanced Binary Emulation Framework |
| 4 | +# |
| 5 | + |
| 6 | +import os |
| 7 | +import functools |
| 8 | +import json |
| 9 | +import ctypes |
| 10 | +from typing import Set |
| 11 | +import libr |
| 12 | +from qiling.bin import QlBinAnalyzer |
| 13 | +from qiling.bin import QlBinFunction, QlBinSection, QlBinString, QlBinSymbol |
| 14 | + |
| 15 | + |
| 16 | +class R2(QlBinAnalyzer): |
| 17 | + def __init__(self, filename: str): |
| 18 | + super().__init__() |
| 19 | + filename = filename.encode() |
| 20 | + filename = os.path.realpath(filename) |
| 21 | + self._r2c = libr.r_core.r_core_new() |
| 22 | + fh = libr.r_core.r_core_file_open(self._r2c, filename, 0b101, 0) |
| 23 | + libr.r_core.r_core_bin_load(self._r2c, filename, (1 << 64) - 1) |
| 24 | + |
| 25 | + def _cmd(self, cmd): |
| 26 | + r = libr.r_core.r_core_cmd_str( |
| 27 | + self._r2c, ctypes.create_string_buffer(cmd.encode("utf-8"))) |
| 28 | + return ctypes.string_at(r).decode('utf-8') |
| 29 | + |
| 30 | + @functools.cached_property |
| 31 | + def sections(self) -> Set[QlBinSection]: |
| 32 | + res = self._cmd("iSj") |
| 33 | + sec_lst = json.loads(res) |
| 34 | + return {QlBinSection(**dic) for dic in sec_lst} |
| 35 | + |
| 36 | + @functools.cached_property |
| 37 | + def strings(self) -> Set[QlBinString]: |
| 38 | + res = self._cmd("izzj") |
| 39 | + str_lst = json.loads(res) |
| 40 | + return {QlBinString(**dic) for dic in str_lst} |
| 41 | + |
| 42 | + @functools.cached_property |
| 43 | + def symbols(self) -> Set[QlBinSymbol]: |
| 44 | + res = self._cmd("isj") |
| 45 | + sym_lst = json.loads(res) |
| 46 | + return {QlBinSymbol(**dic) for dic in sym_lst} |
| 47 | + |
| 48 | + @functools.cached_property |
| 49 | + def functions(self) -> Set[QlBinFunction]: |
| 50 | + self._cmd("aaa") |
| 51 | + res = self._cmd("aflj") |
| 52 | + fcn_lst = json.loads(res) |
| 53 | + return {QlBinFunction(**dic) for dic in fcn_lst} |
| 54 | + |
| 55 | + @functools.cached_property |
| 56 | + def baddr(self) -> int: |
| 57 | + _bin = ctypes.cast(self._r2c.contents.bin, |
| 58 | + ctypes.POINTER(libr.r_bin.RBin)) |
| 59 | + return libr.r_bin.r_bin_get_baddr(_bin) |
| 60 | + |
| 61 | + def addr_of_str(self, name: str) -> int | None: |
| 62 | + strs = self.strings |
| 63 | + for str in strs: |
| 64 | + if str.string == name: |
| 65 | + return str.vaddr |
| 66 | + |
| 67 | + def addr_of_sym(self, name: str) -> int | None: |
| 68 | + syms = self.symbols |
| 69 | + for sym in syms: |
| 70 | + if sym.name == name or sym.realname == name: |
| 71 | + return sym.vaddr |
| 72 | + |
| 73 | + def addr_of_fcn(self, name: str) -> int | None: |
| 74 | + fcns = self.functions |
| 75 | + for fcn in fcns: |
| 76 | + if fcn.name == name or fcn.name.endswith(name): |
| 77 | + return fcn.offset |
| 78 | + |
| 79 | + def addr_of(self, name: str) -> int | None: |
| 80 | + return self.addr_of_sym(name) or self.addr_of_fcn(name) |
| 81 | + |
| 82 | + def __del__(self): |
| 83 | + libr.r_core.r_core_free(self._r2c) |
| 84 | + |
| 85 | + |
| 86 | +if __name__ == '__main__': |
| 87 | + r2 = R2("examples/fuzzing/linux_x8664/x8664_fuzz") |
| 88 | + print(r2.strings) |
| 89 | + print(r2.sections) |
| 90 | + print(hex(r2.baddr)) |
| 91 | + print(hex(r2.addr_of("main"))) |
| 92 | + while True: |
| 93 | + print("> ", end="") |
| 94 | + cmd = input() |
| 95 | + if cmd.strip() == "q": |
| 96 | + break |
| 97 | + print(r2._cmd(cmd)) |
0 commit comments