The emulator is actually a userland application cross-compiled for the ARM architecture. It opens the target app (app.elf) from the filesystem and maps it as is in memory. The emulator is launched with qemu-arm-static and eventually jumps to the app entrypoint.

Apps can be debugged with gdb-multiarch thanks to qemu-arm-static.

Syscall hooks

The svc instruction is replaced with udf (undefined) to generate a SIGILL signal upon execution. It allows to catch syscalls and emulate them. It can unfortunately lead to unexpected bytes being patched if \x01\xdf is found in the binary (and isn't the svc instruction).

A disassembler could give better results, but it doesn't look worth it. As a side note, the SVC_Call() function can't be hooked because some syscalls are inlined.

Other alternatives were considered (for instance seccomp or ptrace) but they seem not practicable because QEMU don't support the associated syscalls.