You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Qiling Framework provides powerful features for debugging emulated code, allowing you to inspect the machine state, trace execution, and integrate with external debuggers like GDB.
Interactive Debugger (QDB)
Qiling includes its own interactive debugger, QDB, which is similar in concept to GDB. It allows you to pause emulation, inspect state, and control execution flow.
Enabling QDB
To use QDB, you need to enable it in your Qiling script.
fromqilingimportQilingfromqiling.debuggerimportQdbif__name__=="__main__":
ql=Qiling(['/bin/ls'], 'path/to/rootfs/x8664_linux')
# Attach the debuggerdebugger=Qdb(ql)
# Set a breakpoint at the entry pointentry_point=ql.loader.elf_entrydebugger.add_bp(entry_point)
# Run the emulation. It will stop at the breakpoint.ql.run()
When the breakpoint is hit, you will be dropped into the QDB interactive shell, where you can use commands like:
c: Continue execution.
r: Print register values.
x/16xb <address>: Examine memory at a given address.
s: Step to the next instruction.
b <address>: Set a new breakpoint.
d <bp_id>: Delete a breakpoint.
GDB Stub
For a more feature-rich debugging experience, Qiling can act as a GDB stub, allowing you to connect a standard GDB client to the emulated process.
How it Works
Start Qiling with the GDB stub enabled. Your Qiling script will listen on a specified TCP port.
Connect your GDB client to that port.
Debug the emulated program using familiar GDB commands.
Enabling the GDB Stub
You can enable the GDB stub with a single line in your Python script.
fromqilingimportQilingif__name__=="__main__":
ql=Qiling(['/bin/ls'], 'path/to/rootfs/x8664_linux')
# Enable the GDB stub on localhost, port 1234ql.debugger="gdb:1234"# Run the emulation. It will wait for a GDB client to connect.ql.run()
Alternatively, you can use QlTool from the command line:
From another terminal, launch GDB and connect to the Qiling stub.
# For a more integrated experience, you can point GDB to the executable# This allows GDB to load symbols and source code.
gdb /bin/ls
(gdb) target remote localhost:1234
(gdb) # You are now connected and can start debugging
(gdb) b main
Breakpoint 1 at 0x4018b0
(gdb) c
Continuing.
Breakpoint 1, 0x00000000004018b0 inmain ()
(gdb) info registers
rax 0x4018b0 4199520
rbx 0x0 0
...
Verbose Output and Tracing
For simpler debugging scenarios, you might not need a full debugger. Qiling's verbose logging can provide valuable insights.
Enabling Verbose Modes
You can set the verbosity level during Qiling initialization.
fromqiling.constimportQL_VERBOSE# Show basic information like syscallsql=Qiling(argv, rootfs, verbose=QL_VERBOSE.DEFAULT)
# Show detailed instruction-by-instruction tracingql=Qiling(argv, rootfs, verbose=QL_VERBOSE.DEBUG)
# Show syscalls and their parametersql=Qiling(argv, rootfs, verbose=QL_VERBOSE.DISASM)
This will print detailed information about the emulation process to the console, which can help you quickly identify issues without the overhead of an interactive debugger.
Complete GDB Stub Example
Here is a self-contained script to demonstrate the GDB stub feature. It emulates a simple Linux binary and waits for a GDB client to connect.
Target Binary (hello): A standard "Hello, World!" compiled with gcc -g -o hello hello.c (the -g flag includes debug symbols, which improves the GDB experience).
Qiling Script:
fromqilingimportQilingfromqiling.constimportQL_VERBOSEif__name__=="__main__":
# Path to the Linux executable and its rootfsexecutable_path='./hello'rootfs_path='path/to/your/rootfs/x8664_linux'ql=Qiling([executable_path], rootfs_path, verbose=QL_VERBOSE.OFF)
# Enable the GDB stub on localhost, port 1234.# You can also specify an address, e.g., "127.0.0.1:1234"ql.debugger="gdb:1234"print(f"[*] Starting emulation. Waiting for GDB client to connect on port 1234...")
print(f"[*] In another terminal, run: gdb {executable_path}")
print(f"[*] Then, in GDB: target remote :1234")
# When run(), Qiling will pause and wait for the GDB connection# before starting the actual emulation.ql.run()
print("[*] Emulation finished. GDB client disconnected.")
Debugging Workflow
Run the Qiling script. It will print the instructions and then hang, waiting for you.
Open a new terminal.
Launch GDB and point it to your executable so it can load the symbols:
gdb ./hello
Inside GDB, connect to Qiling:
(gdb) target remote :1234
Remote debugging using :12340x00007f73726f6090 in ?? ()
You are now in control. You can set breakpoints, step through code, inspect memory, and use all the familiar GDB commands to debug the program running inside the Qiling emulator.
(gdb) b main
Breakpoint 1 at 0x401130: file hello.c, line5.
(gdb) c
Continuing.
Breakpoint 1, main () at hello.c:55 printf("Hello, World!\n");
(gdb)