Commit 82331db5 authored by swift_gan's avatar swift_gan

fix bug & add arm32 inst check

parent 60554bc6
......@@ -30,7 +30,7 @@ ext {
userOrg = 'ganyao114'
groupId = 'com.swift.sandhook'
repoName = 'SandHook'
publishVersion = '0.0.5'
publishVersion = '1.1.1'
desc = 'android art hook'
website = 'https://github.com/ganyao114/SandHook'
licences = ['Apache-2.0']
......
......@@ -28,6 +28,8 @@ add_library( # Sets the name of the library.
src/main/cpp/art/art_method.cpp
src/main/cpp/trampoline/arch/arm32.S
src/main/cpp/trampoline/arch/arm64.S
src/main/cpp/inst/insts_arm32.cpp
src/main/cpp/inst/insts_arm64.cpp
)
# Searches for a specified prebuilt library and stores the path as a
......
......@@ -13,7 +13,7 @@ android {
externalNativeBuild {
cmake {
arguments '-DBUILD_TESTING=OFF'
arguments '-DBUILD_TESTING=OFF', '-DANDROID_TOOLCHAIN=gcc'
cppFlags "-frtti -fexceptions"
abiFilters 'armeabi-v7a', 'arm64-v8a'
}
......
......@@ -7,6 +7,7 @@
#include "../includes/hide_api.h"
#include "../includes/utils.h"
extern int SDK_INT;
using namespace art::mirror;
using namespace SandHook;
......
......@@ -5,6 +5,8 @@
#include "../includes/cast_art_method.h"
#include "../includes/utils.h"
extern int SDK_INT;
namespace SandHook {
class CastDexCacheResolvedMethods : public ArrayMember<art::mirror::ArtMethod, void *> {
......@@ -119,8 +121,7 @@ namespace SandHook {
};
void CastArtMethod::init(JNIEnv *env, int sdk) {
SDK_INT = sdk;
void CastArtMethod::init(JNIEnv *env) {
//init ArtMethodSize
jclass sizeTestClass = env->FindClass("com/swift/sandhook/ArtMethodSizeTest");
Size artMethod1 = (Size) env->GetStaticMethodID(sizeTestClass, "method1", "()V");
......
......@@ -15,8 +15,6 @@
namespace SandHook {
static int SDK_INT = 0;
template <typename T>
class cast {
public:
......
......@@ -22,7 +22,7 @@ namespace SandHook {
static void* genericJniStub;
static void* staticResolveStub;
static void init(JNIEnv *env, int sdk);
static void init(JNIEnv *env);
static void copy(art::mirror::ArtMethod* from, art::mirror::ArtMethod* to);
};
......
......@@ -8,6 +8,9 @@
#include <cstdint>
#include "arch.h"
#define CASE(inst,mask,match,type) \
if ((inst & mask) == match) { return type; } \
namespace SandHook {
union Arm32Code {
......@@ -23,32 +26,85 @@ namespace SandHook {
} units;
};
union Arm16Code {
uint16_t code;
struct {
uint32_t cond:16;
} units;
};
enum InstArch {
ARM32,
Thumb,
Thumb2,
AARCH64,
ARM32 = 0,
Thumb16,
Thumb32,
Arm64,
X86,
X64
};
enum class InstType_Thumb32 {
// BLX <label>
BLX_THUMB32 = 0,
// BL <label>
BL_THUMB32,
// B.W <label>
B1_THUMB32,
// B.W <label>
B2_THUMB32,
// ADR.W Rd, <label>
ADR1_THUMB32,
// ADR.W Rd, <label>
ADR2_THUMB32,
// LDR.W Rt, <label>
LDR_THUMB32,
// TBB [PC, Rm]
TBB_THUMB32,
// TBH [PC, Rm, LSL #1]
TBH_THUMB32,
PC_NO_RELATED
};
enum InstType {
enum class InstType_Thumb16 {
// B <label>
B1_THUMB16 = 0,
// B <label>
B2_THUMB16,
// BX PC
BX_THUMB16,
// ADD <Rdn>, PC (Rd != PC, Rn != PC) 在对ADD进行修正时,
//采用了替换PC为Rr的方法,当Rd也为PC时,由于之前更改了Rr的值,
//可能会影响跳转后的正常功能。
ADD_THUMB16,
// MOV Rd, PC
MOV_THUMB16,
// ADR Rd, <label>
ADR_THUMB16,
// LDR Rt, <label>
LDR_THUMB16,
PC_NO_RELATED
};
enum class InstType_Arm64 {
PC_NO_RELATED
};
class Inst {
public:
uint32_t opcode;
InstArch arch;
InstType type;
virtual int instLen() const = 0;
virtual InstArch instArch() const = 0;
virtual bool pcRelated() = 0;
};
class InstVisitor {
public:
virtual bool visit(Inst inst, Size offset, Size length) const = 0;
virtual bool visit(Inst* inst, Size offset, Size length) = 0;
};
class InstDecode {
public:
static void decode(void* codeStart, Size codeLen, InstVisitor* visitor);
};
}
......
......@@ -190,12 +190,12 @@ namespace SandHook {
}
//work for thumb
Code getThumbCodeAddress(Code code) {
static Code getThumbCodeAddress(Code code) {
Size addr = reinterpret_cast<Size>(code) & (~0x00000001);
return reinterpret_cast<Code>(addr);
}
Code getThumbCodePcAddress(Code code) {
static Code getThumbCodePcAddress(Code code) {
Size addr = reinterpret_cast<Size>(code) & (~0x00000001);
return reinterpret_cast<Code>(addr + 1);
}
......
......@@ -37,9 +37,8 @@ namespace SandHook {
public:
TrampolineManager() = default;
void init(int sdk, Size quickCompileOffset) {
void init(Size quickCompileOffset) {
this->quickCompileOffset = quickCompileOffset;
SDK_INT = sdk;
}
Code allocExecuteSpace(Size size);
......@@ -47,7 +46,7 @@ namespace SandHook {
HookTrampoline* installReplacementTrampoline(mirror::ArtMethod* originMethod, mirror::ArtMethod* hookMethod, mirror::ArtMethod* backupMethod);
HookTrampoline* installInlineTrampoline(mirror::ArtMethod* originMethod, mirror::ArtMethod* hookMethod, mirror::ArtMethod* backupMethod);
bool canSafeInline(mirror::ArtMethod* method, char* msg);
bool canSafeInline(mirror::ArtMethod* method);
uint32_t sizeOfEntryCode(mirror::ArtMethod* method);
......@@ -90,7 +89,6 @@ namespace SandHook {
private:
Size quickCompileOffset;
int SDK_INT = 0;
std::map<mirror::ArtMethod*,HookTrampoline*> trampolines;
std::list<Code> executeSpaceList = std::list<Code>();
std::mutex allocSpaceLock;
......
//
// Created by SwiftGan on 2019/2/11.
//
#if defined(__arm__)
#include "../includes/inst.h"
#include "../includes/trampoline.h"
namespace SandHook {
class InstThumb32 : public Inst {
public:
Arm32Code code;
InstType_Thumb32 instType = InstType_Thumb32::PC_NO_RELATED;
InstThumb32(uint32_t code) {
this->code.code = code;
instType = initType();
}
private:
int instLen() const override {
return 4;
}
InstArch instArch() const override {
return Thumb32;
}
bool pcRelated() override {
return instType < InstType_Thumb32::PC_NO_RELATED;
}
InstType_Thumb32 initType() {
CASE(code.code, 0xF800D000, 0xF000C000, InstType_Thumb32::BLX_THUMB32)
CASE(code.code, 0xF800D000, 0xF000D000, InstType_Thumb32::BL_THUMB32)
CASE(code.code, 0xF800D000, 0xF0008000, InstType_Thumb32::B1_THUMB32)
CASE(code.code, 0xF800D000, 0xF0009000, InstType_Thumb32::B2_THUMB32)
CASE(code.code, 0xFBFF8000, 0xF2AF0000, InstType_Thumb32::ADR1_THUMB32)
CASE(code.code, 0xFBFF8000, 0xF20F0000, InstType_Thumb32::ADR2_THUMB32)
CASE(code.code, 0xFF7F0000, 0xF85F0000, InstType_Thumb32::LDR_THUMB32)
CASE(code.code, 0xFFFF00F0, 0xE8DF0000, InstType_Thumb32::TBB_THUMB32)
CASE(code.code, 0xFFFF00F0, 0xE8DF0010, InstType_Thumb32::TBH_THUMB32)
return InstType_Thumb32::PC_NO_RELATED;
}
};
class InstThumb16 : public Inst {
public:
Arm16Code code;
InstType_Thumb16 instType = InstType_Thumb16::PC_NO_RELATED;
InstThumb16(uint16_t code) {
this->code.code = code;
instType = initType();
}
private:
int instLen() const override {
return 2;
}
InstArch instArch() const override {
return Thumb16;
}
bool pcRelated() override {
return instType < InstType_Thumb16 ::PC_NO_RELATED;
}
InstType_Thumb16 initType() {
CASE(code.code, 0xF000, 0xD000, InstType_Thumb16::B1_THUMB16)
CASE(code.code, 0xF800, 0xE000, InstType_Thumb16::B2_THUMB16)
CASE(code.code, 0xFFF8, 0x4778, InstType_Thumb16::BX_THUMB16)
CASE(code.code, 0xFF78, 0x4478, InstType_Thumb16::ADD_THUMB16)
CASE(code.code, 0xFF78, 0x4678, InstType_Thumb16::MOV_THUMB16)
CASE(code.code, 0xF800, 0xA000, InstType_Thumb16::ADR_THUMB16)
CASE(code.code, 0xF800, 0x4800, InstType_Thumb16::LDR_THUMB16)
return InstType_Thumb16::PC_NO_RELATED;
}
};
bool isThumbCode(Size codeAddr) {
return (codeAddr & 0x1) == 0x1;
}
bool isThumb32(uint32_t code) {
return code >> 16 != 0;
}
void InstDecode::decode(void *codeStart, Size codeLen, InstVisitor *visitor) {
Size offset = 0;
Inst* inst = nullptr;
if (isThumbCode(reinterpret_cast<Size>(codeStart))) {
codeStart = Trampoline::getThumbCodeAddress(static_cast<Code>(codeStart));
Size codeAddr = reinterpret_cast<Size>(codeStart);
while (offset <= codeLen) {
uint32_t ram32 = *reinterpret_cast<uint32_t*>(codeAddr + offset);
if (isThumb32(ram32)) {
//thumb32
inst = new InstThumb32(ram32);
} else {
//thumb16
inst = new InstThumb16(static_cast<uint16_t>(ram32));
}
if (!visitor->visit(inst, offset, codeLen)) {
delete inst;
break;
}
offset += inst->instLen();
delete inst;
}
}
}
}
#endif
\ No newline at end of file
//
// Created by SwiftGan on 2019/2/11.
//
#if defined(__aarch64__)
#include "../includes/inst.h"
#include "../includes/trampoline.h"
namespace SandHook {
class InstArm64 : public Inst {
public:
Arm32Code code;
InstType_Arm64 instType;
InstArm64(uint32_t code) {
this->code.code = code;
instType = initType();
}
private:
int instLen() const override {
return 4;
}
InstArch instArch() const override {
return Arm64;
}
bool pcRelated() override {
return instType < InstType_Arm64::PC_NO_RELATED;
}
InstType_Arm64 initType() {
return InstType_Arm64::PC_NO_RELATED;
}
};
void InstDecode::decode(void *codeStart, Size codeLen, InstVisitor *visitor) {
Size offset = 0;
Inst *inst = nullptr;
codeStart = Trampoline::getThumbCodeAddress(static_cast<Code>(codeStart));
Size codeAddr = reinterpret_cast<Size>(codeStart);
while (offset <= codeLen) {
uint32_t ram32 = *reinterpret_cast<uint32_t *>(codeAddr + offset);
inst = new InstArm64(ram32);
if (!visitor->visit(inst, offset, codeLen)) {
delete inst;
break;
}
offset += inst->instLen();
delete inst;
}
}
}
#endif
\ No newline at end of file
......@@ -5,7 +5,7 @@
SandHook::TrampolineManager trampolineManager;
int SDK_INT = 0;
extern "C" int SDK_INT = 0;
enum HookMode {
AUTO = 0,
......@@ -19,8 +19,8 @@ Java_com_swift_sandhook_SandHook_initNative(JNIEnv *env, jclass type, jint sdk)
// TODO
SDK_INT = sdk;
SandHook::CastArtMethod::init(env, sdk);
trampolineManager.init(sdk, SandHook::CastArtMethod::entryPointQuickCompiled->getOffset());
SandHook::CastArtMethod::init(env);
trampolineManager.init(SandHook::CastArtMethod::entryPointQuickCompiled->getOffset());
initHideApi(env, sdk);
return JNI_TRUE;
......@@ -182,10 +182,7 @@ Java_com_swift_sandhook_SandHook_hookMethod(JNIEnv *env, jclass type, jobject or
label_hook:
char *msg;
if (isInlineHook && trampolineManager.canSafeInline(origin, msg)) {
if (isInlineHook && trampolineManager.canSafeInline(origin)) {
return static_cast<jboolean>(doHookWithInline(env, origin, hook, backup));
} else {
return static_cast<jboolean>(doHookWithReplacement(env, origin, hook, backup));
......
......@@ -3,6 +3,9 @@
//
#include "../includes/trampoline_manager.h"
#include "../includes/trampoline.h"
#include "../includes/inst.h"
extern int SDK_INT;
namespace SandHook {
......@@ -18,18 +21,35 @@ namespace SandHook {
return size;
}
bool TrampolineManager::canSafeInline(mirror::ArtMethod *method, char *msg) {
class PCRelatedCheckVisitor : public InstVisitor {
public:
bool pcRelated = false;
bool visit(Inst *inst, Size offset, Size length) override {
if (inst->pcRelated()) {
pcRelated = true;
return false;
}
return true;
}
};
bool TrampolineManager::canSafeInline(mirror::ArtMethod *method) {
//check size
if (!method->isNative()) {
uint32_t originCodeSize = sizeOfEntryCode(method);
if (originCodeSize < SIZE_DIRECT_JUMP_TRAMPOLINE) {
msg = "code entry size < inject code size";
return false;
}
}
//TODO
//check pc relate inst
return true;
PCRelatedCheckVisitor visitor;
InstDecode::decode(method->getQuickCodeEntry(), SIZE_DIRECT_JUMP_TRAMPOLINE, &visitor);
return !visitor.pcRelated;
}
Code TrampolineManager::allocExecuteSpace(Size size) {
......
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