jmpews / Dobby

a lightweight, multi-platform, multi-architecture hook framework.
Apache License 2.0
3.89k stars 796 forks source link

fix relocation bug for call instructions (x86/x64) #207

Closed marcelbthk closed 1 year ago

marcelbthk commented 1 year ago

There is a bug in the relocation of call instructions when doing inline hooks. Consider the following function prologue in x64 as an example:

push r14
push rbx
push rax
call _Z27__bionic_atfork_run_preparev

Dobby will try to place a jmp trampoline and consequently overwrite the instruction. As a result Dobby will relocate _Z27__bionic_atfork_run_preparev in the relocation stub.

However, the generated relocation stub looks like this:

00007F63B634F000 push r14
00007F63B634F002 push rbx
00007F63B634F003 push rax
00007F63B634F004 call cs:off_7F63B634F00A
00007F63B634F00A off_7F63B634F00A dq offset _Z27__bionic_atfork_run_preparev
00007F63B634F012 jmp cs:off_7F63B634F018
00007F63B634F018 off_7F63B634F018 dq offset loc_7F63B34CC9F9

Due to the call at 00007F63B634F004 and the call target being placed at 00007F63B634F00A, the caller will continue execution at 00007F63B634F00A when returning from _Z27__bionic_atfork_run_preparev leading to a crash/undefined behaviour.

I modified InstructionRelocationX86Shared.cc such that it will place a jmp after the call, meaning when returning from the call it will jump over the data:

000071E7E8812020 push    r14
000071E7E8812022 push    rbx
000071E7E8812023 push    rax
000071E7E8812024 call    cs:off_71E7E881202C             ; __bionic_atfork_run_prepare(void)
000071E7E881202A jmp     short loc_71E7E8812034
000071E7E881202A ; ---------------------------------------------------------------------------
000071E7E881202C off_71E7E881202C dq offset _Z27__bionic_atfork_run_preparev
000071E7E881202C                                         ; DATA XREF: debug029:000071E7E8812024↑r
000071E7E881202C                                         ; __bionic_atfork_run_prepare(void)
000071E7E8812034 ; ---------------------------------------------------------------------------
000071E7E8812034
000071E7E8812034 loc_71E7E8812034:                       ; CODE XREF: debug029:000071E7E881202A↑j
000071E7E8812034 jmp     cs:off_71E7E881203A
000071E7E8812034 ; ---------------------------------------------------------------------------
000071E7E881203A off_71E7E881203A dq offset loc_71E7E74849F9