### Manual Installation Steps for Qiling on Ubuntu Source: https://docs.qiling.io/en/latest/install Performs a manual installation of Qiling Framework on Ubuntu by updating the system, installing necessary tools (pip, git, cmake), cloning the repository, and running the setup script. It also includes initializing submodules. ```bash sudo apt-get update sudo apt-get upgrade sudo apt install python3-pip git cmake ``` ```bash git clone https://github.com/qilingframework/qiling cd qiling sudo pip3 install . ``` ```bash git submodule update --init --recursive ``` -------------------------------- ### Qiling Setup: Post-Initialization Source: https://docs.qiling.io/en/latest/howto This snippet outlines the setup steps available after initializing a Qiling object but before calling `ql.run()`. It includes configuring filesystem mappings, controlling debug stops, setting up remote debuggers, and adjusting verbosity levels. ```python # Map an host file or directory from qiling file or directory to a actual folder # ql.fs_mapper('/etc','/real_etc') # Set to True to stop after missing posix syscall or api (default is False) # ql.debug_stop = True # Set a remote debugger # ql.debugger = 'remote_debugger_instance' # Set Qiling logging verbosity level (from 1 till n) # ql.verbose = 2 ``` -------------------------------- ### Install System Dependencies on Ubuntu Source: https://docs.qiling.io/en/latest/install Installs essential packages required for Qiling Framework on Ubuntu systems using apt. This includes build tools, libraries, and Python development packages. ```bash sudo apt install -y ack antlr3 aria2 asciidoc autoconf automake autopoint binutils bison build-essential \ bzip2 ccache cmake cpio curl device-tree-compiler fastjar flex gawk gettext gcc-multilib g++-multilib \ git gperf haveged help2man intltool libc6-dev-i386 libelf-dev libglib2.0-dev libgmp3-dev libltdl-dev \ libmpc-dev libmpfr-dev libncurses5-dev libncursesw5-dev libreadline-dev libssl-dev libtool lrzsz \ mkisofs msmtp nano ninja-build p7zip p7zip-full patch pkgconf python2.7 python3 python3-pip libpython3-dev qemu-utils \ rsync scons squashfs-tools subversion swig texinfo uglifyjs upx-ucl unzip vim wget xmlto xxd zlib1g-dev ``` -------------------------------- ### Install Qiling with Pyenv (Development Branch) Source: https://docs.qiling.io/en/latest/install Sets up a Python virtual environment using pyenv, clones the Qiling repository's development branch, and installs Qiling within that environment. This is recommended for the latest features. ```bash python3 -m venv qilingenv source qilingenv/bin/activate git clone -b dev https://github.com/qilingframework/qiling.git cd qiling && git submodule update --init --recursive pip3 install . ``` -------------------------------- ### Install Qiling using pip (Stable Version) Source: https://docs.qiling.io/en/latest/install Installs the latest stable version of the Qiling Framework directly from pip. This is a straightforward method for users who prefer a tested release. ```bash pip3 install qiling ``` -------------------------------- ### Checkout and Update RootFS Example Source: https://docs.qiling.io/en/latest/checklist This snippet demonstrates how to navigate to the rootfs examples directory, pull the latest changes from the master branch, and update the local repository. ```bash - cd examples/rootfs - git pull origin master ``` -------------------------------- ### Run Qiling Docker Container with Bind Mounts Source: https://docs.qiling.io/en/latest/install Launches a Qiling Framework Docker container and configures it with bind mounts for Windows DLLs and registry hives. This allows the container to access necessary files from the host system. ```bash docker run -dt --name qiling \ -v /analysis/win/rootfs/x86_windows:/qiling/examples/rootfs/x86_windows \ -v /analysis/win/rootfs/x8664_windows:/qiling/examples/rootfs/x8664_windows \ qilingframework/qiling:latest ``` -------------------------------- ### Install Keystone-Engine from Source on macOS Source: https://docs.qiling.io/en/latest/install A workaround for macOS users experiencing issues with keystone-engine compilation. It involves cloning the keystone-engine repository, building it from source, and then installing the Python bindings. ```bash git clone https://github.com/keystone-engine/keystone cd keystone mkdir build cd build ../make-share.sh cd ../bindings/python sudo make install ``` -------------------------------- ### Emulate Windows EXE on Linux with Qiling Source: https://docs.qiling.io/en/latest/demo This example demonstrates how to use the Qiling Framework to emulate a Windows executable on a Linux machine. It sets up the Qiling engine and runs the specified EXE within a provided root file system. ```python from qiling import * # sandbox to emulate the EXE def my_sandbox(path, rootfs): # setup Qiling engine ql = Qiling(path, rootfs) # now emulate the EXE ql.run() if __name__ == "__main__": # execute Windows EXE under our rootfs my_sandbox(["examples/rootfs/x86_windows/bin/x86_hello.exe"], "examples/rootfs/x86_windows") ``` -------------------------------- ### Emulate Binary with Qiling Source: https://docs.qiling.io/en/latest/howto This snippet shows how to emulate a binary executable using the Qiling Framework. It involves setting up command-line arguments, the root filesystem, and Qiling's profile for emulation. The `ql.run()` method executes the emulated binary. ```python from qiling import Qiling from qiling.const import QL_VERBOSE if __name__ == "__main__": # set up command line argv and emulated os root path argv = r'examples/rootfs/netgear_r6220/bin/mini_httpd -d /www -r NETGEAR R6220 -c **.cgi -t 300'.split() rootfs = r'examples/rootfs/netgear_r6220' # instantiate a Qiling object using above arguments and set emulation verbosity level to DEBUG. # additional settings are read from profile file ql = Qiling(argv, rootfs, verbose=QL_VERBOSE.DEBUG, profile='netgear.ql') # map emulated fs '/proc' dir to the hosting os '/proc' dir ql.add_fs_mapper('/proc', '/proc') # do the magic! ql.run() ``` -------------------------------- ### Emulate Windows Registry with Qiling Source: https://docs.qiling.io/en/latest/demo This code snippet shows how to emulate the Windows registry using the Qiling Framework. It initializes the Qiling engine with debugging verbosity and runs a registry-related demonstration executable. ```python import sys sys.path.append("..") from qiling import * from qiling.const import QL_VERBOSE def my_sandbox(path, rootfs): ql = Qiling(path, rootfs, verbose=QL_VERBOSE.DEBUG) ql.run() if __name__ == "__main__": my_sandbox(["rootfs/x86_windows/bin/RegDemo.exe"], "rootfs/x86_windows") ``` -------------------------------- ### Collect Windows DLLs and Registry for Qiling Source: https://docs.qiling.io/en/latest/install Executes a batch script on Windows to collect necessary DLL files and registry information for Qiling Framework emulation. This is crucial for accurate Windows environment emulation. ```batch examples/scripts/dllscollector.bat ``` -------------------------------- ### Install Latest Dev Branch with Pip Source: https://docs.qiling.io/en/latest/faq This command installs the latest development version of the Qiling Framework using pip3 from a zip archive hosted on GitHub. ```bash pip3 install --user https://github.com/qilingframework/qiling/archive/dev.zip ``` -------------------------------- ### Qiling Initialization Options Source: https://docs.qiling.io/en/latest/howto This section details the various options available when initializing a Qiling object. It covers parameters specific to binary emulation (like `argv` and `rootfs`) and shellcode emulation (like `code`, `archtype`, and `ostype`), as well as common options applicable to both. ```python # Basic Qiling initialization options for **binary** emulation: # argv: Sequence[str] - command line arguments # rootfs: str - emulated filesystem root directory # env: MutableMapping[AnyStr, AnyStr] (optional) - environment variables # Basic Qiling initialization options for **shellcode** emulation: # code: bytes - shellcode to emulate # rootfs: str (optional) - emulated filesystem root directory # ostype: str or QL_OS - target operating system # archtype: str or QL_ARCH - target architecture # endian: bool (optional) - architecture endianness # thumb: bool (optional) - ARM thumb mode # Common Qiling initialization options: # verbose: QL_VERBOSE (optional) - logging verbosity level # profile: str (optional) - path to profile file # console: bool (optional) - disable Qiling logging # multithread: bool (optional) - emulate as multi-threaded program # libcache: bool (optional) - load libraries from cache (Windows only) # Example initialization for binary: # ql = Qiling(argv=['/path/to/binary'], rootfs='/path/to/rootfs', verbose=QL_VERBOSE.DEBUG) # Example initialization for shellcode: # shellcode_bytes = b'\x90\x90\xc3' # ql = Qiling(code=shellcode_bytes, archtype='x86', ostype='Linux', verbose=QL_VERBOSE.INFO) ``` -------------------------------- ### Install Qiling Framework EVM Module Source: https://docs.qiling.io/en/latest/evm Installs the Qiling Framework with the EVM module. This involves cloning the repository, checking out the development branch, updating submodules, and installing the framework with the EVM extra dependencies. ```bash git clone https://github.com/qilingframework/qiling.git git checkout dev git submodule update --init pip3 install -e .[evm] ``` -------------------------------- ### Advanced Custom User Script with Context Logging Source: https://docs.qiling.io/en/latest/ida An example of a more complex custom user script for the Qiling IDA plugin. This script logs the current CPU context (registers) before emulation starts, and every time the execution continues or steps. It defines a helper function `_show_context` for logging and uses Python's `logging` module. ```python from qiling import * import logging class QILING_IDA(): def __init__(self): pass # Log all registers to console. def _show_context(self, ql:Qiling): registers = [ k for k in ql.arch.regs.register_mapping.keys() if type(k) is str ] for idx in range(0, len(registers), 3): regs = registers[idx:idx+3] s = "\t".join(map(lambda v: f"{v:4}: {ql.arch.regs.__getattribute__(v):016x}", regs)) logging.info(s) # Before emulation def custom_prepare(self, ql:Qiling): logging.info('Context before starting emulation:') self._show_context(ql) # Continue def custom_continue(self, ql:Qiling): logging.info('custom_continue hook.') self._show_context(ql) hook = [] return hook # Step def custom_step(self, ql:Qiling): def step_hook(ql, addr, size): logging.info(f"Executing: {hex(addr)}") self._show_context(ql) logging.info('custom_step hook') hook = [] hook.append(ql.hook_code(step_hook)) return hook ``` -------------------------------- ### Emulate Shellcode with Qiling Source: https://docs.qiling.io/en/latest/howto This example demonstrates emulating shellcode using Qiling. It requires explicitly specifying the architecture and operating system types, as these cannot be inferred from shellcode alone. The shellcode is provided as a bytes object. ```python from qiling import Qiling from qiling.const import QL_VERBOSE # set up a shellcode to emulate shellcode = bytes.fromhex (''' fc4881e4f0ffffffe8d0000000415141505251564831d265488b52603e488b52 183e488b52203e488b72503e480fb74a4a4d31c94831c0ac3c617c022c2041c1 c90d4101c1e2ed5241513e488b52203e8b423c4801d03e8b80880000004885c0 746f4801d0503e8b48183e448b40204901d0e35c48ffc93e418b34884801d64d 31c94831c0ac41c1c90d4101c138e075f13e4c034c24084539d175d6583e448b 40244901d0663e418b0c483e448b401c4901d03e418b04884801d0415841585e 595a41584159415a4883ec204152ffe05841595a3e488b12e949ffffff5d49c7 c1000000003e488d95fe0000003e4c8d850f0100004831c941ba45835607ffd5 4831c941baf0b5a256ffd548656c6c6f2c2066726f6d204d534621004d657373 616765426f7800 ''') # instantiate a Qiling object to emulate the shellcode. when emulating a binary Qiling would be able to automatically # infer the target architecture and operating system. this, however, is not possible when emulating a shellcode, therefore # both 'archtype' and 'ostype' arguments must be provided ql = Qiling(code=shellcode, rootfs=r'examples/rootfs/x8664_windows', archtype='x8664', ostype='Windows', verbose=QL_VERBOSE.DEBUG) # do the magic! ql.run() ``` -------------------------------- ### Catch WannaCry Kill Switch with Qiling Source: https://docs.qiling.io/en/latest/demo This example demonstrates how to use Qiling to execute the WannaCry ransomware binary and hook a specific address to detect and stop execution upon finding the kill switch URL. It utilizes debug verbosity for detailed output. ```python import sys sys.path.append("..") from qiling import * from qiling.const import QL_VERBOSE def stopatkillerswtich(ql): print("killerswtch found") ql.emu_stop() if __name__ == "__main__": ql = Qiling(["rootfs/x86_windows/bin/wannacry.bin"], "rootfs/x86_windows", verbose=QL_VERBOSE.DEBUG) ql.hook_address(stopatkillerswtich, 0x40819a) ql.run() ``` -------------------------------- ### Control Binary Execution with ql.run() in Qiling Source: https://docs.qiling.io/en/latest/howto The ql.run() function initiates binary execution in Qiling. It accepts optional parameters like 'begin', 'end', 'timeout', and 'count' for fine-grained control over the execution range and duration. This is useful for targeted operations such as fuzzing specific sections of a binary. ```python ql.run(begin, end, timeout, count) ``` ```python ql = Qiling() ql.run(begin = 0xFE, end = 0xFF) ql.run(begin = 0xAE, end = 0xFF) ``` -------------------------------- ### Python Struct Unpack Example Source: https://docs.qiling.io/en/latest/struct Demonstrates using Python's 'struct' library to unpack binary data according to a specified format string. The example shows unpacking a record containing a string, two unsigned shorts, and a signed char, with '<' indicating little-endian byte order. ```python record = b'raymond \x32\x12\x08\x01\x08' name, serialnum, school, gradelevel = unpack('<10sHHb', record) ``` -------------------------------- ### Exception Logging with ql.log.exception Source: https://docs.qiling.io/en/latest/contribution Demonstrates how to use `ql.log.exception` to log detailed information when catching exceptions, which is more helpful than a simple print statement. This is part of the Qiling Framework's logging convention. ```python try: 1/0 except ZeroDivisionError as e: #print(e) ql.log.exception("Divide by zero!") ``` -------------------------------- ### Fuzz Binary with Qiling AFL Extension Source: https://docs.qiling.io/en/latest/demo This section outlines the steps to set up and use Qiling's AFL++ extension for fuzzing. It includes building AFL++ with unicorn mode and running the fuzzing process with a Python script that interfaces with the Qiling emulator. ```bash # Build AFL++'s unicorn mode git clone https://github.com/AFLplusplus/AFLplusplus.git -b dev make -C AFLplusplus cd AFLplusplus/unicorn_mode ; ./build_unicorn_support.sh # Fuzz simple x86_64 binary AFL_AUTORESUME=1 AFL_PATH="$(realpath ./AFLplusplus)" PATH="$AFL_PATH:$PATH" afl-fuzz -i afl_inputs -o afl_outputs -U -- python3 ./fuzz_x8664_linux.py @@ ``` -------------------------------- ### Python Emulation of Netgear R6220 Router with Qiling Source: https://docs.qiling.io/en/latest/demo This Python script demonstrates the emulation of a Netgear R6220 router using Qiling. It configures the Qiling environment with a specific rootfs, profile, and custom syscall handling for the 'write' operation. The script aims to emulate the router's environment to run its binary, such as 'mini_httpd'. ```python import sys sys.path.append("..") from qiling import * from qiling.os.posix import syscall from qiling.const import QL_VERBOSE def my_syscall_write(ql, write_fd, write_buf, write_count, *rest): if write_fd == 2 and ql.os.file_des[2].__class__.__name__ == 'ql_pipe': ql.os.definesyscall_return(-1) else: syscall.ql_syscall_write(ql, write_fd, write_buf, write_count, *rest) def my_netgear(path, rootfs): ql = Qiling( path, rootfs, verbose = QL_VERBOSE.DEBUG, profile = "netgear_6220.ql" ) ql.root = False ql.bindtolocalhost = True ql.multithread = False ql.add_fs_mapper('/proc', '/proc') ql.os.set_syscall(4004, my_syscall_write) ql.run() if __name__ == "__main__": my_netgear(["rootfs/netgear_r6220/bin/mini_httpd", "-d","/www", "-r","NETGEAR R6220", "-c","**.cgi", "-t","300"], "rootfs/netgear_r6220") ``` -------------------------------- ### Emulate UEFI with Qiling Framework Source: https://docs.qiling.io/en/latest/demo This Python code snippet demonstrates how to emulate UEFI (Unified Extensible Firmware Interface) using the Qiling Framework. It includes a function `force_notify_RegisterProtocolNotify` that hooks into the `RegisterProtocolNotify` API to force notifications for specific protocols. This is useful for testing or analyzing UEFI firmware behavior. ```python import sys import pickle sys.path.append("..\..") from qiling import * from qiling.os.uefi.const import * def force_notify_RegisterProtocolNotify(ql, address, params): event_id = params['Event'] if event_id in ql.loader.events: ql.loader.events[event_id]['Guid'] = params["Protocol"] # let's force notify event = ql.loader.events[event_id] event["Set"] = True ql.loader.notify_list.append((event_id, event['NotifyFunction'], event['NotifyContext'])) ###### return EFI_SUCCESS return EFI_INVALID_PARAMETER if __name__ == "__main__": with open("rootfs/x8664_efi/rom2_nvar.pickel", 'rb') as f: env = pickle.load(f) ql = Qiling(["rootfs/x8664_efi/bin/TcgPlatformSetupPolicy"], "rootfs/x8664_efi", env=env) ql.os.set_api("hook_RegisterProtocolNotify", force_notify_RegisterProtocolNotify) ql.run() ``` -------------------------------- ### Relative Imports for Qiling Modules Source: https://docs.qiling.io/en/latest/contribution Illustrates the preferred way to import modules within the Qiling framework using relative imports. It also shows acceptable ways to import built-in modules. ```python from .mapper import QlFsMapper # Built in modules should be imported either in one line or fully seperately. # ok import logging, os, re # ok import logging import re import os # no import logging, re import os # Note # Due to the historical design problem on project structure, you may have to use full import like `from qiling.os.utils import *` sometimes. ``` -------------------------------- ### Emulate a disk image using QlDisk in Qiling Source: https://docs.qiling.io/en/latest/hijack This example shows how to use Qiling's fs mapper to emulate a disk. It maps a raw disk image file ('out_1M.raw') to a specific drive index (0x80), enabling the emulated program to interact with it as if it were a physical disk. ```python from qiling import Qiling from qiling.os.disk import QlDisk if __name__ == "__main__": ql = Qiling([r'rootfs/8086_dos/petya/mbr.bin'], r'rootfs/8086_dos') # Note that this image is only intended for PoC purposes since the core petya code # resides in the sepecific sectors of a hard disk. It doesn't contain any data, either # encryted or unencrypted. emu_path = 0x80 emu_disk = QlDisk(r'rootfs/8086_dos/petya/out_1M.raw', emu_path) ql.add_fs_mapper(emu_path, emu_disk) ql.run() ``` -------------------------------- ### Example Custom Qiling Profile (INI) Source: https://docs.qiling.io/en/latest/profile This is an example of a custom Qiling Framework profile file. It specifies configuration options for a specific architecture, such as the memory map address and logging directory. This file is referenced when initializing Qiling. ```ini [MIPS] mmap_address = 0x7f7ee000 log_dir = qlog log_split = True ``` -------------------------------- ### Enable Qiling Debugger (Qdb) in Python Source: https://docs.qiling.io/en/latest/qdb This Python code snippet demonstrates how to enable the Qiling Debugger (Qdb) within a Qiling instance. It shows the basic setup and comments on alternative configurations for enabling record and replay or setting an initial breakpoint. ```python from qiling import Qiling from qiling.const import QL_VERBOSE if __name__ == "__main__": ql = Qiling([r'rootfs/arm_linux/bin/arm_hello'], r'rootfs/arm_linux', verbose=QL_VERBOSE.DEBUG) ql.debugger = "qdb" # enable qdb without options # other possible alternatives: # ql.debugger = "qdb::rr" # switch on record and replay with rr # ql.debugger = "qdb:0x1030c" # enable qdb and setup breakpoin at 0x1030c ql.run() ``` -------------------------------- ### Hijack stdin with custom content in Qiling Source: https://docs.qiling.io/en/latest/hijack This example demonstrates how to hijack the standard input (stdin) of an emulated program using Qiling's pipe extension. It feeds the program with predefined content, useful for bypassing input prompts or providing necessary data. ```python from qiling import Qiling from qiling.extensions import pipe def force_call_dialog_func(ql: Qiling) -> None: # get DialogFunc address lpDialogFunc = ql.mem.read_ptr(ql.arch.regs.esp - 0x8, 4) # setup stack for DialogFunc ql.stack_push(0) ql.stack_push(1001) ql.stack_push(273) ql.stack_push(0) ql.stack_push(0x0401018) # force EIP to DialogFunc ql.arch.regs.eip = lpDialogFunc if __name__ == "__main__": # expected flag: Ea5yR3versing ql = Qiling([r'rootfs/x86_windows/bin/Easy_CrackMe.exe'], r'rootfs/x86_windows') # hijack program's stdin and feed it with the expected flag ql.os.stdin = pipe.SimpleInStream(0) ql.os.stdin.write(b'Ea5yR3versing\n') ql.hook_address(force_call_dialog_func, 0x00401016) ql.run() ``` -------------------------------- ### Map virtual /dev/urandom to host /dev/urandom in Qiling Source: https://docs.qiling.io/en/latest/hijack This example demonstrates how to map a virtual file path within the Qiling environment to an existing file on the host system. Specifically, it maps the emulated '/dev/urandom' to the host's '/dev/urandom', allowing the emulated program to access system entropy. ```python from qiling import Qiling if __name__ == "__main__": ql = Qiling([r'rootfs/x86_linux/bin/x86_fetch_urandom'], r'rootfs/x86_linux') ql.add_fs_mapper(r'/dev/urandom', r'/dev/urandom') ql.run() ``` -------------------------------- ### Python Type Hinting for Function Signatures Source: https://docs.qiling.io/en/latest/contribution Shows how to implement Python type hinting in function signatures to provide extra information for autocompletion and static analysis. This follows Qiling's convention for type hinting. ```python def ql_is_multithread(ql: Qiling) -> bool: return ql.multithread ``` -------------------------------- ### UEFI SetVariable API Hook Source: https://docs.qiling.io/en/latest/hijack This snippet demonstrates how to hook the `SetVariable` UEFI service to capture variable name, GUID, attributes, data size, and data. The decorator `@dxeapi` is used, which applies to both DXE and SMM APIs. ```APIDOC ## POST /uefi/SetVariable ### Description Hooks the `SetVariable` UEFI service to capture variable name, GUID, attributes, data size, and the actual data being set. This is useful for monitoring system configuration changes. ### Method POST ### Endpoint `/uefi/SetVariable` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **VariableName** (WSTRING) - Required - The name of the variable to set. - **VendorGuid** (GUID) - Required - The GUID of the vendor associated with the variable. - **Attributes** (UINT) - Required - Attributes of the variable. - **DataSize** (UINT) - Required - Size of the data buffer. - **Data** (POINTER) - Required - Pointer to the data buffer. ### Request Example ```json { "VariableName": "MyVariable", "VendorGuid": "11223344-5566-7788-99AA-BBCCDDEEFF00", "Attributes": 1, "DataSize": 10, "Data": "0x12345678" } ``` ### Response #### Success Response (200) - **status** (string) - Indicates success, returns 'EFI_SUCCESS'. #### Response Example ```json { "status": "EFI_SUCCESS" } ``` ``` -------------------------------- ### Dynamically Patch Windows Crackme with Qiling Source: https://docs.qiling.io/en/latest/demo This Python code uses the Qiling Framework to dynamically patch a Windows crackme binary. It NOPs out specific code sections and hooks an address to force a 'Congratulation' dialog, making the crackme always succeed. ```python from qiling import * def force_call_dialog_func(ql): # get DialogFunc address lpDialogFunc = ql.unpack32(ql.mem.read(ql.arch.regs.esp - 0x8, 4)) # setup stack memory for DialogFunc ql.stack_push(0) ql.stack_push(1001) ql.stack_push(273) ql.stack_push(0) ql.stack_push(0x0401018) # force EIP to DialogFunc ql.arch.regs.eip = lpDialogFunc def my_sandbox(path, rootfs): ql = Qiling(path, rootfs) # 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() if __name__ == "__main__": my_sandbox(["rootfs/x86_windows/bin/Easy_CrackMe.exe"], "rootfs/x86_windows") ``` -------------------------------- ### Copy Qiling IDA Plugin to IDA Pro Plugins Folder Source: https://docs.qiling.io/en/latest/ida Copies the Qiling IDA plugin script directly into the IDA Pro plugins folder. This is an alternative to using symbolic links for installation. ```bash # Linux/macOS: cp ~/.local/lib//site-packages/qiling/extensions/idaplugin/qilingida.py /path/to/your/ida/plugins/ # Windows: copy C:\Users\\AppData\Roaming\Python\\site-packages\qiling\extensions\idaplugin\qilingida.py C:\absolute\path\to\IDA\plugins\qilingida.py ``` -------------------------------- ### Initialize Qiling with Custom Profile (Python) Source: https://docs.qiling.io/en/latest/profile This Python snippet shows how to initialize the Qiling Framework with a custom profile file. It imports necessary modules, defines a sandbox function that sets up Qiling with a specified profile, and includes an example of how to run this function with specific arguments. ```python from qiling import * from qiling.const import QL_VERBOSE.DEBUG def my_sandbox(path, rootfs): ql = Qiling(path, rootfs, verbose=QL_VERBOSE.DEBUG, profile= "netgear.ql") ql.add_fs_mapper("/proc", "/proc") ql.run() if __name__ == "__main__": my_sandbox(["rootfs/netgear_r6220/bin/mini_httpd","-d","/www","-r","NETGEAR R6220","-c","**.cgi","-t","300"], "rootfs/netgear_r6220") ``` -------------------------------- ### Memory Leak Detection with malloc and free Hooks Source: https://docs.qiling.io/en/latest/hijack This example shows how to hook `malloc` and `free` to detect memory leaks and double-free issues. `malloc` is hooked on exit to record allocated pointers, and `free` is hooked on entry to check if the pointer has already been freed. ```APIDOC ## Memory Management Hooks (malloc, free) ### Description Demonstrates hooking `malloc` and `free` to detect memory leaks and double-free vulnerabilities. `malloc` is hooked on exit to track allocated memory addresses, while `free` is hooked on entry to verify if an address is being freed for the first time. ### Method POST ### Endpoint `/memory/hooks` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **hook_malloc** (boolean) - Optional - Set to true to enable `malloc` hooking. - **hook_free** (boolean) - Optional - Set to true to enable `free` hooking. ### Request Example ```json { "hook_malloc": true, "hook_free": true } ``` ### Response #### Success Response (200) - **message** (string) - Confirmation message indicating hooks have been set. - **potential_memory_leaks** (array) - List of addresses suspected of memory leaks. - **double_free_warnings** (array) - List of addresses suspected of double-free. #### Response Example ```json { "message": "malloc and free hooks enabled successfully.", "potential_memory_leaks": ["0x12345678", "0x98765432"], "double_free_warnings": ["0xABCDEF01"] } ``` ``` -------------------------------- ### Access Cross-Architecture PC and SP - Qiling Python Source: https://docs.qiling.io/en/latest/register Provides examples for accessing the program counter (PC) and stack pointer (SP) registers, which are architecture-specific. This functionality is limited to 'pc' and 'sp' registers and relies on the architecture defined by `ql.arch.type`. ```python ql.arch.regs.arch_pc ql.arch.regs.arch_sp ``` ```python ql.arch.regs.arch_pc = 0xFF ql.arch.regs.arch_sp = 0xFF ``` -------------------------------- ### Emulate ARM Router Firmware with Qiling Source: https://docs.qiling.io/en/latest/demo This code snippet demonstrates how to emulate ARM router firmware (httpd) on an x86_64 Ubuntu machine using the Qiling Framework. It includes a patcher function to modify memory and a nvram_listener to handle socket communication for configuration parameters. The script sets up a Unix domain socket server to intercept and respond to requests related to network configuration. ```python import os, socket, sys, threading sys.path.append("..\..") from qiling import * from qiling.const import QL_VERBOSE def patcher(ql): br0_addr = ql.mem.search("br0".encode() + b'\x00') for addr in br0_addr: ql.mem.write(addr, b'lo\x00') def nvram_listener(): server_address = 'rootfs/var/cfm_socket' data = "" try: os.unlink(server_address) except OSError: if os.path.exists(server_address): raise # Create UDS socket sock = socket.socket(socket.AF_UNIX,socket.SOCK_STREAM) sock.bind(server_address) sock.listen(1) while True: connection, client_address = sock.accept() try: while True: data += str(connection.recv(1024)) if "lan.webiplansslen" in data: connection.send('192.168.170.169'.encode()) elif "wan_ifname" in data: connection.send('eth0'.encode()) elif "wan_ifnames" in data: connection.send('eth0'.encode()) elif "wan0_ifname" in data: connection.send('eth0'.encode()) elif "wan0_ifnames" in data: connection.send('eth0'.encode()) elif "sys.workmode" in data: connection.send('bridge'.encode()) elif "wan1.ip" in data: connection.send('1.1.1.1'.encode()) else: break data = "" finally: connection.close() def my_sandbox(path, rootfs): ql = Qiling(path, rootfs, verbose=QL_VERBOSE.DEBUG) ql.add_fs_mapper("/dev/urandom","/dev/urandom") ql.hook_address(patcher ,ql.loader.elf_entry) ql.run() if __name__ == "__main__": nvram_listener_therad = threading.Thread(target=nvram_listener, daemon=True) nvram_listener_therad.start() my_sandbox(["rootfs/bin/httpd"], "rootfs") ``` -------------------------------- ### Enable Qiling Remote Debugger (Python) Source: https://docs.qiling.io/en/latest/debugger This Python code snippet demonstrates how to enable the remote debugging server in Qiling. It initializes Qiling with a specified path and rootfs, then sets `ql.debugger = True` to start the gdbserver. The debugger defaults to listening on localhost:9999, but custom addresses and ports can be configured. The emulated code execution pauses at the entrypoint by default. ```python from qiling import * from qiling.const import QL_VERBOSE def test_gdb(path, rootfs): ql = Qiling(path, rootfs, verbose=QL_VERBOSE.OFF) # Enable debugger to listen at localhost address, default port 9999 ql.debugger = True # You can also customize address & port or type of debugging server # ql.debugger= ":9999" # GDB server listens to 0.0.0.0:9999 # ql.debugger = "127.0.0.1:9999" # GDB server listens to 127.0.0.1:9999 # ql.debugger = "gdb:127.0.0.1:9999" # GDB server listens to 127.0.0.1:9999 # ql.debugger = "idapro:127.0.0.1:9999" # IDA pro server listens to 127.0.0.1:9999 ql.run() if __name__ == "__main__": test_gdb(["../examples/rootfs/x8664_linux/bin/x8664_hello_static"], "../examples/rootfs/x8664_linux") ``` -------------------------------- ### Intercept POSIX 'puts' libc Function with Custom Handler Source: https://docs.qiling.io/en/latest/hijack This example demonstrates how to hook the POSIX 'puts' function using Qiling. The custom handler 'my_puts' receives the Qiling instance and resolves the function arguments. It then prints the string argument to the console and returns its length, emulating the behavior of 'puts'. ```python from qiling import Qiling from qiling.const import QL_INTERCEPT from qiling.os.const import STRING # customized POSIX libc methods accept a single argument that refers to the active # Qiling instance. The Qiling instance may be used to interact with various subsystems, # such as the memory or registers. The customized method may or may not return a value def my_puts(ql: Qiling): # Qiling offers a few conviniency methods that abstract away the access to the call # parameters. specifying the arguments names and types woud allow Qiling to retrieve # their values and parse them accordingly. # # the following call lists a single argument named 's', whose type is 'STRING'. # a dictionary will be created having the key 's' mapped to the null-terminated # string read from the memory address pointed by the first argument. params = ql.os.resolve_fcall_params({'s': STRING}) s = params['s'] ql.log.info(f'my_puts: got "{s}" as an argument') # emulate puts functionality print(s) return len(s) if __name__ == "__main__": ql = Qiling([r'rootfs/x8664_linux/bin/x8664_hello'], r'rootfs/x8664_linux') ql.os.set_api('puts', my_puts, QL_INTERCEPT.CALL) ql.run() ``` -------------------------------- ### Update Development Status to Beta Source: https://docs.qiling.io/en/latest/checklist Modifies the development status in setup.py to indicate a beta release. ```python 'Development Status :: 3 - Beta' ``` -------------------------------- ### Pull Qiling Framework Docker Image Source: https://docs.qiling.io/en/latest/install Pulls the latest Qiling Framework Docker image from Docker Hub. This command is used to download the pre-built container image for easy deployment. ```bash docker pull qilingframework/qiling:latest ``` ```bash docker pull qilingframework/qiling:1.0 ``` -------------------------------- ### Adding Docstrings to Python Functions Source: https://docs.qiling.io/en/latest/contribution Provides an example of how to add a docstring to a Python function, which is a standard practice for documenting code and improving maintainability. This aligns with Qiling's docstring convention. ```python def ql_dumb_function(): """ This is a docstring """ pass ``` -------------------------------- ### Execute Commands Inside Qiling Docker Container Source: https://docs.qiling.io/en/latest/install Attaches to a running Qiling Framework Docker container to execute commands within its environment. This is useful for interacting with the emulated system or running Qiling scripts. ```bash docker exec -it qiling bash ``` -------------------------------- ### Update Version and Development Status Source: https://docs.qiling.io/en/latest/checklist This section shows how to update the version string and the development status in the setup.py file to reflect a stable release. ```python __version__ = "1.[x].[x]" 'Development Status :: 5 - Production/Stable' ``` -------------------------------- ### Filter Qiling Log Entries with Regular Expressions Source: https://docs.qiling.io/en/latest/print Illustrates how to filter Qiling log entries using regular expressions. This is useful for reducing log noise and focusing on relevant messages. The example filters logs to show only those starting with 'open'. ```python from qiling import Qiling if __name__ == "__main__": ql = Qiling([r'examples/rootfs/arm_linux/bin/arm_hello'], r'examples/rootfs/arm_linux') # show only log entries that start with "open" ql.filter = '^open' ql.run() ``` -------------------------------- ### Update Version for Development Build Source: https://docs.qiling.io/en/latest/checklist Appends '-dev' to the version string in setup.py to denote a development build. ```python __version__ = "X.X.X" + "-dev" ``` -------------------------------- ### Tagging a New Release Source: https://docs.qiling.io/en/latest/checklist Commands to checkout the master branch, pull the latest changes, create a new git tag for the release, and push the tags to the origin. ```bash git checkout master git pull git tag 1.[x].[x] git push origin --tags ``` -------------------------------- ### Execute EVM Smart Contract Bytecode with Qiling Source: https://docs.qiling.io/en/latest/evm Demonstrates how to execute EVM smart contract bytecode using the Qiling Framework. It covers initializing the Qiling EVM environment, creating accounts, setting up transaction messages, and running the contract. ```python import sys from qiling import * if __name__ == '__main__': ql = Qiling(archtype="evm") contract = "0x60606040..." # Smart Contract Bytecode bal = ql.arch.evm.abi.convert(['uint256'], [20]) contract = contract + bal # add Bytecode init parameters(Optional) user1 = ql.arch.evm.create_account(balance=100*10**18) # Creating a user account with 100 ETH c1 = ql.arch.evm.create_account() # Creating a contract account call_data = '0x...' # Function Sign and parameters msg1 = ql.arch.evm.create_message(user1, c1, call_data) # Creating a transaction message result = ql.run(code=msg1) # Running this transaction ``` -------------------------------- ### Sync Development Branch with Master Source: https://docs.qiling.io/en/latest/checklist Steps to switch to the 'dev' branch and merge the latest changes from the 'master' branch into it. ```bash git checkout dev git merge master ``` -------------------------------- ### Understanding Data Structures Source: https://docs.qiling.io/en/latest/struct Guidance on how to understand and work with complex data structures in memory, whether they are known or unknown. ```APIDOC ## Understanding Data Structures ### Description To effectively pack and unpack complex data structures, it's crucial to understand their composition in memory. This section outlines strategies for dealing with both known and unknown structures. ### Known Structures For well-documented structures (e.g., from operating systems, standard libraries), information can typically be found through online searches or technical books. ### Unknown Structures For proprietary or custom libraries, a decompiler (like IDA Pro, Ghidra, or Radare2) is often necessary to analyze the structure in memory and determine its layout. ### Example: sockaddr_in Structure This example demonstrates analyzing a known structure (`sockaddr_in`) for a specific target environment. #### Info - Target: Netgear 6220 - CPU-Arch: mips32el - Endian: Little Endian (el) - API: bind - Struct: sockaddr_in #### Structure Definition ```c struct sockaddr_in { sa_family_t sin_family; /* address family: AF_INET */ in_port_t sin_port; /* port in network byte order */ struct in_addr sin_addr; /* internet address */ }; /* Internet address. */ struct in_addr { uint32_t s_addr; /* address in network byte order */ }; ``` ### Method N/A (Informational) ### Endpoint N/A ### Parameters N/A ### Request Example N/A ### Response N/A ### Success Response (200) N/A ### Response Example N/A ``` -------------------------------- ### Python Naming Conventions for Code Elements Source: https://docs.qiling.io/en/latest/contribution Demonstrates the standard Python naming conventions for classes (PascalCase), functions and variables (snake_case), and constants (UPPERCASE), as recommended by Qiling's coding standards. ```python # Class: PascalCase class QlOsDumb: pass # Function: snake_case def ql_dumb_function(): pass # Variable: snake_case mem_ptr = 0 # Constants: UPPERCASE # If the constant is from other place, e.g. Linux Kernel, follow their naming convention. ERROR = 0 ``` -------------------------------- ### Get Register Mapping Table - Qiling Python Source: https://docs.qiling.io/en/latest/register Demonstrates how to retrieve the register mapping for the current architecture. This function, `register_mapping()`, returns a table that maps register names to their corresponding internal representations. ```python ql.arch.regs.register_mapping() ``` -------------------------------- ### Get Register Bit Size - Qiling Python Source: https://docs.qiling.io/en/latest/register Shows how to determine the bit size (32 or 64) of a register for architectures that support both. The `reg_bits()` function takes a register name as input and returns its size in bits. ```python ql.arch.reg_bits("rax") ``` ```python ql.arch.reg_bits("eax") ``` -------------------------------- ### Clone and Checkout Dev Branch Source: https://docs.qiling.io/en/latest/faq This snippet shows how to clone the Qiling Framework repository and switch to the development branch using Git. ```bash git clone https://github.com/qilingframework/qiling.git git checkout dev ``` -------------------------------- ### Checking Memory Availability in Qiling Source: https://docs.qiling.io/en/latest/memory Explains how to check if a memory region, starting at a given address and with a specified size, is available for allocation. The `is_available` function returns `True` if the region can be used, and `False` otherwise. ```python ql.mem.is_available(addr, size) ``` -------------------------------- ### Using Python Properties for Class Members Source: https://docs.qiling.io/en/latest/contribution Illustrates the use of Python's `@property` decorator for class members, promoting readability and better code autocompletion compared to direct attribute access. This adheres to Qiling's coding convention for properties. ```python class QlOsDumb: def __init__(self): #self.dumb = 1 self._dumb = 1 @property def dumb(self): return self._dumb def do_something(self): print(self.dumb) ``` -------------------------------- ### Finding Free Memory Space in Qiling Source: https://docs.qiling.io/en/latest/memory Demonstrates how to find an available memory region of a specified size within the emulated memory space using Qiling. The `find_free_space` function returns the starting address of a suitable free block. ```python ql.mem.find_free_space(size) ```