2020-09-25 16:43:53 +00:00
# include <stdio.h>
2020-11-10 00:49:41 +00:00
# include <stdlib.h>
2020-09-25 16:43:53 +00:00
# include <string.h>
# include <unistd.h>
# include <sys/mman.h>
# include <stdint.h>
2020-11-10 20:06:29 +00:00
# include <errno.h>
2020-09-25 16:43:53 +00:00
2021-01-27 21:26:19 +00:00
# include <libreborn/libreborn.h>
2020-09-25 16:43:53 +00:00
2021-06-17 21:32:24 +00:00
# ifndef __arm__
# error "Patching Code Is ARM Only"
2022-03-14 23:09:25 +00:00
# endif
2020-10-01 15:08:46 +00:00
2020-11-10 00:49:41 +00:00
// BL Instruction Magic Number
# define BL_INSTRUCTION 0xeb
2021-06-30 22:38:43 +00:00
# define B_INSTRUCTION 0xea
2020-09-25 16:43:53 +00:00
2020-11-10 00:49:41 +00:00
// Generate A BL Instruction
2021-06-30 22:38:43 +00:00
static uint32_t generate_bl_instruction ( void * from , void * to , int use_b_instruction ) {
2023-05-28 04:45:58 +00:00
if ( abs ( ( ( int32_t ) to ) - ( ( int32_t ) from ) ) > 32000000 ) {
IMPOSSIBLE ( ) ;
}
2020-11-10 00:49:41 +00:00
uint32_t instruction ;
unsigned char * instruction_array = ( unsigned char * ) & instruction ;
2020-10-01 15:08:46 +00:00
2021-06-30 22:38:43 +00:00
instruction_array [ 3 ] = use_b_instruction ? B_INSTRUCTION : BL_INSTRUCTION ;
2020-10-01 15:08:46 +00:00
2020-11-10 00:49:41 +00:00
unsigned char * pc = ( ( unsigned char * ) from ) + 8 ;
int32_t offset = ( int32_t ) to - ( int32_t ) pc ;
int32_t target = offset > > 2 ;
unsigned char * target_array = ( unsigned char * ) & target ;
instruction_array [ 0 ] = target_array [ 0 ] ;
instruction_array [ 1 ] = target_array [ 1 ] ;
instruction_array [ 2 ] = target_array [ 2 ] ;
return instruction ;
2020-10-01 15:08:46 +00:00
}
2020-11-10 00:49:41 +00:00
// Run For Every .text Section
2023-12-25 22:29:30 +00:00
static int _overwrite_calls_within_internal ( const char * file , int line , void * from , void * to , void * target , void * replacement ) {
int found = 0 ;
for ( uint32_t i = ( uint32_t ) from ; i < ( uint32_t ) to ; i = i + 4 ) {
unsigned char * addr = ( unsigned char * ) i ;
2021-06-30 22:38:43 +00:00
int use_b_instruction = addr [ 3 ] = = B_INSTRUCTION ;
// Check If Instruction is B Or BL
if ( addr [ 3 ] = = BL_INSTRUCTION | | use_b_instruction ) {
2023-12-25 22:29:30 +00:00
uint32_t check_instruction = generate_bl_instruction ( addr , target , use_b_instruction ) ;
2020-11-10 00:49:41 +00:00
unsigned char * check_instruction_array = ( unsigned char * ) & check_instruction ;
2021-06-30 22:38:43 +00:00
// Check If Instruction Calls Target
2020-11-10 00:49:41 +00:00
if ( addr [ 0 ] = = check_instruction_array [ 0 ] & & addr [ 1 ] = = check_instruction_array [ 1 ] & & addr [ 2 ] = = check_instruction_array [ 2 ] ) {
2021-06-30 22:38:43 +00:00
// Patch Instruction
2023-12-25 22:29:30 +00:00
uint32_t new_instruction = generate_bl_instruction ( addr , replacement , use_b_instruction ) ;
_patch ( file , line , addr , ( unsigned char * ) & new_instruction ) ;
found + + ;
2020-11-10 00:49:41 +00:00
}
}
}
2023-12-25 22:29:30 +00:00
return found ;
}
struct overwrite_data {
const char * file ;
int line ;
void * target ;
void * replacement ;
int found ;
} ;
static void overwrite_calls_callback ( ElfW ( Addr ) section_addr , ElfW ( Word ) size , void * data ) {
struct overwrite_data * args = ( struct overwrite_data * ) data ;
void * section = ( void * ) section_addr ;
args - > found + = _overwrite_calls_within_internal ( args - > file , args - > line , section , ( void * ) ( section_addr + size ) , args - > target , args - > replacement ) ;
2020-11-10 00:49:41 +00:00
}
// Limit To 512 overwrite_calls() Uses
# define CODE_BLOCK_SIZE 4096
static unsigned char * code_block = NULL ;
2020-11-10 20:06:29 +00:00
# define CODE_SIZE 8
static int code_block_remaining = CODE_BLOCK_SIZE ;
2020-11-10 00:49:41 +00:00
2022-07-07 04:37:53 +00:00
static void _long_overwrite ( void * start , void * target ) {
unsigned char patch_data [ 4 ] = { 0x04 , 0xf0 , 0x1f , 0xe5 } ; // "ldr pc, [pc, #-0x4]"
_patch ( NULL , - 1 , start , patch_data ) ;
_patch_address ( NULL , - 1 , ( void * ) ( ( ( unsigned char * ) start ) + 4 ) , target ) ;
}
2020-11-20 18:36:03 +00:00
static void update_code_block ( void * target ) {
2020-11-10 00:49:41 +00:00
// BL Instructions Can Only Access A Limited Portion of Memory, So This Allocates Memory Closer To The Original Instruction, That When Run, Will Jump Into The Actual Target
if ( code_block = = NULL ) {
code_block = mmap ( ( void * ) 0x200000 , CODE_BLOCK_SIZE , PROT_READ | PROT_WRITE , MAP_PRIVATE | MAP_ANONYMOUS , - 1 , 0 ) ;
2020-11-10 20:06:29 +00:00
if ( code_block = = MAP_FAILED ) {
ERR ( " Unable To Allocate Code Block: %s " , strerror ( errno ) ) ;
}
2022-03-10 03:37:37 +00:00
DEBUG ( " Code Block Allocated At: 0x%08x " , ( uint32_t ) code_block ) ;
2020-10-03 16:57:58 +00:00
}
2020-11-10 20:06:29 +00:00
if ( code_block_remaining < CODE_SIZE ) {
2022-04-15 01:12:42 +00:00
ERR ( " Maximum Amount Of overwrite_calls() Uses Reached " ) ;
2020-11-10 20:06:29 +00:00
}
2022-07-07 04:37:53 +00:00
_long_overwrite ( code_block , target ) ;
2020-11-20 18:36:03 +00:00
}
2020-11-20 19:29:34 +00:00
static void increment_code_block ( ) {
code_block = code_block + CODE_SIZE ;
code_block_remaining = code_block_remaining - CODE_SIZE ;
}
2020-11-20 18:36:03 +00:00
2022-06-25 21:30:08 +00:00
// Overwrite Specific B(L) Instruction
2022-07-07 04:37:53 +00:00
static void _overwrite_call_internal ( const char * file , int line , void * start , void * target , int use_b_instruction ) {
2020-11-20 19:29:34 +00:00
// Add New Target To Code Block
2020-11-20 18:36:03 +00:00
update_code_block ( target ) ;
2022-05-14 02:36:12 +00:00
// Patch
uint32_t new_instruction = generate_bl_instruction ( start , code_block , use_b_instruction ) ;
2020-11-20 18:36:03 +00:00
_patch ( file , line , start , ( unsigned char * ) & new_instruction ) ;
2020-11-20 19:29:34 +00:00
// Increment Code Block Position
increment_code_block ( ) ;
2020-11-20 18:36:03 +00:00
}
2022-07-07 04:37:53 +00:00
void _overwrite_call ( const char * file , int line , void * start , void * target ) {
int use_b_instruction = ( ( unsigned char * ) start ) [ 3 ] = = B_INSTRUCTION ;
_overwrite_call_internal ( file , line , start , target , use_b_instruction ) ;
}
2020-11-20 18:36:03 +00:00
2022-06-25 21:30:08 +00:00
// Overwrite All B(L) Intrusctions That Target The Specified Address
2020-11-20 18:36:03 +00:00
void _overwrite_calls ( const char * file , int line , void * start , void * target ) {
2020-11-20 19:29:34 +00:00
// Add New Target To Code Block
2020-11-20 18:36:03 +00:00
update_code_block ( target ) ;
2020-10-01 15:08:46 +00:00
2020-11-10 00:49:41 +00:00
struct overwrite_data data ;
data . file = file ;
data . line = line ;
data . target = start ;
data . replacement = code_block ;
2020-11-10 20:06:29 +00:00
data . found = 0 ;
2022-05-30 02:54:57 +00:00
iterate_segments ( overwrite_calls_callback , & data ) ;
2020-11-10 00:49:41 +00:00
2020-11-20 19:29:34 +00:00
// Increment Code Block Position
increment_code_block ( ) ;
2020-11-10 20:06:29 +00:00
2021-09-12 03:18:12 +00:00
// Check
2020-11-10 20:06:29 +00:00
if ( data . found < 1 ) {
ERR ( " (%s:%i) Unable To Find Callsites For 0x%08x " , file , line , ( uint32_t ) start ) ;
}
2020-11-10 00:49:41 +00:00
}
2023-12-25 22:29:30 +00:00
void _overwrite_calls_within ( const char * file , int line , void * from , void * to , void * target , void * replacement ) {
// Add New Target To Code Block
update_code_block ( replacement ) ;
// Patch
int found = _overwrite_calls_within_internal ( file , line , from , to , target , code_block ) ;
// Check
if ( found < 1 ) {
ERR ( " (%s:%i) Unable To Find Callsites For 0x%08x " , file , line , ( uint32_t ) target ) ;
}
// Increment Code Block Position
increment_code_block ( ) ;
}
2020-10-03 16:57:58 +00:00
2022-06-25 21:30:08 +00:00
// Extract Target Address From B(L) Instruction
void * extract_from_bl_instruction ( unsigned char * from ) {
unsigned char * pc = ( ( unsigned char * ) from ) + 8 ;
2023-05-28 04:45:58 +00:00
int32_t target = * ( int32_t * ) from ;
target = ( target < < 8 ) > > 8 ;
2022-06-25 21:30:08 +00:00
int32_t offset = target < < 2 ;
return ( void * ) ( pc + offset ) ;
}
2020-11-10 00:49:41 +00:00
// Overwrite Function
void _overwrite ( const char * file , int line , void * start , void * target ) {
2022-07-07 04:37:53 +00:00
_overwrite_call_internal ( file , line , start , target , 1 ) ;
2020-09-25 16:43:53 +00:00
}
2020-11-10 00:49:41 +00:00
// Print Patch Debug Data
2022-03-10 03:37:37 +00:00
# define PATCH_PRINTF(file, line, start, str) if (file != NULL) DEBUG("(%s:%i): Patching (0x%08x) - " str ": 0x%02x 0x%02x 0x%02x 0x%02x", file, line, (uint32_t) start, data[0], data[1], data[2], data[3]);
2020-11-10 00:49:41 +00:00
// Patch Instruction
2021-07-19 01:08:51 +00:00
void _patch ( const char * file , int line , void * start , unsigned char patch [ 4 ] ) {
2021-06-17 21:32:24 +00:00
if ( ( ( uint32_t ) start ) % 4 ! = 0 ) {
2022-04-15 01:12:42 +00:00
ERR ( " Invalid Address " ) ;
2021-06-17 21:32:24 +00:00
}
2020-10-03 16:57:58 +00:00
size_t page_size = sysconf ( _SC_PAGESIZE ) ;
uintptr_t end = ( ( uintptr_t ) start ) + 4 ;
uintptr_t page_start = ( ( uintptr_t ) start ) & - page_size ;
2021-01-30 05:07:13 +00:00
// Allow Writing To Code Memory
mprotect ( ( void * ) page_start , end - page_start , PROT_READ | PROT_WRITE | PROT_EXEC ) ; // PROT_EXEC Is Needed Because Other Code In The Page May Be Being Executed
2020-10-03 16:57:58 +00:00
unsigned char * data = ( unsigned char * ) start ;
PATCH_PRINTF ( file , line , start , " original " ) ;
2020-09-25 16:43:53 +00:00
memcpy ( data , patch , 4 ) ;
2020-10-03 16:57:58 +00:00
PATCH_PRINTF ( file , line , start , " result " ) ;
2021-01-30 05:07:13 +00:00
// Reset Code Memory Permissions
2020-10-03 16:57:58 +00:00
mprotect ( ( void * ) page_start , end - page_start , PROT_READ | PROT_EXEC ) ;
2020-10-16 22:23:39 +00:00
2020-10-26 19:58:28 +00:00
// Clear ARM Instruction Cache
2020-10-17 21:18:18 +00:00
__clear_cache ( start , ( void * ) end ) ;
2020-09-25 16:43:53 +00:00
}
2020-10-02 23:28:31 +00:00
2020-11-10 00:49:41 +00:00
// Patch Address
2020-10-04 00:30:15 +00:00
void _patch_address ( const char * file , int line , void * start , void * target ) {
2020-10-03 00:07:08 +00:00
uint32_t addr = ( uint32_t ) target ;
2021-07-19 01:08:51 +00:00
unsigned char * patch_data = ( unsigned char * ) & addr ;
2020-10-03 16:57:58 +00:00
_patch ( file , line , start , patch_data ) ;
2020-10-02 23:28:31 +00:00
}