Sometimes it's desirable to break into the kernel debugger from user software running in EL0. Inserting a BRK opcode usually results in it being intercepted by the operating system kernel. But if you want to end up directly in the kernel debugger instead, you can use the following opcode sequence:
After running this code, the device will enter a paused state. If a debugger is attached, this will result in the debugger registering a debug event (similar to a breakpoint).
Sometimes, when writing patches to kernel or user applications, it's nice to be able to print output without having to ask the operating system to do so. It can be fairly hard to get to debug output from some places, such as EL0 software that has no standard output and disabled debugging calls.
This feature helps you get debug output from patches, shellcodes, or maybe just helper programs without having to deal with operating system constraints.
Both EL0 and EL1 codes can print directly to the device's console via a special HVC (hypervisor call). The form of the HVC itself depends on the environment:
To use the HVC, set registers x0 .. x2 (or r0 .. r2 for 32-bit code) to the following values:
prints a zero-terminated (C) string
prints a number as a hex
prints a number as a signed decimal
prints a buffer as a hex dump
The memory printing calls (CONSLOG_REQ_STR and CONSLOG_REQ_HEX) return status in x0. If negative, the call failed. If not negative, returns the number of bytes retrieved from the buffer (or string). The other calls simply return zero in x0.
Text printed through this output path will show up in the device console, in cyan color using ANSI control characters.
An example of the string printing function, including handling EL0 page faults, is in the Corellium GitHub repository at guest-tools - the conslog
program will echo its standard input to the VM console (in the highly visible cyan color of hypervisor messages).
Discover more insights into mobile app virtualization and userspace interactions — book a meeting with Corellium today!