How can I set a breakpoint to target this emulated location when it's at a different offset in WinDbg?

656 Views Asked by At

I'm using the qiling framework to emulate a snake game which runs fine in my x86 64 Windows environment, but it's failing in the emulated environment. It works fine run normally, but I'm having trouble getting a breakpoint to work in WinDbg at the place it's failing. My question is more about understanding my problem in WinDbg, but I'll provide the emulator logs for context:

[=]     Initiate stack address at 0xfffdd000
[=]     Loading snake.exe to 0x400000
[=]     PE entry point at 0x4033ae
[=]     TEB addr is 0x6000
[=]     PEB addr is 0x6044
[=]     Loading ../examples/rootfs/x8664_windows\Windows\System32\ntdll.dll ...
[!]     Warnings while loading ../examples/rootfs/x8664_windows\Windows\System32\ntdll.dll:
[!]      - SizeOfHeaders is smaller than AddressOfEntryPoint: this file cannot run under Windows 8.
[!]      - AddressOfEntryPoint lies outside the sections' boundaries. AddressOfEntryPoint: 0x0
[=]     Done with loading ../examples/rootfs/x8664_windows\Windows\System32\ntdll.dll
[=]     Loading ../examples/rootfs/x8664_windows\Windows\System32\kernel32.dll ...
[=]     Done with loading ../examples/rootfs/x8664_windows\Windows\System32\kernel32.dll
[=]     Loading ../examples/rootfs/x8664_windows\Windows\System32\mscoree.dll ...
[=]     Done with loading ../examples/rootfs/x8664_windows\Windows\System32\mscoree.dll
0x4033ae:       jmp     qword ptr [rip + 0x402000]
[!]     api _CorExeMain is not implemented

This seems like a likely culprit, so I try to set a breakpoint at 0x4033ae in WinDbg with the command bu 0x4033ae. I also tried bp.

0x102bdbd1:     push    rbx
0x102bdbd3:     sub     esp, 0x20
0x102bdbd7:     and     dword ptr [rsp + 0x30], 0
0x102bdbdd:     lea     ecx, [rsp + 0x30]
0x102bdbe1:     call    0x102b4548
0x102b4549:     push    rbx
0x102b454b:     sub     esp, 0x20
0x102b454e:     mov     eax, dword ptr [rip + 0x5b4dc]
[x]     CPU Context:
[x]     ah      : 0xff
... snip ...
[x]     gs      : 0x78
[x]     Hexdump:
[x]     8b 05 dc b4 05 00 48 8b
[x]     Disassembly:
[=]     102b454e [mscoree.dll          + 0x00154e]  8b 05 dc b4 05 00 48 8b d9 85 c0 75 05 e8 c4 fc ff ff 8b 05 ca b4 05 00 83 f8 02 75 0f 48 85 db 74 0a 48 8b 05 c9 b4 05 00 48 89 03 8b 05 b0 b4 05 00 48 83 c4 20 5b c3 cc cc cc cc cc cc cc ccmov                  eax, dword ptr [0x5b4dc]
> dec                  eax
> mov                  ebx, ecx
> test                 eax, eax
> jne                  0x102b4560
> call                 0x102b4224
> mov                  eax, dword ptr [0x5b4ca]
> cmp                  eax, 2
> jne                  0x102b457a
> dec                  eax
> test                 ebx, ebx
> je                   0x102b457a
> dec                  eax
> mov                  eax, dword ptr [0x5b4c9]
> dec                  eax
> mov                  dword ptr [ebx], eax
> mov                  eax, dword ptr [0x5b4b0]
> dec                  eax
> add                  esp, 0x20
> pop                  ebx
> ret
> int3
> int3
> int3
> int3
> int3
> int3
> int3
> int3
[x]     PC = 0x102b454e (../examples/rootfs/x8664_windows\Windows\System32\mscoree.dll + 0x154e)

[=]     Memory map:
[=]     Start      End        Perm    Label          Image
[=]     00006000 - 0000c000   rwx     [FS/GS]
[=]     00030000 - 00031000   rwx     [GDT]
[=]     00400000 - 00408000   rwx     [PE]           snake.exe
[=]     05000000 - 05001000   rwx     [heap]
[=]     06000000 - 0c000000   rwx     [FS/GS]
[=]     10000000 - 101f5000   rwx     ntdll.dll      ../examples/rootfs/x8664_windows\Windows\System32\ntdll.dll
[=]     101f5000 - 102b3000   rwx     kernel32.dll   ../examples/rootfs/x8664_windows\Windows\System32\kernel32.dll
[=]     102b3000 - 10318000   rwx     mscoree.dll    ../examples/rootfs/x8664_windows\Windows\System32\mscoree.dll
[=]     fffdd000 - ffffe000   rwx     [stack]
Traceback (most recent call last):
  ... snip ...
  File "C:\Users\jonat\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\unicorn\unicorn.py", line 465, in emu_start
    raise UcError(status)
unicorn.unicorn.UcError: Invalid memory mapping (UC_ERR_MAP)

In WinDbg, I get:

CommandLine: C:\Users\jonat\Documents\GitHub\synthesis\obfu\snake.exe

************* Path validation summary **************
Response                         Time (ms)     Location
Deferred                                       srv*
Symbol search path is: srv*
Executable search path is: 
ModLoad: 00e60000 00e68000   ConsoleGraphics.exe
ModLoad: 770f0000 77293000   ntdll.dll
ModLoad: 74810000 74862000   C:\WINDOWS\SysWOW64\MSCOREE.DLL
ModLoad: 74fb0000 750a0000   C:\WINDOWS\SysWOW64\KERNEL32.dll
ModLoad: 75fa0000 761b5000   C:\WINDOWS\SysWOW64\KERNELBASE.dll
(9b8.7854): Break instruction exception - code 80000003 (first chance)
eax=00000000 ebx=00000000 ecx=3c560000 edx=00000000 esi=77102054 edi=7710261c
eip=771a1ba2 esp=00fff9cc ebp=00fff9f8 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
ntdll!LdrpDoDebuggerBreak+0x2b:
771a1ba2 cc              int     3

Which seems to be a standard breakpoint triggered by ntdll but by the time this is triggered, we have already passed the address 0x4033ae where I was trying to apply it. I realized that this is probably because the addressing scheme of the process seems to be mapped differently by the execution context within my OS / WinDbg and the qiling emulation. How can I begin debugging this problem, or at least finding the relevant breakpoint in WinDbg.

1

There are 1 best solutions below

1
On BEST ANSWER

the query isn't exactly related to windbg

as I commented Qiling Framework hasn't yet implemented dotnet and needs someone to contribute the implementation

since this query has a windbg tag and a debugging tag too and
I have been wanting to test the Qiling framework for sometime now on a windows machine
I took this query as an opportunity to do so

Qiling is built upon unicorn emulation framework
I have dabbled with unicorn and found it quiet useful

installed Qiling [pip3 install Qiling] on a x64 windows10 machine windows documentation is quiet scarce and the one example disasm_x886_windows.py indicated in github repo is missing in the repo

had to scratch around to get a working setup

after installing Qiling it needs a virtual filesystem to operate upon with pertient windows dlls and registry hives
this is done by using the dllcollector.bat provided by in the repo

basically the collector.bat xcopies relevent 32 bit and 64 bit dlls and reg saves registry hives

f:\>md QILING

f:\>cd QILING

f:\QILING>ls

f:\QILING>f:\wget\wget.exe -c https://raw.githubusercontent.com/qilingframework/qiling/master/examples/scripts/dllscollector.bat

2021-11-14 03:03:05 (1.28 MB/s) - 'dllscollector.bat' saved [10085/10085]

f:\QILING>ls
dllscollector.bat

f:\QILING>file dllscollector.bat
dllscollector.bat: DOS batch file, ASCII text, with very long lines

f:\QILING>dllscollector.bat
Does F:\QILING\examples\rootfs\x8664_windows\Windows\registry\NTUSER.DAT specify a file name
or directory name on the target
(F = file, D = directory)? f
C:\Users\Default\NTUSER.DAT -> F:\QILING\examples\rootfs\x8664_windows\Windows\registry\NTUSER.DAT
1 File(s) copied
The operation completed successfully.
snip all copy and save operations 

f:\QILING>ls
dllscollector.bat  examples

now that we have collected the dlls lets copy two test binaries
one an x64 console app and
another a .net console binary and
write a python script to emulate them using QILING framework

f:\QILING>ls
dllscollector.bat  examples

f:\QILING>md testqiling

f:\QILING>xcopy ..\tbins .\testqiling\
..\tbins\mcall.exe
..\tbins\printxcode.exe
..\tbins\qiliwin.py
3 File(s) copied

f:\QILING>cd testqiling

f:\QILING\testqiling>file *
mcall.exe:      PE32+ executable (GUI) x86-64, for MS Windows
printxcode.exe: PE32 executable (console) Intel 80386 Mono/.Net assembly, for MS Windows
qiliwin.py:     Python script, ASCII text executable, with CRLF line terminators
f:\QILING\testqiling>printxcode.exe |head -n 2
HResult is 80070057      xcode is E0434352      Value does not fall within the expected range.
HResult is 80004003      xcode is E0434352      Value cannot be null.

f:\QILING\testqiling>start /wait mcall.exe

f:\QILING\testqiling>echo %errorlevel%
1677

the script as follows
the stop_on_exit_trap is added to avoid crashing of mcall.exe when it returns to crt from main() due to unreachable PC (0x0 as rip)
trace traces and prints all executed instructions
verbose provides some additional logs

f:\QILING\testqiling>cat qiliwin.py
import os
from qiling import *
from qiling.const import QL_VERBOSE
from qiling.extensions import trace
os.system('') #bug explotation to make ansi colors
rootfs = r"F:\QILING\examples\rootfs\x8664_windows"
bin2exec = [
r"F:\QILING\testqiling\mcall.exe",
r"F:\QILING\testqiling\printxcode.exe"
]
for binary in bin2exec:
    print("executing binary\n=====================\n%s\n=====================\n" % binary);
    ql = Qiling([binary],rootfs,verbose=QL_VERBOSE.DEBUG,stop_on_exit_trap=True)
    trace.enable_full_trace(ql)
    ql.run()

executing the script we get

qiling.exception.QlErrorFileNotFound: Cannot find dll in F:\QILING\examples\rootfs\x8664_windows\Windows\System32\mscoree.dll

copying the mscoree.dll from system32 to rootfs/system2 and checking it crashes again with unmapped error as pointed in query

lets open the .net binary in an x64 windbg and check

F:\QILING\testqiling>cdb -c "sxe ld:mscoree;g;q" printxcode.exe | awk /Reading/,/quit/
0:000> cdb: Reading initial command 'sxe ld:mscoree;g;q'
ModLoad: 00000000`77e30000 00000000`77e39000   C:\WINDOWS\System32\wow64cpu.dll
ModLoad: 00000000`73f90000 00000000`73fe2000   C:\WINDOWS\SysWOW64\MSCOREE.DLL
quit:

so this binary needs the mscoree from syswow

f:\QILING\testqiling>copy c:\Windows\SysWOW64\mscoree.dll F:\QILING\examples\rootfs\x8664_windows\Windows\System32\.
Overwrite F:\QILING\examples\rootfs\x8664_windows\Windows\System32\.\mscoree.dll? (Yes/No/All): y
        1 file(s) copied.

Execution now doesnt crash

F:\QILING\testqiling>python qiliwin.py
executing binary
=====================
F:\QILING\testqiling\mcall.exe
=====================

[+]     Profile: Default
[+]     Windows Registry PATH: F:\QILING\examples\rootfs\x8664_windows\Windows\registry
[=]     Initiate stack address at 0x7ffffffde000
[=]     Loading F:\QILING\testqiling\mcall.exe to 0x140000000
[=]     PE entry point at 0x140001030
[=]     TEB addr is 0x6000030
[=]     PEB addr is 0x60000b8
[=]     Loading F:\QILING\examples\rootfs\x8664_windows\Windows\System32\ntdll.dll ...
[!]     Warnings while loading F:\QILING\examples\rootfs\x8664_windows\Windows\System32\ntdll.dll:
[!]      - SizeOfHeaders is smaller than AddressOfEntryPoint: this file cannot run under Windows 8.
[!]      - AddressOfEntryPoint lies outside the sections' boundaries. AddressOfEntryPoint: 0x0
[+]     DLL preferred base address: 0x180000000
[=]     Done with loading F:\QILING\examples\rootfs\x8664_windows\Windows\System32\ntdll.dll
[=]     Loading F:\QILING\examples\rootfs\x8664_windows\Windows\System32\kernel32.dll ...
[+]     DLL preferred base address: 0x180000000
[+]     DLL preferred base address is taken, loading to: 0x1801f0000
[=]     Done with loading F:\QILING\examples\rootfs\x8664_windows\Windows\System32\kernel32.dll
[+]     Done with loading F:\QILING\testqiling\mcall.exe
[+]     Setting up exit trap at 0x0x140004000
[+]     140001030 | 4883ec48                 sub        rsp, 0x48                                                | rsp = 0x0
[+]     140001034 | 41b803000000             mov        r8d, 0x3                                                 |
[+]     14000103a | ba02000000               mov        edx, 0x2                                                 |
[+]     14000103f | b901000000               mov        ecx, 0x1                                                 |
[+]     140001044 | e8b7ffffff               call       0x140001000                                              | rsp = 0x0, rip = 0x0
[+]     140001000 | 4489442418               mov        dword ptr [0x18], r8d                                    | rsp = 0x0, r8d = 0x0
[+]     140001005 | 89542410                 mov        dword ptr [0x10], edx                                    | rsp = 0x0, edx = 0x2
[+]     140001009 | 894c2408                 mov        dword ptr [0x8], ecx                                     | rsp = 0x0, ecx = 0x1
[+]     14000100d | 8b442410                 mov        eax, dword ptr [0x10]                                    | rsp = 0x0
[+]     140001011 | 8b4c2408                 mov        ecx, dword ptr [0x8]                                     | rsp = 0x0
[+]     140001015 | 03c8                     add        ecx, eax                                                 | ecx = 0x1, eax = 0x2
[+]     140001017 | 8bc1                     mov        eax, ecx                                                 | ecx = 0x3
[+]     140001019 | 03442418                 add        eax, dword ptr [0x18]                                    | eax = 0x3, rsp = 0x0
[+]     14000101d | c3                       ret                                                                 | rsp = 0x0
[+]     140001049 | 89442428                 mov        dword ptr [0x28], eax                                    | rsp = 0x0, eax = 0x6
[+]     14000104d | 41b806000000             mov        r8d, 0x6                                                 |
[+]     140001053 | ba07000000               mov        edx, 0x7                                                 |
[+]     140001058 | b908000000               mov        ecx, 0x8                                                 |
[+]     14000105d | e89effffff               call       0x140001000                                              | rsp = 0x0, rip = 0x0
snipoff
[+]     140004000 | 90                       nop                                                                 |
[=]     Process returned from entrypoint (exit_trap)!
[+]     Syscalls called:
[+]     Registries accessed:
[+]     Strings:
executing binary
=====================
F:\QILING\testqiling\printxcode.exe
=====================

[+]     Profile: Default
[+]     Map GDT at 0x30000 with GDT_LIMIT=4096
[+]     Write to 0x30018 for new entry b'\x00\xf0\x00\x00\x00\xfeO\x00'
[+]     Write to 0x30028 for new entry b'\x00\xf0\x00\x00\x00\x96O\x00'
[+]     Write to 0x30070 for new entry b'\x00`\x00`\x00\xf6@\x00'
[+]     Write to 0x30078 for new entry b'\x00\x00\x00\x00\x00\xf6@\x06'
[+]     Windows Registry PATH: F:\QILING\examples\rootfs\x8664_windows\Windows\registry
[=]     Initiate stack address at 0xfffdd000
[=]     Loading F:\QILING\testqiling\printxcode.exe to 0x400000
[=]     PE entry point at 0x402eda
[=]     TEB addr is 0x6000
[=]     PEB addr is 0x6044
[=]     Loading F:\QILING\examples\rootfs\x8664_windows\Windows\System32\ntdll.dll ...
[!]     Warnings while loading F:\QILING\examples\rootfs\x8664_windows\Windows\System32\ntdll.dll:
[!]      - SizeOfHeaders is smaller than AddressOfEntryPoint: this file cannot run under Windows 8.
[!]      - AddressOfEntryPoint lies outside the sections' boundaries. AddressOfEntryPoint: 0x0
[+]     DLL preferred base address: 0x180000000
[+]     DLL preferred base address exceeds memory upper bound, loading to: 0x10000000
[=]     Done with loading F:\QILING\examples\rootfs\x8664_windows\Windows\System32\ntdll.dll
[=]     Loading F:\QILING\examples\rootfs\x8664_windows\Windows\System32\kernel32.dll ...
[+]     DLL preferred base address: 0x180000000
[+]     DLL preferred base address exceeds memory upper bound, loading to: 0x101f0000
[=]     Done with loading F:\QILING\examples\rootfs\x8664_windows\Windows\System32\kernel32.dll
[=]     Loading F:\QILING\examples\rootfs\x8664_windows\Windows\System32\mscoree.dll ...
[+]     DLL preferred base address: 0x10000000
[+]     DLL preferred base address is taken, loading to: 0x102b0000
[=]     Done with loading F:\QILING\examples\rootfs\x8664_windows\Windows\System32\mscoree.dll
[+]     Done with loading F:\QILING\testqiling\printxcode.exe
[+]     Setting up exit trap at 0x0xc000000
[+]     00402eda | ff2500204000             jmp        dword ptr [0x402000]                                     |
[!]     api _CorExeMain is not implemented
[+]     102c4330 | 8bff                     mov        edi, edi                                                 | edi = 0x0
[+]     102c4332 | 56                       push       esi                                                      | esp = 0x0, esi = 0xffffd000
snipoff
[+]     0c000000 | 90                       nop                                                                 |
[=]     Process returned from entrypoint (exit_trap)!
[+]     Syscalls called:
[+]     Registries accessed:
[+]     Strings: