frida / frida-gum

Cross-platform instrumentation and introspection library written in C

Home Page:https://frida.re

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Under certain cases, `_gum_interceptor_backend_create_trampoline` does not relocate instructions properly on aarch64 for the `on_invoke_trampoline`

mineo333 opened this issue · 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.