Skip to content

Instantly share code, notes, and snippets.

@liutgnu
Created September 4, 2023 10:30
Show Gist options
  • Save liutgnu/037e2bc3d8ac174cde0ea78af88eb70a to your computer and use it in GitHub Desktop.
Save liutgnu/037e2bc3d8ac174cde0ea78af88eb70a to your computer and use it in GitHub Desktop.
It's a demo of function inline hook for ppc64le
/*
* This program is a demo of function inline hook for ppc64le,
* Please compile and test in ppc64le, 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 14 instructions(56 Byte)
*/
__attribute__ ((aligned(2 << 16))) 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 (
"addis %0,2,origin_sub_code_space@toc@ha\n\t"
"addi %0,%0,origin_sub_code_space@toc@l\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"
"ld 10, 0(1)\n\t"
"mtlr 10\n\t"
"ld 10, 16(1)\n\t"
"addi 1, 1, 32\n\t"
"b hooked_sub\n\t"
".align 16\n\t" // We want page aligned, also required by mprotect
"origin_sub_code_space:\n\t"
/*
* Space for the start 14 instructions of original sub function
*/
".long 0\n\t"
".long 0\n\t"
".long 0\n\t"
".long 0\n\t"
".long 0\n\t"
".long 0\n\t"
".long 0\n\t"
".long 0\n\t"
".long 0\n\t"
".long 0\n\t"
".long 0\n\t"
".long 0\n\t"
".long 0\n\t"
".long 0\n\t"
/*
* Space for long jmp back to original
* sub function offset 14 instructions(56 Byte)
*/
".long 0\n\t"
".long 0\n\t"
".long 0\n\t"
".long 0\n\t"
".long 0\n\t"
".long 0\n\t"
".long 0\n\t"
".long 0\n\t"
".long 0\n\t"
".long 0\n\t"
".long 0\n\t"
".long 0\n\t"
".long 0\n\t"
".long 0\n\t"
);
void patch_function()
{
void *code_space_addr, *hook_trampoline_addr, *return_addr = &sub + 40;
__asm__ volatile (
"addis %0,2,origin_sub_code_space@toc@ha\n\t"
"addi %0,%0,origin_sub_code_space@toc@l\n\t":
"=r"(code_space_addr)
);
__asm__ volatile (
"addis %0,2,hook_trampoline@toc@ha\n\t"
"addi %0,%0,hook_trampoline@toc@l\n\t":
"=r"(hook_trampoline_addr)
);
/*
* Fill in the origin_sub_code_space in asm{}
* Long jmp code:
stdu 10, -16(1) # push r10
mflr 10
stdu 10, -16(1) # push lr
bcl 20,31,.+4
mflr 10
ld 10, 16(10)
mtctr 10
bctr
.addr(low)
.addr(high)
ld 10, 0(1)
mtlr 10
ld 10, 16(1)
addi 1, 1, 32
*/
memcpy(code_space_addr, &sub, 56);
memcpy(code_space_addr + 56, "\xf1\xff\x41\xf9\xa6\x02\x48\x7d\xf1\xff\x41\xf9\x05\x00\x9f\x42\xa6\x02\x48\x7d\x10\x00\x4a\xe9\xa6\x03\x49\x7d"
"\x20\x04\x80\x4e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x41\xe9\xa6\x03\x48\x7d\x10\x00\x41\xe9\x20\x00\x21\x38", 56);
memcpy(code_space_addr + 56 + 32, &return_addr, 8);
/*
* Patch the start of sub function
* Same long jmp code
*/
memcpy(&sub, "\xf1\xff\x41\xf9\xa6\x02\x48\x7d\xf1\xff\x41\xf9\x05\x00\x9f\x42\xa6\x02\x48\x7d\x10\x00\x4a\xe9\xa6\x03\x49\x7d"
"\x20\x04\x80\x4e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x41\xe9\xa6\x03\x48\x7d\x10\x00\x41\xe9\x20\x00\x21\x38", 56);
memcpy(&sub + 32, &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 (
"addis %0,2,origin_sub_code_space@toc@ha\n\t"
"addi %0,%0,origin_sub_code_space@toc@l\n\t":
"=r"(sub_code_space_addr)
);
int ret1 = mprotect(sub_code_space_addr, 56 * 2, PROT_READ|PROT_WRITE|PROT_EXEC);
int ret2 = mprotect(&sub, 56, 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