Last active
August 16, 2024 02:33
-
-
Save liutgnu/b85c96fb46af243e716e5ff92fbf3c19 to your computer and use it in GitHub Desktop.
This is a demo of function inline hook for arm64
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* This program is a demo of function inline hook for aarch64, | |
* Please compile and test in aarch64, WITHOUT any compile optimization | |
* | |
* Function sub will be hooked by hooked_sub, when invoke function sub, | |
* hooked_sub will be invoked first, then it can decide whether to invoke the | |
* original sub or not. | |
*/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <sys/mman.h> | |
/* | |
* We want the function to be page aligned, required by mprotect. | |
* And we want the function length longer than 6 instructions(24 Byte) | |
*/ | |
__attribute__ ((optimize("align-functions"))) int sub(int a, int b) | |
{ | |
int aa = a; | |
int bb = b; | |
return aa - bb; | |
} | |
int hooked_sub(int a, int b) | |
{ | |
void *code_space_addr; | |
__asm__ volatile ("ldr %0, =origin_sub_code_space\n\t":"=r"(code_space_addr)); | |
int (*origin_sub)(int, int) = (int (*)(int, int))(code_space_addr); | |
printf("We can view parameters in hooked_sub: %d, %d\n", a, b); | |
printf("Now resume origin sub\n"); | |
return (*origin_sub)(a, b); | |
} | |
asm ( | |
"hook_trampoline:\n\t" | |
"ldp x1, x0, [sp], #0x20\n\t" | |
"b hooked_sub\n\t" | |
".align 12\n\t" // We want page aligned, also required by mprotect | |
"origin_sub_code_space:\n\t" | |
/* | |
* Space for the start 6 instructions of original sub function | |
*/ | |
".word 0\n\t" | |
".word 0\n\t" | |
".word 0\n\t" | |
".word 0\n\t" | |
".word 0\n\t" | |
".word 0\n\t" | |
/* | |
* Space for long jmp back to original | |
* sub function offset 6 instructions(24 Byte) | |
*/ | |
".word 0\n\t" | |
".word 0\n\t" | |
".word 0\n\t" | |
".word 0\n\t" | |
".word 0\n\t" | |
".word 0\n\t" | |
); | |
void patch_function() | |
{ | |
void *code_space_addr, *hook_trampoline_addr, *return_addr = &sub + 20; | |
__asm__ volatile ("ldr %0, =origin_sub_code_space\n\t":"=r"(code_space_addr)); | |
__asm__ volatile ("ldr %0, =hook_trampoline\n\t":"=r"(hook_trampoline_addr)); | |
/* | |
* Fill in the origin_sub_code_space in asm{} | |
* Long jmp code: | |
* stp x1, x0, [sp, #-0x20]! | |
ldr x0, 8 | |
br x0 | |
.addr(low) | |
.addr(high) | |
ldp x1, x0, [sp], #0x20 | |
*/ | |
memcpy(code_space_addr, &sub, 24); | |
memcpy(code_space_addr + 24, "\xe1\x03\xbe\xa9\x40\x00\x00\x58\x00\x00\x1f\xd6\x00\x00\x00\x00" | |
"\x00\x00\x00\x00\xe1\x03\xc2\xa8", 24); | |
memcpy(code_space_addr + 36, &return_addr, 8); | |
/* | |
* Patch the start of sub function | |
* Same long jmp code | |
*/ | |
memcpy(&sub, "\xe1\x03\xbe\xa9\x40\x00\x00\x58\x00\x00\x1f\xd6\x00\x00\x00\x00" | |
"\x00\x00\x00\x00\xe1\x03\xc2\xa8", 24); | |
memcpy(&sub + 12, &hook_trampoline_addr, 8); | |
} | |
/* | |
* Before real patch, we need to change permissions of patched-areas | |
*/ | |
int remove_mem_protect() | |
{ | |
void *sub_code_space_addr = NULL; | |
__asm__ volatile("ldr %0, =origin_sub_code_space\n\t":"=r"(sub_code_space_addr)); | |
int ret1 = mprotect(sub_code_space_addr, 48, PROT_READ|PROT_WRITE|PROT_EXEC); | |
int ret2 = mprotect(&sub, 24, PROT_READ|PROT_WRITE|PROT_EXEC); | |
return (ret1|ret2); | |
} | |
int main() | |
{ | |
if (remove_mem_protect()) { | |
printf("mprotect error!\n"); | |
return -1; | |
} | |
printf("***************************************************\n"); | |
printf("This is the result of unhooked sub(2, 100): %d\n", sub(2, 100)); | |
printf("This is the result of unhooked sub(50, 2): %d\n", sub(50, 2)); | |
printf("***************************************************\n"); | |
patch_function(); | |
printf("This is the result of hooked sub(2, 100): %d\n", sub(2, 100)); | |
printf("This is the result of hooked sub(50, 2): %d\n", sub(50, 2)); | |
printf("***************************************************\n"); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment