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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions