Qiling IDA Pro Plugin
Qiling IDA Pro Plugin
Combines IDA Pro static analysis with Qiling dynamic emulation.
Supported Platforms
| 8086 | x86 | x86-64 | ARM | ARM64 | MIPS | |
|---|---|---|---|---|---|---|
| Windows (PE) | - | ✓ | ✓ | - | ✗ | - |
| Linux (ELF) | - | ✓ | ✓ | ✓ | ✓ | ✓ |
| MacOS (MachO) | - | ✗ | ✓ | - | ✗ | - |
| BSD (ELF) | - | ✗ | ✓ | ✗ | ✗ | ✗ |
| UEFI | - | ✓ | ✓ | - | - | - |
| DOS (COM) | ✓ | - | - | - | - | - |
| MBR | ✓ | - | - | - | - | - |
Installation
Prerequisites: Qiling installed (pip3 install qiling or dev branch).
As IDA Plugin (symlink)
1# Linux
2ln -s ~/.local/lib/<python>/site-packages/qiling/extensions/idaplugin/qilingida.py /path/to/ida/plugins/
3
4# macOS
5ln -s /usr/local/lib/<python>/site-packages/qiling/extensions/idaplugin/qilingida.py /Applications/<IDA>/ida.app/Contents/MacOS/plugins/
6
7# Windows
8mklink C:\path\to\IDA\plugins\qilingida.py C:\Users\<user>\AppData\Roaming\Python\<python>\site-packages\qiling\extensions\idaplugin\qilingida.py
As Script File
File → Script file... → select qilingida.py.
Available under Edit → Plugins → Qiling Emulator and right-click context menu.
Requirements: IDA Pro 7.x, Python 3.6+. Recommended: macOS or Linux. Avoid Python 3.8 (IDA crashes; see Hex-Rays blog for fix).
Setup
Right-click → Qiling Emulator → Setup. Provide:
rootfs: root directory for emulation (e.g.examples/rootfs/<arch>)custom user script: Python file withQILING_IDAclassenv: optional JSON environment variables file
Success message: "Qiling is initialized successfully" in output window.
Emulation Controls
- Continue: Run from entry point to end; executed path highlighted green
- Execute Till: Run to cursor address; path highlighted in different color
- Step (
CTRL+SHIFT+F9): Execute single instruction; register/stack views update - Restart: Re-initialize with new rootfs and script
- Breakpoints: Set with
F2, then Continue
View Windows
- View Register: Shows current CPU register state
- View Stack: Shows current stack content
- View Memory: Shows memory at specified address/size
To edit a register: right-click in register view → Edit Register.
Accessing the Qiling Object in IDAPython Console
1ql_plugin = ida_ida.ql_plugin
2qlemu = ql_plugin.qlemu
3ql = qlemu.ql # safe to use in most cases
4
5# Address conversion
6qladdr = qlemu.ql_addr_from_ida(idaaddr)
7ql.mem.read(qladdr, 4)
8idaaddr = qlemu.ida_addr_from_ql_addr(qladdr)
Custom User Scripts
A Python file with a QILING_IDA class. Three callback methods:
| Method | When called |
|---|---|
custom_prepare(ql) | Before ql.run() |
custom_continue(ql) | When user clicks Continue |
custom_step(ql) | When user steps an instruction |
custom_continue and custom_step must return a list of hooks (plugin removes them after each action).
Minimal template
1from qiling import *
2
3class QILING_IDA():
4 def __init__(self):
5 pass
6
7 def custom_prepare(self, ql):
8 pass
9
10 def custom_continue(self, ql):
11 return []
12
13 def custom_step(self, ql):
14 return []
Register logging example
1from qiling import *
2import logging
3
4class QILING_IDA():
5 def _show_context(self, ql):
6 registers = [k for k in ql.arch.regs.register_mapping.keys() if type(k) is str]
7 for idx in range(0, len(registers), 3):
8 regs = registers[idx:idx+3]
9 s = "\t".join(map(lambda v: f"{v:4}: {ql.arch.regs.__getattribute__(v):016x}", regs))
10 logging.info(s)
11
12 def custom_prepare(self, ql):
13 self._show_context(ql)
14
15 def custom_continue(self, ql):
16 self._show_context(ql)
17 return []
18
19 def custom_step(self, ql):
20 def step_hook(ql, addr, size):
21 logging.info(f"Executing: {hex(addr)}")
22 self._show_context(ql)
23 return [ql.hook_code(step_hook)]
Scripts can be reloaded dynamically: Reload User Scripts in the menu.
Snapshots
- Save Snapshot: Menu →
Save Snapshot→ specify file path - Load Snapshot: Menu →
Load Snapshot
Snapshots capture full emulation context (registers, memory, file descriptors).
OLLVM De-flattening
Removes Control Flow Flattening obfuscation from OLLVM-protected binaries.
Block types after auto-analysis:
- Green: Real blocks (original logic)
- Blue: Dispatcher blocks (
switch/casecontrol flow) - Gray: Fake blocks (no real logic)
- Pink: Return blocks
- Yellow: Entry block
Workflow:
- Complete basic Setup (rootfs + script)
- Right-click →
Auto Analysis For Deflat - Manually correct misclassified blocks via right-click →
Mark as Real/Fake/Return Block - Right-click →
Deflat - Press
F5to decompile — output is clean without obfuscation