Qiling Advanced Binary Emulation Framework

Overview

Documentation Status Downloads Chat on Telegram


Qiling's usecase, blog and related work

Qiling is an advanced binary emulation framework, with the following features:

  • Emulate multi-platforms: Windows, MacOS, Linux, Android, BSD, UEFI, DOS, MBR, Ethereum Virtual Machine
  • Emulate multi-architectures: 8086, X86, X86_64, ARM, ARM64, MIPS, RISCV, PowerPC
  • Support multiple file formats: PE, MachO, ELF, COM, MBR
  • Support Windows Driver (.sys), Linux Kernel Module (.ko) & MacOS Kernel (.kext) via Demigod
  • Emulates & sandbox code in an isolated environment
  • Provides a fully configurable sandbox
  • Provides in-depth memory, register, OS level and filesystem level API
  • Fine-grain instrumentation: allows hooks at various levels (instruction/basic-block/memory-access/exception/syscall/IO/etc)
  • Provides virtual machine level API such as save and restore current execution state
  • Supports cross architecture and platform debugging capabilities
  • Built-in debugger with reverse debugging capability
  • Allows dynamic hotpatch on-the-fly running code, including the loaded library
  • True framework in Python, making it easy to build customized security analysis tools on top

Qiling also made its way to various international conferences.

2021:

2020:

2019:

Qiling is backed by Unicorn engine.

Visit our website https://www.qiling.io for more information.


License

This project is released and distributed under free software license GPLv2 and later version.


Qiling vs other Emulators

There are many open source emulators, but two projects closest to Qiling are Unicorn & Qemu usermode. This section explains the main differences of Qiling against them.

Qiling vs Unicorn engine

Built on top of Unicorn, but Qiling & Unicorn are two different animals.

  • Unicorn is just a CPU emulator, so it focuses on emulating CPU instructions, that can understand emulator memory. Beyond that, Unicorn is not aware of higher level concepts, such as dynamic libraries, system calls, I/O handling or executable formats like PE, MachO or ELF. As a result, Unicorn can only emulate raw machine instructions, without Operating System (OS) context
  • Qiling is designed as a higher level framework, that leverages Unicorn to emulate CPU instructions, but can understand OS: it has executable format loaders (for PE, MachO & ELF at the moment), dynamic linkers (so we can load & relocate shared libraries), syscall & IO handlers. For this reason, Qiling can run executable binary without requiring its native OS
Qiling vs Qemu usermode

Qemu usermode does similar thing to our emulator, that is to emulate whole executable binaries in cross-architecture way. However, Qiling offers some important differences against Qemu usermode.

  • Qiling is a true analysis framework, that allows you to build your own dynamic analysis tools on top (in friendly Python language). Meanwhile, Qemu is just a tool, not a framework
  • Qiling can perform dynamic instrumentation, and can even hotpatch code at runtime. Qemu does not do either
  • Not only working cross-architecture, Qiling is also cross-platform, so for example you can run Linux ELF file on top of Windows. In contrast, Qemu usermode only run binary of the same OS, such as Linux ELF on Linux, due to the way it forwards syscall from emulated code to native OS
  • Qiling supports more platforms, including Windows, MacOS, Linux & BSD. Qemu usermode can only handle Linux & BSD

Installation

Please see setup guide file for how to install Qiling Framework.


Examples

  • The example below shows how to use Qiling framework in the most striaghtforward 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()
  • The following example shows how a Windows crackme may be patched dynamically to make it always display the "Congratulation" dialog.
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.

Emulating ARM router firmware on Ubuntu X64 machine

  • Qiling Framework hot-patch and emulates ARM router's /usr/bin/httpd on a X86_64Bit Ubuntu

qiling Tutorial: Emulating and Fuzz ARM router firmware

Qiling's IDAPro Plugin: Instrument and Decrypt Mirai's Secret

  • This video demonstrate how Qiling's IDAPro plugin able to make IDApro run with Qiling instrumentation engine

GDBserver with IDAPro demo

  • Solving a simple CTF challenge with Qiling Framework and IDAPro

Solving a simple CTF challenge with Qiling Framework and IDAPro

Emulating MBR

  • Qiling Framework emulates MBR

qiling DEMO: Emulating MBR


Qltool

Qiling also provides a friendly tool named qltool to quickly emulate shellcode & executable binaries.

With qltool, easy execution can be performed:

With shellcode:

$ ./qltool shellcode --os linux --arch arm --hex -f examples/shellcodes/linarm32_tcp_reverse_shell.hex

With binary file:

$ ./qltool run -f examples/rootfs/x8664_linux/bin/x8664_hello --rootfs  examples/rootfs/x8664_linux/

With binary and GDB debugger enable:

$ ./qltool run -f examples/rootfs/x8664_linux/bin/x8664_hello --gdb 127.0.0.1:9999 --rootfs examples/rootfs/x8664_linux

With code coverage collection (UEFI only for now):

$ ./qltool run -f examples/rootfs/x8664_efi/bin/TcgPlatformSetupPolicy --rootfs examples/rootfs/x8664_efi --coverage-format drcov --coverage-file TcgPlatformSetupPolicy.cov

With json output (Windows mainly):

$ ./qltool run -f examples/rootfs/x86_windows/bin/x86_hello.exe --rootfs  examples/rootfs/x86_windows/ --console False --json

Contact

Get the latest info from our website https://www.qiling.io

Contact us at email [email protected], or via Twitter @qiling_io or Weibo


Core developers, Key Contributors and etc

Please refer to CREDITS.md


This is an awesome project! Can I donate?

Yes, checkout SWAG

Comments
  • GandCrab PR

    GandCrab PR

    Anyrun of sample: https://app.any.run/tasks/48406845-690f-47ee-b385-38534d75d00a/

    What Qiling do: Pass checks for OSVersion (is possible to change value inside variables.py) Pass check for Administrator Privilege (variable inside SID) Pass check for Keyboard Layout (depends of your NTUSER.DAT) Pass check for System/User Default Language (needs a better solution here tbh) Crashes on call SHGetSpecialFolderPathW, probably because my DLL doesn't have this function since its deprecated.

    opened by 0ssigeno 33
  • ld-linux-x86-64.so.2  Invalid memory read (UC_ERR_READ_UNMAPPED)

    ld-linux-x86-64.so.2 Invalid memory read (UC_ERR_READ_UNMAPPED)

    *Describe the bug A clear and concise description of what the bug is.

    Sample Code

    from capstone import *
    from qiling import *
    
    def my_puts(ql):
        addr = ql.os.function_arg[0]
        print("puts(%s)" % ql.mem.string(addr))
    
    def hook_code(ql, address, size):
        print('>>> Tracing instruction at 0x%x, instruction size = 0x%x' %(address, size))
        buf = ql.mem.read(address, size)
        for i in md.disasm(buf, address):
            print(":: 0x%x:\t%s\t%s" % (i.address, i.mnemonic, i.op_str))
    
    
    if __name__ == "__main__":
        md = Cs(CS_ARCH_X86, CS_MODE_64)
        ql = Qiling(["rootfs/x8664_linux/bin/x8664_hello"], "rootfs/x8664_linux")
        ql.set_api('puts', my_puts)
        ql.hook_code(hook_code)
        ql.run()
    

    Expected behavior

    :: 0x7ffff7df23a2: jne 0x7ffff7df3770

    Tracing instruction at 0x7ffff7df3770, instruction size = 0x4 :: 0x7ffff7df3770: bsf rdx, rdx Tracing instruction at 0x7ffff7df3774, instruction size = 0x4 :: 0x7ffff7df3774: movzx ecx, byte ptr [rsi + rdx] Tracing instruction at 0x7ffff7df3778, instruction size = 0x4 :: 0x7ffff7df3778: movzx eax, byte ptr [rdi + rdx] Tracing instruction at 0x7ffff7df377c, instruction size = 0x2 :: 0x7ffff7df377c: sub eax, ecx Tracing instruction at 0x7ffff7df377e, instruction size = 0x1 :: 0x7ffff7df377e: ret Tracing instruction at 0x7ffff7de6754, instruction size = 0x2 :: 0x7ffff7de6754: test eax, eax Tracing instruction at 0x7ffff7de6756, instruction size = 0x2 :: 0x7ffff7de6756: jne 0x7ffff7de6740 Tracing instruction at 0x7ffff7de6740, instruction size = 0x4 :: 0x7ffff7de6740: mov rbx, qword ptr [rbx + 8] Tracing instruction at 0x7ffff7de6744, instruction size = 0x3 :: 0x7ffff7de6744: test rbx, rbx Tracing instruction at 0x7ffff7de6747, instruction size = 0x2 :: 0x7ffff7de6747: je 0x7ffff7de6730 Tracing instruction at 0x7ffff7de6730, instruction size = 0x2 :: 0x7ffff7de6730: xor edx, edx Tracing instruction at 0x7ffff7de6732, instruction size = 0x4 :: 0x7ffff7de6732: add rsp, 8 Tracing instruction at 0x7ffff7de6736, instruction size = 0x2 :: 0x7ffff7de6736: mov eax, edx Tracing instruction at 0x7ffff7de6738, instruction size = 0x1 :: 0x7ffff7de6738: pop rbx Tracing instruction at 0x7ffff7de6739, instruction size = 0x1 :: 0x7ffff7de6739: pop rbp Tracing instruction at 0x7ffff7de673a, instruction size = 0x1 :: 0x7ffff7de673a: ret Tracing instruction at 0x7ffff7de6a20, instruction size = 0x2 :: 0x7ffff7de6a20: test eax, eax Tracing instruction at 0x7ffff7de6a22, instruction size = 0x2 :: 0x7ffff7de6a22: je 0x7ffff7de6a08 Tracing instruction at 0x7ffff7de6a08, instruction size = 0x4 :: 0x7ffff7de6a08: mov r15, qword ptr [r15 + 0x18] Tracing instruction at 0x7ffff7de6a0c, instruction size = 0x3 :: 0x7ffff7de6a0c: test r15, r15 Tracing instruction at 0x7ffff7de6a0f, instruction size = 0x6 :: 0x7ffff7de6a0f: je 0x7ffff7de6cd0 Tracing instruction at 0x7ffff7de6a15, instruction size = 0x3 :: 0x7ffff7de6a15: mov rsi, r15 Tracing instruction at 0x7ffff7de6a18, instruction size = 0x3 :: 0x7ffff7de6a18: mov rdi, rbx Tracing instruction at 0x7ffff7de6a1b, instruction size = 0x5 :: 0x7ffff7de6a1b: call 0x7ffff7de6700 Tracing instruction at 0x7ffff7de6700, instruction size = 0x1 :: 0x7ffff7de6700: push rbp Tracing instruction at 0x7ffff7de6701, instruction size = 0x1 :: 0x7ffff7de6701: push rbx Tracing instruction at 0x7ffff7de6702, instruction size = 0x3 :: 0x7ffff7de6702: mov rbx, rsi Tracing instruction at 0x7ffff7de6705, instruction size = 0x3 :: 0x7ffff7de6705: mov rbp, rdi Tracing instruction at 0x7ffff7de6708, instruction size = 0x4 :: 0x7ffff7de6708: sub rsp, 8 Tracing instruction at 0x7ffff7de670c, instruction size = 0x4 :: 0x7ffff7de670c: mov rsi, qword ptr [rsi + 8] Tracing instruction at 0x7ffff7de6710, instruction size = 0x5 :: 0x7ffff7de6710: call 0x7ffff7df2360 Tracing instruction at 0x7ffff7df2360, instruction size = 0x2 :: 0x7ffff7df2360: mov ecx, esi Tracing instruction at 0x7ffff7df2362, instruction size = 0x2 :: 0x7ffff7df2362: mov eax, edi Tracing instruction at 0x7ffff7df2364, instruction size = 0x4 :: 0x7ffff7df2364: and rcx, 0x3f Tracing instruction at 0x7ffff7df2368, instruction size = 0x4 :: 0x7ffff7df2368: and rax, 0x3f Tracing instruction at 0x7ffff7df236c, instruction size = 0x3 :: 0x7ffff7df236c: cmp ecx, 0x30 Tracing instruction at 0x7ffff7df236f, instruction size = 0x2 :: 0x7ffff7df236f: ja 0x7ffff7df23b0 Tracing instruction at 0x7ffff7df2371, instruction size = 0x3 :: 0x7ffff7df2371: cmp eax, 0x30 Tracing instruction at 0x7ffff7df2374, instruction size = 0x2 :: 0x7ffff7df2374: ja 0x7ffff7df23b0 Tracing instruction at 0x7ffff7df2376, instruction size = 0x4 :: 0x7ffff7df2376: movlpd xmm1, qword ptr [rdi] Tracing instruction at 0x7ffff7df237a, instruction size = 0x4 :: 0x7ffff7df237a: movlpd xmm2, qword ptr [rsi] Tracing instruction at 0x7ffff7df237e, instruction size = 0x5 :: 0x7ffff7df237e: movhpd xmm1, qword ptr [rdi + 8] Tracing instruction at 0x7ffff7df2383, instruction size = 0x5 :: 0x7ffff7df2383: movhpd xmm2, qword ptr [rsi + 8] Tracing instruction at 0x7ffff7df2388, instruction size = 0x4 :: 0x7ffff7df2388: pxor xmm0, xmm0 Tracing instruction at 0x7ffff7df238c, instruction size = 0x4 :: 0x7ffff7df238c: pcmpeqb xmm0, xmm1 Tracing instruction at 0x7ffff7df2390, instruction size = 0x4 :: 0x7ffff7df2390: pcmpeqb xmm1, xmm2 Tracing instruction at 0x7ffff7df2394, instruction size = 0x4 :: 0x7ffff7df2394: psubb xmm1, xmm0 Tracing instruction at 0x7ffff7df2398, instruction size = 0x4 :: 0x7ffff7df2398: pmovmskb edx, xmm1 Tracing instruction at 0x7ffff7df239c, instruction size = 0x6 :: 0x7ffff7df239c: sub edx, 0xffff Tracing instruction at 0x7ffff7df23a2, instruction size = 0x6 :: 0x7ffff7df23a2: jne 0x7ffff7df3770 Tracing instruction at 0x7ffff7df3770, instruction size = 0x4 :: 0x7ffff7df3770: bsf rdx, rdx Tracing instruction at 0x7ffff7df3774, instruction size = 0x4 :: 0x7ffff7df3774: movzx ecx, byte ptr [rsi + rdx] Tracing instruction at 0x7ffff7df3778, instruction size = 0x4 :: 0x7ffff7df3778: movzx eax, byte ptr [rdi + rdx] Tracing instruction at 0x7ffff7df377c, instruction size = 0x2 :: 0x7ffff7df377c: sub eax, ecx Tracing instruction at 0x7ffff7df377e, instruction size = 0x1 :: 0x7ffff7df377e: ret Tracing instruction at 0x7ffff7de6715, instruction size = 0x2 :: 0x7ffff7de6715: test eax, eax Tracing instruction at 0x7ffff7de6717, instruction size = 0x5 :: 0x7ffff7de6717: mov edx, 1 Tracing instruction at 0x7ffff7de671c, instruction size = 0x2 :: 0x7ffff7de671c: je 0x7ffff7de6732 Tracing instruction at 0x7ffff7de671e, instruction size = 0x4 :: 0x7ffff7de671e: mov rbx, qword ptr [rbx + 0x38] Tracing instruction at 0x7ffff7de6722, instruction size = 0x3 :: 0x7ffff7de6722: test rbx, rbx Tracing instruction at 0x7ffff7de6725, instruction size = 0x2 :: 0x7ffff7de6725: jne 0x7ffff7de6749 Tracing instruction at 0x7ffff7de6749, instruction size = 0x3 :: 0x7ffff7de6749: mov rsi, qword ptr [rbx] Tracing instruction at 0x7ffff7de674c, instruction size = 0x3 :: 0x7ffff7de674c: mov rdi, rbp Tracing instruction at 0x7ffff7de674f, instruction size = 0x5 :: 0x7ffff7de674f: call 0x7ffff7df2360 Tracing instruction at 0x7ffff7df2360, instruction size = 0x2 :: 0x7ffff7df2360: mov ecx, esi Tracing instruction at 0x7ffff7df2362, instruction size = 0x2 :: 0x7ffff7df2362: mov eax, edi Tracing instruction at 0x7ffff7df2364, instruction size = 0x4 :: 0x7ffff7df2364: and rcx, 0x3f Tracing instruction at 0x7ffff7df2368, instruction size = 0x4 :: 0x7ffff7df2368: and rax, 0x3f Tracing instruction at 0x7ffff7df236c, instruction size = 0x3 :: 0x7ffff7df236c: cmp ecx, 0x30 Tracing instruction at 0x7ffff7df236f, instruction size = 0x2 :: 0x7ffff7df236f: ja 0x7ffff7df23b0 Tracing instruction at 0x7ffff7df2371, instruction size = 0x3 :: 0x7ffff7df2371: cmp eax, 0x30 Tracing instruction at 0x7ffff7df2374, instruction size = 0x2 :: 0x7ffff7df2374: ja 0x7ffff7df23b0 Tracing instruction at 0x7ffff7df2376, instruction size = 0x4 :: 0x7ffff7df2376: movlpd xmm1, qword ptr [rdi] Tracing instruction at 0x7ffff7df237a, instruction size = 0x4 :: 0x7ffff7df237a: movlpd xmm2, qword ptr [rsi] Tracing instruction at 0x7ffff7df237e, instruction size = 0x5 :: 0x7ffff7df237e: movhpd xmm1, qword ptr [rdi + 8] Tracing instruction at 0x7ffff7df2383, instruction size = 0x5 :: 0x7ffff7df2383: movhpd xmm2, qword ptr [rsi + 8] Tracing instruction at 0x7ffff7df2388, instruction size = 0x4 :: 0x7ffff7df2388: pxor xmm0, xmm0 Tracing instruction at 0x7ffff7df238c, instruction size = 0x4 :: 0x7ffff7df238c: pcmpeqb xmm0, xmm1 Tracing instruction at 0x7ffff7df2390, instruction size = 0x4 :: 0x7ffff7df2390: pcmpeqb xmm1, xmm2 Tracing instruction at 0x7ffff7df2394, instruction size = 0x4 :: 0x7ffff7df2394: psubb xmm1, xmm0 Tracing instruction at 0x7ffff7df2398, instruction size = 0x4 :: 0x7ffff7df2398: pmovmskb edx, xmm1 Tracing instruction at 0x7ffff7df239c, instruction size = 0x6 :: 0x7ffff7df239c: sub edx, 0xffff Tracing instruction at 0x7ffff7df23a2, instruction size = 0x6 :: 0x7ffff7df23a2: jne 0x7ffff7df3770 Tracing instruction at 0x7ffff7df3770, instruction size = 0x4 :: 0x7ffff7df3770: bsf rdx, rdx Tracing instruction at 0x7ffff7df3774, instruction size = 0x4 :: 0x7ffff7df3774: movzx ecx, byte ptr [rsi + rdx] Tracing instruction at 0x7ffff7df3778, instruction size = 0x4 :: 0x7ffff7df3778: movzx eax, byte ptr [rdi + rdx] Tracing instruction at 0x7ffff7df377c, instruction size = 0x2 :: 0x7ffff7df377c: sub eax, ecx Tracing instruction at 0x7ffff7df377e, instruction size = 0x1 :: 0x7ffff7df377e: ret Tracing instruction at 0x7ffff7de6754, instruction size = 0x2 :: 0x7ffff7de6754: test eax, eax Tracing instruction at 0x7ffff7de6756, instruction size = 0x2 :: 0x7ffff7de6756: jne 0x7ffff7de6740 Tracing instruction at 0x7ffff7de6758, instruction size = 0x4 :: 0x7ffff7de6758: add rsp, 8 Tracing instruction at 0x7ffff7de675c, instruction size = 0x5 :: 0x7ffff7de675c: mov edx, 1 Tracing instruction at 0x7ffff7de6761, instruction size = 0x2 :: 0x7ffff7de6761: mov eax, edx Tracing instruction at 0x7ffff7de6763, instruction size = 0x1 :: 0x7ffff7de6763: pop rbx Tracing instruction at 0x7ffff7de6764, instruction size = 0x1 :: 0x7ffff7de6764: pop rbp Tracing instruction at 0x7ffff7de6765, instruction size = 0x1 :: 0x7ffff7de6765: ret Tracing instruction at 0x7ffff7de6a20, instruction size = 0x2 :: 0x7ffff7de6a20: test eax, eax Tracing instruction at 0x7ffff7de6a22, instruction size = 0x2 :: 0x7ffff7de6a22: je 0x7ffff7de6a08 Tracing instruction at 0x7ffff7de6a24, instruction size = 0x4 :: 0x7ffff7de6a24: mov ecx, dword ptr [rsp + 0x4c] Tracing instruction at 0x7ffff7de6a28, instruction size = 0x2 :: 0x7ffff7de6a28: test ecx, ecx Tracing instruction at 0x7ffff7de6a2a, instruction size = 0x6 :: 0x7ffff7de6a2a: jne 0x7ffff7de6daf Tracing instruction at 0x7ffff7de6a30, instruction size = 0x5 :: 0x7ffff7de6a30: mov rax, qword ptr [rsp + 0x38] Tracing instruction at 0x7ffff7de6a35, instruction size = 0x5 :: 0x7ffff7de6a35: mov qword ptr [rsp + 0x20], r15 Tracing instruction at 0x7ffff7de6a3a, instruction size = 0x4 :: 0x7ffff7de6a3a: mov r15d, dword ptr [rsp] Tracing instruction at 0x7ffff7de6a3e, instruction size = 0x5 :: 0x7ffff7de6a3e: mov qword ptr [rsp + 0x10], r13 Tracing instruction at 0x7ffff7de6a43, instruction size = 0x3 :: 0x7ffff7de6a43: mov ebx, dword ptr [rax + 8] Tracing instruction at 0x7ffff7de6a46, instruction size = 0x3 :: 0x7ffff7de6a46: add rbx, rax Tracing instruction at 0x7ffff7de6a49, instruction size = 0x8 :: 0x7ffff7de6a49: lea rax, [rsp + 0x80] Tracing instruction at 0x7ffff7de6a51, instruction size = 0x5 :: 0x7ffff7de6a51: mov qword ptr [rsp + 0x30], rax Tracing instruction at 0x7ffff7de6a56, instruction size = 0xa :: 0x7ffff7de6a56: nop word ptr cs:[rax + rax] Tracing instruction at 0x7ffff7de6a60, instruction size = 0x4 :: 0x7ffff7de6a60: movzx eax, word ptr [rbx + 4] Tracing instruction at 0x7ffff7de6a64, instruction size = 0x4 :: 0x7ffff7de6a64: mov r12d, dword ptr [rbx + 8] Tracing instruction at 0x7ffff7de6a68, instruction size = 0x5 :: 0x7ffff7de6a68: add r12, qword ptr [rsp + 0x18] Tracing instruction at 0x7ffff7de6a6d, instruction size = 0x3 :: 0x7ffff7de6a6d: mov r13d, dword ptr [rbx] Tracing instruction at 0x7ffff7de6a70, instruction size = 0x5 :: 0x7ffff7de6a70: mov word ptr [rsp + 0x42], ax Tracing instruction at 0x7ffff7de6a75, instruction size = 0x5 :: 0x7ffff7de6a75: mov rax, qword ptr [rsp + 0x20] Tracing instruction at 0x7ffff7de6a7a, instruction size = 0x4 :: 0x7ffff7de6a7a: mov qword ptr [rsp], r12 Tracing instruction at 0x7ffff7de6a7e, instruction size = 0x4 :: 0x7ffff7de6a7e: mov rbp, qword ptr [rax + 0x28] Tracing instruction at 0x7ffff7de6a82, instruction size = 0x5 :: 0x7ffff7de6a82: mov rax, qword ptr [rsp + 0x10] Tracing instruction at 0x7ffff7de6a87, instruction size = 0x4 :: 0x7ffff7de6a87: mov r12, qword ptr [rax + 8] Tracing instruction at 0x7ffff7de6a8b, instruction size = 0x5 :: 0x7ffff7de6a8b: cmp byte ptr [r12], 0 Tracing instruction at 0x7ffff7de6a90, instruction size = 0x2 :: 0x7ffff7de6a90: jne 0x7ffff7de6aaa Tracing instruction at 0x7ffff7de6a92, instruction size = 0x7 :: 0x7ffff7de6a92: mov rax, qword ptr [rip + 0x215ca7] Tracing instruction at 0x7ffff7de6a99, instruction size = 0x3 :: 0x7ffff7de6a99: mov r12, qword ptr [rax] Tracing instruction at 0x7ffff7de6a9c, instruction size = 0x7 :: 0x7ffff7de6a9c: lea rax, [rip + 0xef4c] Tracing instruction at 0x7ffff7de6aa3, instruction size = 0x3 :: 0x7ffff7de6aa3: test r12, r12 Tracing instruction at 0x7ffff7de6aa6, instruction size = 0x4 :: 0x7ffff7de6aa6: cmove r12, rax Tracing instruction at 0x7ffff7de6aaa, instruction size = 0x4 :: 0x7ffff7de6aaa: mov rax, qword ptr [rbp + 0x68] Tracing instruction at 0x7ffff7de6aae, instruction size = 0x4 :: 0x7ffff7de6aae: mov rax, qword ptr [rax + 8] [x] CPU Context: [x] ah : 0x0 [x] al : 0x0 [x] ch : 0x0 [x] cl : 0x0 [x] dh : 0x0 [x] dl : 0x1 [x] bh : 0x44 [x] bl : 0x0 [x] ax : 0x0 [x] cx : 0x0 [x] dx : 0x1 [x] bx : 0x4400 [x] sp : 0xda00 [x] bp : 0xe930 [x] si : 0xedc0 [x] di : 0x4361 [x] ip : 0x6aae [x] eax : 0x0 [x] ecx : 0x0 [x] edx : 0x1 [x] ebx : 0x55554400 [x] esp : 0xda00 [x] ebp : 0xf7ffe930 [x] esi : 0xf7ffedc0 [x] edi : 0x55554361 [x] eip : 0xf7de6aae [x] rax : 0x0 [x] rbx : 0x555555554400 [x] rcx : 0x0 [x] rdx : 0x1 [x] rsi : 0x7ffff7ffedc0 [x] rdi : 0x555555554361 [x] rbp : 0x7ffff7ffe930 [x] rsp : 0x80000000da00 [x] r8 : 0x0 [x] r9 : 0x0 [x] r10 : 0x32 [x] r11 : 0x3ec860 [x] r12 : 0x80000000dfd8 [x] r13 : 0x9691a75 [x] r14 : 0x7ffff7df5840 [x] r15 : 0x0 [x] rip : 0x7ffff7de6aae [x] cr0 : 0x11 [x] cr1 : 0x0 [x] cr2 : 0x0 [x] cr3 : 0x0 [x] cr4 : 0x0 [x] cr8 : 0x0 [x] st0 : 0x0 [x] st1 : 0x0 [x] st2 : 0x0 [x] st3 : 0x0 [x] st4 : 0x0 [x] st5 : 0x0 [x] st6 : 0x0 [x] st7 : 0x0 [x] ef : 0x4 [x] cs : 0x1b [x] ss : 0x28 [x] ds : 0x28 [x] es : 0x28 [x] fs : 0x0 [x] gs : 0x0 [x] r8b : 0x0 [x] r9b : 0x0 [x] r10b : 0x32 [x] r11b : 0x60 [x] r12b : 0xd8 [x] r13b : 0x75 [x] r14b : 0x40 [x] r15b : 0x0 [x] r8w : 0x0 [x] r9w : 0x0 [x] r10w : 0x32 [x] r11w : 0xc860 [x] r12w : 0xdfd8 [x] r13w : 0x1a75 [x] r14w : 0x5840 [x] r15w : 0x0 [x] r8d : 0x0 [x] r9d : 0x0 [x] r10d : 0x32 [x] r11d : 0x3ec860 [x] r12d : 0xdfd8 [x] r13d : 0x9691a75 [x] r14d : 0xf7df5840 [x] r15d : 0x0 [x] fsbase : 0x0 [x] gsbase : 0x6000000 [x] Hexdump: [x] 48 8b 40 08 48 89 44 24 [x] Disassembly: [=] 00007ffff7de6aae [ld-linux-x86-64.so.2 + 0x011aae] 48 8b 40 08 48 89 44 24 08 48 8d 05 a2 5c 21 00 f6 00 10 0f 85 b9 01 00 00 48 8b 85 68 01 00 00 48 85 c0 0f 84 61 01 00 00 48 8b 50 08 48 85 d2 0f 84 c7 05 00 00 48 03 55 00 66 83 3a 01 75 35mov rax, qword ptr [rax + 8] mov qword ptr [rsp + 8], rax lea rax, [rip + 0x215ca2] test byte ptr [rax], 0x10 jne 0x7ffff7de6c80 mov rax, qword ptr [rbp + 0x168] test rax, rax je 0x7ffff7de6c38 mov rdx, qword ptr [rax + 8] test rdx, rdx je 0x7ffff7de70ab add rdx, qword ptr [rbp] cmp word ptr [rdx], 1 jne 0x7ffff7de6b23 [x] PC = 0x00007ffff7de6aae

    [=] Memory map: [=] Start End Perm Label Image [=] 00030000 - 00031000 rwx [GDT]
    [=] 06000000 - 07400000 rwx [GS]
    [=] 555555554000 - 555555555000 r-x rootfs/x8664_linux/bin/x8664_hello rootfs/x8664_linux/bin/x8664_hello [=] 555555754000 - 555555756000 rw- rootfs/x8664_linux/bin/x8664_hello rootfs/x8664_linux/bin/x8664_hello [=] 555555756000 - 555555758000 rwx [hook_mem]
    [=] 7fffb7dd6000 - 7fffb81c7000 rwx [syscall_mmap]
    [=] 7fffb7dd6000 - 7fffb81c7000 rwx [mmap] D:\code\python\my_qiling\qiling\rootfs\x8664_linux\lib\libc.so.6
    [=] 7fffb81bd000 - 7fffb81c3000 rwx [mmap] D:\code\python\my_qiling\qiling\rootfs\x8664_linux\lib\libc.so.6
    [=] 7ffff7dd5000 - 7ffff7fff000 rwx D:\code\python\my_qiling\qiling\rootfs\x8664_linux\lib64\ld-linux-x86-64.so.2
    [=] 7ffffffde000 - 80000000e000 rwx [stack]
    [=] ffffffffff600000 - ffffffffff601000 rwx [vsyscall]
    Traceback (most recent call last): File "D:\code\python\my_qiling\venv\lib\site-packages\qiling\os\linux\linux.py", line 133, in run self.ql.emu_start(self.ql.loader.entry_point, entry_address, self.ql.timeout) File "D:\code\python\my_qiling\venv\lib\site-packages\qiling\core.py", line 867, in emu_start self.uc.emu_start(begin, end, timeout, count) File "D:\code\python\my_qiling\venv\lib\site-packages\unicorn\unicorn.py", line 428, in emu_start raise UcError(status) unicorn.unicorn.UcError: Invalid memory read (UC_ERR_READ_UNMAPPED) python-BaseException

    Process finished with exit code 1

    opened by chinaDL 28
  • feat(r2): human-friendly disassembler

    feat(r2): human-friendly disassembler

    Checklist

    Which kind of PR do you create?

    • [ ] This PR only contains minor fixes.
    • [x] This PR contains major feature update.
    • [x] This PR introduces a new function/api for Qiling Framework.

    Coding convention?

    • [x] The new code conforms to Qiling Framework naming convention.
    • [x] The imports are arranged properly.
    • [x] Essential comments are added.
    • [] The reference of the new code is pointed out.

    Extra tests?

    • [ ] No extra tests are needed for this PR.
    • [ ] I have added enough tests for this PR.
    • [x] Tests will be added after some discussion and review.

    Changelog?

    • [ ] This PR doesn't need to update Changelog.
    • [x] Changelog will be updated after some proper review.
    • [ ] Changelog has been updated in my PR.

    Target branch?

    • [x] The target branch is dev branch.

    One last thing


    This is part of the further work discussed in #1172 r2 has pD to disassemble N bytes and pd to disassemble N instructions directly. Though the latter may be used more often, counting bytes is more compatible with the callback type ql.hook_code() expects, like QlArchUtils.disassembler.

    Now there is no change in qiling core, so the code looks a bit ugly. If we can integrate r2 into qiling, the feature can be implemented with only a few lines and no attention of users.

    opened by chinggg 27
  • double print in log file

    double print in log file

    test case will be with netgear in example

    with multithread = Faslse and contain fork

    @ucgJhe will you be able to help ?

    close(6) = 0
    close(6) = 0
    fcntl(4, 6) = 0
    fcntl(4, 6) = 0
    close(4) = 0
    close(4) = 0
    
    write(1,7fd71458,2173) = 0
    
    write(1,7fd71458,2173) = 0
    write(1,7fd71458,2173) = -1
    write(1,7fd71458,2173) = -1
    [!] SYSCALL ERROR: ql_syscall_write
    [!] SYSCALL ERROR: ql_syscall_write
    [!] SYSCALL ERROR: ql_syscall_execve
    [!] SYSCALL ERROR: ql_syscall_execve
    
    opened by xwings 26
  • How can I have buffer overflows (Invalid memory fetch) fail gracefully? I already tried hooking.

    How can I have buffer overflows (Invalid memory fetch) fail gracefully? I already tried hooking.

    I wanted to test using qiling for exploitation development. So I'm passing a cyclic buffer to the program to generate a buffer overflow. A core file gets generated upon the crash, but I can't seem to figure out how to make it fail gracefully so that I can analyze the register states (core file) after the program crashes:

    from cyclic import cyclic, cyclic_find
    
    # Qiling
    # Full system emulation
    from qiling import *
    
    
    buffer = cyclic(50, n=4)
    print(f'generated cyclic buffer: {buffer}')
    
    # pass it to program for an overflow
    BIN_PATH = ["exploit_this", buffer]
    ENV = "../examples/rootfs/x86_linux"
    
    ql = Qiling(BIN_PATH, ENV)
    
    def dissassem(ql, address, size):
        buf = ql.mem.read(address, size)
        for i in md.disasm(buf, address):
            print("0x%x:\t%s\t%s" %(i.address, i.mnemonic, i.op_str))
    
    def dump_regs(ql, int_code):
        print(f'registers:')
        for reg_key in ql.reg.register_mapping:
            print(f'{reg_key.upper()}: {ql.reg.read(reg_key.upper())}')
    
    # ql.hook_code(dissassem)
    ql.hook_intr(dump_regs)
    ql.hook_mem_unmapped(dump_regs)
    ql.hook_mem_read_invalid(dump_regs)
    ql.hook_mem_write_invalid(dump_regs)
    ql.hook_mem_fetch_invalid(dump_regs)
    ql.hook_mem_invalid(dump_regs)
    ql.run()
    this_reg_was_tainted = ql.reg.read("EAX")
    print(f'EAX: {this_reg_was_tainted}')
    offset = cyclic_find(this_reg_was_tainted)
    # now we know where to insert a payload
    
    [+] Buffer: aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaama
    [=]	write(fd = 0x1, buf = 0x804d160, count = 0x3f) = 0x3f
    registers:
    AH: 0
    AL: 63
    CH: 209
    CL: 96
    DH: 0
    DL: 63
    BH: 0
    BL: 1
    AX: 63
    CX: 53600
    DX: 63
    BX: 1
    SP: 51100
    BP: 32128
    SI: 53600
    DI: 63
    IP: 44114
    EAX: 63
    ECX: 134533472
    EDX: 63
    EBX: 1
    ESP: 2146682780
    EBP: 2003402112
    ESI: 134533472
    EDI: 63
    EIP: 75213906
    CR0: 17
    CR1: 0
    CR2: 0
    CR3: 0
    CR4: 0
    CR8: 0
    ST0: 0
    ST1: 0
    ST2: 0
    ST3: 0
    ST4: 0
    ST5: 0
    ST6: 0
    ST7: 0
    EF: 68
    CS: 27
    SS: 40
    DS: 40
    ES: 40
    FS: 0
    GS: 99
    [x]	CPU Context:
    [x]	ah	: 0x0
    [x]	al	: 0x3f
    [x]	ch	: 0x0
    [x]	cl	: 0x0
    [x]	dh	: 0x88
    [x]	dl	: 0x90
    [x]	bh	: 0x61
    [x]	bl	: 0x61
    [x]	ax	: 0x3f
    [x]	cx	: 0x0
    [x]	dx	: 0x8890
    [x]	bx	: 0x6161
    [x]	sp	: 0xce20
    [x]	bp	: 0x6161
    [x]	si	: 0x7000
    [x]	di	: 0x0
    [x]	ip	: 0x6161
    [x]	eax	: 0x3f
    [x]	ecx	: 0x0
    [x]	edx	: 0x77698890
    [x]	ebx	: 0x61696161
    [x]	esp	: 0x7ff3ce20
    [x]	ebp	: 0x616a6161
    [x]	esi	: 0x77697000
    [x]	edi	: 0x0
    [x]	eip	: 0x616b6161
    [x]	cr0	: 0x11
    [x]	cr1	: 0x0
    [x]	cr2	: 0x0
    [x]	cr3	: 0x0
    [x]	cr4	: 0x0
    [x]	cr8	: 0x0
    [x]	st0	: 0x0
    [x]	st1	: 0x0
    [x]	st2	: 0x0
    [x]	st3	: 0x0
    [x]	st4	: 0x0
    [x]	st5	: 0x0
    [x]	st6	: 0x0
    [x]	st7	: 0x0
    [x]	ef	: 0x4
    [x]	cs	: 0x1b
    [x]	ss	: 0x28
    [x]	ds	: 0x28
    [x]	es	: 0x28
    [x]	fs	: 0x0
    [x]	gs	: 0x63
    [x]	PC = 0x616b6161 (unreachable)
    
    [=]	Memory map:
    [=]	Start      End        Perm    Label          Image
    [=]	00030000 - 00031000   rwx     [GDT]          exploit_this
    [=]	047ba000 - 047e2000   rwx     /home/student/synthesis/examples/rootfs/x86_linux/lib/ld-linux.so.2   exploit_this
    [=]	08048000 - 08049000   r-x     exploit_this   exploit_this
    [=]	08049000 - 0804b000   rw-     exploit_this   exploit_this
    [=]	0804b000 - 0804d000   rwx     [hook_mem]     
    [=]	0804d000 - 0806e000   rwx     [brk]          
    [=]	0806e000 - 0806f000   rwx     [brk]          
    [=]	774bf000 - 7769b000   rwx     [syscall_mmap2]   
    [=]	774bf000 - 7769b000   rwx     [mmap2] /home/student/synthesis/reverse/../examples/rootfs/x86_linux/lib/libc.so.6   
    [=]	77695000 - 77698000   rwx     [mmap2] /home/student/synthesis/reverse/../examples/rootfs/x86_linux/lib/libc.so.6   
    [=]	7769b000 - 7769d000   rwx     [syscall_mmap2]   
    [=]	7ff0d000 - 7ff3d000   rwx     [stack]        
    Traceback (most recent call last):
      File "reverse.py", line 34, in <module>
        ql.run()
      File "/usr/local/lib/python3.6/dist-packages/qiling/core.py", line 707, in run
        self.os.run()
      File "/usr/local/lib/python3.6/dist-packages/qiling/os/linux/linux.py", line 139, in run
        self.ql.emu_start(self.ql.loader.elf_entry, self.exit_point, self.ql.timeout, self.ql.count)
      File "/usr/local/lib/python3.6/dist-packages/qiling/core.py", line 867, in emu_start
        self.uc.emu_start(begin, end, timeout, count)
      File "/usr/local/lib/python3.6/dist-packages/unicorn/unicorn.py", line 465, in emu_start
        raise UcError(status)
    unicorn.unicorn.UcError: Invalid memory fetch (UC_ERR_FETCH_UNMAPPED)
    

    You can see in the core file dumped during the crash, the EIP value 0x616b6161 is my buffer overflow, but in the last hooked handler the EIP isnt set to that, so I never have access to a crashed instance of the registers.

    Is there something else I need to do to prevent the python code from throwing an error when the emulated program crashes after an invalid memory fetch? I thought just hooking the invalid fetch would work but that hook doesn't even seem to trigger.

    opened by jt0dd 25
  • Ref to #296

    Ref to #296 "Error while trying Demo "Emulating ARM router firmware on Ubuntu X64 machine""

    Hi, I am also currently facing the same issue when trying to emulate ARM router firmware and would like some help.

    I am currently using Ubuntu 18.04.4 LTS to host Qiling and the router firmware that I'm using is Tenda AC15 Firmware V15.03.1.17_EN.

    Here is my current code:

    import sys
    sys.path.append("..")
    from qiling import *
    def my_sandbox(path, rootfs):
        ql = Qiling(path, rootfs, stdin = sys.stdin, stdout = sys.stdout, stderr = sys.stderr)
        # Patch 0x00005930 from br0 to ens33
        ql.patch(0x00005930, b'ens33\x00', file_name = b'libChipApi.so')
        #ql.root = False
        ql.run()
    
    
    if __name__ == "__main__":
        my_sandbox(["rootfs/tenda-15.03.1.17/bin/httpd"], "rootfs/tenda-15.03.1.17")
    

    To ensure that I am patching at the correct address, below is a screenshot of the hexdump command. image

    Here are the network interfaces that I currently have and I am using ens33 as my preferred interface. image

    However, I still get the same error message like #296 . Firstly, it says that there is an Emulation Error. image

    Followed by a syscall error where it failed to patch "libChipApi.so" and there is an “Invalid memory write (UC_ERR_WRITE_UNMAPPED)” error.

    image

    Finally the program exits itself. image

    I've also tried using the other 2 network interfaces but it did not work too. Is there anything else I should look out for? I was also wondering if it could be due to a missing syscall? Thank you.

    opened by dozenmatter 25
  • Ret main

    Ret main

    Currently, qiling raises errors when main returns (on windows PE binaries), however on windows this gracefully exits the current thread.

    To emulate this behavior, a sentinel is allocated, and the address to this is stored on the stack when emulating a windows executable. Since threading does not seem complete yet, for now emulation just halts when the sentinel is hit.

    Additionally, the sentinel address is stored in the loader, so that it can be used for other exit points as well

    32 and 64 bit testcases are included.

    opened by learn-more 23
  • Error while trying Demo

    Error while trying Demo "Emulating ARM router firmware on Ubuntu X64 machine"

    Hi, I tried exploring Qiling. Tried with the demo "Emulating ARM router firmware on Ubuntu X64 machine" as given on https://docs.qiling.io/en/latest/demo/#emulating-arm-router-firmware-on-ubuntu-x64-machine I downloaded the tenda firmware version AC15 Firmware V15.03.1.16_EN from https://www.tendacn.com/en/download/detail-2600.html

    And ran the same script as given in the Demo in the doc

    from qiling import *
    def my_sandbox(path, rootfs):
        ql = Qiling(path, rootfs, stdin = sys.stdin, stdout = sys.stdout, stderr = sys.stderr)
        # Patch 0x00005930 from br0 to ens33
        ql.patch(0x00005930, b'ens33\x00', file_name = b'libChipApi.so')
        ql.root = False
        ql.run()
    
    
    if __name__ == "__main__":
        my_sandbox(["rootfs/tendaac15/bin/httpd"], "rootfs/tendaac15")
    

    I am getting Invalid memory write error as in attached screenshot below Selection_164

    I suppose there might be some mem_map error, but I don't know how to deal with it. Any supportive guidance would be helpful for me to explore it further.

    Thanks Asmita

    opened by asmitaj08 20
  • Rewrite in Rust

    Rewrite in Rust

    Python is a poor choice for anything remotely complex, especially that affects the execution times like emulation. Projects like Angr and Miasm met a bottleneck of Python, it's slowness, GIL, memory hunger, and poor parallelism. On the other hand, reimplementing most of the code in Rust will still allow to provide Python interface, see Rust-Python example.

    opened by XVilka 19
  • memory management API request

    memory management API request

    As per our discussion, this section will be in qiling/os/memory.py

        def add_mapinfo(self, mem_s, mem_e, mem_p, mem_info):
            tmp_map_info = []
            insert_flag = 0
            map_info = self.map_info
            if len(map_info) == 0:
                tmp_map_info.append([mem_s, mem_e, mem_p, mem_info])
            else:
                for s, e, p, info in map_info:
                    if e <= mem_s:
                        tmp_map_info.append([s, e, p, info])
                        continue
                    if s >= mem_e:
                        if insert_flag == 0:
                            insert_flag = 1
                            tmp_map_info.append([mem_s, mem_e, mem_p, mem_info])
                        tmp_map_info.append([s, e, p, info])
                        continue
                    if s < mem_s:
                        tmp_map_info.append([s, mem_s, p, info])
    
                    if s == mem_s:
                        pass
    
                    if insert_flag == 0:
                        insert_flag = 1
                        tmp_map_info.append([mem_s, mem_e, mem_p, mem_info])
    
                    if e > mem_e:
                        tmp_map_info.append([mem_e, e, p, info])
    
                    if e == mem_e:
                        pass
                if insert_flag == 0:
                    tmp_map_info.append([mem_s, mem_e, mem_p, mem_info])
            map_info = []
            map_info.append(tmp_map_info[0])
    
            for s, e, p, info in tmp_map_info[1:]:
                if s == map_info[-1][1] and info == map_info[-1][3] and p == map_info[-1][2]:
                    map_info[-1][1] = e
                else:
                    map_info.append([s, e, p, info])
    
            self.map_info = map_info
    
    
        def del_mapinfo(self, mem_s, mem_e):
            tmp_map_info = []
    
            for s, e, p, info in self.map_info:
                if e <= mem_s:
                    tmp_map_info.append([s, e, p, info])
                    continue
    
                if s >= mem_e:
                    tmp_map_info.append([s, e, p, info])
                    continue
    
                if s < mem_s:
                    tmp_map_info.append([s, mem_s, p, info])
    
                if s == mem_s:
                    pass
    
                if e > mem_e:
                    tmp_map_info.append([mem_e, e, p, info])
    
                if e == mem_e:
                    pass
    
            self.map_info = tmp_map_info
    
    
        def show_mapinfo(self):
            self.ql.nprint("[+] Start      End        Perm.  Path\n")
            for s, e, p, info in self.map_info:
                self.ql.nprint("[+] %08x - %08x - %s    %s\n" % (s, e, p, info))
    
    
        def get_lib_base(self, filename):
            for s, e, p, info in self.map_info:
                if os.path.split(info)[1] == filename:
                    return s
            return -1
    
    
        def _align(self, addr, alignment=0x1000):
            # rounds up to nearest alignment
            mask = ((1 << self.ql.archbit) - 1) & -alignment
            return (addr + (alignment - 1)) & mask
    
    
    
        def read(self, addr: int, size: int) -> bytearray:
            return self.ql.uc.mem_read(addr, size)
    
    
        def write(self, addr: int, data: bytes) -> None:
            return self.ql.uc.mem_write(addr, data)
    
    
        def unmap(self, addr, size) -> None:
            '''
            The main function of mem_unmap is to reclaim memory.
            This function will reclaim the memory starting with addr and length of size.
            Upon successful completion, munmap() shall return 0; 
            otherwise, it shall return -1 and set errno to indicate the error.
            '''        
            return self.ql.uc.mem_unmap(addr, size)
    
    
        def unmap_all(self):
            for region in list(self.ql.uc.mem_regions()):
                print("start 0x%x end 0x%x"% (region[0],(region[1] - region[0])+0x1))
                if region[0] and region[1]:
                    return self.unmap(region[0], ((region[1] - region[0])+0x1))
    
    
        def is_available(self, addr, size):
            '''
            The main function of is_available is to determine 
            whether the memory starting with addr and having a size of length can be used for allocation.
    
            If it can be allocated, returns True.
    
            If it cannot be allocated, it returns False.
            '''
            try:
                self.map(addr, addr)
            except:
                return False    
            
            self.unmap(addr, addr)
            return True
    
    
        def is_mapped(self, address, size): 
            '''
            The main function of is_mmaped is to determine 
            whether the memory starting with addr and size has been mapped.
            Returns true if it has already been allocated.
            If unassigned, returns False.
            '''   
            for region in list(self.ql.uc.mem_regions()):
                if address >= region[0] and (address + size -1) <= region[1]:
                    return True
    
            return False
            
        
        def is_free(self, address, size):
            '''
            The main function of is_free first must fufull is_mapped condition.
            then, check for is the mapped range empty, either fill with 0xFF or 0x00
            Returns true if mapped range is empty else return Flase
            If not not mapped, map it and return true
            '''
            if self.is_mapped(address, size) == True:
                address_end = (address + size)
                while address < address_end:
                    mem_read = self.ql.mem.read(address, 0x1)
                    if (mem_read[0] != 0x00) and (mem_read[0] != 0xFF):
                        return False
                    address += 1
                return True
            else:
                return True
    
    
        def find_free_space(
            self, size, min_addr=0, max_addr = 0, alignment=0x10000
        ):
            """
            Finds a region of memory that is free, larger than 'size' arg,
            and aligned.
            """
            mapped = []
            
            for address_start, address_end, perm, info in self.ql.mem.map_info:
                mapped += [[address_start, (address_end - address_start)]]
            
            for address_start, address_end, perms in self.ql.uc.mem_regions():
                mapped += [[address_start, (address_end - address_start)]]
            
            for i in range(0, len(mapped)):
                addr = self._align(
                    mapped[i][0] + mapped[i][1], alignment=alignment
                )
                # Enable allocating memory in the middle of a gap when the
                # min requested address falls in the middle of a gap
                if addr < min_addr:
                    addr = min_addr
                # Cap the gap's max address by accounting for the next
                # section's start address, requested max address, and the
                # max possible address
    
                max_gap_addr = (
                    self.max_addr
                    if i == len(mapped) - 1
                    else mapped[i + 1][1]
                )
    
                max_gap_addr = min(max_gap_addr, self.max_mem_addr)
                # Ensure the end address is less than the max and the start
                # address is free
                if addr + size < max_gap_addr and self.is_mapped(addr, size) == False:
                    return addr
            raise QlOutOfMemory("[!] Out Of Memory")
    
    
        def map_anywhere(
            self,
            size,
            #name = "",
            #kind = "",
            min_addr = 0,
            alignment = 0x1000,
            #prot: int = ProtType.RWX,
        ) -> int:
            """
            Maps a region of memory with requested size, within the
            addresses specified. The size and start address will respect the
            alignment.
    
            Args:
                size: # of bytes to map. This will be rounded up to match
                    the alignment.
                name: String used to identify mapped region. Used for
                    debugging.
                kind: String used to identify the purpose of the mapped
                    region. Used for debugging.
                min_addr: The lowest address that could be mapped.
                max_addr: The highest address that could be mapped.
                alignment: Ensures the size and start address are multiples
                    of this. Must be a multiple of 0x1000. Default 0x1000.
                prot: RWX permissions of the mapped region. Defaults to
                    granting all permissions.
            Returns:
                Start address of mapped region.
            """
            max_mem_addr = self.max_mem_addr
            address = self.find_free_space(
                size, min_addr=min_addr, max_addr=max_mem_addr, alignment=alignment
            )
            """
            we need a better mem_map as defined in the issue
            """
            #self.map(address, util.align(size), name, kind)
            self.map(address, self._align(size))
            return address
    
        def protect(self, addr, size, perms):
            aligned_address = addr & 0xFFFFF000  # Address needs to align with
            aligned_size = self._align((addr & 0xFFF) + size)
            self.ql.uc.mem_protect(aligned_address, aligned_size, perms)
    
    
        def map(self, addr, size, perms=UC_PROT_ALL, ptr = None):
            '''
    	    The main function of mem_mmap is to implement memory allocation in unicorn, 
    	    which is slightly similar to the function of syscall_mmap. 
    
    	    When the memory can satisfy the given addr and size, 
    	    it needs to be allocated to the corresponding address space.
    	    
    	    Upon successful completion, mem_map() shall return 0; 
    
        	otherwise, it shall return -1 and set errno to indicate the error.
             
            is should call other API to get_available mainly gives a length, 
            and then the memory manager returns  an address that can apply for that length.
    
            '''
            if ptr == None:
                if self.is_mapped(addr, size) == False:
                   self.ql.uc.mem_map(addr, size)
                else:
                    raise QlMemoryMappedError("[!] Memory Mapped")    
                
                if perms != UC_PROT_ALL:
                    self.protect(addr, size, perms)
            else:
                self.ql.uc.mem_map_ptr(addr, size, perms, ptr)
    
    documentation 
    opened by xwings 19
  • remove redundant ip converting

    remove redundant ip converting

    as title.

    and does this confusing you guys ?

    ...
    bind(3,:::8080,28) = -1
    [+] syscall bind host: :: and port: 8080 sin_family: 10
    socket(2, 1, 0) = 4
    fcntl64(4, 2, 1) = 0
    setsockopt
    bind(4,0.0.0.0:8080,16) = 0
    [+] syscall bind host: 0.0.0.0 and port: 8080 sin_family: 2
    ...
    

    maybe ipv6 localhost should be printed in a more explicit way

    opened by ucgJhe 19
  • Fix ELF argv encoding

    Fix ELF argv encoding

    Changed ELF argv encoding from "utf-8" to "latin" to avoid corruption of specially crafted command line arguments (more details in the fixed issue).

    Fixes #1269

    opened by elicn 0
  • can I boot a kernel with qiling?

    can I boot a kernel with qiling?

    If I have a linux kernel image with ramfs inside. And I hook the io exception to handle the serial port output and input (for example, uart8250). In this way I don't need to simulate a hard drive. Can I boot this kernel and get a bash console by using qiling?

    My question is: Does qiling support full system simulation if everything is handled properly? if not, what is missed?

    opened by XinDistance 0
  • Update Qiling to work within Ghidra (using Ghidrathon)

    Update Qiling to work within Ghidra (using Ghidrathon)

    First, thank you creating qiling. It is an amazing capability to automate analysis.

    Is your feature request related to a problem? Please describe. Currently I cannot run qiling within Ghidra using Ghidrathon.

    Describe the solution you'd like A partial solution is to add a try/except statement similar to the one for IDAPython in qiling/os/os.py. As a test, I replaced import ida_idaapi with import ghidra in os.py and I was able to run Qiling within Ghidra using Ghidrathon. However, I could only run a script once. If I attempted to run the same script again, I received an error:

    image

    Unfortunately I'm not sure how this error can be resolved.

    Thank you for your help.

    opened by as0ni 1
  • Clear memory before restore.

    Clear memory before restore.

    This fixes #1136 by unmapping everything before applying the restore operation. This will make sure that after a restore, the memory state will be exactly the same as it was when the memory's save method was called.

    Checklist

    Which kind of PR do you create?

    • [x] This PR only contains minor fixes.
    • [ ] This PR contains major feature update.
    • [ ] This PR introduces a new function/api for Qiling Framework.

    Coding convention?

    • [x] The new code conforms to Qiling Framework naming convention.
    • [x] The imports are arranged properly.
    • [x] Essential comments are added.
    • [x] The reference of the new code is pointed out.

    Extra tests?

    • [x] No extra tests are needed for this PR.
    • [ ] I have added enough tests for this PR.
    • [ ] Tests will be added after some discussion and review.

    Changelog?

    • [ ] This PR doesn't need to update Changelog.
    • [ ] Changelog will be updated after some proper review.
    • [ ] Changelog has been updated in my PR.

    Target branch?

    • [x] The target branch is dev branch.

    One last thing


    opened by LukeSerne 2
  • Do not support epoll mode

    Do not support epoll mode

    When I tried to emulate an epoll-mode program which is on linux-c mipsel, the qiling engine came up with this:

    [!] 	0x90083df4: syscall ql_syscall_epoll_create number = 0x1098(4248) not implemented
    [=] 	fcntl64(fd = 0x3, cmd = 0x3, arg = 0x0) = 0x2
    [=] 	fcntl64(fd = 0x3, cmd = 0x4, arg = 0x82) = 0x0
    [!] 	0x90083e6c: syscall ql_syscall_epoll_ctl number = 0x1099(4249) not implemented
    [=] 	rt_sigaction(signum = 0x2, act = 0x7ff3cc40, oldact = 0x9003ebc8) = 0x0
    [=] 	rt_sigaction(signum = 0x12, act = 0x7ff3cc40, oldact = 0x9003ebe4) = 0x0
    [=] 	clock_gettime(clock_id = 0x1, tp = 0x7ff3cc60) = 0x0
    [Hit] waitpid
    [=] 	my_waitpid(pid = 0xffffffff, wstatus = 0x7ff3cc88, options = 0x1) = 0x0
    [=] 	clock_gettime(clock_id = 0x1, tp = 0x7ff3cc60) = 0x0
    [!] 	0x90083ee8: syscall ql_syscall_epoll_wait number = 0x109a(4250) not implemented
    

    So I properly need to implement this by myself if I want to make through this

    opened by squarepants0 1
  • Simple 32bit C binary has invalid memory write

    Simple 32bit C binary has invalid memory write

    I've written a simple C binary like so:

    #include <stdio.h>
    
    int main() {
        printf("hi!");
        return 0;
    }
    

    I compiled it with gcc -m32 -o test test.c

    My qiling script loads the binary like this:

    from qiling import *
    from qiling.const import *
    
    rootfs = '/mnt/d/rootfs/x86_linux'
    ql = Qiling(['./test'], rootfs, archtype='x86', ostype='Linux', verbose=QL_VERBOSE.DEBUG)
    
    ql.run()
    

    I execute the script with python3 test.py.

    Results:

    [+]     Profile: default
    [+]     Mapping GDT at 0x30000 with limit 0x1000
    [+]     Mapped 0x56555000-0x56556000
    [+]     Mapped 0x56556000-0x56557000
    [+]     Mapped 0x56557000-0x56558000
    [+]     Mapped 0x56558000-0x5655a000
    [+]     mem_start : 0x56555000
    [+]     mem_end   : 0x5655a000
    [+]     Interpreter path: /mnt/d/rootfs/x86_linux/lib/ld-linux.so.2
    [+]     Interpreter addr: 0x47ba000
    [+]     Mapped 0x47ba000-0x47e0000
    [+]     Mapped 0x47e0000-0x47e2000
    [+]     mmap_address is : 0x90000000
    [+]     rel name b'_ITM_deregisterTMCloneTable'
    [+]     rel name b'__cxa_finalize'
    [+]     rel name b'__gmon_start__'
    [+]     rel name b'_ITM_registerTMCloneTable'
    [+]     rel name b'__libc_start_main'
    [+]     rel name b'printf'
    [+]     Received interrupt: 0x80
    [+]     0x047d32c7: brk(inp = 0x0) = 0x5655c000
    [+]     Received interrupt: 0x80
    [+]     0x047d484d: uname(buf = 0x7ff3caca) = 0x0
    [+]     Received interrupt: 0x80
    [+]     No such file or directory: /etc/ld.so.nohwcap
    [+]     0x047c8946: access(path = 0x47d7203, mode = 0x0) = -0x1 (EPERM)
    [+]     Received interrupt: 0x80
    [+]     No such file or directory: /etc/ld.so.preload
    [+]     0x047d468b: access(path = 0x47d891c, mode = 0x4) = -0x1 (EPERM)
    [+]     Received interrupt: 0x80
    [+]     openat(fd = -100, path = /etc/ld.so.cache, mode = 0o0) = -2
    [+]     0x047d44b7: openat(fd = 0xffffff9c, path = 0x47d759b, flags = 0x80000, mode = 0x0) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     openat(fd = -100, path = /lib/i386-linux-gnu/tls/i686/sse2/libc.so.6, mode = 0o0) = -2
    [+]     0x047d44b7: openat(fd = 0xffffff9c, path = 0x7ff3c6f0, flags = 0x80000, mode = 0x0) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     stat64("/lib/i386-linux-gnu/tls/i686/sse2", 0x7ff3c770) read/write fail
    [+]     0x047d43db: stat64(path = 0x7ff3c6f0, buf_ptr = 0x7ff3c770) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     openat(fd = -100, path = /lib/i386-linux-gnu/tls/i686/libc.so.6, mode = 0o0) = -2
    [+]     0x047d44b7: openat(fd = 0xffffff9c, path = 0x7ff3c6f0, flags = 0x80000, mode = 0x0) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     stat64("/lib/i386-linux-gnu/tls/i686", 0x7ff3c770) read/write fail
    [+]     0x047d43db: stat64(path = 0x7ff3c6f0, buf_ptr = 0x7ff3c770) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     openat(fd = -100, path = /lib/i386-linux-gnu/tls/sse2/libc.so.6, mode = 0o0) = -2
    [+]     0x047d44b7: openat(fd = 0xffffff9c, path = 0x7ff3c6f0, flags = 0x80000, mode = 0x0) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     stat64("/lib/i386-linux-gnu/tls/sse2", 0x7ff3c770) read/write fail
    [+]     0x047d43db: stat64(path = 0x7ff3c6f0, buf_ptr = 0x7ff3c770) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     openat(fd = -100, path = /lib/i386-linux-gnu/tls/libc.so.6, mode = 0o0) = -2
    [+]     0x047d44b7: openat(fd = 0xffffff9c, path = 0x7ff3c6f0, flags = 0x80000, mode = 0x0) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     stat64("/lib/i386-linux-gnu/tls", 0x7ff3c770) read/write fail
    [+]     0x047d43db: stat64(path = 0x7ff3c6f0, buf_ptr = 0x7ff3c770) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     openat(fd = -100, path = /lib/i386-linux-gnu/i686/sse2/libc.so.6, mode = 0o0) = -2
    [+]     0x047d44b7: openat(fd = 0xffffff9c, path = 0x7ff3c6f0, flags = 0x80000, mode = 0x0) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     stat64("/lib/i386-linux-gnu/i686/sse2", 0x7ff3c770) read/write fail
    [+]     0x047d43db: stat64(path = 0x7ff3c6f0, buf_ptr = 0x7ff3c770) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     openat(fd = -100, path = /lib/i386-linux-gnu/i686/libc.so.6, mode = 0o0) = -2
    [+]     0x047d44b7: openat(fd = 0xffffff9c, path = 0x7ff3c6f0, flags = 0x80000, mode = 0x0) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     stat64("/lib/i386-linux-gnu/i686", 0x7ff3c770) read/write fail
    [+]     0x047d43db: stat64(path = 0x7ff3c6f0, buf_ptr = 0x7ff3c770) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     openat(fd = -100, path = /lib/i386-linux-gnu/sse2/libc.so.6, mode = 0o0) = -2
    [+]     0x047d44b7: openat(fd = 0xffffff9c, path = 0x7ff3c6f0, flags = 0x80000, mode = 0x0) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     stat64("/lib/i386-linux-gnu/sse2", 0x7ff3c770) read/write fail
    [+]     0x047d43db: stat64(path = 0x7ff3c6f0, buf_ptr = 0x7ff3c770) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     openat(fd = -100, path = /lib/i386-linux-gnu/libc.so.6, mode = 0o0) = -2
    [+]     0x047d44b7: openat(fd = 0xffffff9c, path = 0x7ff3c6f0, flags = 0x80000, mode = 0x0) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     stat64("/lib/i386-linux-gnu", 0x7ff3c770) read/write fail
    [+]     0x047d43db: stat64(path = 0x7ff3c6f0, buf_ptr = 0x7ff3c770) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     openat(fd = -100, path = /usr/lib/i386-linux-gnu/tls/i686/sse2/libc.so.6, mode = 0o0) = -2
    [+]     0x047d44b7: openat(fd = 0xffffff9c, path = 0x7ff3c6f0, flags = 0x80000, mode = 0x0) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     stat64("/usr/lib/i386-linux-gnu/tls/i686/sse2", 0x7ff3c770) read/write fail
    [+]     0x047d43db: stat64(path = 0x7ff3c6f0, buf_ptr = 0x7ff3c770) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     openat(fd = -100, path = /usr/lib/i386-linux-gnu/tls/i686/libc.so.6, mode = 0o0) = -2
    [+]     0x047d44b7: openat(fd = 0xffffff9c, path = 0x7ff3c6f0, flags = 0x80000, mode = 0x0) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     stat64("/usr/lib/i386-linux-gnu/tls/i686", 0x7ff3c770) read/write fail
    [+]     0x047d43db: stat64(path = 0x7ff3c6f0, buf_ptr = 0x7ff3c770) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     openat(fd = -100, path = /usr/lib/i386-linux-gnu/tls/sse2/libc.so.6, mode = 0o0) = -2
    [+]     0x047d44b7: openat(fd = 0xffffff9c, path = 0x7ff3c6f0, flags = 0x80000, mode = 0x0) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     stat64("/usr/lib/i386-linux-gnu/tls/sse2", 0x7ff3c770) read/write fail
    [+]     0x047d43db: stat64(path = 0x7ff3c6f0, buf_ptr = 0x7ff3c770) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     openat(fd = -100, path = /usr/lib/i386-linux-gnu/tls/libc.so.6, mode = 0o0) = -2
    [+]     0x047d44b7: openat(fd = 0xffffff9c, path = 0x7ff3c6f0, flags = 0x80000, mode = 0x0) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     stat64("/usr/lib/i386-linux-gnu/tls", 0x7ff3c770) read/write fail
    [+]     0x047d43db: stat64(path = 0x7ff3c6f0, buf_ptr = 0x7ff3c770) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     openat(fd = -100, path = /usr/lib/i386-linux-gnu/i686/sse2/libc.so.6, mode = 0o0) = -2
    [+]     0x047d44b7: openat(fd = 0xffffff9c, path = 0x7ff3c6f0, flags = 0x80000, mode = 0x0) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     stat64("/usr/lib/i386-linux-gnu/i686/sse2", 0x7ff3c770) read/write fail
    [+]     0x047d43db: stat64(path = 0x7ff3c6f0, buf_ptr = 0x7ff3c770) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     openat(fd = -100, path = /usr/lib/i386-linux-gnu/i686/libc.so.6, mode = 0o0) = -2
    [+]     0x047d44b7: openat(fd = 0xffffff9c, path = 0x7ff3c6f0, flags = 0x80000, mode = 0x0) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     stat64("/usr/lib/i386-linux-gnu/i686", 0x7ff3c770) read/write fail
    [+]     0x047d43db: stat64(path = 0x7ff3c6f0, buf_ptr = 0x7ff3c770) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     openat(fd = -100, path = /usr/lib/i386-linux-gnu/sse2/libc.so.6, mode = 0o0) = -2
    [+]     0x047d44b7: openat(fd = 0xffffff9c, path = 0x7ff3c6f0, flags = 0x80000, mode = 0x0) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     stat64("/usr/lib/i386-linux-gnu/sse2", 0x7ff3c770) read/write fail
    [+]     0x047d43db: stat64(path = 0x7ff3c6f0, buf_ptr = 0x7ff3c770) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     openat(fd = -100, path = /usr/lib/i386-linux-gnu/libc.so.6, mode = 0o0) = -2
    [+]     0x047d44b7: openat(fd = 0xffffff9c, path = 0x7ff3c6f0, flags = 0x80000, mode = 0x0) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     stat64("/usr/lib/i386-linux-gnu", 0x7ff3c770) read/write fail
    [+]     0x047d43db: stat64(path = 0x7ff3c6f0, buf_ptr = 0x7ff3c770) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     openat(fd = -100, path = /lib/tls/i686/sse2/libc.so.6, mode = 0o0) = -2
    [+]     0x047d44b7: openat(fd = 0xffffff9c, path = 0x7ff3c6f0, flags = 0x80000, mode = 0x0) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     stat64("/lib/tls/i686/sse2", 0x7ff3c770) read/write fail
    [+]     0x047d43db: stat64(path = 0x7ff3c6f0, buf_ptr = 0x7ff3c770) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     openat(fd = -100, path = /lib/tls/i686/libc.so.6, mode = 0o0) = -2
    [+]     0x047d44b7: openat(fd = 0xffffff9c, path = 0x7ff3c6f0, flags = 0x80000, mode = 0x0) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     stat64("/lib/tls/i686", 0x7ff3c770) read/write fail
    [+]     0x047d43db: stat64(path = 0x7ff3c6f0, buf_ptr = 0x7ff3c770) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     openat(fd = -100, path = /lib/tls/sse2/libc.so.6, mode = 0o0) = -2
    [+]     0x047d44b7: openat(fd = 0xffffff9c, path = 0x7ff3c6f0, flags = 0x80000, mode = 0x0) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     stat64("/lib/tls/sse2", 0x7ff3c770) read/write fail
    [+]     0x047d43db: stat64(path = 0x7ff3c6f0, buf_ptr = 0x7ff3c770) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     openat(fd = -100, path = /lib/tls/libc.so.6, mode = 0o0) = -2
    [+]     0x047d44b7: openat(fd = 0xffffff9c, path = 0x7ff3c6f0, flags = 0x80000, mode = 0x0) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     stat64("/lib/tls", 0x7ff3c770) read/write fail
    [+]     0x047d43db: stat64(path = 0x7ff3c6f0, buf_ptr = 0x7ff3c770) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     openat(fd = -100, path = /lib/i686/sse2/libc.so.6, mode = 0o0) = -2
    [+]     0x047d44b7: openat(fd = 0xffffff9c, path = 0x7ff3c6f0, flags = 0x80000, mode = 0x0) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     stat64("/lib/i686/sse2", 0x7ff3c770) read/write fail
    [+]     0x047d43db: stat64(path = 0x7ff3c6f0, buf_ptr = 0x7ff3c770) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     openat(fd = -100, path = /lib/i686/libc.so.6, mode = 0o0) = -2
    [+]     0x047d44b7: openat(fd = 0xffffff9c, path = 0x7ff3c6f0, flags = 0x80000, mode = 0x0) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     stat64("/lib/i686", 0x7ff3c770) read/write fail
    [+]     0x047d43db: stat64(path = 0x7ff3c6f0, buf_ptr = 0x7ff3c770) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     openat(fd = -100, path = /lib/sse2/libc.so.6, mode = 0o0) = -2
    [+]     0x047d44b7: openat(fd = 0xffffff9c, path = 0x7ff3c6f0, flags = 0x80000, mode = 0x0) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     stat64("/lib/sse2", 0x7ff3c770) read/write fail
    [+]     0x047d43db: stat64(path = 0x7ff3c6f0, buf_ptr = 0x7ff3c770) = -0x2 (ENOENT)
    [+]     Received interrupt: 0x80
    [+]     openat(fd = -100, path = /lib/libc.so.6, mode = 0o0) = 3
    [+]     0x047d44b7: openat(fd = 0xffffff9c, path = 0x7ff3c6f0, flags = 0x80000, mode = 0x0) = 0x3
    [+]     Received interrupt: 0x80
    [+]     read() CONTENT: b'\x7fELF\x01\x01\x01\x03\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x03\x00\x01\x00\x00\x00`\x17\x02\x004\x00\x00\x00\x90j"\x00\x00\x00\x00\x004\x00 \x00\r\x00(\x00?\x00>\x00\x06\x00\x00\x004\x00\x00\x004\x00\x00\x004\x00\x00\x00\xa0\x01\x00\x00\xa0\x01\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x03\x00\x00\x00\xa08\x1c\x00\xa08\x1c\x00\xa08\x1c\x00\x13\x00\x00\x00\x13\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xf8\x01\x00d\xf8\x01\x00\x04\x00\x00\x00\x00\x10\x00\x00\x01\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x02\x00\xe2\xdc\x17\x00\xe2\xdc\x17\x00\x05\x00\x00\x00\x00\x10\x00\x00\x01\x00\x00\x00\x00\xe0\x19\x00\x00\xe0\x19\x00\x00\xe0\x19\x00\xfcJ\x08\x00\xfcJ\x08\x00\x04\x00\x00\x00\x00\x10\x00\x00\x01\x00\x00\x00\x143"\x00\x14C"\x00\x14C"\x00\x04,\x00\x00\xa8\xc4\x00\x00\x06\x00\x00\x00\x00\x10\x00\x00\x02\x00\x00\x00\xacM"\x00\xac]"\x00\xac]"\x00\xe8\x00\x00\x00\xe8\x00\x00\x00\x06\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\xd4\x01\x00\x00\xd4\x01\x00\x00\xd4\x01\x00\x00`\x00\x00\x00`\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x07\x00\x00\x00\x143"\x00\x14C"\x00\x14C"\x00\x08\x00\x00\x00T\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00S\xe5td\x18\x02\x00\x00\x18\x02\x00\x00\x18\x02\x00\x00\x1c\x00\x00\x00\x1c\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00P\xe5td\xb48\x1c\x00\xb48\x1c\x00\xb48\x1c\x00\xec{\x00\x00\xec{\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00Q\xe5td\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00R\xe5td\x143"\x00\x14C"\x00\x14C"\x00\xec\x1c\x00\x00\xec\x1c\x00\x00\x04\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00\xf1\xd0\x8a9\x18\xf1\xa3\x8e\x9f\x08]\xfa\xdb9\xcf\x8a\xc2u\x0cj\x04\x00\x00\x00\x10\x00\x00\x00'
    [+]     0x047d4580: read(fd = 0x3, buf = 0x7ff3c840, length = 0x200) = 0x200
    [+]     Received interrupt: 0x80
    [+]     0x047d4619: _llseek(fd = 0x3, offset_high = 0x0, offset_low = 0x1d4, result = 0x7ff3c5f0, whence = 0x0) = 0x0
    [+]     Received interrupt: 0x80
    [+]     read() CONTENT: b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00\xf1\xd0\x8a9\x18\xf1\xa3\x8e\x9f\x08]\xfa\xdb9\xcf\x8a\xc2u\x0cj\x04\x00\x00\x00\x10\x00\x00\x00\x01\x00\x00\x00GNU\x00\x00\x00\x00\x00\x03\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x0c\x00\x00\x00\x05\x00\x00\x00GNU\x00\x02\x00\x00\xc0\x04\x00\x00\x00\x03\x00\x00\x00'
    [+]     0x047d4580: read(fd = 0x3, buf = 0x7ff3c620, length = 0x60) = 0x60
    [+]     Received interrupt: 0x80
    [+]     0x047d441b: fstat64(fd = 0x3, buf_ptr = 0x7ff3c770) = 0x0
    [+]     Received interrupt: 0x80
    [+]     mmap2 - mapping needed for 0x90000000
    [+]     mmap2 - addr range  0x90000000 - 0x90001fff: 
    [+]     0x047d47b0: mmap2(addr = 0x0, length = 0x2000, prot = 0x3, flags = 0x22, fd = 0xffffffff, pgoffset = 0x0) = 0x90000000
    [+]     Received interrupt: 0x80
    [+]     mmap2 - mapping needed for 0x90002000
    [+]     mmap2 - addr range  0x90002000 - 0x90232fff:
    [+]     mem write : 0x227468
    [+]     mem mmap  : /mnt/d/rootfs/x86_linux/lib/libc.so.6
    [+]     0x047d47b0: mmap2(addr = 0x0, length = 0x2307bc, prot = 0x1, flags = 0x802, fd = 0x3, pgoffset = 0x0) = 0x90002000
    [+]     Received interrupt: 0x80
    [+]     0x047d4824: mprotect(start = 0x90022000, mlen = 0x204000, prot = 0x0) = 0x0
    [+]     Received interrupt: 0x80
    [+]     mmap2 - MAP_FIXED, mapping not needed
    [+]     mem write : 0x17e000
    [+]     mem mmap  : /mnt/d/rootfs/x86_linux/lib/libc.so.6
    [+]     0x047d47b0: mmap2(addr = 0x90022000, length = 0x17e000, prot = 0x5, flags = 0x812, fd = 0x3, pgoffset = 0x20) = 0x90022000
    [+]     Received interrupt: 0x80
    [+]     mmap2 - MAP_FIXED, mapping not needed
    [+]     mem write : 0x85000
    [+]     mem mmap  : /mnt/d/rootfs/x86_linux/lib/libc.so.6
    [+]     0x047d47b0: mmap2(addr = 0x901a0000, length = 0x85000, prot = 0x1, flags = 0x812, fd = 0x3, pgoffset = 0x19e) = 0x901a0000
    [+]     Received interrupt: 0x80
    [+]     mmap2 - MAP_FIXED, mapping not needed
    [+]     mem write : 0x3000
    [+]     mem mmap  : /mnt/d/rootfs/x86_linux/lib/libc.so.6
    [+]     0x047d47b0: mmap2(addr = 0x90226000, length = 0x3000, prot = 0x3, flags = 0x812, fd = 0x3, pgoffset = 0x223) = 0x90226000
    [+]     Received interrupt: 0x80
    [+]     mmap2 - MAP_FIXED, mapping not needed
    [+]     0x047d47b0: mmap2(addr = 0x90229000, length = 0x97bc, prot = 0x3, flags = 0x32, fd = 0xffffffff, pgoffset = 0x0) = 0x90229000
    [+]     Received interrupt: 0x80
    [+]     0x047d4757: close(fd = 0x3) = 0x0
    [+]     Received interrupt: 0x80
    [+]     set_thread_area base : 0x90001000 limit is : 0xfffff
    [+]     0x047babdb: set_thread_area(u_info_addr = 0x7ff3cc50) = 0x0
    [+]     Received interrupt: 0x80
    [+]     0x047d4824: mprotect(start = 0x90226000, mlen = 0x2000, prot = 0x1) = 0x0
    [+]     Received interrupt: 0x80
    [+]     0x047d4824: mprotect(start = 0x56558000, mlen = 0x1000, prot = 0x1) = 0x0
    [+]     Received interrupt: 0x80
    [+]     0x047d4824: mprotect(start = 0x47e0000, mlen = 0x1000, prot = 0x1) = 0x0
    [+]     Received interrupt: 0x80
    [+]     getrandom() CONTENT: ff 68 9b be
    [+]     0x047bac52: getrandom(buf = 0x9022bb50, buflen = 0x4, flags = 0x1) = 0x4
    [+]     Received interrupt: 0x80
    [+]     mmap2 - mapping needed for 0x90233000
    [+]     mmap2 - addr range  0x90233000 - 0x90332fff:
    [+]     0x047bac52: mmap2(addr = 0x0, length = 0x100000, prot = 0x3, flags = 0x22, fd = 0xffffffff, pgoffset = 0x0) = 0x90233000
    [x]     CPU Context:
    [x]     ah      : 0x0
    [x]     al      : 0x0
    [x]     ch      : 0x75
    [x]     cl      : 0x20
    [x]     dh      : 0x75
    [x]     dl      : 0x89
    [x]     bh      : 0x80
    [x]     bl      : 0x0
    [x]     ax      : 0x0
    [x]     cx      : 0x7520
    [x]     dx      : 0x7589
    [x]     bx      : 0x8000
    [x]     sp      : 0xcda0
    [x]     bp      : 0x7156
    [x]     si      : 0x7156
    [x]     di      : 0x7589
    [x]     ip      : 0xc92d
    [x]     eax     : 0x0
    [x]     ecx     : 0x90237520
    [x]     edx     : 0x90237589
    [x]     ebx     : 0x90228000
    [x]     esp     : 0x7ff0cda0
    [x]     ebp     : 0x47d7156
    [x]     esi     : 0x47d7156
    [x]     edi     : 0x90237589
    [x]     eip     : 0x9016c92d
    [x]     cr0     : 0x11
    [x]     cr1     : 0x0
    [x]     cr2     : 0x0
    [x]     cr3     : 0x0
    [x]     cr4     : 0x0
    [x]     cr8     : 0x0
    [x]     st0     : 0x0
    [x]     st1     : 0x0
    [x]     st2     : 0x0
    [x]     st3     : 0x0
    [x]     st4     : 0x0
    [x]     st5     : 0x0
    [x]     st6     : 0x0
    [x]     st7     : 0x0
    [x]     eflags  : 0x6
    [x]     cs      : 0x1b
    [x]     ss      : 0x28
    [x]     ds      : 0x28
    [x]     es      : 0x28
    [x]     fs      : 0x0
    [x]     gs      : 0x63
    [x]     Hexdump:
    [x]     81 c3 d3 b6 0b 00 81 ec
    [x]     Disassembly:
    [=]     9016c92d [[mmap2] libc.so.6    + 0x14a92d]  81 c3 d3 b6 0b 00    add                  ebx, 0xbb6d3
    [=]     9016c933 [[mmap2] libc.so.6    + 0x14a933]  81 ec 2c 04 00 00    sub                  esp, 0x42c
    [=]     9016c939 [[mmap2] libc.so.6    + 0x14a939]  8b 8c 24 40 04 00 00 mov                  ecx, dword ptr [esp + 0x440]
    [=]     9016c940 [[mmap2] libc.so.6    + 0x14a940]  89 4c 24 0c          mov                  dword ptr [esp + 0xc], ecx
    [=]     9016c944 [[mmap2] libc.so.6    + 0x14a944]  65 8b 15 14 00 00 00 mov                  edx, dword ptr gs:[0x14]
    [=]     9016c94b [[mmap2] libc.so.6    + 0x14a94b]  89 94 24 1c 04 00 00 mov                  dword ptr [esp + 0x41c], edx
    [=]     9016c952 [[mmap2] libc.so.6    + 0x14a952]  31 d2                xor                  edx, edx
    [=]     9016c954 [[mmap2] libc.so.6    + 0x14a954]  8d 93 a7 2e f9 ff    lea                  edx, [ebx - 0x6d159]
    [=]     9016c95a [[mmap2] libc.so.6    + 0x14a95a]  89 54 24 08          mov                  dword ptr [esp + 8], edx
    [=]     9016c95e [[mmap2] libc.so.6    + 0x14a95e]  85 c0                test                 eax, eax
    [=]     9016c960 [[mmap2] libc.so.6    + 0x14a960]  75 4a                jne                  0x9016c9ac
    [=]     9016c962 [[mmap2] libc.so.6    + 0x14a962]  80 3f 00             cmp                  byte ptr [edi], 0
    [=]     9016c965 [[mmap2] libc.so.6    + 0x14a965]  8d 8b 1c 31 f9 ff    lea                  ecx, [ebx - 0x6cee4]
    [=]     9016c96b [[mmap2] libc.so.6    + 0x14a96b]  75 06                jne                  0x9016c973
    [x]     PC = 0x9016c92d
    
    [x]     Memory map:
    [x]     Start        End          Perm    Label               Image
    [x]     0000030000 - 0000031000   rwx     [GDT]
    [x]     00047ba000 - 00047e0000   r-x     ld-linux.so.2       /mnt/d/rootfs/x86_linux/lib/ld-linux.so.2
    [x]     00047e0000 - 00047e1000   r--     ld-linux.so.2       /mnt/d/rootfs/x86_linux/lib/ld-linux.so.2
    [x]     00047e1000 - 00047e2000   rw-     ld-linux.so.2       /mnt/d/rootfs/x86_linux/lib/ld-linux.so.2
    [x]     0056555000 - 0056556000   r--     test                /mnt/d/scripts/test
    [x]     0056556000 - 0056557000   r-x     test                /mnt/d/scripts/test
    [x]     0056557000 - 0056558000   r--     test                /mnt/d/scripts/test
    [x]     0056558000 - 0056559000   r--     test                /mnt/d/scripts/test
    [x]     0056559000 - 005655a000   rw-     test                /mnt/d/scripts/test
    [x]     005655a000 - 005655c000   rwx     [hook_mem]
    [x]     007ff0d000 - 007ff3d000   rwx     [stack]
    [x]     0090000000 - 0090002000   rw-     [syscall_mmap2]
    [x]     0090002000 - 0090022000   r--     [mmap2] libc.so.6
    [x]     0090022000 - 00901a0000   r-x     [mmap2] libc.so.6
    [x]     00901a0000 - 0090225000   r--     [mmap2] libc.so.6
    [x]     0090225000 - 0090226000   ---     [mmap2] libc.so.6
    [x]     0090226000 - 0090228000   r--     [mmap2] libc.so.6
    [x]     0090228000 - 0090229000   rw-     [mmap2] libc.so.6
    [x]     0090229000 - 0090233000   rw-     [mmap2] libc.so.6
    [x]     0090233000 - 0090333000   rw-     [syscall_mmap2]
    Traceback (most recent call last):
      File "/mnt/d/scripts/test.py", line 7, in <module>
        ql.run()
      File "~/.local/lib/python3.10/site-packages/qiling/core.py", line 574, in run
        self.os.run()
      File "~/.local/lib/python3.10/site-packages/qiling/os/linux/linux.py", line 177, in run
        self.ql.emu_start(self.ql.loader.elf_entry, self.exit_point, self.ql.timeout, self.ql.count)
      File "~/.local/lib/python3.10/site-packages/qiling/core.py", line 713, in emu_start
        self.uc.emu_start(begin, end, timeout, count)
      File "~/.local/lib/python3.10/site-packages/unicorn/unicorn.py", line 547, in emu_start
        raise UcError(status)
    unicorn.unicorn.UcError: Invalid memory write (UC_ERR_WRITE_UNMAPPED)
    
    opened by forensicmike 2
Releases(1.4.5)
  • 1.4.5(Dec 31, 2022)

    Changes since 1.4.4

    New features:

    • Qdb with PE (#1295)

    Improvements:

    • Add pstate in const_arm64.py (#1236)
    • Implement ql_syscall_sched_yield (#1237)
    • Periodic quality PR (#1238)
    • Speed up MCU interrupt handler (#1240)
    • Minor update for setup.py, mcu test and windows registry (#1246)
    • Optimize qltui (#1247)
    • Optimize evm dependency package version manage (#1248)
    • Fix getrlimit related syscall (aka tenda fix) (#1249)
    • Add new ci for arm firmware (#1250)
    • More detailed tenda CI test and cleanup elf multithrad http test (#1251)
    • Fix MIPS relocs (#1252)
    • Newly compiled picohttpd for armeb and new test script (#1254)
    • Update armeb test binary and testing docker (#1255)
    • Update rootfs (#1256)
    • Qdb bug fix and improvement (#1257)
    • Improve handling of gdb 42000 magic pid (#1259)
    • Fix mcu issue in qdb and show flags in uppercase (#1263)
    • Update setup.py (#1267)
    • Handle Cortex M as a specific arch (#1271)
    • Fix some error in syscall fcntl and getsockopt (#1272)
    • Periodic maintenance PR (#1274)
    • Fix gdb attach on ARM thumb mode (#1285)
    • Qdb: add command show_args (#1289)
    • Periodic maintenance PR (#1293)

    Contributors:

    • richor1042
    • vhertz
    • elicn
    • kabeor
    • xwings
    • ucgJhe
    • aquynh
    • owl129
    Source code(tar.gz)
    Source code(zip)
  • 1.4.4(Sep 24, 2022)

    Changes since 1.4.3

    New features:

    • Add r2 extension (#1172)
    • Introduce procfs to Linux OS (#1174)
    • Add a tracer for IDAPro's Tenet plugin (#1205)

    Improvements:

    • Collect a few additional DLLs for x8664 (#1167)
    • Use global cwd in thread (#1170)
    • Fix QlLinuxThreadManagement.threads to be updated appropriately (#1180)
    • Fix Unix socket subsystem (#1181)
    • Maintenance PR for security and code quality (#1182 #1195)
    • Enable android 32bit test (#1184)
    • Fix wrong platform_system for unicornafl (#1185)
    • Fix arm thumb mode shellcode emulation (#1187)
    • Pump unicorn version to 2.0.0 (#1189)
    • Procfs improve & pwndbg compatiblity (#1190)
    • Fix example script issues (#1193 #1194)
    • Introduce a human-friendly disassembler (#1196)
    • Fix gdb step/continue handling (#1200)
    • Fix README.md (#1203)
    • Fix typo of default ip 127.0.0.1 (#1205)
    • Temporarily mask Python versions that are not supported by the EVM module (#1208)
    • Windows Maintenance PR (#1210)
    • Improvements around POSIX sockets (#1216)
    • Add x86_64 debug support for Qdb (#1218)
    • Renew code for picohttpd (#1221)
    • Fix missing retaddr_on_stack in Qdb for arm (#1225)
    • Qdb improvments: Mark, Jump and modify register value in qdb (#1226)
    • Allow user to build config from dictionary other than disk file (#1227)
    • fix(ida): replace getattribute with getattr (#1231)
    Source code(tar.gz)
    Source code(zip)
  • 1.4.3(Jun 1, 2022)

    Changes since 1.4.2

    New features:

    • Introduce PowerPC architecture support (#1140)

    Improvements:

    • Fix fuzzing for tendaac15 (#1096)
    • Update unicorn version to 2.0-rc6 (#1100)
    • Implemented a few more Windows msvcrt functions (#1102)
    • Minor PE Loader fix (#1104)
    • Minor quality changes (#1106)
    • Fix cacheflush syscall typo (#1115)
    • Improvements and fixes for Windows and PE (#1118)
    • Add vm_context to EVM hooks (#1119)
    • Load interpreter segments with correct perms and vaddr (#1120)
    • Fix mistakes in fuzz_x8664_linux binary (#1121)
    • Add EVM ABI helpers, fix EVM DBG stack view (#1123)
    • Fix regression caused by missing exception handling when opening socket (#1124)
    • CI improvement (#1128 #1134)
    • Add macho load command 'LC_LOAD_WEAK_DYLIB' support (#1133)
    • Fix breakage of non-Windows binary emulation on Windows host (#1143)
    • Remove misused region bound check of unmap_all (#1144)
    • Change deprecated interfaces of IDA (#1145)
    • Use importlib to retrieve package version (#1146)
    • New and improved gdbserver (#1148)
    • Rewrite package data reading (#1150)
    • Misc improvements (#1154)
    • Fix memory exhaustion problem caused by the logger (#1161)

    Contributors:

    • wtdcode
    • aquynh
    • elicn
    • xwings
    • cq674350529
    • elicn
    • TheZ3ro
    • bet4it
    • chinggg
    • kabeor
    • chfl4gs
    • profiles
    • OlfillasOdikno
    • nmantan
    • machinewu
    • nullableVoidPtr
    • Phat3
    Source code(tar.gz)
    Source code(zip)
  • 1.4.2(Feb 13, 2022)

    Changes since 1.4.1

    New features:

    • Add stm32f103 support (#1087)
    • Add Arduino Due (SAM3X8E) Support (#1090)

    Improvements:

    • ARM exception handler improvements (#1056)
    • UEFI improvements (#1061)
    • Qdb improvements (#1058)
    • Update rich api in evm dbgcui (#1062)
    • Add security coockies back into PE loader for kernel driver (#1063)
    • Fix ql_open_flag_mapping for Linux binary emulation on Windows (#1064)
    • Minor changes and fixes to the tracing module (#1065)
    • Fix unicornafl for linux_x8664 fuzzing example (#1068)
    • Fuzzing improvements (#1075)
    • Add fix and example for openat path traversion (#1076)
    • Fix _CreateFileA params issue (#1079)

    Contributors:

    • nmantani
    • hardik05
    • cla7aye15I4nd
    • ucgJhe
    • elicn
    • wtdcode
    • kabeor
    • xwings
    Source code(tar.gz)
    Source code(zip)
  • 1.4.1(Dec 29, 2021)

    Changes since 1.4.0

    New features:

    • Introduced riscv, both 32 and 64 (#980)
    • Added U-boot (#1000)
    • Abstract calls to native functions (#1013)

    Improvements:

    • Minor improvements to memory module (#1012)
    • Refactored core hooks (#966)
    • update ql.os.posix.const_mapping with more os/arch match (#973)
    • More update in MCU modules (#971)
    • Fix getpeername and getsockname syscalls (#986)
    • Qdb improvements (#999)

    Contributors:

    • cq674350529
    • ucgJhe
    • cla7aye15I4nd
    • elicn
    • xwings
    Source code(tar.gz)
    Source code(zip)
  • 1.4.0(Oct 20, 2021)

  • 1.3.0(Sep 25, 2021)

    Changes since 1.2.4

    • Added QNX
    • Aded Dynamically executed QNX
    • Added more Posix syscall
    • Bugfix: GDB server on MIPS binary
    • Major refactor of Windows DLL
    • Add Win32 16bit compatibility file api
    • Fixed ql.mem.search logic
    • ql.arch refactor
    • Added EVM engine
    Source code(tar.gz)
    Source code(zip)
  • 1.2.4(Jun 15, 2021)

    Changes since 1.2.3

    • Added custom engine extension
    • Added more posix syscall
    • Refactor: Posix syscall- Refactor: Memory management
    • Refactor: Heap management
    • Cleanup and getting ready for engine module
    Source code(tar.gz)
    Source code(zip)
  • 1.2.3(Mar 29, 2021)

    Changes since 1.2.2

    • Improved PR #689, Android syscall and test fix
    • GDB speed optimization
    • Fixed return value for uid/gid related syscall
    • Resolved multilevel symbolic links
    • Demigod set.api implementation
    • Major refactor, see commit 4aa8e59e04d5a8a5520e4e1e2595ecc78a80beba
    • Clean and remove rootfs
    • ql.filter now accepts a regular expression
    • consolidate output into verbose
    Source code(tar.gz)
    Source code(zip)
  • 1.2.2(Feb 8, 2021)

    Changes since 1.2.1

    • Fix _acmdln and _wcmdln handling
    • More UEFI refactor
    • Refactor common OS space
    • Bring sality test to work again
    • Clean up more test case
    • First stage multithread rewrite done
    • Updated Qiling(shellcode=) to Qiling(code=), still keeping Qiling(shellcode=) for legacy purpose
    • Added support for SMM_RUNTIME_SERVICES_TABLE
    • Fixed regression in code coverage collection
    • Added generic ql.mem.read_ptr helper function
    • merged UEFI, windows, linux and macos print_function
    • merged UEFI, windows, linux and macos fncc
    • make MacOS uses more Qiling API
    Source code(tar.gz)
    Source code(zip)
  • 1.2.1(Jan 1, 2021)

    Changes since 1.2

    • Added support for custom envs variables inside IDA plugin
    • Demigod: Fixed lkm mapping and added support for MIPS32EL
    • Demigod: Added support for Linux x86 32bit
    • Added support for binaries that return from their entrypoint (PE / ELF).
    • Configure Qiling with 'stop_on_stackpointer' or 'stop_on_exit_trap'.
    • Add basic Windows driver tests / example
    • UEFI refactor
    Source code(tar.gz)
    Source code(zip)
  • 1.2(Nov 16, 2020)

    Changes since 1.1.3

    • Demigod finally arrived, more information about Demigod
    • Linux: Implement futex bitset && Check library initialization
    • Linux: vfork and fork syscall mappings
    • execve() ql.argv and ql.env fix
    • De-flattern with IDA plugin now supports ARM && ARM64 with experimental IDA mircocode API.
    • Snapshot mechanism allows saving and restoring of OS and Loader information.
    • Improve register handling (uppercase/lowercase) and add LR register support to arm64
    • Fix ELF Memory mapping issues
    • Fixed directory traversal bug
    Source code(tar.gz)
    Source code(zip)
  • 1.1.3(Sep 30, 2020)

    Changes since 1.1.2

    • Added Doogie example and implement more interrupts
    • Added ollvm de-flattern support for IDA plugin
    • Fixed the popup menu doesn't show when the IDA plugin is put into plugins directory
    • Added Json report extension
    • Fix register mapping
    • ql_syscall_writeev: Use ql.dprint instead of checking debug level
    • Added support for fcntl64 F_SETFL and non-blocking sockets
    • drcov_exact: coverage collection at instruction granularity
    • Added UDP support
    Source code(tar.gz)
    Source code(zip)
  • 1.1.2(Sep 6, 2020)

    Changes since 1.1.1

    • Qiling Debugger now comes with reverse debugging
    • Added qltool into pypi packages
    • Added more Windows API
    • Add mapper support for standalone disks.
    • More BIOS/DOS interrupts support shipped with fully emulated Petya as a mbr analysis example.
    Source code(tar.gz)
    Source code(zip)
  • 1.1.1(Aug 23, 2020)

    Changes since 1.1

    • Fix Windows "import resource" issue
    • Add ql.save and ql.restore aka Qiling's Snapshot
    • Add ql.os.fd.save() and ql.os.fd.restore() to save file descriptor
    • Add IDA Plugin
    • Test, patch and make sure arm_thumb can work on its own
    • Added Qiling Debugger - Currently only works with MIPS
    • Add experimental 8086 and DOS support.
    • Fix path transformation on Windows when running Linux.
    • Idaplugin able to instrument code now
    • Refactor ql.fs_mapper (now ql.os.fs_mapper).
    Source code(tar.gz)
    Source code(zip)
  • 1.1(Jul 24, 2020)

  • 1.1-post1(Jul 24, 2020)

  • 1.1-rc1(Jul 17, 2020)

  • 1.1-Alpha2(Jun 26, 2020)

    Changes since 1.1-alpha1

    • More refactors and bug fixes
    • Added Key Developers section in CREDITS.TXT
    • Golang compiled binary support
    • custom ql.fs_mapper
    • fixed x86 and arm multithread
    • moved all posix syscall mapping to complete syscall table
    • Supports more Linux syscalls
    • Supports more Windows APIs
    • OnEnter, OnExit for syscall, windows API and Linux LIB C functions
    Source code(tar.gz)
    Source code(zip)
  • 1.1-alpha1(May 26, 2020)

    Changes since 1.0

    • More refactor and bug fix
    • Support UEFI
    • Added more memory, register related API
    • Support output filtering
    • Support more Linux syscalls
    • Support more Windows APIs
    • Moved more system variable to ql.profile
    • Support shellcode debugging
    • Minor bug fix for gdbserver
    • Welcome KLKS to the team
    Source code(tar.gz)
    Source code(zip)
  • 1.0(Apr 25, 2020)

  • 1.0-rc1(Apr 12, 2020)

    First release candidate for Qiling 1.0

    Below are important changes since our first public release:

    • Support debugger: GDB, IDAPro, Radare
    • Support OS profile to customize API output (Windows)
    • Support more Linux syscalls
    • Support more Windows APIs
    • Support MacOS dyld
    Source code(tar.gz)
    Source code(zip)
Owner
qiling.io
Cross Platform and Multi Architecture Lightweight Emulator
qiling.io
Rosetta Enforcer is a macOS utility designed to help developers convert Universal Binary application to Single Architecture, vice versa.

Rosetta Enforcer Rosetta Enforcer is a macOS utility designed to help developers convert Universal Binary application to Single Architecture, vice ver

John Seong 21 Sep 25, 2022
Start your next Open-Source Swift Framework 📦

SwiftKit enables you to easily generate a cross platform Swift Framework from your command line. It is the best way to start your next Open-Source Swi

Sven Tiigi 821 Dec 28, 2022
Easily generate cross platform Swift framework projects from the command line

SwiftPlate Easily generate cross platform Swift framework projects from the command line. SwiftPlate will generate Xcode projects for you in seconds,

John Sundell 1.8k Dec 27, 2022
A Swift wrapper around the CoreSymbolication private framework on macOS.

CoreSymbolication provides a very powerful system for looking up and extracting symbolic information from mach-o executables, dyld shared caches, and dSYMs.

Stacksift 7 Nov 21, 2022
ConfettiKit is a custom framework used to add Confetti on your iOS/iPadOS projects.

ConfettiKit is a custom framework used to add Confetti on your iOS/iPadOS projects. The kit provides variety of customisations inorder to design a confetti which matches your project's UI. ConfettiKit makes your work of adding Confetti on your project with just one line of code.

Gokul Nair 14 Sep 27, 2022
A ARM macOS Virtual Machine, using macOS 12's new Virtualization framework.

macOS Virtual Machine A ARM macOS Virtual Machine, using macOS 12's new Virtualization framework. I copied KhaosT's code from here, all I did is chang

Ming Chang 127 Nov 30, 2022
Alchemy, an elegant, batteries included backend framework for Swift.

Elegant, batteries included web framework for Swift.

Alchemy 313 Jan 2, 2023
SandboxKit - Framework that makes it easy to launch a single Scene of your application

SandboxKit This framework makes debugging more efficient in your application. Sandbox is the name of a structure that improves the efficiency of debug

Aoi Okawa 10 Apr 24, 2022
The QuoteKit is a Swift framework to use the free APIs provided by Quotable created by Luke Peavey.

QuoteKit The QuoteKit is a Swift framework to use the free APIs provided by Quotable created by Luke Peavey. It uses the latest async/await syntax for

rryam 17 Jun 23, 2022
contoh pembuatan framework untuk ios swift

circularContohFramework Example To run the example project, clone the repo, and run pod install from the Example directory first. Requirements Install

null 0 Oct 31, 2021
Useless tools for exploring Virtualization.framework

Tools for exploring the internals of Virtualization.framework's Mac virtualization support. I made this since I don't have an Apple Silicon Mac but st

null 18 Aug 9, 2022
How to develop an iOS 14 application with SwiftUI 2.0 framework. How to create an Onboarding Screen with Page Tab View

Ama-Fruits USER INTERFACE AND USER EXPERIENCE APP DESIGN How to develop an iOS 14 application with SwiftUI 2.0 framework. How to create an Onboarding

Noye Samuel 1 Dec 11, 2021
A simple composition framework to create transformations that are either unidirectional or bidirectional

c is a simple composition framework. You have the ability to create transformations that are either unidirectional or bidirectional. There is also a cache that values can be set and resolved.

OpenBytes 4 May 10, 2022
A simple framework to output to a file, url, the console, or even register notification using UserNotifications

o is a simple framework to output to a file, url, the console, or even register notification using UserNotifications. o can also get input from a file, url, or console.

OpenBytes 4 Mar 18, 2022
A Swift SPM framework for running and managing Lua code from Swift

LuaKit A Swift Package for running and managing Lua code from Swift. Documentation For documentation, add this package as Swift Package Dependency, an

GGorAA 5 Nov 24, 2022
Generic model framework

Pistachio Pistachio is a generic model framework. By leveraging lenses and value transformers, it allows you to create type safe adapters for any recu

Felix Visée 164 Jun 29, 2022
IBSKit - an Xcode Fat Framework written in Swift 5

IBSKit framework is designed to solve everyday tasks that any iOS developer faces when developing a new project.

IBS Mobile iOS 9 Nov 11, 2022
A robust drag-and-drop framework for iOS.

# BetweenKit ###Overview BetweenKit is a robust framework, built on UIKit that allows you to build drag-and-drop functionallity into your iOS applicat

IceCube Software 269 Nov 6, 2022
macOS Virtual Machine using Virtualization.framework

virtualOS Run a virtual macOS machine on your Apple Silicon computer. On first start, the latest macOS restore image is automatically downloaded from

null 102 Dec 24, 2022