Commit 2e3b55f1 authored by swift_gan's avatar swift_gan Committed by swift_gan

[NativeHook]add elf & tweak cmake

parent 2f56fd50
...@@ -9,6 +9,28 @@ cmake_minimum_required(VERSION 3.4.1) ...@@ -9,6 +9,28 @@ cmake_minimum_required(VERSION 3.4.1)
# or SHARED, and provides the relative paths to its source code. # or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you. # You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK. # Gradle automatically packages shared libraries with your APK.
if(${CMAKE_ANDROID_ARCH_ABI} STREQUAL "arm64-v8a")
set(OS_DEPENDENDED_SRC
src/main/cpp/archs/arm/arm64/assembler/assembler_arm64.cpp
src/main/cpp/archs/arm/arm64/inst/inst_arm64.cpp
src/main/cpp/archs/arm/arm64/register/register_arm64.cpp
src/main/cpp/archs/arm/arm64/register/register_list_arm64.cpp
src/main/cpp/archs/arm/arm64/decoder/decoder_arm64.cpp
src/main/cpp/archs/arm/arm64/relocate/code_relocate_arm64.cpp
src/main/cpp/archs/arm/arm64/hook/hook_arm64.cpp)
elseif (${CMAKE_ANDROID_ARCH_ABI} STREQUAL "armeabi-v7a")
set(OS_DEPENDENDED_SRC
src/main/cpp/archs/arm/arm32/inst/inst_arm32.cpp
src/main/cpp/archs/arm/arm32/inst/inst_t32.cpp
src/main/cpp/archs/arm/arm32/inst/inst_t16.cpp
src/main/cpp/archs/arm/arm32/register/register_arm32.cpp
src/main/cpp/archs/arm/arm32/register/register_list_arm32.cpp
src/main/cpp/archs/arm/arm32/assembler/assembler_arm32.cpp
src/main/cpp/archs/arm/arm32/decoder/decoder_arm32.cpp
src/main/cpp/archs/arm/arm32/hook/hook_arm32.cpp
src/main/cpp/archs/arm/arm32/relocate/code_relocate_arm32.cpp)
endif()
add_library( # Sets the name of the library. add_library( # Sets the name of the library.
sandhook-native sandhook-native
...@@ -19,29 +41,13 @@ add_library( # Sets the name of the library. ...@@ -19,29 +41,13 @@ add_library( # Sets the name of the library.
# Provides a relative path to your source file(s). # Provides a relative path to your source file(s).
src/main/cpp/sandhook_native.cpp src/main/cpp/sandhook_native.cpp
src/main/cpp/decoder/decoder.cpp src/main/cpp/decoder/decoder.cpp
src/main/cpp/archs/arm/arm64/assembler/assembler_arm64.cpp
src/main/cpp/archs/arm/arm64/inst/inst_arm64.cpp
src/main/cpp/archs/arm/arm64/register/register_arm64.cpp
src/main/cpp/archs/arm/arm64/register/register_list_arm64.cpp
src/main/cpp/archs/arm/arm64/decoder/decoder_arm64.cpp
src/main/cpp/archs/arm/arm64/relocate/code_relocate_arm64.cpp
src/main/cpp/archs/arm/arm64/hook/hook_arm64.cpp
src/main/cpp/archs/arm/arm32/inst/inst_arm32.cpp
src/main/cpp/archs/arm/arm32/inst/inst_t32.cpp
src/main/cpp/archs/arm/arm32/inst/inst_t16.cpp
src/main/cpp/archs/arm/arm32/register/register_arm32.cpp
src/main/cpp/archs/arm/arm32/register/register_list_arm32.cpp
src/main/cpp/archs/arm/arm32/assembler/assembler_arm32.cpp
src/main/cpp/archs/arm/arm32/decoder/decoder_arm32.cpp
src/main/cpp/archs/arm/arm32/hook/hook_arm32.cpp
src/main/cpp/archs/arm/arm32/relocate/code_relocate_arm32.cpp
src/main/cpp/relocate/code_relocate.cpp src/main/cpp/relocate/code_relocate.cpp
src/main/cpp/elf/elf.cpp src/main/cpp/elf/elf.cpp
src/main/cpp/assembler/assembler.cpp src/main/cpp/assembler/assembler.cpp
src/main/cpp/buffer/code_buffer.cpp src/main/cpp/buffer/code_buffer.cpp
src/main/cpp/utils/platform.cpp src/main/cpp/utils/platform.cpp
src/main/cpp/hook/hook.cpp src/main/cpp/hook/hook.cpp
) ${OS_DEPENDENDED_SRC})
include_directories( include_directories(
......
...@@ -85,7 +85,7 @@ IMPL_RELOCATE(B_BL) { ...@@ -85,7 +85,7 @@ IMPL_RELOCATE(B_BL) {
Addr targetAddr = inst->getImmPCOffsetTarget(); Addr targetAddr = inst->getImmPCOffsetTarget();
if (inst->op == inst->BL) { if (inst->op == inst->BL) {
__ Mov(LR, (Addr)toPc + inst->size()); __ Mov(LR, (Addr)inst->getPC() + inst->size());
} }
__ Mov(IP1, targetAddr); __ Mov(IP1, targetAddr);
__ Br(IP1); __ Br(IP1);
...@@ -207,10 +207,5 @@ IMPL_RELOCATE(LDR_LIT) { ...@@ -207,10 +207,5 @@ IMPL_RELOCATE(LDR_LIT) {
} }
IMPL_RELOCATE(ADR_ADRP) { IMPL_RELOCATE(ADR_ADRP) {
if (inRelocateRange(inst->offset, sizeof(Addr))) {
__ Mov(*inst->rd, (Addr) toPc);
}
__ Mov(*inst->rd, inst->getImmPCOffsetTarget()); __ Mov(*inst->rd, inst->getImmPCOffsetTarget());
} }
...@@ -3,3 +3,149 @@ ...@@ -3,3 +3,149 @@
// //
#include "elf.h" #include "elf.h"
#include <malloc.h>
#include <string.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include "log.h"
using namespace SandHook::Elf;
ElfImg::ElfImg(const char *elf) {
this->elf = elf;
//load elf
int fd = open(elf, O_RDONLY);
if (fd < 0) {
LOGE("failed to open %s", elf);
return;
}
size = lseek(fd, 0, SEEK_END);
if (size <= 0) {
LOGE("lseek() failed for %s", elf);
}
header = reinterpret_cast<Elf_Ehdr *>(mmap(0, size, PROT_READ, MAP_SHARED, fd, 0));
close(fd);
Elf_Off symtab_entsize = 0;
section_header = reinterpret_cast<Elf_Shdr *>(((uint8_t *) header) + header->e_shoff);
uint8_t* shoff = reinterpret_cast<uint8_t *>(section_header);
char* section_str = reinterpret_cast<char *>(section_header[header->e_shstrndx].sh_offset + ((uint8_t *) header));
bool has_strtab = false;
bool has_dynsym = false;
for (int i = 0; i < header->e_shnum; i++, shoff += header->e_shentsize) {
Elf_Shdr *section_h = (Elf_Shdr *) shoff;
char* sname = section_h->sh_name + section_str;
switch (section_h->sh_type) {
case SHT_DYNSYM:
has_dynsym = true;
dynsym = section_h;
break;
case SHT_SYMTAB:
if (strcmp(sname, ".symtab") == 0) {
symtab = section_h;
symtab_offset = section_h->sh_offset;
symtab_size = section_h->sh_size;
symtab_entsize = section_h->sh_entsize;
symtab_count = symtab_size / symtab_entsize;
}
break;
case SHT_STRTAB:
has_strtab = true;
if (strcmp(sname, ".strtab") == 0) {
strtab = section_h;
symstr_offset = section_h->sh_offset;
}
break;
case SHT_PROGBITS:
if (has_dynsym && has_strtab && bias == -4396) {
bias = (off_t) section_h->sh_addr - (off_t) section_h->sh_offset;
}
break;
}
}
if(!symtab_offset) {
LOGW("can't find symtab from sections\n");
}
sym_start = reinterpret_cast<Elf_Sym *>(((uint8_t *) header) + symtab_offset);
//load module base
base = reinterpret_cast<uint8_t *>(getModuleBase(elf));
}
ElfImg::~ElfImg() {
//open elf file local
if (buffer) {
free(buffer);
buffer = nullptr;
}
//use mmap
if (header) {
munmap(header, size);
}
}
Elf_Addr ElfImg::getSymbOffset(const char *name) {
Elf_Addr _offset = 0;
for(int i = 0 ; i < symtab_count; i++) {
unsigned int st_type = ELF_ST_TYPE(sym_start[i].st_info);
char* st_name = reinterpret_cast<char *>(((uint8_t *) header) + symstr_offset + sym_start[i].st_name);
if (st_type == STT_FUNC && sym_start[i].st_size) {
if(strcmp(st_name, name) == 0) {
_offset = sym_start[i].st_value;
LOGD("find %s: %x\n", elf ,_offset);
break;
}
}
}
return _offset;
}
Elf_Addr ElfImg::getSymbAddress(const char *name) {
Elf_Addr offset = getSymbOffset(name);
if (offset > 0 && base != nullptr) {
return reinterpret_cast<Elf_Addr>(base + offset - bias);
} else {
return 0;
}
}
void *ElfImg::getModuleBase(const char *name) {
FILE *maps;
char buff[256];
off_t load_addr;
int found = 0;
maps = fopen("/proc/self/maps", "r");
while (fgets(buff, sizeof(buff), maps)) {
if ((strstr(buff, "r-xp") || strstr(buff, "r--p")) && strstr(buff, name)) {
found = 1;
LOGD("dlopen", "%s\n", buff);
break;
}
}
if (!found) {
LOGE("failed to read load address for %s", name);
return nullptr;
}
if (sscanf(buff, "%lx", &load_addr) != 1)
LOGE("failed to read load address for %s", name);
fclose(maps);
LOGD("get module base %s: %lu", name, load_addr);
return reinterpret_cast<void *>(load_addr);
}
...@@ -5,4 +5,64 @@ ...@@ -5,4 +5,64 @@
#ifndef SANDHOOK_NH_ELF_H #ifndef SANDHOOK_NH_ELF_H
#define SANDHOOK_NH_ELF_H #define SANDHOOK_NH_ELF_H
#include <linux/elf.h>
#include "base.h"
#if defined(__LP64__)
typedef Elf64_Ehdr Elf_Ehdr;
typedef Elf64_Shdr Elf_Shdr;
typedef Elf64_Addr Elf_Addr;
typedef Elf64_Dyn Elf_Dyn;
typedef Elf64_Rela Elf_Rela;
typedef Elf64_Sym Elf_Sym;
typedef Elf64_Off Elf_Off;
#define ELF_R_SYM(i) ELF64_R_SYM(i)
#else
typedef Elf32_Ehdr Elf_Ehdr;
typedef Elf32_Shdr Elf_Shdr;
typedef Elf32_Addr Elf_Addr;
typedef Elf32_Dyn Elf_Dyn;
typedef Elf32_Rel Elf_Rela;
typedef Elf32_Sym Elf_Sym;
typedef Elf32_Off Elf_Off;
#define ELF_R_SYM(i) ELF32_R_SYM(i)
#endif
namespace SandHook {
namespace Elf {
class ElfImg {
public:
ElfImg(const char* elf);
Elf_Addr getSymbOffset(const char* name);
void* getModuleBase(const char* name);
Elf_Addr getSymbAddress(const char* name);
~ElfImg();
private:
const char* elf = nullptr;
U8 * base = nullptr;
char* buffer = nullptr;
off_t size = 0;
off_t bias = -4396;
Elf_Ehdr* header = nullptr;
Elf_Shdr* section_header = nullptr;
Elf_Shdr* symtab = nullptr;
Elf_Shdr* strtab = nullptr;
Elf_Shdr* dynsym = nullptr;
Elf_Sym* sym_start = nullptr;
Elf_Off symtab_count = 0;
Elf_Off symstr_offset = 0;
Elf_Off symtab_offset = 0;
Elf_Off symtab_size = 0;
};
}
}
#endif //SANDHOOK_NH_ELF_H #endif //SANDHOOK_NH_ELF_H
...@@ -4,17 +4,13 @@ ...@@ -4,17 +4,13 @@
#include <jni.h> #include <jni.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <log.h>
#include "sandhook_native.h" #include "sandhook_native.h"
#include "inst_arm64.h"
#include "decoder_arm64.h"
#include "hook.h" #include "hook.h"
#include "log.h" #include "elf.h"
using namespace SandHook::Asm;
using namespace SandHook::Decoder;
using namespace SandHook::Hook; using namespace SandHook::Hook;
using namespace SandHook::AsmA64; using namespace SandHook::Elf;
int m1 = 5; int m1 = 5;
int m3 = 1036; int m3 = 1036;
...@@ -25,15 +21,12 @@ void (*dosth3Backup)(int, int) = nullptr; ...@@ -25,15 +21,12 @@ void (*dosth3Backup)(int, int) = nullptr;
void (*dosth4Backup)() = nullptr; void (*dosth4Backup)() = nullptr;
void (*dosth4Backup2)() = nullptr; void (*dosth4Backup2)() = nullptr;
bool memUnprotect(Addr addr, Addr len) { void (*innerSuspendVM)() = nullptr;
long pagesize = 4096;
unsigned alignment = (unsigned)((unsigned long long)addr % pagesize);
int i = mprotect((void *) (addr - alignment), (size_t) (alignment + len), void SuspendVMReplace() {
PROT_READ | PROT_WRITE | PROT_EXEC); LOGE("VM Suspend!");
if (i == -1) { innerSuspendVM();
return false;
}
return true;
} }
void do2() { void do2() {
...@@ -57,10 +50,6 @@ void do5() { ...@@ -57,10 +50,6 @@ void do5() {
} }
void do4() { void do4() {
if (m3 > m2) {
return;
}
do5();
int a = 1 + 1; int a = 1 + 1;
int b = a + 1; int b = a + 1;
int d = a + 1; int d = a + 1;
...@@ -78,7 +67,6 @@ void do4replace() { ...@@ -78,7 +67,6 @@ void do4replace() {
void do4replace2() { void do4replace2() {
int a = 1 + 1; int a = 1 + 1;
int b = 1 + 1;
int c = 1 + 1; int c = 1 + 1;
int d = 1 + 1; int d = 1 + 1;
dosth4Backup2(); dosth4Backup2();
...@@ -96,6 +84,7 @@ void do1() { ...@@ -96,6 +84,7 @@ void do1() {
do2(); do2();
} }
class Visitor : public InstVisitor { class Visitor : public InstVisitor {
bool visit(Unit<Base> *unit, void *pc) override { bool visit(Unit<Base> *unit, void *pc) override {
Instruction<Base>* instruction = reinterpret_cast<Instruction<Base> *>(unit); Instruction<Base>* instruction = reinterpret_cast<Instruction<Base> *>(unit);
...@@ -108,44 +97,6 @@ extern "C" ...@@ -108,44 +97,6 @@ extern "C"
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_com_swift_sandhook_nativehook_NativeHook_test(JNIEnv *env, jclass jclass1) { Java_com_swift_sandhook_nativehook_NativeHook_test(JNIEnv *env, jclass jclass1) {
// union {
// InstA64 raw = 0xF9001043;
// STRUCT_A64(STR_UIMM) str;
// } test;
//
// InstA64* codebl = reinterpret_cast<InstA64 *>((Addr)do1 + 8);
//
// if (IS_OPCODE_A64(*codebl, B_BL)) {
//
// //decode
// A64_B_BL a64bl(*reinterpret_cast<STRUCT_A64(B_BL)*>(codebl));
// Off off = a64bl.offset;
// void (*dosth2)() =reinterpret_cast<void (*)()>(a64bl.getImmPCOffsetTarget());
// dosth2();
//
// //asm
// memUnprotect(reinterpret_cast<Addr>(a64bl.get()), a64bl.size());
// a64bl.assembler();
// Off off1 = a64bl.getImmPCOffset();
//
// do1();
//
// }
//
// if (IS_OPCODE_A64(test.raw, STR_UIMM)) {
// A64_STR_UIMM str(test.str);
// str.assembler();
// str.get();
// }
//
// Arm64Decoder arm64Decoder = Arm64Decoder();
//
// Visitor visitor = Visitor();
//
// arm64Decoder.decode(reinterpret_cast<void *>(do1), 4 * 8, visitor);
//
// InlineHookArm64Android inlineHookArm64Android = InlineHookArm64Android();
//
void* do5addr = reinterpret_cast<void *>(do5); void* do5addr = reinterpret_cast<void *>(do5);
void* do4addr = reinterpret_cast<void *>(do4); void* do4addr = reinterpret_cast<void *>(do4);
...@@ -154,11 +105,27 @@ Java_com_swift_sandhook_nativehook_NativeHook_test(JNIEnv *env, jclass jclass1) ...@@ -154,11 +105,27 @@ Java_com_swift_sandhook_nativehook_NativeHook_test(JNIEnv *env, jclass jclass1)
reinterpret_cast<void *>(do4), reinterpret_cast<void *>(do4),
reinterpret_cast<void *>(do4replace))); reinterpret_cast<void *>(do4replace)));
dosth4Backup2 = reinterpret_cast<void (*)()>(InlineHook::instance->inlineHook(
reinterpret_cast<void *>(do4),
reinterpret_cast<void *>(do4replace2)));
do4(); do4();
//innerSuspendVM = reinterpret_cast<void (*)()>(SandInlineHookSym("/system/lib/libart.so", "_ZN3art3Dbg9SuspendVMEv",
// reinterpret_cast<void *>(SuspendVMReplace)));
}
extern "C"
EXPORT void* SandInlineHook(void* origin, void* replace) {
return InlineHook::instance->inlineHook(origin, replace);
}
extern "C"
EXPORT void* SandInlineHookSym(const char* so, const char* symb, void* replace) {
ElfImg elfImg(so);
void* origin = reinterpret_cast<void *>(elfImg.getSymbAddress(symb));
if (origin == nullptr)
return nullptr;
return InlineHook::instance->inlineHook(origin, replace);
} }
\ No newline at end of file
...@@ -5,4 +5,12 @@ ...@@ -5,4 +5,12 @@
#ifndef SANDHOOK_SANDHOOK_NATIVE_H #ifndef SANDHOOK_SANDHOOK_NATIVE_H
#define SANDHOOK_SANDHOOK_NATIVE_H #define SANDHOOK_SANDHOOK_NATIVE_H
#define EXPORT __attribute__ ((visibility ("default")))
extern "C"
EXPORT void* SandInlineHook(void* origin, void* replace);
extern "C"
EXPORT void* SandInlineHookSym(const char* so, const char* symb, void* replace);
#endif //SANDHOOK_SANDHOOK_NATIVE_H #endif //SANDHOOK_SANDHOOK_NATIVE_H
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment