Under certain cases, `_gum_interceptor_backend_create_trampoline` does not relocate instructions properly on aarch64 for the `on_invoke_trampoline`
mineo333 opened this issue · 1 comments
I'm doing some stuff with gum_interceptor_replace
on LibAFL, and under certain cases it does not seem to relocate certain branches properly.
Right now, my platform is darwin (MacOS) and I'm trying to replace _platform_memcmp
. The unmodified implementation looks as follows in lldb:
subs x2, x2, #0x10
b.lo #0x2c
nop
nop
...
When the code eventually calls the original implementation of _platform_memcmp
, it, as intended, jumps to the ctx->on_invoke_trampoline
as seen here. However, the on_invoke_trampoline
looks as follows in lldb:
subs x2, x2, #0x10
b.lo #0x2c
nop
nop
ldr x16, #0x8
br x16
.long 0x8dfbc2c0
udf #0x1
As can be seen, the first 4 instructions are there followed by the br
to the original implementation. This is as intended as seen in here. But, the b.lo
cuts the block short and branches to zeroed memory resulting in the program crashing.
From what I understand, the current implementation of the trampoline builder doesn't support this kind of rewriting with branches in the first ~4 instructions because if there's no eoi
it seems to dump the instructions verbatim as seen here.
Based on the current implementation of gum_arm64_relocator_read_one
, it seems that this will occur for any block with an direct branch in the first 4 instructions.
The best solution here seems to be writing support for relocating these kinds of situations. I'm unsure if that is the best course of action here however.
This seems to be a problem associated with libafl and/or frida-rust. frida/frida-rust#81 may still be a problem.
More specifically, the capstone IDs do not match for the correct instructions. For example, for a cbz
, capstone may return a different insn->id
than the id
that frida receives. This behavior seems to be exclusive to the rust.