132 lines
3.7 KiB
C
132 lines
3.7 KiB
C
//
|
|
// Created by liuruikai756 on 05/07/2017.
|
|
//
|
|
#include <sys/mman.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <stdio.h>
|
|
#include <malloc.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <sys/syscall.h>
|
|
|
|
#include "common.h"
|
|
#include "env.h"
|
|
#include "trampoline.h"
|
|
|
|
static unsigned char *trampolineCode; // place where trampolines are saved
|
|
static unsigned int trampolineSize; // trampoline size required for each hook
|
|
|
|
unsigned int hookCap = 0;
|
|
unsigned int hookCount = 0;
|
|
|
|
// trampoline:
|
|
// 1. set eax/r0/x0 to the hook ArtMethod addr
|
|
// 2. jump into its entry point
|
|
#if defined(__i386__)
|
|
// b8 78 56 34 12 ; mov eax, 0x12345678 (addr of the hook method)
|
|
// ff 70 20 ; push DWORD PTR [eax + 0x20]
|
|
// c3 ; ret
|
|
unsigned char trampoline[] = {
|
|
0xb8, 0x78, 0x56, 0x34, 0x12,
|
|
0xff, 0x70, 0x20,
|
|
0xc3
|
|
};
|
|
|
|
#elif defined(__x86_64__)
|
|
// 48 bf 78 56 34 12 78 56 34 12 ; movabs rdi, 0x1234567812345678
|
|
// ff 77 20 ; push QWORD PTR [rdi + 0x20]
|
|
// c3 ; ret
|
|
unsigned char trampoline[] = {
|
|
0x48, 0xbf, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,
|
|
0xff, 0x77, 0x20,
|
|
0xc3
|
|
};
|
|
|
|
#elif defined(__arm__)
|
|
// 00 00 9F E5 ; ldr r0, [pc, #0]
|
|
// 20 F0 90 E5 ; ldr pc, [r0, 0x20]
|
|
// 78 56 34 12 ; 0x12345678 (addr of the hook method)
|
|
unsigned char trampoline[] = {
|
|
0x00, 0x00, 0x9f, 0xe5,
|
|
0x20, 0xf0, 0x90, 0xe5,
|
|
0x78, 0x56, 0x34, 0x12
|
|
};
|
|
|
|
#elif defined(__aarch64__)
|
|
// 60 00 00 58 ; ldr x0, 12
|
|
// 10 00 40 F8 ; ldr x16, [x0, #0x00]
|
|
// 00 02 1f d6 ; br x16
|
|
// 78 56 34 12
|
|
// 89 67 45 23 ; 0x2345678912345678 (addr of the hook method)
|
|
unsigned char trampoline[] = {
|
|
0x60, 0x00, 0x00, 0x58,
|
|
0x10, 0x00, 0x40, 0xf8,
|
|
0x00, 0x02, 0x1f, 0xd6,
|
|
0x78, 0x56, 0x34, 0x12,
|
|
0x89, 0x67, 0x45, 0x23
|
|
};
|
|
#endif
|
|
static unsigned int trampolineSize = roundUpToPtrSize(sizeof(trampoline));
|
|
|
|
void *genTrampoline(void *hookMethod) {
|
|
void *targetAddr;
|
|
|
|
targetAddr = trampolineCode + trampolineSize * hookCount;
|
|
memcpy(targetAddr, trampoline,
|
|
sizeof(trampoline)); // do not use trampolineSize since it's a rounded size
|
|
|
|
// replace with the actual ArtMethod addr
|
|
#if defined(__i386__)
|
|
memcpy(targetAddr+1, &hookMethod, pointer_size);
|
|
|
|
#elif defined(__x86_64__)
|
|
memcpy((char*)targetAddr + 2, &hookMethod, pointer_size);
|
|
|
|
#elif defined(__arm__)
|
|
memcpy(targetAddr+8, &hookMethod, pointer_size);
|
|
|
|
#elif defined(__aarch64__)
|
|
memcpy(targetAddr + 12, &hookMethod, pointer_size);
|
|
#endif
|
|
|
|
return targetAddr;
|
|
}
|
|
|
|
void setupTrampoline() {
|
|
#if defined(__i386__)
|
|
trampoline[7] = (unsigned char)OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod;
|
|
#elif defined(__x86_64__)
|
|
trampoline[12] = (unsigned char)OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod;
|
|
#elif defined(__arm__)
|
|
trampoline[4] = (unsigned char)OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod;
|
|
#elif defined(__aarch64__)
|
|
trampoline[5] |=
|
|
((unsigned char) OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod) << 4;
|
|
trampoline[6] |=
|
|
((unsigned char) OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod) >> 4;
|
|
#endif
|
|
}
|
|
|
|
int doInitHookCap(unsigned int cap) {
|
|
if (cap == 0) {
|
|
LOGE("invalid capacity: %d", cap);
|
|
return 1;
|
|
}
|
|
if (hookCap) {
|
|
LOGI("allocating new space for trampoline code");
|
|
}
|
|
unsigned int allSize = trampolineSize * cap;
|
|
unsigned char *buf = mmap(NULL, allSize, PROT_READ | PROT_WRITE | PROT_EXEC,
|
|
MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
|
|
if (buf == MAP_FAILED) {
|
|
LOGE("mmap failed, errno = %s", strerror(errno));
|
|
return 1;
|
|
}
|
|
hookCap = cap;
|
|
hookCount = 0;
|
|
trampolineCode = buf;
|
|
return 0;
|
|
}
|