Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

single instruction hook #23

Merged
merged 3 commits into from
Jul 16, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion app/src/main/java/com/swift/sandhook/MyApp.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import android.os.Build;
import android.util.Log;

import com.swift.sandhook.nativehook.NativeHook;
import com.swift.sandhook.test.TestClass;
import com.swift.sandhook.testHookers.ActivityHooker;
import com.swift.sandhook.testHookers.CtrHook;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,4 +177,8 @@ void AssemblerA32::Nop16() {
Mov(IP, IP);
}

void AssemblerA32::Hvc(U16 num) {
Emit(reinterpret_cast<BaseUnit*>(new INST_T32(HVC)(num)));
}


Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ namespace SandHook {

void Nop16();

void Hvc(U16 num);

public:
CodeContainer code_container = CodeContainer(nullptr);
};
Expand Down
63 changes: 61 additions & 2 deletions nativehook/src/main/cpp/archs/arm/arm32/hook/hook_arm32.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
//

#include <log.h>
#include <cstdlib>
#include "code_relocate_arm32.h"
#include "hook_arm32.h"
#include "code_buffer.h"
Expand All @@ -18,7 +19,7 @@ using namespace SandHook::Utils;
#include "assembler_arm32.h"
using namespace SandHook::RegistersA32;
void *InlineHookArm32Android::Hook(void *origin, void *replace) {
AutoLock lock(hookLock);
AutoLock lock(hook_lock);

void* origin_code;
if (IsThumbCode((Addr) origin)) {
Expand Down Expand Up @@ -74,7 +75,7 @@ IMPORT_SHELLCODE(BP_SHELLCODE)
IMPORT_LABEL(callback_addr_s, Addr)
IMPORT_LABEL(origin_addr_s, Addr)
bool InlineHookArm32Android::BreakPoint(void *origin, void (*callback)(REG *)) {
AutoLock lock(hookLock);
AutoLock lock(hook_lock);

void* origin_code;
if (IsThumbCode((Addr) origin)) {
Expand Down Expand Up @@ -126,3 +127,61 @@ bool InlineHookArm32Android::BreakPoint(void *origin, void (*callback)(REG *)) {

return true;
}

void *InlineHookArm32Android::SingleInstHook(void *origin, void *replace) {
if (!InitForSingleInstHook()) {
return nullptr;
}
AutoLock lock(hook_lock);

void* origin_code;
if (IsThumbCode((Addr) origin)) {
origin_code = GetThumbCodeAddress(origin);
} else {
LOGE("hook %d error!, only support thumb2 now!", origin);
return nullptr;
}

void* backup = nullptr;
AssemblerA32 assembler_backup(backup_buffer);

StaticCodeBuffer inline_buffer = StaticCodeBuffer(reinterpret_cast<Addr>(origin_code));
AssemblerA32 assembler_inline(&inline_buffer);
CodeContainer* code_container_inline = &assembler_inline.code_container;

//build inline trampoline
#define __ assembler_inline.
__ Hvc(static_cast<U16>(hook_infos.size()));
#undef __

//build backup method
CodeRelocateA32 relocate = CodeRelocateA32(assembler_backup);
backup = relocate.Relocate(origin, code_container_inline->Size(), nullptr);
#define __ assembler_backup.
Label* origin_addr_label = new Label();
ALIGN_FOR_LDR
__ Ldr(PC, origin_addr_label);
__ Emit(origin_addr_label);
__ Emit((Addr) GetThumbPC(reinterpret_cast<void *>(reinterpret_cast<Addr>(origin_code) + relocate.cur_offset)));
__ Finish();
#undef __

hook_infos.push_back({origin, replace, GetThumbPC(backup)});

//commit inline trampoline
assembler_inline.Finish();
return GetThumbPC(backup);
}

void InlineHookArm32Android::ExceptionHandler(int num, sigcontext *context) {
InstT32 *code = reinterpret_cast<InstT32*>(context->arm_pc);
if (!IS_OPCODE_T32(*code, HVC)) {
abort();
}
INST_T32(HVC) hvc(code);
hvc.Disassemble();
if (hvc.imme >= hook_infos.size())
return;
HookInfo &hook_info = hook_infos[hvc.imme];
context->arm_pc = reinterpret_cast<U32>(hook_info.replace);
}
15 changes: 7 additions & 8 deletions nativehook/src/main/cpp/archs/arm/arm32/hook/hook_arm32.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,23 @@
#pragma once

#include "hook.h"
#include <vector>

namespace SandHook {
namespace Hook {

class InlineHookArm32Android : public InlineHook {
public:
inline InlineHookArm32Android() {
hookLock = new std::mutex();
};
inline ~InlineHookArm32Android() {
delete hookLock;
}
void *Hook(void *origin, void *replace) override;

bool BreakPoint(void *point, void (*callback)(REG *)) override;

protected:
std::mutex* hookLock;
void *SingleInstHook(void *origin, void *replace) override;

void ExceptionHandler(int num, sigcontext *context) override;

private:
std::vector<HookInfo> hook_infos;
};

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,5 @@ enum class InstCodeT32 : InstCode {
LDR_UIMM,
MOV_MOVT_IMM,
SUB_IMM,
HVC
};
Original file line number Diff line number Diff line change
Expand Up @@ -95,3 +95,12 @@ DEFINE_STRUCT_T32(SUB_IMM) {
InstT32 imm3:3;
InstT32 opcode2:1;
};

DEFINE_OPCODE_T32(HVC_1, 0b111101111110)
DEFINE_OPCODE_T32(HVC_2, 0b1000)
DEFINE_STRUCT_T32(HVC) {
InstT32 imm4:4;
InstT32 opcode1:12;
InstT32 imm12:12;
InstT32 opcode2:4;
};
16 changes: 16 additions & 0 deletions nativehook/src/main/cpp/archs/arm/arm32/inst/inst_t32.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,3 +239,19 @@ void T32_LDR_IMM::Assemble() {

T32_SUB_IMM::T32_SUB_IMM(void *inst) : InstructionT32(inst) {
}


T32_HVC::T32_HVC(void *inst) : InstructionT32(inst) {}

T32_HVC::T32_HVC(U16 imme) : imme(imme) {}

void T32_HVC::Disassemble() {
imme = static_cast<U16>(COMBINE(Get()->imm4, Get()->imm12, 12));
}

void T32_HVC::Assemble() {
SET_OPCODE_MULTI(HVC, 1);
SET_OPCODE_MULTI(HVC, 2);
Get()->imm12 = BITS(imme, 0, 11);
Get()->imm4 = BITS(imme, 12, 15);
}
17 changes: 17 additions & 0 deletions nativehook/src/main/cpp/archs/arm/arm32/inst/inst_t32.h
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,23 @@ namespace SandHook {

};


DEFINE_INST(HVC) {
public:
T32_HVC(void *inst);

T32_HVC(U16 imme);

DEFINE_IS_EXT(HVC, TEST_INST_OPCODE(HVC, 1) && TEST_INST_OPCODE(HVC, 2))

void Disassemble() override;

void Assemble() override;

public:
U16 imme;
};

}
}

Expand Down
51 changes: 51 additions & 0 deletions nativehook/src/main/cpp/archs/arm/arm64/hook/hook_arm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Created by swift on 2019/5/23.
//

#include <cstdlib>
#include "hook_arm64.h"
#include "code_buffer.h"
#include "lock.h"
Expand Down Expand Up @@ -131,3 +132,53 @@ bool InlineHookArm64Android::BreakPoint(void *point, void (*callback)(REG regs[]

return true;
}


void *InlineHookArm64Android::SingleInstHook(void *origin, void *replace) {
if (!InitForSingleInstHook()) {
return nullptr;
}
AutoLock lock(hook_lock);
void* backup = nullptr;
AssemblerA64 assembler_backup(backup_buffer);

StaticCodeBuffer inline_buffer = StaticCodeBuffer(reinterpret_cast<Addr>(origin));
AssemblerA64 assembler_inline(&inline_buffer);
CodeContainer* code_container_inline = &assembler_inline.code_container;

//build inline trampoline
#define __ assembler_inline.
__ Hvc(static_cast<U16>(hook_infos.size()));
#undef __

//build backup method
CodeRelocateA64 relocate = CodeRelocateA64(assembler_backup);
backup = relocate.Relocate(origin, code_container_inline->Size(), nullptr);
#define __ assembler_backup.
Label* origin_addr_label = new Label();
__ Ldr(IP1, origin_addr_label);
__ Br(IP1);
__ Emit(origin_addr_label);
__ Emit((Addr) origin + code_container_inline->Size());
__ Finish();
#undef __

hook_infos.push_back({origin, replace, backup});

//commit inline trampoline
assembler_inline.Finish();
return backup;
}

void InlineHookArm64Android::ExceptionHandler(int num, sigcontext *context) {
InstA64 *code = reinterpret_cast<InstA64*>(context->pc);
if (!IS_OPCODE_A64(*code, EXCEPTION_GEN)) {
abort();
}
INST_A64(EXCEPTION_GEN) hvc(code);
hvc.Disassemble();
if (hvc.imme >= hook_infos.size())
return;
HookInfo &hook_info = hook_infos[hvc.imme];
context->pc = reinterpret_cast<U64>(hook_info.replace);
}
8 changes: 8 additions & 0 deletions nativehook/src/main/cpp/archs/arm/arm64/hook/hook_arm64.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,21 @@
#pragma once

#include "hook.h"
#include <vector>

namespace SandHook {
namespace Hook {
class InlineHookArm64Android : public InlineHook {
public:
void *Hook(void *origin, void *replace) override;
bool BreakPoint(void *point, void (*callback)(REG[])) override;

void *SingleInstHook(void *origin, void *replace) override;

void ExceptionHandler(int num, sigcontext *context) override;

private:
std::vector<HookInfo> hook_infos;
};
}
}
10 changes: 5 additions & 5 deletions nativehook/src/main/cpp/elf/elf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ ElfImg::ElfImg(const char *elf) {
}

//load module rang
baseInRam = getModuleBase(elf);
baseInRam = GetModuleBase(elf);
}

ElfImg::~ElfImg() {
Expand All @@ -105,7 +105,7 @@ ElfImg::~ElfImg() {
}
}

Elf_Addr ElfImg::getSymbOffset(const char *name) {
Elf_Addr ElfImg::GetSymOffset(const char *name) {
Elf_Addr _offset = 0;

//search dynmtab
Expand Down Expand Up @@ -139,16 +139,16 @@ Elf_Addr ElfImg::getSymbOffset(const char *name) {
return 0;
}

Elf_Addr ElfImg::getSymbAddress(const char *name) {
Elf_Addr offset = getSymbOffset(name);
Elf_Addr ElfImg::GetSymAddress(const char *name) {
Elf_Addr offset = GetSymOffset(name);
if (offset > 0 && baseInRam != nullptr) {
return static_cast<Elf_Addr>((size_t) baseInRam + offset - bias);
} else {
return 0;
}
}

void *ElfImg::getModuleBase(const char *name) {
void *ElfImg::GetModuleBase(const char *name) {
FILE *maps;
char buff[256];
off_t load_addr;
Expand Down
27 changes: 25 additions & 2 deletions nativehook/src/main/cpp/hook/hook.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
//
// Created by swift on 2019/5/14.
//

#include "hook.h"
#include "lock.h"

#if defined(__arm__)
#include "hook_arm32.h"
Expand All @@ -11,11 +11,34 @@
#endif

using namespace SandHook::Hook;
using namespace SandHook::Utils;

CodeBuffer* InlineHook::backup_buffer = new AndroidCodeBuffer();

#if defined(__arm__)
InlineHook* InlineHook::instance = new InlineHookArm32Android();
#elif defined(__aarch64__)
InlineHook* InlineHook::instance = new InlineHookArm64Android();
#endif
#endif

void InterruptHandler(int signum, siginfo_t* siginfo, void* uc) {
if (signum != SIGILL)
return;
sigcontext &context = reinterpret_cast<ucontext_t *>(uc)->uc_mcontext;
InlineHook::instance->ExceptionHandler(signum, &context);
}

bool InlineHook::InitForSingleInstHook() {
AutoLock lock(hook_lock);
if (inited)
return true;
struct sigaction sig{};
sigemptyset(&sig.sa_mask);
// Notice: remove this flag if needed.
sig.sa_flags = SA_SIGINFO;
sig.sa_sigaction = InterruptHandler;
if (sigaction(SIGILL, &sig, nullptr) != -1) {
inited = true;
}
return inited;
}
6 changes: 3 additions & 3 deletions nativehook/src/main/cpp/includes/elf.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,11 @@ namespace SandHook {

ElfImg(const char* elf);

Elf_Addr getSymbOffset(const char* name);
Elf_Addr GetSymOffset(const char *name);

static void* getModuleBase(const char* name);
static void* GetModuleBase(const char *name);

Elf_Addr getSymbAddress(const char* name);
Elf_Addr GetSymAddress(const char *name);

~ElfImg();

Expand Down
Loading