From 07012b17d141a053b95f8cfec8725f4ad657b61b Mon Sep 17 00:00:00 2001 From: Alexandre Iooss Date: Wed, 27 Sep 2023 13:09:00 +0200 Subject: [PATCH] Add loaders.cleloader --- rainbow/loaders/__init__.py | 14 ++++++----- rainbow/loaders/cleloader.py | 45 ++++++++++++++++++++++++++++++++++++ setup.py | 1 + 3 files changed, 54 insertions(+), 6 deletions(-) create mode 100644 rainbow/loaders/cleloader.py diff --git a/rainbow/loaders/__init__.py b/rainbow/loaders/__init__.py index cd7a2dd..ecfcec5 100644 --- a/rainbow/loaders/__init__.py +++ b/rainbow/loaders/__init__.py @@ -19,17 +19,19 @@ import os from typing import Optional +from .cleloader import cleloader from .elfloader import elfloader from .hexloader import hexloader from .peloader import peloader -LOADERS = {".hex": hexloader, ".elf": elfloader, ".so": elfloader, ".exe": peloader} +LOADERS = {".hex": hexloader, ".elf": elfloader, ".so": cleloader, ".exe": peloader} def load_selector(filename, rainbow_instance, typ=None, *args, **kwargs) -> Optional[int]: - if typ is None: - ext = os.path.splitext(filename)[1] - loader = LOADERS[ext] - else: - loader = LOADERS[typ] + """Select the appropriate loader. + + Default to CLE loader if unknown as it has the most chance of succeeding. + """ + typ = typ if typ is not None else os.path.splitext(filename)[1] + loader = LOADERS.get(typ, cleloader) return loader(filename, rainbow_instance, *args, **kwargs) diff --git a/rainbow/loaders/cleloader.py b/rainbow/loaders/cleloader.py new file mode 100644 index 0000000..78274dd --- /dev/null +++ b/rainbow/loaders/cleloader.py @@ -0,0 +1,45 @@ +# This file is part of rainbow +# +# rainbow is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . +# +# +# Copyright 2022 A Iooss, ANSSI + +import cle + + +def cleloader(path: str, emu, ld_path=(), verbose=False) -> None: + """Load binary using CLE + + It will try to load their associated libraries and resolves imports. + """ + if verbose: + print(f"[+] Opening {path}") + ld = cle.Loader(path, except_missing_libs=True, ld_path=ld_path) + + # Map memory + if verbose: + for obj in ld.all_objects: + print(f"[ ] Mapping at 0x{obj.min_addr:08X}: {obj.binary_basename}") + emu.map_space(ld.min_addr, ld.max_addr, verbose=verbose) + for start_addr, backer in ld.memory.backers(): + emu.emu.mem_write(start_addr, bytes(backer)) + + # Load symbols + func_symbols = [s for s in ld.symbols if s.is_function and s.is_export] + if verbose: + print(f"[+] Loading {len(func_symbols)} functions symbol") + for symbol in func_symbols: + emu.functions[symbol.name] = symbol.rebased_addr + emu.function_names.update({symbol.rebased_addr: symbol.name}) diff --git a/setup.py b/setup.py index e247063..dae4713 100644 --- a/setup.py +++ b/setup.py @@ -43,6 +43,7 @@ install_requires=[ "unicorn>=2.0.1", "capstone>=4.0.0", + "cle>=9.2", "lief>=0.10.0", "intelhex", "colorama",