First look at the x86 under the hook.
1. The principle is to find the address you want to hook.
2. Save the original data for this address. (This saves at least 5 bytes of data because a call instruction is 5 bytes
3. Change this address to call 0Xxxxx (5 bytes) that corresponds to opcode for E9 0Xxxxx after four bytes for a function address
4. Fill the 0XXXXX formula for its own function address-current address-5
5. Restore the original 5-byte opcode from the hook point to start the execution
Arm under
1th There are two modes of ARM mode and thumb mode
In ARM version 7 and above, its instruction set is divided into arm instruction set and thumb instruction set. The arm instruction is 4 byte aligned, each instruction length is 32 bits, the thumb instruction is 2 byte aligned, also divides into THUMB16, THUMB32, wherein the THUMB16 instruction length is 16 bits, the Thumb32 instruction length is 32 bits.
The 2nd function call instruction is:
B series directive: B, BL, BX, BLX
PC register equivalent to EIP
The 3rd is not the two models of pipeline series different. ARM is generally level 3. That is, in the arm mode the PC refers to the next instruction to a line. Because the hook is a PC to rollback 4 bytes (4 byte aligned)
Therefore corresponds:
LDR PC, [PC, #-4]addr
While the thumb (32-bit) does not have to be rolled back
LDR.W PC, [PC, #0]addr
Because it is also equivalent to LDR. W pc, [PC, #0]/ldr pc, [pc, #-4] corresponds to call opcode in x86
Call:e9
LDR. W pc, [PC, #0]:0x00f0dff8 (ldr.w Force with 4 bytes)
LDR pc, [pc, #-4]: 0xe51ff004
Just like the x86 way. Modify Address:
x86 call 0XxxxxarmLDR PC, [PC, #-4]Thumb(32位)addrLDR.W PC, [PC, #0]addr
Finally note that a very easy to ignore point is that the address is generally 4 bytes, which means that each instruction of the thumb (32 bits) is 2 byte aligned and therefore only 2 bytes of write. and arm each instruction is 4 byte aligned. It should therefore be considered that sometimes only 2 bytes are required, and the latter two bytes must be padded with NOP. Because the directive does not have 4-byte alignment as an illegal instruction.
This is the notation:
Start Hook//arm Way There are two kinds of//thumb way is to turn into arm again hook a direct hookstatic void Doinlinehook (struct Inlinehookitem *item) {// Modify Page Properties Mprotect ((void *) Page_start (clear_bit0 (ITEM->TARGET_ADDR)), Page_size * 2, Prot_read | Prot_write | PROT_EXEC); if (item->proto_addr! = NULL) {* (ITEM->PROTO_ADDR) = Test_bit0 (item->target_addr)? (uint32_t *) Set_bit0 ((uint32_t) item->trampoline_instructions): item->trampoline_instructions; The//arm instruction is 4-byte aligned, each instruction length is 32 bits, the thumb instruction is 2 byte aligned,//is divided into Thumb16, Thumb32, where the Thumb16 instruction length is 16 bits and the Thumb32 instruction length is 32 bits. Note here: The//arm processor uses a 3-level pipeline to increase the speed of the processor instruction stream, which means that the program counter R15 (PC) always points to the "fetching" instruction,//instead of pointing to "executing", that is, the PC always points to the address of the currently executing instruction address plus 2 instructions. For example, the current instruction address is 0x8000,//Then the current PC value, under the thumb is 0x8000 + 2*2, under arm is 0x8000 + 4*2. For ARM instruction set, the jump instruction is:////ldr PC, [pc, #-4] to rollback a//addr////ldr pc, [pc, #-4] corresponding machine code: 0XE51FF004,ADDR for the address to jump 。 The jump instruction range is 32 bits, which is the full address jump for a 32-bit system. For the Thumb32 instruction set, the jump instruction is:////LDR. W pc, [pc, #0] do not rewind just pointing to the next//addR////ldr. W pc, [pc, #0] The corresponding machine code is: 0X00F0DFF8,ADDR for the address to jump. also supports arbitrary address jumps. Thumb mode (THUMB32 instruction set) is two-byte aligned if (Test_bit0 (ITEM->TARGET_ADDR)) {int i; i = 0; Determine if 4-byte alignment is populated with NOP if (clear_bit0 (ITEM->TARGET_ADDR)% 4! = 0) {((uint16_t *) clear_bit0 (item-> TARGET_ADDR)) [i++] = 0xbf00; NOP}//ldr pseudo instruction LDR. W forces 32 bits//two bytes to be a set of//LDR. W pc, [pc, #0] corresponds to the machine code: 0X00F0DFF8 Each time a four bytes to be divided into two 2 bytes ((uint16_t *) clear_bit0 (ITEM->TARGET_ADDR)) [i++] = 0XF8DF; ((uint16_t *) clear_bit0 (ITEM->TARGET_ADDR)) [i++] = 0xf000; LDR. W pc, [PC]//A four-byte address is also divided into two 2-byte//take-down four-bit ((uint16_t *) clear_bit0 (ITEM->TARGET_ADDR)) [i++] = item-& Gt;new_addr & 0xFFFF; High four-bit ((uint16_t *) clear_bit0 (ITEM->TARGET_ADDR)) [i++] = item->new_addr >> 16; The//arm mode instruction is 4-byte aligned else {//four bytes for a set ((uint32_t *) (ITEM->TARGET_ADDR)) [0] = 0xe51ff004;//LDR PC , [PC, #-4] Next 4-byte address ((uint32_t *) (ITEM->TARGET_ADDR)) [1] = item->new_addr; } mprotect ((void *) Page_start (clear_bit0 (ITEM->TARGET_ADDR)), Page_size * 2, Prot_read | PROT_EXEC); Item->status = hooked; Cacheflush (Clear_bit0 (ITEM->TARGET_ADDR), clear_bit0 (item->target_addr) + item->length, 0);}
Source:
Https://github.com/ele7enxxh/Android-Inline-Hook
Other Blog address:
Http://ele7enxxh.com/Android-Arm-Inline-Hook.html
Https://www.cnblogs.com/mmmmar/p/8185549.html
Android Inline Hook