当前位置:网站首页>[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");}边栏推荐
- 试题库管理系统–数据库设计[通俗易懂]
- QQ get group member operation time
- Getting started with window functions
- Take advantage of the world's sleeping gap to improve and surpass yourself -- get up early
- Capl: timer event
- [Yunju entrepreneurial foundation notes] Chapter II entrepreneur test 8
- [Yunju entrepreneurial foundation notes] Chapter II entrepreneur test 9
- QQ set group information
- 2018 meisai modeling summary +latex standard meisai template sharing
- Canoe - description of common database attributes
猜你喜欢

Btrace tells you how to debug online without restarting the JVM

Climb Phoenix Mountain on December 19, 2021

Canoe - description of common database attributes

Failed to configure a DataSource: ‘url‘ attribute is not specified... Bug solution

Function parameters (positional parameters, default value parameters, variable parameters, named keyword parameters, keyword parameters)

OSI model notes

Fundamentals of software testing

Function introduction of canbedded component

Canoe: what is vtsystem

How to create a new virtual machine
随机推荐
DDS-YYDS
Post man JSON script version conversion
C language memory layout
QQ set group information
Object. Assign () & JS (= >) arrow function & foreach () function
本地Mysql忘记密码的修改方法(windows)
Customized version of cacti host template
Lvs+kept realizes four layers of load and high availability
Cacti主机模板之定制版
[Yunju entrepreneurial foundation notes] Chapter II entrepreneur test 14
Introduction to Lichuang EDA
QQ get group member operation time
Canoe: the fourth simulation project -- bug debugging experience
Function parameters (positional parameters, default value parameters, variable parameters, named keyword parameters, keyword parameters)
20 kinds of hardware engineers must be aware of basic components | the latest update to 8.13
守护进程Xinted和日志记录Syslogd
Oracle11g | getting started with database. It's enough to read this 10000 word analysis
2021-10-20
[Yunju entrepreneurial foundation notes] Chapter II entrepreneur test 22
Dos and path