A True Instrumentable Binary Emulation Framework
Qiling's use case, blog and related work
Qiling is an advanced binary emulation framework, with the following features:
Qiling also made its way to various international conferences.
2022:
2021:
2020:
2019:
Qiling is backed by Unicorn Engine.
Visit our website for more information.
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
There are many open-source emulators, but two projects closest to Qiling are Unicorn & QEMU user mode. This section explains the main differences of Qiling against them.
Built on top of Unicorn, but Qiling & Unicorn are two different animals.
QEMU user mode does a similar thing to our emulator, that is, to emulate whole executable binaries in a cross-architecture way. However, Qiling offers some important differences against QEMU user mode:
Please see setup guide file for how to install Qiling Framework.
The example below shows how to use Qiling framework in the most straightforward way to emulate a Windows executable.
from qiling import Qiling
if __name__ == "__main__":
# initialize Qiling instance, specifying the executable to emulate and the emulated system root.
# note that the current working directory is assumed to be Qiling home
ql = Qiling([r'examples/rootfs/x86_windows/bin/x86_hello.exe'], r'examples/rootfs/x86_windows')
# start emulation
ql.run()
from qiling import Qiling
def force_call_dialog_func(ql: Qiling):
# get DialogFunc address from current stack frame
lpDialogFunc = ql.stack_read(-8)
# setup stack memory for DialogFunc
ql.stack_push(0)
ql.stack_push(1001) # IDS_APPNAME
ql.stack_push(0x111) # WM_COMMAND
ql.stack_push(0)
# push return address
ql.stack_push(0x0401018)
# resume emulation from DialogFunc address
ql.arch.regs.eip = lpDialogFunc
if __name__ == "__main__":
# initialize Qiling instance
ql = Qiling([r'rootfs/x86_windows/bin/Easy_CrackMe.exe'], r'rootfs/x86_windows')
# NOP out some code
ql.patch(0x004010B5, b'\x90\x90')
ql.patch(0x004010CD, b'\x90\x90')
ql.patch(0x0040110B, b'\x90\x90')
ql.patch(0x00401112, b'\x90\x90')
# hook at an address with a callback
ql.hook_address(force_call_dialog_func, 0x00401016)
ql.run()
The below YouTube video shows how the above example works.