Unverified Commit 6a4150d7 authored by ganyao114's avatar ganyao114 Committed by GitHub

Merge pull request #13 from SwiftOSSite/native_hook

Native hook
parents c6f7398e 44246cfd
...@@ -27,5 +27,6 @@ dependencies { ...@@ -27,5 +27,6 @@ dependencies {
androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation project(':hooklib') implementation project(':hooklib')
implementation project(':nativehook')
implementation project(':xposedcompat') implementation project(':xposedcompat')
} }
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.4.1)
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
add_library( # Sets the name of the library.
sandhook-native
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/sandhook_native.cpp
src/main/cpp/decoder/decoder.cpp
src/main/cpp/archs/arm64/assembler/assembler_a64.cpp
src/main/cpp/archs/arm64/inst/inst_arm64.cpp
src/main/cpp/archs/arm64/register/register_a64.cpp
src/main/cpp/archs/arm64/register/register_list_a64.cpp
src/main/cpp/archs/arm64/decoder/decoder_arm64.cpp
src/main/cpp/archs/arm64/relocate/code_relocate_a64.cpp
src/main/cpp/archs/arm32/inst/inst_arm32.cpp
src/main/cpp/archs/arm32/register/register_a32.cpp
src/main/cpp/relocate/code_relocate.cpp
src/main/cpp/elf/elf.cpp
src/main/cpp/assembler/assembler.cpp
src/main/cpp/buffer/code_buffer.cpp
src/main/cpp/utils/platform.cpp
src/main/cpp/hook/hook.cpp
)
include_directories(
src/main/cpp/asm
src/main/cpp/decoder
src/main/cpp/elf
src/main/cpp/utils
src/main/cpp/includes
src/main/cpp/buffer
src/main/cpp/archs/arm64/inst
src/main/cpp/archs/arm64/register
src/main/cpp/archs/arm64/decoder
src/main/cpp/archs/arm64/assembler
src/main/cpp/archs/arm64/relocate
src/main/cpp/archs/arm32/inst
src/main/cpp/archs/arm32/register
)
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library.
sandhook-native
# Links the target library to the log library
# included in the NDK.
${log-lib} )
add_definitions(-std=c++11)
ENABLE_LANGUAGE(ASM)
\ No newline at end of file
apply plugin: 'com.android.library'
android {
compileSdkVersion 28
defaultConfig {
minSdkVersion 16
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
arguments '-DBUILD_TESTING=OFF'
cppFlags "-frtti -fexceptions -Wpointer-arith"
abiFilters 'armeabi-v7a', 'arm64-v8a'
}
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
package com.swift.sandhook.nativehook;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();
assertEquals("com.swift.sandhook.nativehook.test", appContext.getPackageName());
}
}
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.swift.sandhook.nativehook" />
//
// Created by swift on 2019/5/12.
//
#include "inst_arm32.h"
//// STR IMM
//A64_STR_IMM::A64_STR_IMM() {}
//
//A64_STR_IMM::A64_STR_IMM(STRUCT_A64(STR_IMM) *inst) : InstructionA64(inst) {
// decode(inst);
//}
//
//A64_STR_IMM::A64_STR_IMM(RegisterA64 &rt, const MemOperand &operand) : rt(&rt), operand(operand) {}
//
//A64_STR_IMM::A64_STR_IMM(Condition condition, RegisterA64 &rt, const MemOperand &operand)
// : condition(condition), rt(&rt), operand(operand) {}
//
//AddrMode A64_STR_IMM::decodeAddrMode() {
// if (get()->P == 1 && get()->W == 0) {
// return Offset;
// } else if (get()->P == 0 && get()->W == 0) {
// return PostIndex;
// } else if (get()->P == 1 && get()->W == 1) {
// return PreIndex;
// } else {
// valid = false;
// return NonAddrMode;
// }
//}
//
//void A64_STR_IMM::decode(STRUCT_A64(STR_IMM) *inst) {
// imm32 = zeroExtend32(12, inst->imm12);
// condition = Condition(inst->cond);
// operand.addr_mode = decodeAddrMode();
// index = inst->P == 1;
// wback = inst->P == 1 || inst->W == 0;
// add = inst->U == 0;
// rt = XReg(static_cast<U8>(inst->rt));
// operand.base = XReg(static_cast<U8>(inst->rn));
// operand.offset = add ? imm32 : -imm32;
//}
//
//
//void A64_STR_IMM::assembler() {
// INST_DCHECK(condition, Condition::nv)
//
//}
\ No newline at end of file
//
// Created by swift on 2019/5/12.
//
#ifndef SANDHOOK_NH_INST_ARM32_H
#define SANDHOOK_NH_INST_ARM32_H
namespace SandHook {
namespace Asm {
// class INST_A64(STR_IMM) : public InstructionA64<STRUCT_A64(STR_IMM)> {
// public:
// A64_STR_IMM();
//
// A64_STR_IMM(STRUCT_A64(STR_IMM) *inst);
//
// A64_STR_IMM(RegisterA64 &rt, const MemOperand &operand);
//
// A64_STR_IMM(Condition condition, RegisterA64 &rt, const MemOperand &operand);
//
// DEFINE_IS_EXT(STR_IMM, TEST_INST_FIELD(opcode, OPCODE_A64(STR_IMM)) && TEST_INST_FIELD(unkown1_0, 0) && TEST_INST_FIELD(unkown2_0, 0))
//
// inline U32 instCode() override {
// return STR_x;
// }
//
// void decode(STRUCT_A64(STR_IMM) *inst) override;
//
// void assembler() override;
//
// AddrMode getAddrMode() {
// return operand.addr_mode;
// }
//
// private:
// AddrMode decodeAddrMode();
//
// public:
// Condition condition = Condition::al;
// RegisterA64* rt;
// MemOperand operand = MemOperand(nullptr);
// private:
// bool wback;
// U32 imm32;
// bool add;
// bool index;
//};
}
}
#endif //SANDHOOK_NH_INST_ARM32_H
//
// Created by swift on 2019/5/12.
//
#ifndef SANDHOOK_NH_INST_STRCUT_ARM32_H
#define SANDHOOK_NH_INST_STRCUT_ARM32_H
#include "../../../asm/instruction.h"
#define STRUCT_A32(X) A32_STRUCT_##X
#define OPCODE_A32(X) A32_OPCODE_##X
#define DEFINE_OPCODE(X, V) const U32 OPCODE_A32(X) = V;
#define DEFINE_STRUCT_A32(X) struct STRUCT_A32(X) : public Base
DEFINE_OPCODE(STR_IMM, 0b010)
DEFINE_STRUCT_A32(STR_IMM) {
InstA64 imm12:12;
InstA64 rt:4;
InstA64 rn:4;
InstA64 unkown2_0:1;
InstA64 W:1;
InstA64 unkown1_0:1;
InstA64 U:1;
InstA64 P:1;
InstA64 opcode:3;
InstA64 cond:4;
};
#endif //SANDHOOK_NH_INST_STRCUT_ARM32_H
//
// Created by swift on 2019/5/12.
//
#include "register_a32.h"
SandHook::Asm::RegisterA32::RegisterA32(U8 code) : Register(code) {
}
SandHook::Asm::RegisterA32::RegisterA32() {
}
//
// Created by swift on 2019/5/12.
//
#ifndef SANDHOOK_NH_REGISTER_A32_H
#define SANDHOOK_NH_REGISTER_A32_H
#include "base.h"
#include "register.h"
namespace SandHook {
namespace Asm {
class RegisterA32 : public Register {
public:
enum RegisterType {
// The kInvalid value is used to detect uninitialized static instances,
// which are always zero-initialized before any constructors are called.
kInvalid = 0,
kRegister,
kVRegister,
kFPRegister = kVRegister,
kNoRegister
};
RegisterA32();
RegisterA32(U8 code);
};
}
}
#endif //SANDHOOK_NH_REGISTER_A32_H
//
// Created by swift on 2019/5/11.
//
#include "assembler_a64.h"
using namespace SandHook::Assembler;
AssemblerA64::AssemblerA64(CodeBuffer* codeBuffer) {
codeContainer.setCodeBuffer(codeBuffer);
}
void *AssemblerA64::getPC() {
return reinterpret_cast<void *>(codeContainer.curPc);
}
void *AssemblerA64::getStartPC() {
return reinterpret_cast<void *>(codeContainer.startPc);
}
void AssemblerA64::allocBufferFirst(U32 size) {
codeContainer.allocBufferFirst(size);
}
void *AssemblerA64::finish() {
codeContainer.commit();
return reinterpret_cast<void *>(codeContainer.startPc);
}
void AssemblerA64::Emit(U64 data64) {
Emit(reinterpret_cast<Unit<Base>*>(new Data64(data64)));
}
void AssemblerA64::Emit(U32 data32) {
Emit(reinterpret_cast<Unit<Base>*>(new Data32(data32)));
}
void AssemblerA64::Emit(Unit<Base> *unit) {
codeContainer.append(unit);
}
void
AssemblerA64::MoveWide(RegisterA64 &rd, INST_A64(MOV_WIDE)::OP op, U64 imme,
INST_A64(MOV_WIDE)::Shift shift) {
Emit(reinterpret_cast<Unit<Base> *>(new INST_A64(MOV_WIDE)(op, &rd, imme, shift)));
}
void AssemblerA64::Mov(WRegister &rd, U32 imme) {
const U16 h0 = BITS16L(imme);
const U16 h1 = BITS16H(imme);
Movz(rd, h0, INST_A64(MOV_WIDE)::Shift0);
Movk(rd, h1, INST_A64(MOV_WIDE)::Shift1);
}
void AssemblerA64::Mov(XRegister &rd, U64 imme) {
const U32 wl = BITS32L(imme);
const U32 wh = BITS32H(imme);
const U16 h0 = BITS16L(wl);
const U16 h1 = BITS16H(wl);
const U16 h2 = BITS16L(wh);
const U16 h3 = BITS16H(wh);
Movz(rd, h0, INST_A64(MOV_WIDE)::Shift0);
Movk(rd, h1, INST_A64(MOV_WIDE)::Shift1);
Movk(rd, h2, INST_A64(MOV_WIDE)::Shift2);
Movk(rd, h3, INST_A64(MOV_WIDE)::Shift3);
}
void AssemblerA64::Movz(RegisterA64 &rd, U64 imme,
INST_A64(MOV_WIDE)::Shift shift) {
MoveWide(rd, INST_A64(MOV_WIDE)::MOV_WideOp_Z, imme, shift);
}
void AssemblerA64::Movk(RegisterA64 &rd, U64 imme,
INST_A64(MOV_WIDE)::Shift shift) {
MoveWide(rd, INST_A64(MOV_WIDE)::MOV_WideOp_K, imme, shift);
}
void AssemblerA64::Movn(RegisterA64 &rd, U64 imme,
INST_A64(MOV_WIDE)::Shift shift) {
MoveWide(rd, INST_A64(MOV_WIDE)::MOV_WideOp_N, imme, shift);
}
void AssemblerA64::Br(XRegister &rn) {
Emit(reinterpret_cast<Unit<Base> *>(new INST_A64(BR_BLR_RET)(INST_A64(BR_BLR_RET)::BR, rn)));
}
void AssemblerA64::B(Off offset) {
Emit(reinterpret_cast<Unit<Base> *>(new INST_A64(B_BL)(INST_A64(B_BL)::B, offset)));
}
void AssemblerA64::B(Label *label) {
Emit(reinterpret_cast<Unit<Base> *>(new INST_A64(B_BL)(INST_A64(B_BL)::B, *label)));
}
void AssemblerA64::Bl(Off offset) {
Emit(reinterpret_cast<Unit<Base> *>(new INST_A64(B_BL)(INST_A64(B_BL)::BL, offset)));
}
void AssemblerA64::Bl(Label *label) {
Emit(reinterpret_cast<Unit<Base> *>(new INST_A64(B_BL)(INST_A64(B_BL)::BL, *label)));
}
void AssemblerA64::B(Condition condition, Off offset) {
Emit(reinterpret_cast<Unit<Base> *>(new INST_A64(B_COND)(condition, offset)));
}
void AssemblerA64::B(Condition condition, Label *label) {
Emit(reinterpret_cast<Unit<Base> *>(new INST_A64(B_COND)(condition, *label)));
}
void AssemblerA64::Tbz(RegisterA64 &rt, U32 bit, Label *label) {
Emit((reinterpret_cast<Unit<Base> *>(new INST_A64(TBZ_TBNZ)(INST_A64(TBZ_TBNZ)::TBZ, rt, bit, *label))));
}
void AssemblerA64::Tbz(RegisterA64 &rt, U32 bit, Off offset) {
Emit((reinterpret_cast<Unit<Base> *>(new INST_A64(TBZ_TBNZ)(INST_A64(TBZ_TBNZ)::TBZ, rt, bit, offset))));
}
void AssemblerA64::Tbnz(RegisterA64 &rt, U32 bit, Off offset) {
Emit((reinterpret_cast<Unit<Base> *>(new INST_A64(TBZ_TBNZ)(INST_A64(TBZ_TBNZ)::TBNZ, rt, bit, offset))));
}
void AssemblerA64::Tbnz(RegisterA64 &rt, U32 bit, Label *label) {
Emit((reinterpret_cast<Unit<Base> *>(new INST_A64(TBZ_TBNZ)(INST_A64(TBZ_TBNZ)::TBNZ, rt, bit, *label))));
}
void AssemblerA64::Cbz(RegisterA64 &rt, Off offset) {
Emit((reinterpret_cast<Unit<Base> *>(new INST_A64(CBZ_CBNZ)(INST_A64(CBZ_CBNZ)::CBZ, offset, rt))));
}
void AssemblerA64::Cbz(RegisterA64 &rt, Label *label) {
Emit((reinterpret_cast<Unit<Base> *>(new INST_A64(CBZ_CBNZ)(INST_A64(CBZ_CBNZ)::CBZ, *label, rt))));
}
void AssemblerA64::Cbnz(RegisterA64 &rt, Off offset) {
Emit((reinterpret_cast<Unit<Base> *>(new INST_A64(CBZ_CBNZ)(INST_A64(CBZ_CBNZ)::CBNZ, offset, rt))));
}
void AssemblerA64::Cbnz(RegisterA64 &rt, Label *label) {
Emit((reinterpret_cast<Unit<Base> *>(new INST_A64(CBZ_CBNZ)(INST_A64(CBZ_CBNZ)::CBNZ, *label, rt))));
}
void AssemblerA64::Str(RegisterA64 &rt, const MemOperand& memOperand) {
if (memOperand.addr_mode == Offset) {
Emit(reinterpret_cast<Unit<Base> *>(new INST_A64(STR_UIMM)(rt, memOperand)));
} else {
Emit(reinterpret_cast<Unit<Base> *>(new INST_A64(STR_IMM)(rt, memOperand)));
}
}
void AssemblerA64::Ldr(RegisterA64 &rt, const MemOperand &memOperand) {
if (memOperand.addr_mode == Offset) {
Emit(reinterpret_cast<Unit<Base> *>(new INST_A64(LDR_UIMM)(rt, memOperand)));
} else {
Emit(reinterpret_cast<Unit<Base> *>(new INST_A64(LDR_IMM)(rt, memOperand)));
}
}
void AssemblerA64::Ldr(RegisterA64 &rt, Label &label) {
Emit(reinterpret_cast<Unit<Base> *>(new INST_A64(LDR_LIT)(rt.isX() ? INST_A64(LDR_LIT)::LDR_X : INST_A64(LDR_LIT)::LDR_W, rt, label)));
}
void AssemblerA64::Ldrsw(XRegister &rt, const MemOperand& memOperand) {
if (memOperand.addr_mode == Offset) {
Emit(reinterpret_cast<Unit<Base> *>(new INST_A64(LDRSW_UIMM)(rt, memOperand)));
} else {
Emit(reinterpret_cast<Unit<Base> *>(new INST_A64(LDRSW_IMM)(rt, memOperand)));
}
}
void AssemblerA64::Pop(RegisterA64 &rd) {
if (rd.isX()) {
Ldr(rd, MemOperand(&SP, -1 * rd.getWideInBytes(), PreIndex));
} else {
Ldr(rd, MemOperand(&WSP, -1 * rd.getWideInBytes(), PreIndex));
}
}
void AssemblerA64::Push(RegisterA64 &rt) {
if (rt.isX()) {
Str(rt, MemOperand(&SP, -1 * rt.getWideInBytes(), PreIndex));
} else {
Str(rt, MemOperand(&WSP, -1 * rt.getWideInBytes(), PreIndex));
}
}
void AssemblerA64::Cmp(RegisterA64 &rn, const Operand &operand) {
}
//
// Created by swift on 2019/5/11.
//
#ifndef SANDHOOK_NH_ASSEMBLER_A64_H
#define SANDHOOK_NH_ASSEMBLER_A64_H
#include "assembler.h"
#include "register_a64.h"
#include "inst_arm64.h"
namespace SandHook {
namespace Assembler {
class AssemblerA64 {
public:
AssemblerA64(CodeBuffer* codeBuffer);
void allocBufferFirst(U32 size);
void* getStartPC();
void* getPC();
void* finish();
void Emit(U32 data32);
void Emit(U64 data64);
void Emit(Unit<Base>* unit);
void MoveWide(RegisterA64& rd, INST_A64(MOV_WIDE)::OP op, U64 imme, INST_A64(MOV_WIDE)::Shift shift);
void Movz(RegisterA64& rd, U64 imme, INST_A64(MOV_WIDE)::Shift shift);
void Movk(RegisterA64& rd, U64 imme, INST_A64(MOV_WIDE)::Shift shift);
void Movn(RegisterA64& rd, U64 imme, INST_A64(MOV_WIDE)::Shift shift);
void Mov(WRegister& rd, U32 imme);
void Mov(XRegister& rd, U64 imme);
void Br(XRegister& rn);
void B(Off offset);
void B(Label* label);
void Bl(Off offset);
void Bl(Label* label);
void B(Condition condition, Off offset);
void B(Condition condition, Label* label);
void Tbz(RegisterA64 &rt, U32 bit, Off offset);
void Tbz(RegisterA64 &rt, U32 bit, Label* label);
void Tbnz(RegisterA64 &rt, U32 bit, Off offset);
void Tbnz(RegisterA64 &rt, U32 bit, Label* label);
void Cbz(RegisterA64 &rt, Off offset);
void Cbz(RegisterA64 &rt, Label* label);
void Cbnz(RegisterA64 &rt, Off offset);
void Cbnz(RegisterA64 &rt, Label* label);
void Str(RegisterA64& rt, const MemOperand& memOperand);
void Ldr(RegisterA64& rt, const MemOperand& memOperand);
void Ldr(RegisterA64& rt, Label& label);
void Ldrsw(XRegister& rt, const MemOperand& memOperand);
void Pop(RegisterA64& rt);
void Push(RegisterA64& rt);
void Subs();
void Cmp(RegisterA64& rn, const Operand& operand);
public:
CodeContainer codeContainer = CodeContainer(nullptr);
};
}
}
#endif //SANDHOOK_NH_ASSEMBLER_A64_H
//
// Created by swift on 2019/5/6.
//
#include <inst_arm64.h>
#include "decoder_arm64.h"
using namespace SandHook::Decoder;
#define CASE(X) \
if (IS_OPCODE(*pc, X)) { \
STRUCT_A64(X) *s = reinterpret_cast<STRUCT_A64(X) *>(pc); \
unit = reinterpret_cast<Unit<Base> *>(new INST_A64(X)(*s)); \
goto label_matched; \
}
void Arm64Decoder::decode(void *codeStart, Addr codeLen, InstVisitor &visitor) {
InstA64 *pc = reinterpret_cast<InstA64 *>(codeStart);
Addr endAddr = (Addr) codeStart + codeLen;
Unit<Base>* unit = nullptr;
while((Addr) pc < endAddr) {
CASE(MOV_WIDE)
CASE(MOV_REG)
CASE(ADR_ADRP)
CASE(LDR_LIT)
CASE(LDR_IMM)
CASE(LDR_UIMM)
CASE(LDRSW_IMM)
CASE(LDRSW_UIMM)
CASE(STR_IMM)
CASE(STR_UIMM)
CASE(B_BL)
CASE(B_COND)
CASE(BR_BLR_RET)
CASE(CBZ_CBNZ)
CASE(TBZ_TBNZ)
CASE(SUB_EXT_REG)
CASE(SVC)
CASE(EXCEPTION_GEN)
label_matched:
if (unit == nullptr) {
unit = reinterpret_cast<Unit<Base> *>(new A64_UNKNOW(*reinterpret_cast<STRUCT_A64(UNKNOW) *>(pc)));
}
if (!visitor.visit(unit, pc)) {
break;
}
pc = reinterpret_cast<InstA64 *>((Addr)pc + unit->size());
unit = nullptr;
}
}
//
// Created by swift on 2019/5/6.
//
#ifndef SANDHOOK_NH_DECODER_ARM64_H
#define SANDHOOK_NH_DECODER_ARM64_H
#include "decoder.h"
namespace SandHook {
namespace Decoder {
class Arm64Decoder : public InstDecoder {
public:
void decode(void *codeStart, Addr codeLen, InstVisitor &visitor) override;
};
}
}
#endif //SANDHOOK_NH_DECODER_ARM64_H
This diff is collapsed.
This diff is collapsed.
//
// Created by swift on 2019/5/8.
//
#ifndef SANDHOOK_NH_INST_CODE_ARM64_H
#define SANDHOOK_NH_INST_CODE_ARM64_H
#include "inst_struct_aarch64.h"
enum InstCodeA64 {
UNKNOW,
MOV_WIDE,
MOV_REG,
ADR_ADRP,
LDR_LIT,
LDR_UIMM,
LDR_IMM,
LDRSW_UIMM,
LDRSW_IMM,
STR_IMM,
STR_UIMM,
B_BL,
B_COND,
BR_BLR_RET,
CBZ_CBNZ,
TBZ_TBNZ,
SUB_EXT_REG,
EXCEPTION_GEN,
SVC
};
#endif //SANDHOOK_NH_INST_CODE_ARM64_H
//
// Created by swift on 2019/5/5.
//
#ifndef SANDHOOK_NH_INST_AARCH64_H
#define SANDHOOK_NH_INST_AARCH64_H
#include "instruction.h"
#include "inst_code_arm64.h"
#define STRUCT_A64(X) A64_STRUCT_##X
#define OPCODE_A64(X) A64_OPCODE_##X
#define DEFINE_OPCODE(X, V) const U32 OPCODE_A64(X) = V;
#define DEFINE_STRUCT_A64(X) struct STRUCT_A64(X) : public Base
enum ImmBranchType {
UnknownBranchType = 0,
CondBranchType = 1,
UncondBranchType = 2,
CompareBranchType = 3,
TestBranchType = 4
};
// Condition codes.
enum Condition {
eq = 0, // Z set Equal.
ne = 1, // Z clear Not equal.
cs = 2, // C set Carry set.
cc = 3, // C clear Carry clear.
mi = 4, // N set Negative.
pl = 5, // N clear Positive or zero.
vs = 6, // V set Overflow.
vc = 7, // V clear No overflow.
hi = 8, // C set, Z clear Unsigned higher.
ls = 9, // C clear or Z set Unsigned lower or same.
ge = 10, // N == V Greater or equal.
lt = 11, // N != V Less than.
gt = 12, // Z clear, N == V Greater than.
le = 13, // Z set or N != V Less then or equal
al = 14, // Always.
nv = 15, // Behaves as always/al.
// Aliases.
hs = cs, // C set Unsigned higher or same.
lo = cc // C clear Unsigned lower.
};
enum Shift {
NO_SHIFT = -1,
LSL = 0x0,
LSR = 0x1,
ASR = 0x2,
ROR = 0x3,
MSL = 0x4
};
enum Extend {
NO_EXTEND = -1,
UXTB = 0,
UXTH = 1,
UXTW = 2,
UXTX = 3,
SXTB = 4,
SXTH = 5,
SXTW = 6,
SXTX = 7
};
enum FieldWide {
WideReg = 5,
};
//unknow inst
DEFINE_STRUCT_A64(UNKNOW) {
InstA64 raw;
};
#define IMM_LO_W 2
#define IMM_HI_W 19
DEFINE_OPCODE(ADR_ADRP, 0b10000)
struct STRUCT_A64(ADR_ADRP) {
InstA64 rd:WideReg;
InstA64 immhi:IMM_HI_W;
InstA64 opcode:5;
InstA64 immlo:IMM_LO_W;
InstA64 op:1;
};
DEFINE_OPCODE(MOV_WIDE, 0b100101)
DEFINE_STRUCT_A64(MOV_WIDE) {
InstA64 rd:WideReg;
InstA64 imm16:16;
InstA64 hw:2;
InstA64 opcode:6;
InstA64 opc:2;
InstA64 sf:1;
};
DEFINE_OPCODE(MOV_REG_1, 0b0101010000)
DEFINE_OPCODE(MOV_REG_2, 0b00000011111)
DEFINE_STRUCT_A64(MOV_REG) {
InstA64 rd:WideReg;
InstA64 opcode2:11;
InstA64 rm:WideReg;
InstA64 opcode1:10;
InstA64 sf:1;
};
DEFINE_OPCODE(B_BL, 0b00101)
DEFINE_STRUCT_A64(B_BL) {
InstA64 imm26:26;
InstA64 opcode:5;
InstA64 op:1;
};
DEFINE_OPCODE(CBZ_CBNZ, 0b011010)
DEFINE_STRUCT_A64(CBZ_CBNZ) {
InstA64 rt:WideReg;
InstA64 imm19:19;
InstA64 op:1;
InstA64 opcode:6;
InstA64 sf:1;
};
DEFINE_OPCODE(B_COND, 0b01010100)
DEFINE_STRUCT_A64(B_COND) {
InstA64 cond:4;
InstA64 unkown_0:1;
InstA64 imm19:19;
InstA64 opcode:8;
};
DEFINE_OPCODE(TBZ_TBNZ, 0b011011)
DEFINE_STRUCT_A64(TBZ_TBNZ) {
InstA64 rt:WideReg;
InstA64 imm14:14;
InstA64 b40:5;
InstA64 op:1;
InstA64 opcode:6;
InstA64 b5:1;
};
DEFINE_OPCODE(LDR_LIT, 0b011000)
DEFINE_STRUCT_A64(LDR_LIT) {
InstA64 rt:WideReg;
InstA64 imm19:19;
InstA64 opcode:6;
InstA64 op:2;
};
DEFINE_OPCODE(LDR_UIMM, 0b11100101)
DEFINE_STRUCT_A64(LDR_UIMM) {
InstA64 rt:WideReg;
InstA64 rn:WideReg;
InstA64 imm12:12;
InstA64 opcode:8;
InstA64 size:2;
};
DEFINE_OPCODE(LDR_IMM, 0b111000010)
DEFINE_STRUCT_A64(LDR_IMM) {
InstA64 rt:WideReg;
InstA64 rn:WideReg;
InstA64 addrmode:2;
InstA64 imm9:9;
InstA64 opcode:9;
InstA64 size:2;
};
DEFINE_OPCODE(LDRSW_UIMM, 0b11100110)
struct STRUCT_A64(LDRSW_UIMM) : public STRUCT_A64(LDR_UIMM) {
};
DEFINE_OPCODE(LDRSW_IMM, 0b111000100)
struct STRUCT_A64(LDRSW_IMM) : public STRUCT_A64(LDR_IMM) {
};
DEFINE_OPCODE(BR_BLR_RET_1, 0b110101100)
DEFINE_OPCODE(BR_BLR_RET_2, 0b11111000000)
DEFINE_OPCODE(BR_BLR_RET_3, 0b00000)
DEFINE_STRUCT_A64(BR_BLR_RET) {
InstA64 opcode3:5;
InstA64 rn:WideReg;
InstA64 opcode2:11;
InstA64 op:2;
InstA64 opcode1:9;
};
DEFINE_OPCODE(STR_IMM, 0b111000000)
DEFINE_STRUCT_A64(STR_IMM) {
InstA64 rt:WideReg;
InstA64 rn:WideReg;
InstA64 addrmode:2;
InstA64 imm9:9;
InstA64 opcode:9;
InstA64 size:2;
};
DEFINE_OPCODE(STR_UIMM, 0b11100100)
DEFINE_STRUCT_A64(STR_UIMM) {
InstA64 rt:WideReg;
InstA64 rn:WideReg;
InstA64 imm12:12;
InstA64 opcode:8;
InstA64 size:2;
};
DEFINE_OPCODE(SUB_EXT_REG_1, 0b1)
DEFINE_OPCODE(SUB_EXT_REG_2, 0b01011001)
DEFINE_STRUCT_A64(SUB_EXT_REG) {
InstA64 rd:WideReg;
InstA64 rn:WideReg;
InstA64 imm3:3;
InstA64 option:3;
InstA64 rm:WideReg;
InstA64 opcode2:8;
InstA64 S:1;
InstA64 opcode1:1;
InstA64 sf:1;
};
DEFINE_OPCODE(EXCEPTION_GEN_1, 0b11010100)
DEFINE_OPCODE(EXCEPTION_GEN_2, 0b000)
DEFINE_STRUCT_A64(EXCEPTION_GEN) {
InstA64 ll:2;
InstA64 opcode2:3;
InstA64 imm16:16;
InstA64 op:3;
InstA64 opcode1:8;
};
struct STRUCT_A64(SVC) : STRUCT_A64(EXCEPTION_GEN) {
};
#endif //SANDHOOK_NH_INST_AARCH64_H
//
// Created by swift on 2019/5/8.
//
#include "register_a64.h"
#include "register_list_a64.h"
using namespace SandHook::Asm;
RegisterA64::RegisterA64() {}
RegisterA64::RegisterA64(U8 code) : Register(code) {}
XRegister* XRegister::registers[AARCH64_REGISTER_COUNT] = {
#define DEFINE_REGISTERS_X(N) \
&X##N,
AARCH64_REGISTER_CODE_LIST(DEFINE_REGISTERS_X)
#undef DEFINE_REGISTERS_X
};
XRegister::XRegister(U8 code) : RegisterA64(code) {}
XRegister::XRegister() {}
U8 XRegister::getWide() {
return Reg64Bit;
}
WRegister* WRegister::registers[AARCH64_REGISTER_COUNT] = {
#define DEFINE_REGISTERS_W(N) \
&W##N,
AARCH64_REGISTER_CODE_LIST(DEFINE_REGISTERS_W)
#undef DEFINE_REGISTERS_W
};
WRegister::WRegister(U8 code) : RegisterA64(code) {}
WRegister::WRegister() {}
U8 WRegister::getWide() {
return Reg32Bit;
}
//
// Created by swift on 2019/5/8.
//
#ifndef SANDHOOK_NH_REGISTER_A64_H
#define SANDHOOK_NH_REGISTER_A64_H
#include "register.h"
namespace SandHook {
namespace Asm {
class RegisterA64 : public Register {
public:
enum RegisterType {
// The kInvalid value is used to detect uninitialized static instances,
// which are always zero-initialized before any constructors are called.
kInvalid = 0,
kRegister,
kVRegister,
kFPRegister = kVRegister,
kNoRegister
};
enum SpecialRegisters {
kFpRegCode = 29,
kLinkRegCode = 30,
kSpRegCode = 31,
kZeroRegCode = 31,
kSPRegInternalCode = 63
};
RegisterA64();
RegisterA64(U8 code);
inline bool isX() {
return is64Bit();
}
inline bool isW() {
return is32Bit();
}
};
class XRegister : public RegisterA64 {
public:
XRegister();
XRegister(U8 code);
U8 getWide() override;
static XRegister* get(U8 code) {
return registers[code];
}
private:
static XRegister* registers[];
};
class WRegister : public RegisterA64 {
public:
WRegister();
WRegister(U8 code);
U8 getWide() override;
static WRegister* get(U8 code) {
return registers[code];
}
private:
static WRegister* registers[];
};
}
}
#endif //SANDHOOK_NH_REGISTER_A64_H
//
// Created by swift on 2019/5/9.
//
#include "register_list_a64.h"
#define INIT_REGISTERS(N) \
WRegister W##N = WRegister(N); \
XRegister X##N = XRegister(N);
AARCH64_REGISTER_CODE_LIST(INIT_REGISTERS)
#undef INIT_REGISTERS
WRegister WSP = WRegister(RegisterA64::kSPRegInternalCode);
XRegister SP = XRegister(RegisterA64::kSPRegInternalCode);
XRegister IP0 = X16;
XRegister IP1 = X17;
XRegister LR = X30;
//zero reg
XRegister XZR = X31;
WRegister WZR = W31;
RegisterA64 UnknowRegiser = RegisterA64(38);
//cmp....
#define ZeroRegFor(X) X.isX() ? XZR : WZR
\ No newline at end of file
//
// Created by swift on 2019/5/8.
//
#ifndef SANDHOOK_NH_REGISTER_LIST_A64_H
#define SANDHOOK_NH_REGISTER_LIST_A64_H
#include "register_a64.h"
#include "base.h"
using namespace SandHook::Asm;
// clang-format off
#define AARCH64_REGISTER_COUNT 32
#define AARCH64_REGISTER_CODE_LIST(R) \
R(0) R(1) R(2) R(3) R(4) R(5) R(6) R(7) \
R(8) R(9) R(10) R(11) R(12) R(13) R(14) R(15) \
R(16) R(17) R(18) R(19) R(20) R(21) R(22) R(23) \
R(24) R(25) R(26) R(27) R(28) R(29) R(30) R(31)
#define DEFINE_REGISTERS(N) \
extern WRegister W##N; \
extern XRegister X##N;
AARCH64_REGISTER_CODE_LIST(DEFINE_REGISTERS)
#undef DEFINE_REGISTERS
extern WRegister WSP;
extern XRegister SP;
extern XRegister IP0;
extern XRegister IP1;
extern XRegister LR;
//zero reg
extern XRegister XZR;
extern WRegister WZR;
extern RegisterA64 UnknowRegiser;
#define XReg(N) XRegister::get(N)
#define WReg(N) WRegister::get(N)
#endif //SANDHOOK_NH_REGISTER_LIST_A64_H
//
// Created by swift on 2019/5/12.
//
#include "code_relocate_a64.h"
#include "decoder_arm64.h"
#define __ assemblerA64->
#define IMPL_RELOCATE(X) void CodeRelocateA64::relocate_##X (INST_A64(X)* inst, void* toPc) throw(ErrorCodeException)
#define CASE(X) \
case InstCodeA64::X: \
relocate_##X(reinterpret_cast<INST_A64(X)*>(instruction), toPc); \
break;
CodeRelocateA64::CodeRelocateA64(AssemblerA64 &assembler) : CodeRelocate(assembler.codeContainer) {
this->assemblerA64 = &assembler;
}
void* CodeRelocateA64::relocate(void *startPc, Addr len, void *toPc = nullptr) throw(ErrorCodeException) {
assemblerA64->allocBufferFirst(static_cast<U32>(len * 8));
void* curPc = assemblerA64->getPC();
Arm64Decoder decoder = Arm64Decoder();
if (toPc == nullptr) {
decoder.decode(startPc, len, *this);
} else {
//TODO
}
return curPc;
}
void* CodeRelocateA64::relocate(Instruction<Base> *instruction, void *toPc) throw(ErrorCodeException) {
void* curPc = assemblerA64->getPC();
if (!instruction->pcRelate()) {
__ Emit(instruction);
return curPc;
}
switch (instruction->instCode()) {
CASE(B_BL)
CASE(B_COND)
CASE(TBZ_TBNZ)
CASE(CBZ_CBNZ)
CASE(LDR_LIT)
CASE(ADR_ADRP)
default:
__ Emit(instruction);
}
return curPc;
}
IMPL_RELOCATE(B_BL) {
Addr targetAddr = inst->getImmPCOffsetTarget();
if (inst->op == inst->BL) {
__ Mov(LR, (Addr)inst->getPC() + inst->size());
}
__ Mov(IP1, targetAddr);
__ Br(IP1);
}
IMPL_RELOCATE(B_COND) {
Addr targetAddr = inst->getImmPCOffsetTarget();
Label *true_label = new Label();
Label *false_label = new Label();
__ B(inst->condition, true_label);
__ B(false_label);
__ Emit(true_label);
__ Mov(IP1, targetAddr);
__ Br(IP1);
__ Emit(false_label);
}
IMPL_RELOCATE(TBZ_TBNZ) {
Addr targetAddr = inst->getImmPCOffsetTarget();
Label *true_label = new Label();
Label *false_label = new Label();
if (inst->op == INST_A64(TBZ_TBNZ)::TBNZ) {
__ Tbnz(*inst->rt, inst->bit, true_label);
} else {
__ Tbz(*inst->rt, inst->bit, true_label);
}
__ B(false_label);
__ Emit(true_label);
__ Mov(IP1, targetAddr);
__ Br(IP1);
__ Emit(false_label);
}
IMPL_RELOCATE(CBZ_CBNZ) {
Addr targetAddr = inst->getImmPCOffsetTarget();
Label *true_label = new Label();
Label *false_label = new Label();
if (inst->op == INST_A64(CBZ_CBNZ)::CBNZ) {
__ Cbnz(*inst->rt, true_label);
} else {
__ Cbz(*inst->rt, true_label);
}
__ B(false_label);
__ Emit(true_label);
__ Mov(IP1, targetAddr);
__ Br(IP1);
__ Emit(false_label);
}
IMPL_RELOCATE(LDR_LIT) {
Addr targetAddr = inst->getImmPCOffsetTarget();
XRegister* rtX = XReg(inst->rt->getCode());
WRegister* rtW = WReg(inst->rt->getCode());
switch (inst->op) {
case INST_A64(LDR_LIT)::LDR_X:
__ Mov(*rtX, targetAddr);
__ Ldr(*rtW, MemOperand(rtX, 0, Offset));
break;
case INST_A64(LDR_LIT)::LDR_W:
__ Mov(*rtX, targetAddr);
__ Ldr(*rtX, MemOperand(rtX, 0, Offset));
break;
case INST_A64(LDR_LIT)::LDR_SW:
break;
case INST_A64(LDR_LIT)::LDR_PRFM:
__ Push(X0);
__ Mov(X0, targetAddr);
__ Ldrsw(X0, MemOperand(rtX, 0, Offset));
__ Pop(X0);
break;
}
}
IMPL_RELOCATE(ADR_ADRP) {
__ Mov(*inst->rd, inst->getImmPCOffsetTarget());
}
bool CodeRelocateA64::visit(Unit<Base> *unit, void *pc) {
relocate(reinterpret_cast<Instruction<Base> *>(unit), assemblerA64->getPC());
return true;
}
//
// Created by swift on 2019/5/12.
//
#ifndef SANDHOOK_NH_CODE_RELOCATE_A64_H
#define SANDHOOK_NH_CODE_RELOCATE_A64_H
#include "code_relocate.h"
#include "assembler_a64.h"
using namespace SandHook::Assembler;
using namespace SandHook::Decoder;
#define DEFINE_RELOCATE(X) void relocate_##X (INST_A64(X)* inst, void* toPc) throw(ErrorCodeException);
namespace SandHook {
namespace Asm {
class CodeRelocateA64 : public CodeRelocate {
public:
CodeRelocateA64(AssemblerA64 &assembler);
void* relocate(Instruction<Base> *instruction, void *toPc) throw(ErrorCodeException) override;
void* relocate(void *startPc, Addr len, void *toPc) throw(ErrorCodeException) override;
bool visit(Unit<Base> *unit, void *pc) override;
DEFINE_RELOCATE(B_BL)
DEFINE_RELOCATE(B_COND)
DEFINE_RELOCATE(TBZ_TBNZ)
DEFINE_RELOCATE(CBZ_CBNZ)
DEFINE_RELOCATE(LDR_LIT)
DEFINE_RELOCATE(ADR_ADRP)
private:
AssemblerA64* assemblerA64;
};
}
}
#endif //SANDHOOK_NH_CODE_RELOCATE_A64_H
//
// Created by SwiftGan on 2019/4/15.
//
#ifndef SANDHOOK_CPU_H
#define SANDHOOK_CPU_H
#endif //SANDHOOK_CPU_H
//
// Created by swift on 2019/5/10.
//
#ifndef SANDHOOK_NH_DATA_H
#define SANDHOOK_NH_DATA_H
#include "unit.h"
#define DATA(BITS) STRUCT_DATA_##BITS
#define DEFINE_DATA(BITS) \
struct DATA(BITS) : public Base { \
U##BITS raw_; \
public: \
DATA(BITS)(U##BITS r) { \
raw_ = r; \
} \
};
namespace SandHook {
namespace Asm {
template <typename DType>
class Data : public Unit<DType> {
public:
Data(DType raw) : Unit<DType>() {
this->set(raw);
}
inline UnitType unitType() override {
return UnitType::UnitData;
};
};
DEFINE_DATA(16)
class Data16 : public Data<DATA(16)> {
public:
Data16(U16 raw) : Data(DATA(16)(raw)) {}
};
DEFINE_DATA(32)
class Data32 : public Data<DATA(32)> {
public:
Data32(U32 raw) : Data(DATA(32)(raw)) {}
};
DEFINE_DATA(64)
class Data64 : public Data<DATA(64)> {
public:
Data64(U64 raw) : Data(DATA(64)(raw)) {}
};
}
}
#endif //SANDHOOK_NH_DATA_H
//
// Created by SwiftGan on 2019/4/15.
//
#ifndef SANDHOOK_IMME_H
#define SANDHOOK_IMME_H
#include "../includes/base.h"
namespace SandHook {
namespace Asm {
template <typename ImmeType>
class Imme {
public:
virtual ImmeType get() = 0;
virtual void set(ImmeType imme) = 0;
U8 size() {
return immeSize;
};
private:
//byte
U8 immeSize;
ImmeType value;
Arch arch;
InstType instType;
};
}
}
#endif //SANDHOOK_IMME_H
//
// Created by SwiftGan on 2019/4/15.
//
#ifndef SANDHOOK_INSTRUCTION_H
#define SANDHOOK_INSTRUCTION_H
#include "unit.h"
#include "label.h"
//aarch64
typedef U32 InstA64;
//arm32
typedef U32 InstA32;
//thumb16
typedef U16 InstT16;
//thumb32
typedef U32 InstT32;
#if defined(__aarch64__)
typedef U32 InstRaw;
#endif
#define INST_CHECK(X,V) \
CHECK(X,V, valid = false;)
#define INST_DCHECK(X,V) \
DCHECK(X,V, valid = false;)
#define INST_ASSERT(COND) \
if (COND) { \
valid = false; \
return; \
}
namespace SandHook {
namespace Asm {
template <typename Inst>
class Instruction : public Unit<Inst>, public LabelBinder {
public:
Instruction() {}
Instruction(Inst *inst) : Unit<Inst>(inst) {}
UnitType unitType() override {
return UnitType::UnitInst;
};
virtual InstType instType() {
return unknowInst;
}
virtual Arch arch() {
return unknowArch;
}
virtual U32 instCode() {
return 0;
};
virtual bool pcRelate() {
return false;
}
virtual bool unknow() {
return false;
}
inline bool isValid() const {
return valid;
}
virtual void onOffsetApply(Off offset) {}
void onLabelApply(Addr pc) override {
onOffsetApply(pc - this->getVPC());
}
inline void bindLabel(Label &l) {
label = &l;
l.addBinder(this);
}
virtual void decode(Inst* inst) {}
virtual void assembler() {}
protected:
bool valid = true;
Label* label = nullptr;
};
class Void : public Unit<Base> {
public:
Void(U32 size) : size_(size) {}
U32 size() override {
return size_;
}
private:
U32 size_;
};
}
}
#endif //SANDHOOK_INSTRUCTION_H
//
// Created by swift on 2019/5/10.
//
#ifndef SANDHOOK_NH_LABEL_H
#define SANDHOOK_NH_LABEL_H
#include "unit.h"
#include <list>
namespace SandHook {
namespace Asm {
class LabelBinder {
public:
virtual void onLabelApply(Addr pc) = 0;
};
class Label : public Unit<Base> {
public:
Label() {}
Label(void *pc) : pc(pc) {}
inline UnitType unitType() override {
return UnitType::UnitLabel;
}
inline U32 size() override {
return 0;
}
inline void setPC(void* pc) {
this->pc = pc;
}
inline void *getPC() override {
return pc;
}
inline void addBinder(LabelBinder* binder) {
binders.push_back(binder);
}
inline void removeBinder(LabelBinder* binder) {
binders.push_back(binder);
}
inline void bindLabel() {
std::list<LabelBinder*>::iterator binder;
for(binder = binders.begin();binder != binders.end(); ++binder) {
(*binder)->onLabelApply(getVPC());
}
}
private:
void* pc;
std::list<LabelBinder*> binders = std::list<LabelBinder*>();
};
}
}
#endif //SANDHOOK_NH_LABEL_H
//
// Created by SwiftGan on 2019/4/15.
//
#ifndef SANDHOOK_REGISTER_H
#define SANDHOOK_REGISTER_H
#include "../includes/base.h"
namespace SandHook {
namespace Asm {
enum RegVariant {
Reg32Bit = 32,
Reg64Bit = 64,
Reg128Bit = 128
};
class Register {
public:
Register() {}
Register(U8 code) : code(code) {}
inline U8 getCode() {
return code;
}
virtual bool isFP() {
return false;
};
virtual U8 getWide() {
return 0;
};
inline U8 getWideInBytes() {
return static_cast<U8>(getWide() / BITS_OF_BYTE);
};
inline bool is32Bit() {
return getWide() == Reg32Bit;
}
inline bool is64Bit() {
return getWide() == Reg64Bit;
}
inline bool is128Bit() {
return getWide() == Reg128Bit;
}
virtual bool is(const Register &rhs) {
return rhs.code == code;
}
bool operator==(const Register &rhs) const {
return code == rhs.code;
}
bool operator!=(const Register &rhs) const {
return !(rhs == *this);
}
private:
U8 code;
};
}
}
#endif //SANDHOOK_REGISTER_H
//
// Created by swift on 2019/5/10.
//
#ifndef SANDHOOK_NH_UNIT_H
#define SANDHOOK_NH_UNIT_H
#include <malloc.h>
#include "../includes/base.h"
namespace SandHook {
namespace Asm {
template <typename Raw>
class Unit {
public:
Unit() {
if (unitType() != UnitVoid) {
raw = reinterpret_cast<Raw *>(malloc(size()));
memset(raw, 0, size());
auto_alloc = true;
}
}
Unit<Raw>(Raw *raw) : raw(raw) {}
Unit<Raw>(Raw raw) {
Unit();
*this->raw = raw;
}
virtual void* getPC() {
return auto_alloc ? nullptr : raw;
}
inline Addr getVPC() {
return vPC;
}
inline void setVPC(Addr vPC) {
this->vPC = vPC;
}
inline Raw* get() const {
return raw;
}
inline void set(Raw raw) const {
*this->raw = raw;
}
inline void set(Raw* raw) {
if (auto_alloc) {
free(this->raw);
auto_alloc = false;
}
this->raw = raw;
}
inline void copy(void* dest) {
memcpy(dest, getPC(), size());
}
inline void move(Raw* dest) {
memcpy(dest, raw, size());
if (auto_alloc) {
free(raw);
auto_alloc = false;
}
raw = dest;
}
virtual UnitType unitType() {
return UnitType::UnitUnknow;
};
virtual U32 size() {
return sizeof(Raw);
}
virtual ~Unit() {
if (auto_alloc) {
free(raw);
}
}
private:
Raw* raw;
Addr vPC;
bool auto_alloc = false;
};
}
}
#endif //SANDHOOK_NH_UNIT_H
//
// Created by swift on 2019/5/10.
//
#include <assembler.h>
#include <platform.h>
using namespace SandHook::Assembler;
using namespace SandHook::Asm;
CodeContainer::CodeContainer(CodeBuffer *codeBuffer) : codeBuffer(codeBuffer) {}
void CodeContainer::setCodeBuffer(CodeBuffer *codeBuffer) {
this->codeBuffer = codeBuffer;
}
void CodeContainer::append(Unit<Base> *unit) {
units.push_back(unit);
unit->setVPC(curPc);
switch (unit->unitType()) {
case UnitLabel:
labels.push_back((Label*)unit);
break;
default:
curPc += unit->size();
}
}
void CodeContainer::commit() {
U32 bufferSize = static_cast<U32>(curPc - startPc);
void* bufferStart;
if (startPc > 0) {
bufferStart = reinterpret_cast<void *>(startPc);
codeBuffer->resetLastBufferSize(bufferSize);
} else {
bufferStart = codeBuffer->getBuffer(bufferSize);
}
Addr pcNow = reinterpret_cast<Addr>(bufferStart);
//commit to code buffer & assembler inst
std::list<Unit<Base>*>::iterator unit;
for(unit = units.begin();unit != units.end(); ++unit) {
if ((*unit)->unitType() == UnitData) {
(*unit)->move(reinterpret_cast<Base *>(pcNow));
} else if ((*unit)->unitType() != UnitLabel) {
(*unit)->set(reinterpret_cast<Base *>(pcNow));
}
if ((*unit)->unitType() == UnitInst) {
reinterpret_cast<Instruction<Base>*>(*unit)->assembler();
}
pcNow += (*unit)->size();
}
//bind labels
std::list<Label*>::iterator label;
for(label = labels.begin();label != labels.end(); ++label) {
(*label)->bindLabel();
}
//flush I cache
flushCache(reinterpret_cast<Addr>(bufferStart), pcNow - reinterpret_cast<Addr>(bufferStart));
//set pc
startPc = reinterpret_cast<Addr>(bufferStart);
curPc = pcNow;
}
void CodeContainer::allocBufferFirst(U32 size) {
startPc = reinterpret_cast<Addr>(codeBuffer->getBuffer(size));
curPc = startPc;
}
CodeContainer::~CodeContainer() {
std::list<Unit<Base>*>::iterator unit;
for(unit = units.begin();unit != units.end(); ++unit) {
delete (*unit);
}
}
Addr CodeContainer::size() {
return curPc - startPc;
}
//
// Created by swift on 2019/5/11.
//
#include <sys/mman.h>
#include <platform.h>
#include "code_buffer.h"
#include "lock.h"
using namespace SandHook::Assembler;
using namespace SandHook::Utils;
void *AndroidCodeBuffer::getBuffer(U32 size) {
AutoLock autoLock(allocSpaceLock);
void* mmapRes;
Addr exeSpace = 0;
if (executeSpaceList.size() == 0) {
goto label_alloc_new_space;
} else if (executePageOffset + size > currentExecutePageSize) {
goto label_alloc_new_space;
} else {
exeSpace = reinterpret_cast<Addr>(executeSpaceList.back());
Addr retSpace = exeSpace + executePageOffset;
executePageOffset += size;
return reinterpret_cast<void *>(retSpace);
}
label_alloc_new_space:
currentExecutePageSize = static_cast<U32>(FIT(size, P_SIZE));
mmapRes = mmap(NULL, currentExecutePageSize, PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_ANON | MAP_PRIVATE, -1, 0);
if (mmapRes == MAP_FAILED) {
return 0;
}
memset(mmapRes, 0, currentExecutePageSize);
executeSpaceList.push_back(mmapRes);
executePageOffset = size;
return mmapRes;
}
AndroidCodeBuffer::AndroidCodeBuffer() {}
StaticCodeBuffer::StaticCodeBuffer(Addr pc) : pc(pc) {}
void *StaticCodeBuffer::getBuffer(U32 bufferSize) {
memUnprotect(pc, bufferSize);
return reinterpret_cast<void *>(pc);
}
void AndroidRellocBufferUnsafe::resetLastBufferSize(U32 size) {
if (executePageOffset + (size - lastAllocSize) <= currentExecutePageSize) {
executePageOffset += size - lastAllocSize;
lastAllocSize = size;
}
}
void *AndroidRellocBufferUnsafe::getBuffer(U32 bufferSize) {
void* res = AndroidCodeBuffer::getBuffer(bufferSize);
if (res) {
lastAllocSize = bufferSize;
}
return res;
}
//
// Created by swift on 2019/5/11.
//
#ifndef SANDHOOK_NH_CODE_BUFFER_H
#define SANDHOOK_NH_CODE_BUFFER_H
#include <mutex>
#include "assembler.h"
namespace SandHook {
namespace Assembler {
class AndroidCodeBuffer : public CodeBuffer {
public:
AndroidCodeBuffer();
void *getBuffer(U32 bufferSize) override;
protected:
std::list<void*> executeSpaceList = std::list<void*>();
std::mutex allocSpaceLock;
Addr executePageOffset = 0;
U32 currentExecutePageSize = 0;
};
//thread unsafe
class AndroidRellocBufferUnsafe : public AndroidCodeBuffer {
public:
public:
void resetLastBufferSize(U32 size) override;
void *getBuffer(U32 bufferSize) override;
private:
U32 lastAllocSize;
};
class StaticCodeBuffer : public CodeBuffer {
public:
StaticCodeBuffer(Addr pc);
void *getBuffer(U32 bufferSize) override;
private:
Addr pc;
};
}
}
#endif //SANDHOOK_NH_CODE_BUFFER_H
//
// Created by swift on 2019/5/6.
//
#include "decoder.h"
using namespace SandHook::Decoder;
InstDecoder* Decoder::get(Arch arch) {
switch (arch) {
case arm32:
break;
case arm64:
break;
default:
return nullptr;
}
return nullptr;
}
\ No newline at end of file
//
// Created by swift on 2019/5/10.
//
#include "elf.h"
//
// Created by swift on 2019/5/14.
//
#include "hook.h"
#include "code_buffer.h"
#include "lock.h"
using namespace SandHook::Hook;
using namespace SandHook::Decoder;
using namespace SandHook::Asm;
using namespace SandHook::Assembler;
using namespace SandHook::Utils;
#include "assembler_a64.h"
#include "code_relocate_a64.h"
#include "code_relocate_a64.h"
AndroidCodeBuffer* backupBuffer = new AndroidCodeBuffer();
void *InlineHookArm64Android::inlineHook(void *origin, void *replace) {
AutoLock lock(hookLock);
void* backup = nullptr;
AssemblerA64 assemblerBackup(backupBuffer);
CodeContainer* codeContainerBackup = &assemblerBackup.codeContainer;
StaticCodeBuffer inlineBuffer = StaticCodeBuffer(reinterpret_cast<Addr>(origin));
AssemblerA64 assemblerInline(&inlineBuffer);
CodeContainer* codeContainerInline = &assemblerInline.codeContainer;
//build inline trampoline
#define __ assemblerInline.
Label* target_addr_label = new Label();
__ Ldr(IP1, *target_addr_label);
__ Br(IP1);
__ Emit(target_addr_label);
__ Emit(reinterpret_cast<Addr>(replace));
#undef __
//build backup method
CodeRelocateA64 relocate = CodeRelocateA64(assemblerBackup);
backup = relocate.relocate(origin, codeContainerInline->size(), nullptr);
#define __ assemblerBackup.
Label* origin_addr_label = new Label();
__ Ldr(IP1, *origin_addr_label);
__ Br(IP1);
__ Emit(origin_addr_label);
__ Emit(reinterpret_cast<Addr>(origin) + codeContainerInline->size());
__ finish();
#undef __
//commit inline trampoline
assemblerInline.finish();
return backup;
}
//
// Created by swift on 2019/5/7.
//
#ifndef SANDHOOK_NH_ASSEMBLER_H
#define SANDHOOK_NH_ASSEMBLER_H
#include "label.h"
#include "instruction.h"
#include "data.h"
namespace SandHook {
using namespace Asm;
namespace Assembler {
class Assembler {
};
class CodeBuffer {
public:
virtual void* getBuffer(U32 size) = 0;
virtual void resetLastBufferSize(U32 size){};
};
class CodeContainer {
public:
CodeContainer(CodeBuffer *codeBuffer);
void setCodeBuffer(CodeBuffer *codeBuffer);
//allow code relocate to get new pc first
void allocBufferFirst(U32 size);
void append(Unit<Base>* unit);
void commit();
Addr size();
virtual ~CodeContainer();
public:
//before commit is virtual address so = 0, after commit is real address
Addr startPc = 0;
Addr curPc = 0;
private:
Addr maxSize = 0;
std::list<Unit<Base>*> units = std::list<Unit<Base>*>();
std::list<Label*> labels = std::list<Label*>();
CodeBuffer* codeBuffer = nullptr;
};
}
}
#endif //SANDHOOK_NH_ASSEMBLER_H
//
// Created by SwiftGan on 2019/4/15.
//
#ifndef SANDHOOK_BASE_H
#define SANDHOOK_BASE_H
#include <cstdint>
#include <cstring>
#include "compiler.h"
typedef uint8_t U8;
typedef uint16_t U16;
typedef uint32_t U32;
typedef uint64_t U64;
typedef int8_t S8;
typedef int16_t S16;
typedef int32_t S32;
typedef int64_t S64;
typedef size_t Addr;
//32bit
#if defined(__i386__) || defined(__arm__)
typedef S32 Off;
//64bit
#elif defined(__aarch64__) || defined(__x86_64__)
typedef S64 Off;
#endif
const int PTR_BYTE = sizeof(void*);
#define PAGE_OFFSET 12
const int BITS_OF_BYTE = 8;
const Addr P_SIZE = 2 << PAGE_OFFSET;
enum Arch {
arm32,
arm64,
unknowArch
};
enum UnitType {
UnitInst,
UnitData,
UnitLabel,
UnitVoid,
UnitUnknow
};
enum InstType {
A32,
thumb16,
thumb32,
A64,
unknowInst
};
template <int SizeInBits>
struct Unsigned;
template <>
struct Unsigned<16> {
typedef U16 type;
};
template <>
struct Unsigned<32> {
typedef U32 type;
};
template <>
struct Unsigned<64> {
typedef U64 type;
};
struct Base {};
template <typename T>
T AlignDown(T pointer,
typename Unsigned<sizeof(T) * BITS_OF_BYTE>::type alignment) {
// Use C-style casts to get static_cast behaviour for integral types (T), and
// reinterpret_cast behaviour for other types.
typename Unsigned<sizeof(T)* BITS_OF_BYTE>::type pointer_raw =
(typename Unsigned<sizeof(T) * BITS_OF_BYTE>::type)pointer;
size_t mask = alignment - 1;
return (T)(pointer_raw & ~mask);
}
#define FIT(value, align) value <= align ? align : ((value / align) + align)
#define OFFSET(TYPE, MEMBER) ((size_t) & ((TYPE *)0)->MEMBER)
//data covert
// Macros for compile-time format checking.
#if GCC_VERSION_OR_NEWER(4, 4, 0)
#define PRINTF_CHECK(format_index, varargs_index) \
__attribute__((format(gnu_printf, format_index, varargs_index)))
#else
#define PRINTF_CHECK(format_index, varargs_index)
#endif
#ifdef __GNUC__
#define VIXL_HAS_DEPRECATED_WITH_MSG
#elif defined(__clang__)
#ifdef __has_extension(attribute_deprecated_with_message)
#define VIXL_HAS_DEPRECATED_WITH_MSG
#endif
#endif
#ifdef VIXL_HAS_DEPRECATED_WITH_MSG
#define VIXL_DEPRECATED(replaced_by, declarator) \
__attribute__((deprecated("Use \"" replaced_by "\" instead"))) declarator
#else
#define VIXL_DEPRECATED(replaced_by, declarator) declarator
#endif
//只保留低N位
inline uint64_t TruncateToUintN(unsigned n, uint64_t x) {
return static_cast<uint64_t>(x) & ((UINT64_C(1) << n) - 1);
}
VIXL_DEPRECATED("TruncateToUintN",
inline uint64_t truncate_to_intn(unsigned n, int64_t x)) {
return TruncateToUintN(n, x);
}
// clang-format off
#define INT_1_TO_32_LIST(V) \
V(1) V(2) V(3) V(4) V(5) V(6) V(7) V(8) \
V(9) V(10) V(11) V(12) V(13) V(14) V(15) V(16) \
V(17) V(18) V(19) V(20) V(21) V(22) V(23) V(24) \
V(25) V(26) V(27) V(28) V(29) V(30) V(31) V(32)
#define INT_33_TO_63_LIST(V) \
V(33) V(34) V(35) V(36) V(37) V(38) V(39) V(40) \
V(41) V(42) V(43) V(44) V(45) V(46) V(47) V(48) \
V(49) V(50) V(51) V(52) V(53) V(54) V(55) V(56) \
V(57) V(58) V(59) V(60) V(61) V(62) V(63)
#define INT_1_TO_63_LIST(V) INT_1_TO_32_LIST(V) INT_33_TO_63_LIST(V)
#define DECLARE_TRUNCATE_TO_UINT_32(N) \
inline uint32_t TruncateToUint##N(uint64_t x) { \
return static_cast<uint32_t>(TruncateToUintN(N, x)); \
} \
VIXL_DEPRECATED("TruncateToUint" #N, \
inline uint32_t truncate_to_int##N(int64_t x)) { \
return TruncateToUint##N(x); \
}
INT_1_TO_32_LIST(DECLARE_TRUNCATE_TO_UINT_32)
#undef DECLARE_TRUNCATE_TO_INT_N
//位提取
// Bit field extraction.
inline uint64_t ExtractUnsignedBitfield64(int msb, int lsb, uint64_t x) {
if ((msb == 63) && (lsb == 0)) return x;
return (x >> lsb) & ((static_cast<uint64_t>(1) << (1 + msb - lsb)) - 1);
}
inline int64_t ExtractSignedBitfield64(int msb, int lsb, U64 x) {
uint64_t temp = ExtractUnsignedBitfield64(msb, lsb, x);
// If the highest extracted bit is set, sign extend.
if ((temp >> (msb - lsb)) == 1) {
temp |= ~UINT64_C(0) << (msb - lsb);
}
int64_t result;
memcpy(&result, &temp, sizeof(result));
return result;
}
inline int32_t ExtractSignedBitfield32(int msb, int lsb, U32 x) {
uint32_t temp = TruncateToUint32(ExtractSignedBitfield64(msb, lsb, x));
int32_t result;
memcpy(&result, &temp, sizeof(result));
return result;
}
inline U16 BITS16L(U32 value) {
return static_cast<U16>(value & 0xffff);
}
inline U16 BITS16H(U32 value) {
return static_cast<U16>(value >> 16);
}
inline U32 BITS32L(U64 value) {
return static_cast<U32>(value);
}
inline U32 BITS32H(U64 value) {
return static_cast<U32>(value >> 32);
}
#define COMBINE(hi, lo, lowide) (hi << lowide) | lo
/* borrow from gdb, refer: binutils-gdb/gdb/arch/arm.h */
#define SUB_MASK(x) ((1L << ((x) + 1)) - 1)
#define BITS(obj, st, fn) (((obj) >> (st)) & SUB_MASK((fn) - (st)))
#define BIT(obj, st) (((obj) >> (st)) & 1)
#define SBITS(obj, st, fn) ((long)(BITS(obj, st, fn) | ((long)BIT(obj, fn) * ~SUB_MASK(fn - st))))
#define DCHECK(X,V, ACTION) \
if (X == V) { \
ACTION \
}
#define CHECK(X,V, ACTION) \
if (X != V) { \
ACTION \
}
#endif //SANDHOOK_BASE_H
//
// Created by swift on 2019/5/10.
//
#ifndef SANDHOOK_NH_CODE_RELOCATE_H
#define SANDHOOK_NH_CODE_RELOCATE_H
#include "exception.h"
#include "instruction.h"
#include "assembler.h"
#include "decoder.h"
using namespace SandHook::Assembler;
using namespace SandHook::Decoder;
namespace SandHook {
namespace Asm {
class CodeRelocate : public InstVisitor {
public:
CodeRelocate(CodeContainer &codeContainer) : codeContainer(&codeContainer) {}
virtual void* relocate(Instruction<Base> *instruction, void* toPc) throw(ErrorCodeException) = 0;
virtual void* relocate(void *startPc, Addr len, void *toPc) throw(ErrorCodeException) = 0;
private:
CodeContainer* codeContainer;
};
}
}
#endif //SANDHOOK_NH_CODE_RELOCATE_H
//
// Created by swift on 2019/5/6.
//
#ifndef SANDHOOK_NH_COMPILER_H
#define SANDHOOK_NH_COMPILER_H
// Helper to check whether the version of GCC used is greater than the specified
// requirement.
#define MAJOR 1000000
#define MINOR 1000
#if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
#define GCC_VERSION_OR_NEWER(major, minor, patchlevel) \
((__GNUC__ * (MAJOR) + __GNUC_MINOR__ * (MINOR) + __GNUC_PATCHLEVEL__) >= \
((major) * (MAJOR) + ((minor)) * (MINOR) + (patchlevel)))
#elif defined(__GNUC__) && defined(__GNUC_MINOR__)
#define GCC_VERSION_OR_NEWER(major, minor, patchlevel) \
((__GNUC__ * (MAJOR) + __GNUC_MINOR__ * (MINOR)) >= \
((major) * (MAJOR) + ((minor)) * (MINOR) + (patchlevel)))
#else
#define GCC_VERSION_OR_NEWER(major, minor, patchlevel) 0
#endif
#if defined(__clang__) && !defined(VIXL_NO_COMPILER_BUILTINS)
// clang-format off
#define COMPILER_HAS_BUILTIN_CLRSB (__has_builtin(__builtin_clrsb))
#define COMPILER_HAS_BUILTIN_CLZ (__has_builtin(__builtin_clz))
#define COMPILER_HAS_BUILTIN_CTZ (__has_builtin(__builtin_ctz))
#define COMPILER_HAS_BUILTIN_FFS (__has_builtin(__builtin_ffs))
#define COMPILER_HAS_BUILTIN_POPCOUNT (__has_builtin(__builtin_popcount))
// clang-format on
#elif defined(__GNUC__) && !defined(VIXL_NO_COMPILER_BUILTINS)
// The documentation for these builtins is available at:
// https://gcc.gnu.org/onlinedocs/gcc-$MAJOR.$MINOR.$PATCHLEVEL/gcc//Other-Builtins.html
// clang-format off
# define COMPILER_HAS_BUILTIN_CLRSB (GCC_VERSION_OR_NEWER(4, 7, 0))
# define COMPILER_HAS_BUILTIN_CLZ (GCC_VERSION_OR_NEWER(3, 4, 0))
# define COMPILER_HAS_BUILTIN_CTZ (GCC_VERSION_OR_NEWER(3, 4, 0))
# define COMPILER_HAS_BUILTIN_FFS (GCC_VERSION_OR_NEWER(3, 4, 0))
# define COMPILER_HAS_BUILTIN_POPCOUNT (GCC_VERSION_OR_NEWER(3, 4, 0))
// clang-format on
#else
// One can define VIXL_NO_COMPILER_BUILTINS to force using the manually
// implemented C++ methods.
// clang-format off
#define COMPILER_HAS_BUILTIN_BSWAP false
#define COMPILER_HAS_BUILTIN_CLRSB false
#define COMPILER_HAS_BUILTIN_CLZ false
#define COMPILER_HAS_BUILTIN_CTZ false
#define COMPILER_HAS_BUILTIN_FFS false
#define COMPILER_HAS_BUILTIN_POPCOUNT false
// clang-format on
#endif
#endif //SANDHOOK_NH_COMPILER_H
//
// Created by swift on 2019/5/6.
//
#ifndef SANDHOOK_NH_DECODER_H
#define SANDHOOK_NH_DECODER_H
#include "base.h"
#include "instruction.h"
namespace SandHook {
namespace Decoder {
using namespace Asm;
class InstVisitor {
public:
//need free unit
virtual bool visit(Unit<Base>* unit, void* pc) = 0;
};
class InstDecoder {
public:
virtual void decode(void* codeStart, Addr codeLen, InstVisitor& visitor) = 0;
};
class Decoder {
static InstDecoder* get(Arch arch);
};
}
}
#endif //SANDHOOK_NH_DECODER_H
//
// Created by swift on 2019/5/10.
//
#ifndef SANDHOOK_NH_ELF_H
#define SANDHOOK_NH_ELF_H
#endif //SANDHOOK_NH_ELF_H
//
// Created by swift on 2019/5/10.
//
#include "exception"
#ifndef SANDHOOK_NH_EXCEPTION_H
#define SANDHOOK_NH_EXCEPTION_H
namespace SandHook {
namespace Asm {
class ErrorCodeException : public std::exception {
public:
ErrorCodeException(const char *what_) : what_(what_) {}
const char *what() const noexcept override {
return what_;
}
private:
const char *what_;
};
}
}
#endif //SANDHOOK_NH_EXCEPTION_H
//
// Created by swift on 2019/5/14.
//
#ifndef SANDHOOK_NH_HOOK_H
#define SANDHOOK_NH_HOOK_H
#include <mutex>
#include <hook.h>
#include <decoder.h>
#include "hook.h"
#include "assembler.h"
#include "code_relocate.h"
namespace SandHook {
namespace Hook {
class InlineHook {
public:
//return == backup method
virtual void* inlineHook(void* origin, void* replace) = 0;
};
class InlineHookArm64Android : InlineHook {
public:
inline InlineHookArm64Android() {
hookLock = new std::mutex();
};
inline ~InlineHookArm64Android() {
delete hookLock;
}
void *inlineHook(void *origin, void *replace) override;
protected:
std::mutex* hookLock;
};
}
}
#endif //SANDHOOK_NH_HOOK_H
//
// Created by swift on 2019/5/10.
//
#include "code_relocate.h"
//
// Created by SwiftGan on 2019/4/15.
//
#include <jni.h>
#include <sys/mman.h>
#include "sandhook_native.h"
#include "inst_arm64.h"
#include "decoder_arm64.h"
#include "hook.h"
#include "log.h"
using namespace SandHook::Asm;
using namespace SandHook::Decoder;
using namespace SandHook::Hook;
void (*dosth3Backup)(int, int) = nullptr;
void (*dosth4Backup)() = nullptr;
bool memUnprotect(Addr addr, Addr len) {
long pagesize = 4096;
unsigned alignment = (unsigned)((unsigned long long)addr % pagesize);
int i = mprotect((void *) (addr - alignment), (size_t) (alignment + len),
PROT_READ | PROT_WRITE | PROT_EXEC);
if (i == -1) {
return false;
}
return true;
}
void do2() {
int a = 1 + 1;
int b = 1 + 1;
int c = 1 + 1;
int d = 1 + 1;
}
void do3(int x, int y) {
do2();
int a = 1 + 1;
int b = 1 + 1;
int c = 1 + 1;
int d = a + b + c;
LOGE("x = %d", x);
}
void do5() {
LOGE("x = %d", 5);
}
void do4() {
do5();
LOGE("x = %d", 6);
LOGE("x = %d", 7);
}
void do4replace() {
int a = 1 + 1;
int b = 1 + 1;
int c = 1 + 1;
int d = 1 + 1;
dosth4Backup();
}
void do3replace(int x, int y) {
int a = 1 + 1;
int b = 1 + 1;
int c = 1 + 1;
int d = 1 + 1;
dosth3Backup(x, y);
}
void do1() {
do2();
}
class Visitor : public InstVisitor {
bool visit(Unit<Base> *unit, void *pc) override {
return true;
}
};
extern "C"
JNIEXPORT void JNICALL
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(*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(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();
do4();
dosth4Backup = reinterpret_cast<void (*)()>(inlineHookArm64Android.inlineHook(
reinterpret_cast<void *>(do4),
reinterpret_cast<void *>(do4replace)));
do4();
}
\ No newline at end of file
//
// Created by SwiftGan on 2019/4/15.
//
#ifndef SANDHOOK_SANDHOOK_NATIVE_H
#define SANDHOOK_SANDHOOK_NATIVE_H
#endif //SANDHOOK_SANDHOOK_NATIVE_H
//
// Created by swift on 2019/5/11.
//
#ifndef SANDHOOK_NH_LOCK_H
#define SANDHOOK_NH_LOCK_H
#include <mutex>
namespace SandHook {
namespace Utils {
class AutoLock {
public:
inline AutoLock(std::mutex& mutex) : mLock(mutex) { mLock.lock(); }
inline AutoLock(std::mutex* mutex) : mLock(*mutex) { mLock.lock(); }
inline ~AutoLock() { mLock.unlock(); }
private:
std::mutex& mLock;
};
}
}
#endif //SANDHOOK_NH_LOCK_H
//
// Created by SwiftGan on 2019/2/15.
//
#ifndef SANDHOOK_LOG_H
#define SANDHOOK_LOG_H
#include "android/log.h"
#define TAG "SandHook-Native"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)
#endif //SANDHOOK_LOG_H
//
// Created by swift on 2019/5/11.
//
#include <unistd.h>
#include <sys/mman.h>
#include "platform.h"
bool flushCache(Addr addr, Off len) {
#if defined(__arm__)
int i = cacheflush(addr, addr + len, 0);
if (i == -1) {
return false;
}
return true;
#elif defined(__aarch64__)
char *begin = reinterpret_cast<char *>(addr);
__builtin___clear_cache(begin, begin + len);
#endif
return true;
}
extern "C" bool memUnprotect(Addr addr, Addr len) {
long pagesize = P_SIZE;
unsigned alignment = (unsigned)((unsigned long long)addr % pagesize);
int i = mprotect((void *) (addr - alignment), (size_t) (alignment + len),
PROT_READ | PROT_WRITE | PROT_EXEC);
return i != -1;
}
\ No newline at end of file
//
// Created by swift on 2019/5/11.
//
#ifndef SANDHOOK_NH_PLATFORM_H
#define SANDHOOK_NH_PLATFORM_H
#include "base.h"
extern "C" bool flushCache(Addr addr, Off len);
extern "C" bool memUnprotect(Addr addr, Addr len);
#endif //SANDHOOK_NH_PLATFORM_H
<resources>
<string name="app_name">nativehook</string>
</resources>
package com.swift.sandhook.nativehook;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() {
assertEquals(4, 2 + 2);
}
}
\ No newline at end of file
include ':app', ':hooklib', ':hookers', ':annotation', ':xposedcompat' include ':app', ':hooklib', ':hookers', ':annotation', ':xposedcompat', ':nativehook'
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