Load Python Dependencies With Conflicting Sub-dependencies

130 Views Asked by At

I have created two virtual environments (with virtualenv) for two dependencies I will be importing, namely Qiling (a framework for binary emulation based on Unicorn Emulator) and Angr (a binary analysis framework). In each of these virtual environments' directories, I have downloaded the latest said packages and its dependencies, because, for instance, each of the above said packages requires different versions of Unicorn Python bindings. Question is, how can I import two Python packages with different sub-dependencies into my Python code, such that I would import two different versions of the sub-dependencies at run-time?

For example, doing the following will result in a runtime error with the Unicorn bindings:

import os
_SRC_DIR=os.path.dirname(__file__)
import sys
sys.path.insert(0, os.path.join(_SRC_DIR, "angr-virtualenv/lib/python3.10/site-packages"))
import angr # Quoting this line would allow qiling to run.
sys.path.pop(0)
sys.path.insert(0, os.path.join(_SRC_DIR, "qiling-virtualenv/lib/python3.10/site-packages"))
from qiling import Qiling
from qiling.const import QL_VERBOSE
sys.path.pop(0)

def qiling_fn():
    ql = Qiling(["<path to my binary>"], "<path to my rootfs>", verbose=QL_VERBOSE.OFF)
    ql.run()

if __name__ == "__main__":
    qiling_fn()

and the runtime error I get is the following (which means a Unicorn binding version mismatch):

Traceback (most recent call last):
  File "<path to script>/emulate_hello.py", line 17, in <module>
    qiling_fn()
  File "<path to script>/emulate_hello.py", line 13, in qiling_fn
    ql = Qiling(["<path to my binary>/"], "<path to my rootfs>", verbose=QL_VERBOSE.OFF)
  File "<path to script>/qiling-virtualenv/lib/python3.10/site-packages/qiling/core.py", line 148, in __init__
    self._arch = select_arch(archtype, endian, thumb)(self)
  File "<path to script>/qiling-virtualenv/lib/python3.10/site-packages/qiling/utils.py", line 394, in select_arch
    obj = ql_get_module_function(qlarch_path, qlarch_class)
  File "<path to script>/qiling-virtualenv/lib/python3.10/site-packages/qiling/utils.py", line 80, in ql_get_module_function
    module = ql_get_module(module_name)
  File "<path to script>/qiling-virtualenv/lib/python3.10/site-packages/qiling/utils.py", line 73, in ql_get_module
    module = importlib.import_module(module_name, 'qiling')
  File "/usr/lib64/python3.10/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 883, in exec_module
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "<path to script>/qiling-virtualenv/lib/python3.10/site-packages/qiling/arch/x86.py", line 12, in <module>
    from qiling.arch.arch import QlArch
  File "<path to script>/qiling-virtualenv/lib/python3.10/site-packages/qiling/arch/arch.py", line 9, in <module>
    from unicorn.unicorn import UcContext
ImportError: cannot import name 'UcContext' from 'unicorn.unicorn' (<path to script>/angr-virtualenv/lib/python3.10/site-packages/unicorn/unicorn.py)

However, if I remove import angr, the emulator runs fine, because the correct Unicorn bindings are loaded.

Long story short, I want angr to import its own version requirement of Unicorn while qiling do so as well, from their respective import directories, and not have one common unicorn import for all packages.

0

There are 0 best solutions below