当前位置:网站首页>[Android reverse] function interception instance (③ refresh CPU cache | ④ process interception function | ⑤ return specific results)
[Android reverse] function interception instance (③ refresh CPU cache | ④ process interception function | ⑤ return specific results)
2022-07-04 11:33:00 【Programmer community】
List of articles
- Preface
- One 、 Refresh CPU Cache
- Two 、 Handle interceptor function
- 1、 Pile function
- 2、 Handle interceptor function
- 3、 ... and 、 Return specific results
- Four 、 Relevant complete code
Preface
【Android reverse 】 Function intercept instance ( Function interception process | ① Locate the dynamic library and function location ) The blog briefly introduces hook function ( Function interception ) The process of , This blog series introduces function interception examples ;
Intercept clock_gettime
function ;
#include <time.h>int clock_gettime(clockid_t clk_id,struct timespec *tp);
【Android reverse 】 Function intercept instance ( ② Pile insertion operation | Save the actual function entry 6 Bytes of data | Write a jump instruction at the function entry of the plug-in | Construct the splice pile function ) The blog has carried out the pile insertion operation ,
One 、 Refresh CPU Cache
perform cache_flush
System call function Refresh CPU The cache of ; This step Only in ARM Architecturally CPU In the implementation of , x86 Architecturally CPU There is no need to refresh the cache ;
x86 There is no need to refresh the cache , But you can also perform system call operations syscall
To refresh the cache ;
Refresh CPU Cache Code example :pApi
Is the function pointer actually called , size
yes 6 byte , That is, refresh (int)pApi
Address to (int)pApi + size
Between
6
6
6 Byte corresponding CPU Just cache ;
/* Empty CPU Cache */#if !defined(__i386__) /* stay arm The schema must be refreshed CPU Cache , x86 No need to execute */ cacheflush((int)pApi, (int)pApi + size, ICACHE|DCACHE);#else /* x86 The system call can be executed under */ syscall(0xF002, (int)pApi,(int)pApi + sizeE);
Two 、 Handle interceptor function
1、 Pile function
stay 【Android reverse 】 Function intercept instance ( ② Pile insertion operation | Save the actual function entry 6 Bytes of data | Write a jump instruction at the function entry of the plug-in | Construct the splice pile function ) 3、 ... and 、 Write a jump instruction at the function entry of the plug-in | Construct the splice pile function Blog chapter , The splicing function is introduced do_clock_gettime
function , Implemented the call do_clock_gettime
function With the call clock_gettime
Function has the same effect ;
Construct the splice pile function : front 6 Bytes are saved clock_gettime
Front of function 6 Byte order , Up to the third day 6 Byte time , Jump directly to clock_gettime
function perform , This performs the spliced function Equivalent to the execution of clock_gettime
function ;
take do_clock_gettime
The function is constructed as clock_gettime
Function flow : perform do_clock_gettime
Methods the first 6 Byte instruction , Jump to clock_gettime
The function of the first 6 Byte instruction position , do_clock_gettime
Of 0 ~ 6 The byte instruction is clock_gettime
Before the actual function 6 byte , The reason for this definition , Because clock_gettime
Before 6 Bytes are overwritten with Jump command ;
2、 Handle interceptor function
Handle interceptor function :
When the function executes to clock_gettime
after , Will execute the inserted jump instruction , Jump to dn_clock_gettime
Function ;
In this function , You can call do_clock_gettime
function , Execute the original instructions ;
do_clock_gettime
Before and after function execution , Can insert their own business logic , Monitoring or modification can ;
Handle interceptor function Code example :
/* Intercept function , Intercept clock_gettime After the function , Jump here */int dn_clock_gettime(clockid_t id, struct timespec* ts) {
/*if (ts == NULL) { return -1; }*/ /* If the device implements a system call , You can call the original... Through this code clock_gettime function */ //int ret = syscall(__NR_clock_gettime, id, ts); /* What is actually called here is the original clock_gettime function If the system call is not implemented on the device , Use the following method to call the original clock_gettime function */ do_clock_gettime(id, ts); /* clock_gettime After the function is executed , Continue to implement some of your own implementation */ /* The code above is hook Live real code We can in real code front / Back Perform some customization */ if (id > CLOCK_MONOTONIC)return 0; if (clock_base[id] == 0.0) {
clock_base[id] = ts->tv_sec * 1000000000.0 + ts->tv_nsec; clock_new[id] = clock_base[id]; } else {
//mutex.lock(); double tick = ts->tv_sec * 1000000000.0 + ts->tv_nsec; //printf("tick : %f base: %f delta: %f\n", tick, clock_base[id], tick - clock_base[id]); if (tick > clock_base[id]) {
clock_new[id] += (tick - clock_base[id]) * time_scale; ts->tv_sec = (time_t)(clock_new[id] / 1000000000.0); ts->tv_nsec = (long)(fmod(clock_new[id], 1000000000.0)); clock_base[id] = tick; } //mutex.unlock(); } return 0;}
3、 ... and 、 Return specific results
Carry out the above dn_clock_gettime
The return value of the function , Is the final return result ;
Four 、 Relevant complete code
Here's the code , Only the function in the reverse code intercepts part of the code :
Calling code :
/* This is a hook In the standard library clock_gettime Function entry method , Jump to custom dn_clock_gettime In the method */hook_func((uint8_t*)clock_gettime, (uint8_t*)dn_clock_gettime, (uint8_t*)do_clock_gettime, 6);
Function intercept code :
/* hook The complete flow of the function , Jump instruction size yes 6 byte *//* This is a hook In the standard library clock_gettime Function entry method , Jump to custom dn_clock_gettime In the method *//* hook_func((uint8_t*)clock_gettime, (uint8_t*)dn_clock_gettime, (uint8_t*)do_clock_gettime, 6); */void hook_func(uint8_t* pApi, uint8_t* pUser, uint8_t* pStub, size_t size){
unsigned char code[64] = {
0 }; /* Save the entry of the function before inserting the pile 6 Bytes of data , Because then insert a pile , * Can use jump code 0xE9,0,0,0,0 Overwrite function entry memory * The function will eventually execute , You need to copy , For subsequent actual function calls */ memcpy(code, pApi, size); /* Function stakes , pApi Is the actual function , pUser Is the interception function that jumps to after inserting the pile */ write_code(pApi, pUser); /* perform size + pStub Position command , Jump directly to size + pApi Location Such as : perform do_clock_gettime Methods the first 6 Byte instruction , Jump to clock_gettime The function of the first 6 Byte instruction position do_clock_gettime Of 0 ~ 6 The byte instruction is clock_gettime Before the actual function 6 byte , The reason for this definition , Because clock_gettime Before 6 Bytes are overwritten with Jump command call do_clock_gettime Method , It's like calling */ write_code(size + pStub, size + pApi); /* Will duplicate 6 byte The code is stored in pStub Function 0 ~ 6 Byte position */ memcpy(pStub, code, size); /* Empty CPU Cache */#if !defined(__i386__) /* stay arm The schema must be refreshed CPU Cache , x86 No need to execute */ cacheflush((int)pApi, (int)pApi + size, ICACHE|DCACHE);#else /* x86 The system call can be executed under */ syscall(0xF002, (int)pApi,(int)pApi + sizeE);#endif}/* * unsigned char* pFunc * unsigned char* pStub * The above two parameters are two function pointers * * Be careful : Refresh after writing CPU Cache , call cache_flush System call function */int write_code(unsigned char* pFunc, unsigned char* pStub) {
/* obtain pFunc Function entrance , First get the address of the memory page where the function is located */ void* pBase = (void*)(0xFFFFF000 & (int)pFunc); /* Modify the properties of the entire memory page , It is amended as follows Can be read | Can write | Executable , * Avoid operation failure due to memory access problems * mprotect Function can only modify the properties of the entire page memory * Every Memory page It's big and small 4KB */ int ret = mprotect(pBase, 0x1000, PROT_WRITE | PROT_READ | PROT_EXEC); /* Failure to modify memory page properties */ if (ret == -1) {
perror("mprotect:"); return -1; }#if defined(__i386__) // arm Situation handling /* E9 yes JMP An unconditional jump order , Back 4 Byte is the address of the jump */ unsigned char code[] = {
0xE9,0,0,0,0 }; /* Calculation pStub Function jump address , Objective function pStub Address - The current function pFunc Address - 5 * Jump instruction The jump is Offset , Not an absolute address value */ *(unsigned*)(code + 1) = pStub - pFunc - 5; /* Copy the jump code to pFunc address , This is a pFunc Function's entry address */ memcpy(pFunc, code, sizeof(code));#else // arm Situation handling /* B An unconditional jump order */ unsigned char code[] = {
0x04,0xF0,0x1F,0xE5,0x00,0x00,0x00,0x00 }; /* arm The jump is an absolute address jump , Pass in pStub Function pointer is enough */ *(unsigned*)(code + 4) = (unsigned)pStub; /* Copy the machine code to the beginning of the function */ memcpy(pFunc, code, sizeof(code));#endif return 0;}/* Intercept function , Intercept clock_gettime After the function , Jump here */int dn_clock_gettime(clockid_t id, struct timespec* ts) {
/*if (ts == NULL) { return -1; }*/ /* If the device implements a system call , You can call the original... Through this code clock_gettime function */ //int ret = syscall(__NR_clock_gettime, id, ts); /* What is actually called here is the original clock_gettime function If the system call is not implemented on the device , Use the following method to call the original clock_gettime function */ do_clock_gettime(id, ts); /* clock_gettime After the function is executed , Continue to implement some of your own implementation */ /* The code above is hook Live real code We can in real code front / Back Perform some customization */ if (id > CLOCK_MONOTONIC)return 0; if (clock_base[id] == 0.0) {
clock_base[id] = ts->tv_sec * 1000000000.0 + ts->tv_nsec; clock_new[id] = clock_base[id]; } else {
//mutex.lock(); double tick = ts->tv_sec * 1000000000.0 + ts->tv_nsec; //printf("tick : %f base: %f delta: %f\n", tick, clock_base[id], tick - clock_base[id]); if (tick > clock_base[id]) {
clock_new[id] += (tick - clock_base[id]) * time_scale; ts->tv_sec = (time_t)(clock_new[id] / 1000000000.0); ts->tv_nsec = (long)(fmod(clock_new[id], 1000000000.0)); clock_base[id] = tick; } //mutex.unlock(); } return 0;}int do_clock_gettime(clockid_t which_clock, struct timespec* tp){
// not used , The actual code of this function in the kernel , Disassembly libc.so obtain /* These instructions are not important Will be covered , These instructions are mainly used to occupy the pit It's actually calling theta clock_gettime function The following assembly code will be overwritten as Jump code , Jump to clock_gettime function , Be careful , clock_gettime function Before 6 Byte instructions are copied to the function entry , Execution section 6 Byte position , Jump to clock_gettime function Of the 6 Byte position */ //return syscall(__NR_clock_gettime, which_clock, tp); __asm__ __volatile__("push %%ebx"::: "ebx"); __asm__ __volatile__("push %%ecx\n"::: "ecx"); __asm__ __volatile__("mov 12(%%esp),%%ebx"::: "ebx"); __asm__ __volatile__("mov 16(%%esp),%%ecx"::: "ecx"); __asm__ __volatile__("mov $0x109,%%eax"::: "eax"); __asm__ __volatile__("int $0x80"); __asm__ __volatile__("pop %%ecx":::"ecx"); __asm__ __volatile__("pop %%ebx":::"ebx"); __asm__ __volatile__("retn");}
边栏推荐
- [Yunju entrepreneurial foundation notes] Chapter II entrepreneur test 16
- Canoe: distinguish VT, VN and vteststudio from their development history
- OSI model notes
- How to judge the advantages and disadvantages of low code products in the market?
- QQ get group link, QR code
- re. Sub() usage
- array_ The contains() function uses
- Games101 Lesson 8 shading 2 Notes
- VPS installation virtualmin panel
- Postman advanced
猜你喜欢
Enter the smart Park, and change begins here
Introduction of network security research direction of Shanghai Jiaotong University
Analysis function in SQL
[Yunju entrepreneurial foundation notes] Chapter II entrepreneur test 20
Elevator dispatching (pairing project) ③
Climb Phoenix Mountain on December 19, 2021
Practical dry goods: deploy mini version message queue based on redis6.0
QQ group administrators
Detailed array expansion analysis --- take you step by step analysis
Simple understanding of seesion, cookies, tokens
随机推荐
Serialization oriented - pickle library, JSON Library
(August 10, 2021) web crawler learning - Chinese University ranking directed crawler
Swagger and OpenAPI
Introduction of network security research direction of Shanghai Jiaotong University
Here, the DDS tutorial you want | first experience of fastdds - source code compilation & Installation & Testing
Number and math classes
Digital simulation beauty match preparation -matlab basic operation No. 6
template<typename MAP, typename LIST, typename First, typename ... Keytypes > recursive call with indefinite parameters - beauty of Pan China
Application of slice
array_ The contains() function uses
(2021-08-20) web crawler learning 2
[Yunju entrepreneurial foundation notes] Chapter II entrepreneur test 22
Canoe: the difference between environment variables and system variables
QQ one click cookie acquisition
Canoe the second simulation engineering xvehicle 3 CAPL programming (operation)
[Yunju entrepreneurial foundation notes] Chapter II entrepreneur test 24
Canoe: distinguish VT, VN and vteststudio from their development history
OSI seven layer reference model
TCP fast retransmission sack mechanism
Configure SSH certificate login