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.
CodePudding user response:
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: