Crash when reading from SeExports

Open
#1,351 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
25/100
Issue type
Bug
Clarity
Needs clarification
Activity status
Stale
Tech stack
python

Research direction

Start with the reproducer in qiling_dbg.py and run ql.run() against iOCdrv.sys using the x8664_windows rootfs. Read qiling/core.py and qiling/debugger/qdb/qdb.py around the reported traceback, then trace how the [SeExports] mapping is accessed at the failing instruction. Done means the driver no longer crashes when reading SeExports, with the behavior covered by a reproducible test or documented reproduction.

Written by the indexing model from the issue text.

Description

*Describe the bug
I am running a driver (iOCdrv.sys with md5: 40b021b1b4f2ee2e405f9be2232de9c9) in qiling. The execution fails on the following line:

image

The error is:

   ►   0x14000a795 │ 488b05dca9ffff  mov        rax, qword ptr [rip - 0x5624]
       0x14000a79c │ 498b54fd00      mov        rdx, qword ptr [r13 + rdi*8]
       0x14000a7a1 │ 488b08          mov        rcx, qword ptr [rax]
       0x14000a7a4 │ 488b1c0a        mov        rbx, qword ptr [rdx + rcx]
       0x14000a7a8 │ 33c0            xor        eax, eax
       0x14000a7aa │ 48891e          mov        qword ptr [rsi], rbx
       0x14000a7ad │ 488b5c2450      mov        rbx, qword ptr [rsp + 0x50]
       0x14000a7b2 │ 488b6c2458      mov        rbp, qword ptr [rsp + 0x58]
       0x14000a7b7 │ 488b742460      mov        rsi, qword ptr [rsp + 0x60]
       0x14000a7bc │ 4883c420        add        rsp, 0x20
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Qdb> x/g 0x140005178
0x140005178:    0x0000000140d3e6b8
Qdb> s
[x]     CPU Context:
[x]     ah      : 0xe6
[x]     al      : 0xb8
[x]     ch      : 0x0
[x]     cl      : 0x0
[x]     dh      : 0x1
[x]     dl      : 0x8
[x]     bh      : 0x0
[x]     bl      : 0x0
[x]     ax      : 0xe6b8
[x]     cx      : 0x0
[x]     dx      : 0x108
[x]     bx      : 0x0
[x]     sp      : 0xc998
[x]     bp      : 0x70c4
[x]     si      : 0xca28
[x]     di      : 0x6
[x]     ip      : 0xa7a4
[x]     eax     : 0x40d3e6b8
[x]     ecx     : 0x0
[x]     edx     : 0x108
[x]     ebx     : 0x0
[x]     esp     : 0x1c998
[x]     ebp     : 0x400070c4
[x]     esi     : 0x1ca28
[x]     edi     : 0x6
[x]     eip     : 0x4000a7a4
[x]     rax     : 0x140d3e6b8
[x]     rbx     : 0x0
[x]     rcx     : 0x0
[x]     rdx     : 0x108
[x]     rsi     : 0x80000001ca28
[x]     rdi     : 0x6
[x]     rbp     : 0x1400070c4
[x]     rsp     : 0x80000001c998
[x]     r8      : 0x79
[x]     r9      : 0x0
[x]     r10     : 0x525c
[x]     r11     : 0x1400070c0
[x]     r12     : 0x80000001ca88
[x]     r13     : 0x140007080
[x]     r14     : 0x2
[x]     r15     : 0x14000c318
[x]     rip     : 0x14000a7a4
[x]     cr0     : 0x11
[x]     cr1     : 0x0
[x]     cr2     : 0x0
[x]     cr3     : 0x0
[x]     cr4     : 0x6f8
[x]     cr8     : 0x0
[x]     dr0     : 0x0
[x]     dr1     : 0x0
[x]     dr2     : 0x0
[x]     dr3     : 0x0
[x]     dr4     : 0x0
[x]     dr5     : 0x0
[x]     dr6     : 0xffff0ff0
[x]     dr7     : 0x400
[x]     st0     : 0x0
[x]     st1     : 0x0
[x]     st2     : 0x0
[x]     st3     : 0x0
[x]     st4     : 0x0
[x]     st5     : 0x0
[x]     st6     : 0x0
[x]     st7     : 0x0
[x]     eflags  : 0x97
[x]     cs      : 0x33
[x]     ss      : 0x28
[x]     ds      : 0x0
[x]     es      : 0x0
[x]     fs      : 0x0
[x]     gs      : 0x0
[x]     r8b     : 0x79
[x]     r9b     : 0x0
[x]     r10b    : 0x5c
[x]     r11b    : 0xc0
[x]     r12b    : 0x88
[x]     r13b    : 0x80
[x]     r14b    : 0x2
[x]     r15b    : 0x18
[x]     r8w     : 0x79
[x]     r9w     : 0x0
[x]     r10w    : 0x525c
[x]     r11w    : 0x70c0
[x]     r12w    : 0xca88
[x]     r13w    : 0x7080
[x]     r14w    : 0x2
[x]     r15w    : 0xc318
[x]     r8d     : 0x79
[x]     r9d     : 0x0
[x]     r10d    : 0x525c
[x]     r11d    : 0x400070c0
[x]     r12d    : 0x1ca88
[x]     r13d    : 0x40007080
[x]     r14d    : 0x2
[x]     r15d    : 0x4000c318
[x]     fsbase  : 0x6000
[x]     gsbase  : 0x6000000
[x]     xmm0    : 0x0
[x]     xmm1    : 0x0
[x]     xmm2    : 0x0
[x]     xmm3    : 0x0
[x]     xmm4    : 0x0
[x]     xmm5    : 0x0
[x]     xmm6    : 0x0
[x]     xmm7    : 0x0
[x]     xmm8    : 0x0
[x]     xmm9    : 0x0
[x]     xmm10   : 0x0
[x]     xmm11   : 0x0
[x]     xmm12   : 0x0
[x]     xmm13   : 0x0
[x]     xmm14   : 0x0
[x]     xmm15   : 0x0
[x]     xmm16   : 0x0
[x]     xmm17   : 0x0
[x]     xmm18   : 0x0
[x]     xmm19   : 0x0
[x]     xmm20   : 0x0
[x]     xmm21   : 0x0
[x]     xmm22   : 0x0
[x]     xmm23   : 0x0
[x]     xmm24   : 0x0
[x]     xmm25   : 0x0
[x]     xmm26   : 0x0
[x]     xmm27   : 0x0
[x]     xmm28   : 0x0
[x]     xmm29   : 0x0
[x]     xmm30   : 0x0
[x]     xmm31   : 0x0
[x]     ymm0    : 0x0
[x]     ymm1    : 0x0
[x]     ymm2    : 0x0
[x]     ymm3    : 0x0
[x]     ymm4    : 0x0
[x]     ymm5    : 0x0
[x]     ymm6    : 0x0
[x]     ymm7    : 0x0
[x]     ymm8    : 0x0
[x]     ymm9    : 0x0
[x]     ymm10   : 0x0
[x]     ymm11   : 0x0
[x]     ymm12   : 0x0
[x]     ymm13   : 0x0
[x]     ymm14   : 0x0
[x]     ymm15   : 0x0
[x]     ymm16   : 0x0
[x]     ymm17   : 0x0
[x]     ymm18   : 0x0
[x]     ymm19   : 0x0
[x]     ymm20   : 0x0
[x]     ymm21   : 0x0
[x]     ymm22   : 0x0
[x]     ymm23   : 0x0
[x]     ymm24   : 0x0
[x]     ymm25   : 0x0
[x]     ymm26   : 0x0
[x]     ymm27   : 0x0
[x]     ymm28   : 0x0
[x]     ymm29   : 0x0
[x]     ymm30   : 0x0
[x]     ymm31   : 0x0
[x]     zmm0    : 0x0
[x]     zmm1    : 0x0
[x]     zmm2    : 0x0
[x]     zmm3    : 0x0
[x]     zmm4    : 0x0
[x]     zmm5    : 0x0
[x]     zmm6    : 0x0
[x]     zmm7    : 0x0
[x]     zmm8    : 0x0
[x]     zmm9    : 0x0
[x]     zmm10   : 0x0
[x]     zmm11   : 0x0
[x]     zmm12   : 0x0
[x]     zmm13   : 0x0
[x]     zmm14   : 0x0
[x]     zmm15   : 0x0
[x]     zmm16   : 0x0
[x]     zmm17   : 0x0
[x]     zmm18   : 0x0
[x]     zmm19   : 0x0
[x]     zmm20   : 0x0
[x]     zmm21   : 0x0
[x]     zmm22   : 0x0
[x]     zmm23   : 0x0
[x]     zmm24   : 0x0
[x]     zmm25   : 0x0
[x]     zmm26   : 0x0
[x]     zmm27   : 0x0
[x]     zmm28   : 0x0
[x]     zmm29   : 0x0
[x]     zmm30   : 0x0
[x]     zmm31   : 0x0
[x]     Hexdump:
[x]     48 8b 1c 0a 33 c0 48 89
[x]     Disassembly:
[=]     000000014000a7a4 [iOCdrv.sys           + 0x00a7a4]  48 8b 1c 0a          mov                  rbx, qword ptr [rdx + rcx]
[=]     000000014000a7a8 [iOCdrv.sys           + 0x00a7a8]  33 c0                xor                  eax, eax
[=]     000000014000a7aa [iOCdrv.sys           + 0x00a7aa]  48 89 1e             mov                  qword ptr [rsi], rbx
[=]     000000014000a7ad [iOCdrv.sys           + 0x00a7ad]  48 8b 5c 24 50       mov                  rbx, qword ptr [rsp + 0x50]
[=]     000000014000a7b2 [iOCdrv.sys           + 0x00a7b2]  48 8b 6c 24 58       mov                  rbp, qword ptr [rsp + 0x58]
[=]     000000014000a7b7 [iOCdrv.sys           + 0x00a7b7]  48 8b 74 24 60       mov                  rsi, qword ptr [rsp + 0x60]
[=]     000000014000a7bc [iOCdrv.sys           + 0x00a7bc]  48 83 c4 20          add                  rsp, 0x20
[=]     000000014000a7c0 [iOCdrv.sys           + 0x00a7c0]  41 5f                pop                  r15
[=]     000000014000a7c2 [iOCdrv.sys           + 0x00a7c2]  41 5e                pop                  r14
[=]     000000014000a7c4 [iOCdrv.sys           + 0x00a7c4]  41 5d                pop                  r13
[=]     000000014000a7c6 [iOCdrv.sys           + 0x00a7c6]  41 5c                pop                  r12
[=]     000000014000a7c8 [iOCdrv.sys           + 0x00a7c8]  5f                   pop                  rdi
[=]     000000014000a7c9 [iOCdrv.sys           + 0x00a7c9]  c3                   ret
[=]     000000014000a7ca [iOCdrv.sys           + 0x00a7ca]  cc                   int3
[=]     000000014000a7cb [iOCdrv.sys           + 0x00a7cb]  cc                   int3
[=]     000000014000a7cc [iOCdrv.sys           + 0x00a7cc]  cc                   int3
[=]     000000014000a7cd [iOCdrv.sys           + 0x00a7cd]  cc                   int3
[=]     000000014000a7ce [iOCdrv.sys           + 0x00a7ce]  cc                   int3
[=]     000000014000a7cf [iOCdrv.sys           + 0x00a7cf]  cc                   int3
[=]     000000014000a7d0 [iOCdrv.sys           + 0x00a7d0]  48 89 5c 24 08       mov                  qword ptr [rsp + 8], rbx
[=]     000000014000a7d5 [iOCdrv.sys           + 0x00a7d5]  48 89 6c 24 10       mov                  qword ptr [rsp + 0x10], rbp
[=]     000000014000a7da [iOCdrv.sys           + 0x00a7da]  48 89 74 24 18       mov                  qword ptr [rsp + 0x18], rsi
[=]     000000014000a7df [iOCdrv.sys           + 0x00a7df]  57                   push                 rdi
[=]     000000014000a7e0 [iOCdrv.sys           + 0x00a7e0]  41 56                push                 r14
[=]     000000014000a7e2 [iOCdrv.sys           + 0x00a7e2]  41 57                push                 r15
[x]     PC = 0x000000014000a7a4 (/Users/nw/git/rootfs/x8664_windows/iOCdrv.sys + 0xa7a4)

[x]     Memory map:
[x]     Start            End              Perm    Label                 Image
[x]     00000000006000 - 0000000000c000   rwx     [FS]
[x]     00000000030000 - 00000000031000   rwx     [GDT]
[x]     00000006000000 - 00000007400000   rwx     [GS]
[x]     0000007ffe0000 - 0000007ffe1000   rwx     [kuser shared data]
[x]     0000008ffe0000 - 0000008ffe1000   rwx     [SeExports]
[x]     00000140000000 - 0000014000f000   rwx     iOCdrv.sys            /Users/nw/git/rootfs/x8664_windows/iOCdrv.sys
[x]     00000140010000 - 00000141056000   rwx     ntoskrnl.exe          /Users/nw/git/rootfs/x8664_windows/Windows/System32/ntoskrnl.exe
[x]     00000180000000 - 000001801f8000   rwx     ntdll.dll             /Users/nw/git/rootfs/x8664_windows/Windows/System32/ntdll.dll
[x]     00000180200000 - 000001802bf000   rwx     kernel32.dll          /Users/nw/git/rootfs/x8664_windows/Windows/System32/kernel32.dll
[x]     000001802c0000 - 0000018059a000   rwx     kernelbase.dll        /Users/nw/git/rootfs/x8664_windows/Windows/System32/KERNELBASE.dll
[x]     000001805a0000 - 00000180605000   rwx     mscoree.dll           /Users/nw/git/rootfs/x8664_windows/Windows/System32/mscoree.dll
[x]     00000180610000 - 00000180710000   rwx     ucrtbase.dll          /Users/nw/git/rootfs/x8664_windows/Windows/System32/ucrtbase.dll
[x]     00000500000000 - 00000500001000   rwx     [heap]
[x]     00000500001000 - 00000500002000   rwx     [heap]
[x]     00000500002000 - 00000500003000   rwx     [heap]
[x]     00000500003000 - 00000500004000   rwx     [heap]
[x]     00000500004000 - 00000500006000   rwx     [heap]
[x]     007ffffffde000 - 0080000001e000   rwx     [stack]
Traceback (most recent call last):
  File "/Users/nw/Workspace/RE/driver_research/qiling_dbg.py", line 24, in <module>
    test_gdb([path], "/Users/nw/git/rootfs/x8664_windows")
  File "/Users/nw/Workspace/RE/driver_research/qiling_dbg.py", line 18, in test_gdb
    ql.run()
  File "/Users/nw/git/qiling/qiling/core.py", line 575, in run
    debugger = debugger(self)
               ^^^^^^^^^^^^^^
  File "/Users/nw/git/qiling/qiling/debugger/qdb/qdb.py", line 48, in __init__
    self.dbg_hook(init_hook)
  File "/Users/nw/git/qiling/qiling/debugger/qdb/qdb.py", line 92, in dbg_hook
    self.interactive()
  File "/Users/nw/git/qiling/qiling/debugger/qdb/qdb.py", line 189, in interactive
    return self.cmdloop()
           ^^^^^^^^^^^^^^
  File "/usr/local/Cellar/python@3.11/3.11.3/Frameworks/Python.framework/Versions/3.11/lib/python3.11/cmd.py", line 138, in cmdloop
    stop = self.onecmd(line)
           ^^^^^^^^^^^^^^^^^
  File "/usr/local/Cellar/python@3.11/3.11.3/Frameworks/Python.framework/Versions/3.11/lib/python3.11/cmd.py", line 217, in onecmd
    return func(arg)
           ^^^^^^^^^
  File "/Users/nw/git/qiling/qiling/debugger/qdb/utils.py", line 285, in magic
    func(self, *args, **kwargs)
  File "/Users/nw/git/qiling/qiling/debugger/qdb/qdb.py", line 146, in inner
    func(self, *args, **kwargs)
  File "/Users/nw/git/qiling/qiling/debugger/qdb/qdb.py", line 159, in inner
    func(self, *args, **kwargs)
  File "/Users/nw/git/qiling/qiling/debugger/qdb/qdb.py", line 231, in do_step_in
    self._run(count=step)
  File "/Users/nw/git/qiling/qiling/debugger/qdb/qdb.py", line 125, in _run
    self.ql.os.run()
  File "/Users/nw/git/qiling/qiling/os/windows/windows.py", line 219, in run
    self.ql.emu_start(entry_point, exit_point, self.ql.timeout, self.ql.count)
  File "/Users/nw/git/qiling/qiling/core.py", line 753, in emu_start
    self.uc.emu_start(begin, end, timeout, count)
  File "/usr/local/lib/python3.11/site-packages/unicorn/unicorn.py", line 547, in emu_start
    raise UcError(status)
unicorn.unicorn.UcError: Invalid memory read (UC_ERR_READ_UNMAPPED)

Sample Code

from qiling import *
from qiling.const import QL_VERBOSE


def test_gdb(path, rootfs):
    ql = Qiling(path, rootfs, verbose=QL_VERBOSE.OFF)

    # Enable debugger to listen at localhost address, default port 9999
    ql.debugger = "gdb:0.0.0.0:9999"

    ql.run()


if __name__ == "__main__":
    import sys
    path = sys.argv[1]
    test_gdb([path], "/Users/nw/git/rootfs/x8664_windows")

Then I attach to the debugger and continue execution.

Expected behavior
SeExports should be imported from ntoskrnl correctly and the value should be loaded.

Additional context
I've done some research to try and find out how to implement this. Normally, for an unsupported API call, one would implement a hook that performs an approximation of the expected behaviour. However, in this case, it is not a function call, but instead an imported value. I have dumped the contents of SeExports from memory using WinDBG. I tried to write this buffer to memory in the right location, however, I could not find how to link the SeExports symbol to this buffer.
Maybe someone more well-versed in Qiling and Windows internals can help me with this?

Dominant language
Python
Stars
6.1k
Forks
798
Avg merge
1d 1h
Merged PRs (30d)
9

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from qilingframework/qiling

All issues in qilingframework/qiling

Similar issues

More Python issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.