Fix examples/shellcode_run.py: handle illegal-instruction exceptions and missing Windows DLLs#1630
Open
retrocpugeek wants to merge 4 commits into
Open
Fix examples/shellcode_run.py: handle illegal-instruction exceptions and missing Windows DLLs#1630retrocpugeek wants to merge 4 commits into
retrocpugeek wants to merge 4 commits into
Conversation
ARM and ARM64 Linux only hooked the svc syscall trap (exception 2), so any other CPU exception fell through to the unhandled-interrupt dispatcher and raised QlErrorCoreHook, crashing the framework. This surfaces in examples/shellcode_run.py: since execve was patched to return -1 for paths outside the rootfs, rootfs-less shellcode no longer stops at execve and instead runs into its trailing data. On ARM64 that data decodes as an undefined instruction (exception 1), which a real kernel would deliver as SIGILL and terminate the process. Hook EXCP.UDEF and emulate that termination by stopping cleanly, and replace the magic syscall-trap number with the named EXCP.SWI constant. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Same class of crash as the ARM/ARM64 fix: MIPS Linux only hooked the syscall exception, so any other CPU exception reached the unhandled-interrupt dispatcher and raised QlErrorCoreHook. In examples/shellcode_run.py the rootfs-less MIPS shellcode runs past its denied execve into the trailing "/bin/sh" string, which decodes as a reserved instruction (exception 20) -- delivered as SIGILL on a real kernel. Hook the reserved-instruction exception and route it through the existing hook_cpu_exception handler. Add a small EXCP enum to mips_const so the syscall and reserved-instruction codes are named rather than magic numbers. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The Windows shellcode stages need genuine Windows system DLLs, which are not redistributable and so are not shipped with Qiling; they must be collected from a licensed Windows host via examples/scripts/dllscollector.bat. Without them the loader failed to map ntdll.dll and the example crashed with an unhandled UC_ERR_READ_UNMAPPED traceback. Probe for ntdll.dll under each Windows rootfs and skip those stages with a message pointing at the collector script, so the example runs to completion on a stock checkout. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
test_shellcode.py only exercised little-endian MIPS. Add a big-endian counterpart (MIPS32EB_LIN) so MIPS BE emulation is covered too. The shellcode is the byte-swapped form of MIPS32EL_LIN (instruction words reversed, '/bin/sh' string left intact) and is run with endian=QL_ENDIAN.EB, reusing the existing graceful_execve EXIT hook to end emulation cleanly. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1629
examples/shellcode_run.pycurrently crashes on its first stage and never runs to completion. This PR fixes the underlying issues and gets the example running end-to-end.What's in here
Hook undefined/reserved-instruction exceptions on ARM/ARM64 Linux — these archs only hooked the
svcsyscall trap (exception2), so any other CPU exception reached the unhandled-interrupt dispatcher and raisedQlErrorCoreHook. Sinceexecvewas patched to return-1for paths outside the rootfs, rootfs-less shellcode now runs pastexecveinto its trailing data, which decodes as an undefined instruction (exception1). A real kernel deliversSIGILLand terminates the process; we now emulate that by stopping cleanly. The magic syscall-trap number is also replaced with the namedEXCP.SWIconstant.Same fix for MIPS Linux — MIPS only hooked the syscall exception; the run-off there decodes as a reserved instruction (exception
20). Added a smallEXCPenum tomips_constso the syscall/reserved-instruction codes are named rather than magic numbers, and routed it through the same handler.Skip the Windows stages gracefully when system DLLs are absent — those stages need genuine Windows DLLs collected via
examples/scripts/dllscollector.bat, which are not shipped. Without them the loader failed to mapntdll.dlland the example died with an unhandledUC_ERR_READ_UNMAPPEDtraceback. The example now probes forntdll.dlland skips with a message pointing at the collector script.Add a MIPS32 big-endian shellcode test —
test_shellcode.pyonly covered little-endian MIPS; added a byte-swapped big-endian counterpart run withendian=QL_ENDIAN.EB.Verification
examples/shellcode_run.pyruns to completion (all five Linux stages emulate; Windows stages skip cleanly, or run when DLLs are provisioned).tests/test_shellcode.py: 7/7 pass.Checklist
Which kind of PR do you create?
Coding convention?
Extra tests?
Changelog?
Target branch?
One last thing
🤖 Generated with Claude Code