Skip to content

examples/shellcode_run.py crashes: unhandled CPU exceptions (ARM64/ARM/MIPS) and missing-DLL handling (Windows) #1629

Description

@retrocpugeek

Describe the bug

Running examples/shellcode_run.py does not complete. It crashes on the very first stage and never reaches the later ones. There are two distinct problems.

1. Unhandled CPU exception on ARM64 / ARM / MIPS (QlErrorCoreHook)

Since execve was patched to return -1 for paths outside the rootfs (commit "Patch POSIX execve"), the rootfs-less shellcodes in this example no longer stop at execve. Execution falls through into the trailing data (the sockaddr struct and the /bin/sh string), which decodes as an illegal instruction:

  • ARM64 / ARM: undefined instruction → exception 1 (EXCP_UDEF)
  • MIPS: reserved instruction → exception 20 (EXCP_RI)

The Linux OS layer only hooks the syscall trap (exception 2 for ARM/ARM64, 17 for MIPS), so these exceptions reach the unhandled-interrupt dispatcher and abort the whole run:

qiling.exception.QlErrorCoreHook: _hook_intr_cb : not handled

A real kernel would deliver SIGILL and terminate the process, rather than crashing the framework.

2. Windows stages crash with UC_ERR_READ_UNMAPPED when system DLLs are absent

The two Windows stages need genuine Windows system DLLs (collected via examples/scripts/dllscollector.bat), which are not shipped. On a stock checkout the loader logs Could not find DLL file: .../Windows/System32/ntdll.dll but then continues and dies with an unhandled unicorn.UcError: Invalid memory read (UC_ERR_READ_UNMAPPED) instead of failing with a clear, actionable message.

Sample Code

# examples/shellcode_run.py, first stage
from qiling import Qiling
from qiling.const import QL_ARCH, QL_OS, QL_VERBOSE

ARM64_LIN = bytes.fromhex(
    '420002ca210080d2400080d2c81880d2010000d4e60300aa01020010020280d2'
    '681980d2010000d4410080d2420002cae00306aa080380d2010000d4210400f1'
    '65ffff54e0000010420002ca210001caa81b80d2010000d4020004d27f000001'
    '2f62696e2f736800')

ql = Qiling(code=ARM64_LIN, archtype=QL_ARCH.ARM64, ostype=QL_OS.LINUX, verbose=QL_VERBOSE.DEBUG)
ql.run()   # -> QlErrorCoreHook: _hook_intr_cb : not handled

Expected behavior

examples/shellcode_run.py should run to completion. Illegal-instruction exceptions on the Linux archs should be treated as a fatal signal that ends the emulated process cleanly (as a real kernel would), and the Windows stages should be skipped with a helpful message when the required DLLs are not present.

Additional context

  • Qiling: 1.4.10 (reproduced on current master, da210f07)
  • Unicorn: 2.1.3
  • Python: 3.12.3
  • Host: Linux

I have fixes for all of the above and will open a PR shortly:

  • hook the undefined/reserved-instruction exceptions on ARM/ARM64/MIPS Linux and end emulation cleanly (SIGILL semantics);
  • detect missing Windows DLLs in the example and skip those stages gracefully;
  • plus a MIPS32 big-endian shellcode test.

Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions