qiling icon indicating copy to clipboard operation
qiling copied to clipboard

Un-Imported DLL throwing an error

Open xooxo opened this issue 5 months ago • 5 comments

*Describe the bug I'm trying to emulate a Windows sys driver http.sys from Windows Core 2019. I use dllcollector.bat to collect DLLs. Here is the error:

  File "C:\Users\User\Desktop\curiosity\http_driver_winserver_emufuzz\testQiling.py", line 32, in <module>
    ql = Qiling([DRIVER], ROOTFS,
                ostype=QL_OS.WINDOWS,
                verbose=QL_VERBOSE.DEFAULT)
  File "C:\Users\User\AppData\Local\Programs\Python\Python313\Lib\site-packages\qiling\core.py", line 190, in __init__
    self.loader.run()
    ~~~~~~~~~~~~~~~^^
  File "C:\Users\User\AppData\Local\Programs\Python\Python313\Lib\site-packages\qiling\loader\pe.py", line 725, in run
    self.load(pe)
    ~~~~~~~~~^^^^
  File "C:\Users\User\AppData\Local\Programs\Python\Python313\Lib\site-packages\qiling\loader\pe.py", line 808, in load
    super().init_imports(pe, self.is_driver)
    ~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\User\AppData\Local\Programs\Python\Python313\Lib\site-packages\qiling\loader\pe.py", line 536, in init_imports
    dll_base = self.load_dll(entry.dll.decode(), is_driver)
  File "C:\Users\User\AppData\Local\Programs\Python\Python313\Lib\site-packages\qiling\loader\pe.py", line 250, in load_dll
    self.init_imports(dll, is_driver)
    ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^
  File "C:\Users\User\AppData\Local\Programs\Python\Python313\Lib\site-packages\qiling\loader\pe.py", line 536, in init_imports
    dll_base = self.load_dll(entry.dll.decode(), is_driver)
  File "C:\Users\User\AppData\Local\Programs\Python\Python313\Lib\site-packages\qiling\loader\pe.py", line 128, in load_dll
    dll_casefold_path = self.ql.os.path.host_casefold_path(dll_path)
  File "C:\Users\User\AppData\Local\Programs\Python\Python313\Lib\site-packages\qiling\os\path.py", line 363, in host_casefold_path
    return QlOsPath.__host_casefold_path(hostpath)
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^
  File "C:\Users\User\AppData\Local\Programs\Python\Python313\Lib\site-packages\qiling\os\path.py", line 335, in __host_casefold_path
    for elem in p.relative_to(norm).parts:
                ~~~~~~~~~~~~~^^^^^^
  File "C:\Users\User\AppData\Local\Programs\Python\Python313\Lib\pathlib\_local.py", line 385, in relative_to
    raise ValueError(f"{str(self)!r} is not in the subpath of {str(other)!r}")
ValueError: 'C:\\Users\\User\\Desktop\\curiosity\\http_driver_winserver_emufuzz\\x8664+windowsIis\\x8664+windowsIis\\examples\\rootfs\\x8664_windows\\Windows\\System32\\ext-ms-win-ntos-tm-l1-1-0.dll' is not in the subpath of '.'

It complains ext-ms-win-ntos-tm-l1-1-0.dll is not there; however driver is not even importing mentioned DLL and it is not even in the system. I tried to get it from my own system but it is not there either. Is there a programmatic way to tell Qiling not to load some DLLs? Do I need to get every DLL it asks for from somewhere?

Sample Code

from qiling import Qiling
from qiling.const import QL_OS, QL_VERBOSE

ROOTFS  = "C:\\Users\\User\\Desktop\\curiosity\\http_driver_winserver_emufuzz\\x8664+windowsIis\\x8664+windowsIis\\examples\\rootfs\\x8664_windows"
DRIVER  = f"{ROOTFS}\\http_winserver.sys"


def _stub_success(ql, *args, **kwargs):
    # NTSTATUS STATUS_SUCCESS
    return 0

MISSING_KERNEL_APIS = [
    "KeBugCheckEx",              # bluescreen – just ignore
    "KeInitializeSpinLock",
    "KeAcquireSpinLockRaiseToDpc",
    "KeReleaseSpinLock",
    "IofCompleteRequest",
    # add more as the log complains
]

if __name__ == "__main__":
    ql = Qiling([DRIVER], ROOTFS,
                ostype=QL_OS.WINDOWS,
                verbose=QL_VERBOSE.DEFAULT)

    # register dummy implementations for the APIs Qiling doesn’t have yet
    for api in MISSING_KERNEL_APIS:
        ql.set_api(api, _stub_success)

    # locate exported DriverEntry
    drv_entry = ql.loader.find_export("DriverEntry")
    print(f"[+] DriverEntry found @ 0x{drv_entry:X}")

    # Fake arguments (DriverObject and RegistryPath) – both NULL
    ql.reg.rcx = 0
    ql.reg.rdx = 0

    # optional: stop as soon as we enter DriverEntry
    def _on_entry(ql):
        print("[+] Reached DriverEntry – emulation looks OK so far.")
        ql.emu_stop()
    ql.hook_address(_on_entry, drv_entry)

    # run a very small slice just to prove it starts
    ql.run(begin=drv_entry, timeout=10_000)  # 10 ms wall clock guard

Expected behavior I don't know; couldn't go far yet

Screenshots Driver not importing this dll: Image

Additional context None

xooxo avatar Aug 11 '25 18:08 xooxo

I have solved this by editing pe.py line 536 but it feels hacky and might be incorrect for general cases. So, I'm keeping this open; because I don't know the reason. (unrelated note: I'm vibe-coding this; so there were some errors on above code:) )


try:
    dll_base = self.load_dll(entry.dll.decode(), is_driver)
except ValueError:
    dll_base = False

xooxo avatar Aug 11 '25 22:08 xooxo

Hi @xooxo, welcome and thank you for reporting this issue. It appears that the issue is different than just a non-existing file. Rather it looks like an issue in the path translation (mostly required when emulating NT on top of POSIX or vice versa), which gets confused by a DLL name using a relative path.

I believe that running your Qiling script from within the rootfs directory will work around that. The script can reside anywhere in your system, as long as the CWD is the rootfs directory while you run it. This is not a fix, but just a quick way to work around it.

If you can share a ZIP with the relevant files (binary and Qiling script), that would help us get to the bottom of this and provide a fix.

elicn avatar Aug 15 '25 09:08 elicn

Sure, I attached relevant files

http_driver_winserver_emufuzz.zip

xooxo avatar Aug 19 '25 12:08 xooxo

Hi @xooxo, I think I have stumbled upon the same problem. I got the same error with a different DLL while executing one of Qiling's tests test_pe_sys.py.

  File "C:\Users\dev\Documents\qiling_test\qilingenv13\Lib\site-packages\qiling\os\path.py", line 335, in __host_casefold_path
    for elem in p.relative_to(norm).parts:
                ~~~~~~~~~~~~~^^^^^^
  File "C:\Users\dev\AppData\Local\Programs\Python\Python313\Lib\pathlib\_local.py", line 385, in relative_to
    raise ValueError(f"{str(self)!r} is not in the subpath of {str(other)!r}")
ValueError: 'C:\\Users\\dev\\Documents\\qiling_test\\qiling\\examples\\rootfs\\x86_windows\\Windows\\System32\\symcryptk.dll' is not in the subpath of '.'

That left me quite confused as the GitHub Actions runner had no problems with these tests. As a last resort I switched to the Python version of the runner (from 3.13 to 3.11) and voilà every test passes without a problem.

I believe the problem is related to changes introduced between Python 3.12.0 and 3.13.0 as the tests still work on 3.12.0.

uintmax avatar Oct 31 '25 07:10 uintmax

Hi @xooxo, I think I have stumbled upon the same problem. I got the same error with a different DLL while executing one of Qiling's tests test_pe_sys.py.

File "C:\Users\dev\Documents\qiling_test\qilingenv13\Lib\site-packages\qiling\os\path.py", line 335, in __host_casefold_path for elem in p.relative_to(norm).parts: ~~~~~~~~~~~~~^^^^^^ File "C:\Users\dev\AppData\Local\Programs\Python\Python313\Lib\pathlib_local.py", line 385, in relative_to raise ValueError(f"{str(self)!r} is not in the subpath of {str(other)!r}") ValueError: 'C:\Users\dev\Documents\qiling_test\qiling\examples\rootfs\x86_windows\Windows\System32\symcryptk.dll' is not in the subpath of '.' That left me quite confused as the GitHub Actions runner had no problems with these tests. As a last resort I switched to the Python version of the runner (from 3.13 to 3.11) and voilà every test passes without a problem.

I believe the problem is related to changes introduced between Python 3.12.0 and 3.13.0 as the tests still work on 3.12.0.

hey, it is highly possible! My Python version is 3.9.1 :)

xooxo avatar Nov 06 '25 21:11 xooxo