Commit 0c0d3112 authored by swift_gan's avatar swift_gan

Merge remote-tracking branch 'origin/master'

# Conflicts:
#	nativehook/src/main/cpp/sandhook_native.cpp
parents f6870aeb 1b81d376
This diff is collapsed.
Copyright (c) 2019 <copyright holders>
"Anti 996" License Version 1.0 (Draft)
Permission is hereby granted to any individual or legal entity
obtaining a copy of this licensed work (including the source code,
documentation and/or related items, hereinafter collectively referred
to as the "licensed work"), free of charge, to deal with the licensed
work for any purpose, including without limitation, the rights to use,
reproduce, modify, prepare derivative works of, distribute, publish
and sublicense the licensed work, subject to the following conditions:
1. The individual or the legal entity must conspicuously display,
without modification, this License and the notice on each redistributed
or derivative copy of the Licensed Work.
2. The individual or the legal entity must strictly comply with all
applicable laws, regulations, rules and standards of the jurisdiction
relating to labor and employment where the individual is physically
located or where the individual was born or naturalized; or where the
legal entity is registered or is operating (whichever is stricter). In
case that the jurisdiction has no such laws, regulations, rules and
standards or its laws, regulations, rules and standards are
unenforceable, the individual or the legal entity are required to
comply with Core International Labor Standards.
3. The individual or the legal entity shall not induce, suggest or force
its employee(s), whether full-time or part-time, or its independent
contractor(s), in any methods, to agree in oral or written form, to
directly or indirectly restrict, weaken or relinquish his or her
rights or remedies under such laws, regulations, rules and standards
relating to labor and employment as mentioned above, no matter whether
such written or oral agreements are enforceable under the laws of the
said jurisdiction, nor shall such individual or the legal entity
limit, in any methods, the rights of its employee(s) or independent
contractor(s) from reporting or complaining to the copyright holder or
relevant authorities monitoring the compliance of the license about
its violation(s) of the said license.
THE LICENSED WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN ANY WAY CONNECTION WITH THE
LICENSED WORK OR THE USE OR OTHER DEALINGS IN THE LICENSED WORK.
\ No newline at end of file
# SandHook
Android ART Hook
- Android ART Hook
- Native Inline Hook
## Version
[ ![Version](https://api.bintray.com/packages/ganyao114/maven/hooklib/images/download.svg) ](https://bintray.com/ganyao114/maven/hooklib/_latestVersion)
......@@ -200,11 +200,22 @@ To bypass hidden api on P & Q
# Native Hook
## simple hook(no backup)
#include "includes/sandhook.h"
// can not call origin method now
bool nativeHookNoBackup(void* origin, void* hook);
## need backup origin method(unstabitily)
#include "sanhook_native.h"
void* SandInlineHook(void* origin, void* replace);
void* SandInlineHookSym(const char* so, const char* symb, void* replace);
return is backup method
## more
- disassembler (only implement important instructions)
- assembler (only implement important instructions)
# Demo
## SandVXPosed
......
......@@ -27,5 +27,6 @@ dependencies {
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation project(':hooklib')
implementation project(':nativehook')
implementation project(':xposedcompat')
}
......@@ -5,6 +5,7 @@ import android.app.Application;
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;
......@@ -29,6 +30,8 @@ public class MyApp extends Application {
public void onCreate() {
super.onCreate();
NativeHook.test();
SandHookConfig.DEBUG = BuildConfig.DEBUG;
if (testAndroidQ) {
......
......@@ -45,7 +45,7 @@ namespace SandHook {
private:
const char* elf = nullptr;
uint8_t * base = nullptr;
void* base = nullptr;
char* buffer = nullptr;
off_t size = 0;
off_t bias = -4396;
......
......@@ -31,10 +31,10 @@ ElfImg::ElfImg(const char *elf) {
Elf_Off symtab_entsize = 0;
section_header = reinterpret_cast<Elf_Shdr *>(((uint8_t *) header) + header->e_shoff);
section_header = reinterpret_cast<Elf_Shdr *>(((size_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));
size_t shoff = reinterpret_cast<size_t>(section_header);
char* section_str = reinterpret_cast<char *>(section_header[header->e_shstrndx].sh_offset + ((size_t) header));
bool has_strtab = false;
bool has_dynsym = false;
......@@ -75,10 +75,10 @@ ElfImg::ElfImg(const char *elf) {
LOGW("can't find symtab from sections\n");
}
sym_start = reinterpret_cast<Elf_Sym *>(((uint8_t *) header) + symtab_offset);
sym_start = reinterpret_cast<Elf_Sym *>(((size_t) header) + symtab_offset);
//load module base
base = reinterpret_cast<uint8_t *>(getModuleBase(elf));
base = getModuleBase(elf);
}
ElfImg::~ElfImg() {
......@@ -97,7 +97,7 @@ 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);
char* st_name = reinterpret_cast<char *>(((size_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;
......@@ -112,7 +112,7 @@ Elf_Addr ElfImg::getSymbOffset(const char *name) {
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);
return static_cast<Elf_Addr>((size_t)base + offset - bias);
} else {
return 0;
}
......
# 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.
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.
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/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
${OS_DEPENDENDED_SRC})
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/arm
src/main/cpp/archs/arm/arm64/inst
src/main/cpp/archs/arm/arm64/register
src/main/cpp/archs/arm/arm64/decoder
src/main/cpp/archs/arm/arm64/assembler
src/main/cpp/archs/arm/arm64/relocate
src/main/cpp/archs/arm/arm64/hook
src/main/cpp/archs/arm/arm32/inst
src/main/cpp/archs/arm/arm32/register
src/main/cpp/archs/arm/arm32/assembler
src/main/cpp/archs/arm/arm32/decoder
src/main/cpp/archs/arm/arm32/hook
src/main/cpp/archs/arm/arm32/relocate
)
# 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/22.
//
#include "assembler_arm32.h"
#include "exception.h"
using namespace SandHook::Assembler;
using namespace SandHook::RegistersA32;
using namespace SandHook::AsmA32;
AssemblerA32::AssemblerA32(CodeBuffer* codeBuffer) {
codeContainer.setCodeBuffer(codeBuffer);
}
void *AssemblerA32::getPC() {
return reinterpret_cast<void *>(codeContainer.curPc);
}
void *AssemblerA32::getStartPC() {
return reinterpret_cast<void *>(codeContainer.startPc);
}
void AssemblerA32::allocBufferFirst(U32 size) {
codeContainer.allocBufferFirst(size);
}
void *AssemblerA32::finish() {
codeContainer.commit();
return reinterpret_cast<void *>(codeContainer.startPc);
}
void AssemblerA32::Emit(U32 data32) {
Emit(reinterpret_cast<Unit<Base>*>(new Data32(data32)));
}
void AssemblerA32::Emit(Unit<Base> *unit) {
codeContainer.append(unit);
}
void AssemblerA32::Mov(RegisterA32 &rd, U16 imm16) {
Emit(reinterpret_cast<Unit<Base>*>(new INST_T32(MOV_MOVT_IMM)(INST_T32(MOV_MOVT_IMM)::MOV, rd, imm16)));
}
void AssemblerA32::Movt(RegisterA32 &rd, U16 imm16) {
Emit(reinterpret_cast<Unit<Base>*>(new INST_T32(MOV_MOVT_IMM)(INST_T32(MOV_MOVT_IMM)::MOVT, rd, imm16)));
}
void AssemblerA32::Mov(RegisterA32 &rd, U32 imm32) {
U16 immL = BITS16L(imm32);
U16 immH = BITS16H(imm32);
Mov(rd, immL);
Movt(rd, immH);
}
void AssemblerA32::Ldr(RegisterA32 &rt, Label *label) {
Emit(reinterpret_cast<Unit<Base>*>(new INST_T32(LDR_LIT)(INST_T32(LDR_LIT)::LDR, INST_T32(LDR_LIT)::UnSign, rt, *label)));
}
void AssemblerA32::Ldrb(RegisterA32 &rt, Label *label) {
Emit(reinterpret_cast<Unit<Base>*>(new INST_T32(LDR_LIT)(INST_T32(LDR_LIT)::LDRB, INST_T32(LDR_LIT)::UnSign,rt, *label)));
}
void AssemblerA32::Ldrh(RegisterA32 &rt, Label *label) {
Emit(reinterpret_cast<Unit<Base>*>(new INST_T32(LDR_LIT)(INST_T32(LDR_LIT)::LDRH, INST_T32(LDR_LIT)::UnSign,rt, *label)));
}
void AssemblerA32::Ldrsb(RegisterA32 &rt, Label *label) {
Emit(reinterpret_cast<Unit<Base>*>(new INST_T32(LDR_LIT)(INST_T32(LDR_LIT)::LDRB, INST_T32(LDR_LIT)::Sign,rt, *label)));
}
void AssemblerA32::Ldrsh(RegisterA32 &rt, Label *label) {
Emit(reinterpret_cast<Unit<Base>*>(new INST_T32(LDR_LIT)(INST_T32(LDR_LIT)::LDRH, INST_T32(LDR_LIT)::Sign,rt, *label)));
}
void AssemblerA32::Ldr(RegisterA32 &rt, const MemOperand &operand) {
if (operand.addr_mode == Offset && operand.offset >= 0) {
Emit(reinterpret_cast<Unit<Base>*>(new INST_T32(LDR_UIMM)(rt, *operand.rn, operand.addr_mode)));
} else {
Emit(reinterpret_cast<Unit<Base>*>(new INST_T32(LDR_IMM)(INST_T32(LDR_IMM)::LDR, rt, operand)));
}
}
void AssemblerA32::Ldrb(RegisterA32 &rt, const MemOperand &operand) {
Emit(reinterpret_cast<Unit<Base>*>(new INST_T32(LDR_IMM)(INST_T32(LDR_IMM)::LDRB, rt, operand)));
}
void AssemblerA32::Ldrh(RegisterA32 &rt, const MemOperand &operand) {
Emit(reinterpret_cast<Unit<Base>*>(new INST_T32(LDR_IMM)(INST_T32(LDR_IMM)::LDRH, rt, operand)));
}
void AssemblerA32::Ldrsb(RegisterA32 &rt, const MemOperand &operand) {
Emit(reinterpret_cast<Unit<Base>*>(new INST_T32(LDR_IMM)(INST_T32(LDR_IMM)::LDRSB, rt, operand)));
}
void AssemblerA32::Ldrsh(RegisterA32 &rt, const MemOperand &operand) {
Emit(reinterpret_cast<Unit<Base>*>(new INST_T32(LDR_IMM)(INST_T32(LDR_IMM)::LDRSH, rt, operand)));
}
void AssemblerA32::B(Label *label) {
Emit(reinterpret_cast<Unit<Base>*>(new INST_T16(B)(*label)));
}
void AssemblerA32::Bl(Label *label) {
Emit(reinterpret_cast<Unit<Base>*>(new INST_T32(B32)(INST_T32(B32)::BL, INST_T32(B32)::arm, *label)));
}
void AssemblerA32::Blx(Label *label) {
Emit(reinterpret_cast<Unit<Base>*>(new INST_T32(B32)(INST_T32(B32)::BL, INST_T32(B32)::thumb, *label)));
}
void AssemblerA32::Bx(Label *label) {
Emit(reinterpret_cast<Unit<Base>*>(new INST_T32(B32)(INST_T32(B32)::B, INST_T32(B32)::thumb, *label)));
}
void AssemblerA32::Mov(RegisterA32 &rd, RegisterA32 &rm) {
Emit(reinterpret_cast<Unit<Base>*>(new INST_T16(MOV_REG)(rd, rm)));
}
void AssemblerA32::Bx(RegisterA32 &rm) {
Emit(reinterpret_cast<Unit<Base>*>(new INST_T16(BX_BLX)(INST_T16(BX_BLX)::BX, rm)));
}
void AssemblerA32::Blx(RegisterA32 &rm) {
Emit(reinterpret_cast<Unit<Base>*>(new INST_T16(BX_BLX)(INST_T16(BX_BLX)::BLX, rm)));
}
void AssemblerA32::B(Condition condition, Label* label) {
Emit(reinterpret_cast<Unit<Base>*>(new INST_T16(B_COND)(condition, *label)));
}
void AssemblerA32::Add(RegisterA32 &rdn, U8 imm8) {
Emit(reinterpret_cast<Unit<Base>*>(new INST_T16(ADD_IMM_RDN)(&rdn, imm8)));
}
void AssemblerA32::Add(RegisterA32 &rd, RegisterA32 &rn, RegisterA32 &rm) {
Emit(reinterpret_cast<Unit<Base>*>(new INST_T16(ADD_REG)(&rd, &rn, &rm)));
}
void AssemblerA32::Cmp(RegisterA32 &rd, RegisterA32 &rn) {
if (rd.getCode() < 8 && rn.getCode() < 8) {
Emit(reinterpret_cast<Unit<Base>*>(new INST_T16(CMP_REG)(rd, rn)));
} else {
Emit(reinterpret_cast<Unit<Base>*>(new INST_T16(CMP_REG_EXT)(rd, rn)));
}
}
void AssemblerA32::Pop(RegisterA32 &rt) {
if (rt.getCode() < 8 || rt == PC) {
Emit(reinterpret_cast<Unit<Base>*>(new INST_T16(POP)(RegisterList(rt))));
} else {
throw ErrorCodeException("error pop inst");
}
}
void AssemblerA32::Push(RegisterA32 &rt) {
if (rt.getCode() < 8 || rt == PC) {
Emit(reinterpret_cast<Unit<Base>*>(new INST_T16(PUSH)(RegisterList(rt))));
} else {
throw ErrorCodeException("error pop inst");
}
}
void AssemblerA32::Adr(RegisterA32 &rd, Label *label) {
Emit(reinterpret_cast<Unit<Base>*>(new INST_T16(ADR)(rd, *label)));
}
void AssemblerA32::Nop16() {
Mov(IP, IP);
}
//
// Created by swift on 2019/5/22.
//
#ifndef SANDHOOK_ASSEMBLER_A32_H
#define SANDHOOK_ASSEMBLER_A32_H
#include "assembler.h"
#include "register_arm32.h"
#include "inst_t16.h"
#include "inst_t32.h"
using namespace SandHook::AsmA32;
namespace SandHook {
namespace Assembler {
class AssemblerA32 {
public:
AssemblerA32(CodeBuffer* codeBuffer);
void allocBufferFirst(U32 size);
void* getStartPC();
void* getPC();
void* finish();
void Emit(U32 data32);
void Emit(Unit<Base>* unit);
void Mov(RegisterA32 &rd, U16 imm16);
void Movt(RegisterA32 &rd, U16 imm16);
void Mov(RegisterA32 &rd, U32 imm32);
void Mov(RegisterA32 &rd, RegisterA32 &rm);
void Ldr(RegisterA32 &rt, Label* label);
void Ldrb(RegisterA32 &rt, Label* label);
void Ldrh(RegisterA32 &rt, Label* label);
void Ldrsb(RegisterA32 &rt, Label* label);
void Ldrsh(RegisterA32 &rt, Label* label);
void Ldr(RegisterA32 &rt, const MemOperand& operand);
void Ldrb(RegisterA32 &rt, const MemOperand& operand);
void Ldrh(RegisterA32 &rt, const MemOperand& operand);
void Ldrsb(RegisterA32 &rt, const MemOperand& operand);
void Ldrsh(RegisterA32 &rt, const MemOperand& operand);
void B(Label* label);
void Bl(Label* label);
void Blx(Label* label);
void Bx(Label* label);
void Blx(RegisterA32 &rm);
void Bx(RegisterA32 &rm);
void B(Condition condition, Label* label);
void Add(RegisterA32 &rdn, U8 imm8);
void Add(RegisterA32 &rd, RegisterA32 &rn, RegisterA32& rm);
void Cmp(RegisterA32 &rn, RegisterA32 &rm);
void Pop(RegisterA32& rt);
void Push(RegisterA32& rt);
void Adr(RegisterA32& rd, Label* label);
void Nop16();
public:
CodeContainer codeContainer = CodeContainer(nullptr);
};
}
}
#endif //SANDHOOK_ASSEMBLER_A32_H
//
// Created by swift on 2019/5/23.
//
#include "inst_t16.h"
#include "inst_t32.h"
#include "decoder_arm32.h"
using namespace SandHook::Decoder;
using namespace SandHook::AsmA32;
#define CASE(T, X) \
if (IS_OPCODE_##T(*reinterpret_cast<Inst##T *>(pc), X)) { \
STRUCT_##T(X) *s = reinterpret_cast<STRUCT_##T(X) *>(pc); \
unit = reinterpret_cast<Unit<Base> *>(new INST_##T(X)(s)); \
goto label_matched; \
}
#define CASE_A32(X) CASE(A32, X)
#define CASE_T16(X) CASE(T16, X)
#define CASE_T32(X) CASE(T32, X)
Arm32Decoder* Arm32Decoder::instant = new Arm32Decoder();
void Arm32Decoder::decode(void *codeStart, Addr codeLen, InstVisitor &visitor) {
bool thumb = isThumbCode(reinterpret_cast<Addr>(codeStart));
if (thumb) {
codeStart = getThumbCodeAddress(codeStart);
}
void *pc = codeStart;
Addr endAddr = (Addr) codeStart + codeLen;
Unit<Base>* unit = nullptr;
while((Addr) pc < endAddr) {
bool thumb32 = isThumb32(*reinterpret_cast<InstT16*>(pc));
if (thumb && thumb32) {
CASE_T32(B32)
CASE_T32(LDR_LIT)
CASE_T32(LDR_IMM)
CASE_T32(LDR_UIMM)
CASE_T32(MOV_MOVT_IMM)
if (unit == nullptr) {
unit = reinterpret_cast<Unit<Base> *>(new INST_T32(UNKNOW)(*reinterpret_cast<STRUCT_T32(UNKNOW) *>(pc)));
}
} else if (thumb) {
CASE_T16(B)
CASE_T16(B_COND)
CASE_T16(BX_BLX)
CASE_T16(CBZ_CBNZ)
CASE_T16(LDR_LIT)
CASE_T16(ADD_IMM_RDN)
CASE_T16(ADR)
CASE_T16(ADD_REG)
CASE_T16(CMP_REG)
CASE_T16(CMP_REG_EXT)
CASE_T16(MOV_REG)
CASE_T16(POP)
CASE_T16(PUSH)
if (unit == nullptr) {
unit = reinterpret_cast<Unit<Base> *>(new INST_T16(UNKNOW)(*reinterpret_cast<STRUCT_T16(UNKNOW) *>(pc)));
}
} else {
//TODO
unit = reinterpret_cast<Unit<Base> *>(new INST_T32(UNKNOW)(*reinterpret_cast<STRUCT_T32(UNKNOW) *>(pc)));
}
label_matched:
if (!visitor.visit(unit, pc)) {
break;
}
pc = reinterpret_cast<InstA64 *>((Addr)pc + unit->size());
unit = nullptr;
}
}
//
// Created by swift on 2019/5/23.
//
#ifndef SANDHOOK_DECODER_A32_H
#define SANDHOOK_DECODER_A32_H
#include "decoder.h"
namespace SandHook {
namespace Decoder {
class Arm32Decoder : public InstDecoder {
public:
void decode(void *codeStart, Addr codeLen, InstVisitor &visitor) override;
public:
static Arm32Decoder* instant;
};
}
}
#endif //SANDHOOK_DECODER_A32_H
//
// Created by swift on 2019/5/23.
//
#include "code_relocate_arm32.h"
#include "hook_arm32.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_arm32.h"
using namespace SandHook::RegistersA32;
void *InlineHookArm32Android::inlineHook(void *origin, void *replace) {
AutoLock lock(hookLock);
void* originCode = origin;
if (isThumbCode((Addr)origin)) {
originCode = getThumbCodeAddress(origin);
}
if (isThumbCode((Addr)origin)) {
replace = getThumbPC(replace);
}
void* backup = nullptr;
AssemblerA32 assemblerBackup(backupBuffer);
StaticCodeBuffer inlineBuffer = StaticCodeBuffer(reinterpret_cast<Addr>(originCode));
AssemblerA32 assemblerInline(&inlineBuffer);
CodeContainer* codeContainerInline = &assemblerInline.codeContainer;
//build inline trampoline
#define __ assemblerInline.
Label* target_addr_label = new Label();
__ Ldr(PC, target_addr_label);
__ Emit(target_addr_label);
__ Emit((Addr)replace);
#undef __
//build backup method
CodeRelocateA32 relocate = CodeRelocateA32(assemblerBackup);
backup = relocate.relocate(origin, codeContainerInline->size(), nullptr);
#define __ assemblerBackup.
__ Mov(IP ,(Addr) getThumbPC(reinterpret_cast<void *>((Addr)originCode + relocate.curOffset)));
__ Bx(IP);
__ finish();
#undef __
//commit inline trampoline
assemblerInline.finish();
return getThumbPC(backup);
}
\ No newline at end of file
//
// Created by swift on 2019/5/23.
//
#ifndef SANDHOOK_HOOK_ARM32_H
#define SANDHOOK_HOOK_ARM32_H
#include "hook.h"
namespace SandHook {
namespace Hook {
class InlineHookArm32Android : public InlineHook {
public:
inline InlineHookArm32Android() {
hookLock = new std::mutex();
};
inline ~InlineHookArm32Android() {
delete hookLock;
}
void *inlineHook(void *origin, void *replace) override;
protected:
std::mutex* hookLock;
};
}
}
#endif //SANDHOOK_HOOK_ARM32_H
//
// Created by swift on 2019/5/16.
//
#ifndef SANDHOOK_ARM32_BASE_H
#define SANDHOOK_ARM32_BASE_H
#include <ostream>
#include "arm_base.h"
#include "register_list_arm32.h"
#include "instruction.h"
#define DECODE_OFFSET(bits, ext) signExtend32(bits + ext, COMBINE(get()->imm##bits, 0, ext))
#define ENCODE_OFFSET(bits, ext) get()->imm##bits = TruncateToUint##bits(offset >> ext)
#define CODE_OFFSET(I) I->offset + I->instType() == A32 ? 2 * 4 : 2 * 2
using namespace SandHook::RegistersA32;
namespace SandHook {
namespace AsmA32 {
enum Sign { Plus, Minus };
class MemOperand {
public:
explicit MemOperand()
: rn(&UnknowRegiser), rm(&UnknowRegiser), offset(0), addr_mode(Offset) {}
explicit MemOperand(RegisterA32* rn, S32 offset = 0, AddrMode am = Offset)
: rn(rn), rm(&UnknowRegiser), offset(offset), addr_mode(am) {}
explicit MemOperand(RegisterA32* rn, RegisterA32* rm, AddrMode am = Offset)
: rn(rn), rm(rm), shift(LSL), shift_imm(0), addr_mode(am) {
}
explicit MemOperand(RegisterA32* rn, RegisterA32* rm, Shift shift, int shift_imm, AddrMode am = Offset)
: rn(rn), rm(rm), shift(shift), shift_imm(shift_imm & 31), addr_mode(am) {
}
// =====
bool IsImmediateOffset() const { return (addr_mode == Offset); }
bool IsRegisterOffset() const { return (addr_mode == Offset); }
bool IsPreIndex() const { return addr_mode == PreIndex; }
bool IsPostIndex() const { return addr_mode == PostIndex; }
public:
RegisterA32* rn; // base
RegisterA32* rm; // register offset
S32 offset; // valid if rm_ == no_reg
Shift shift;
Sign sign;
int shift_imm; // valid if rm_ != no_reg && rs_ == no_reg
AddrMode addr_mode; // bits P, U, and W
};
class RegisterList {
public:
RegisterList() : list_(0) {}
RegisterList(RegisterA32& reg) // NOLINT(runtime/explicit)
: list_(RegisterToList(reg)) {}
RegisterList(RegisterA32& reg1, RegisterA32& reg2)
: list_(RegisterToList(reg1) | RegisterToList(reg2)) {}
RegisterList(RegisterA32& reg1, RegisterA32& reg2, RegisterA32& reg3)
: list_(RegisterToList(reg1) | RegisterToList(reg2) |
RegisterToList(reg3)) {}
RegisterList(RegisterA32& reg1, RegisterA32& reg2, RegisterA32& reg3, RegisterA32& reg4)
: list_(RegisterToList(reg1) | RegisterToList(reg2) |
RegisterToList(reg3) | RegisterToList(reg4)) {}
explicit RegisterList(U16 list) : list_(list) {}
U16 GetList() const { return list_; }
void SetList(U16 list) { list_ = list; }
bool Includes(RegisterA32& reg) const {
return (list_ & RegisterToList(reg)) != 0;
}
void Combine(RegisterList& other) { list_ |= other.GetList(); }
void Combine(RegisterA32& reg) { list_ |= RegisterToList(reg); }
void Remove(RegisterList& other) { list_ &= ~other.GetList(); }
void Remove(RegisterA32& reg) { list_ &= ~RegisterToList(reg); }
bool Overlaps(RegisterList& other) const {
return (list_ & other.list_) != 0;
}
bool IsR0toR7orPC() const {
// True if all the registers from the list are not from r8-r14.
return (list_ & 0x7f00) == 0;
}
bool IsR0toR7orLR() const {
// True if all the registers from the list are not from r8-r13 nor from r15.
return (list_ & 0xbf00) == 0;
}
bool IsEmpty() const { return list_ == 0; }
static RegisterList Union(const RegisterList& list_1,
const RegisterList& list_2) {
return RegisterList(list_1.list_ | list_2.list_);
}
static RegisterList Union(const RegisterList& list_1,
const RegisterList& list_2,
const RegisterList& list_3) {
return Union(list_1, Union(list_2, list_3));
}
static RegisterList Union(const RegisterList& list_1,
const RegisterList& list_2,
const RegisterList& list_3,
const RegisterList& list_4) {
return Union(Union(list_1, list_2), Union(list_3, list_4));
}
static RegisterList Intersection(const RegisterList& list_1,
const RegisterList& list_2) {
return RegisterList(list_1.list_ & list_2.list_);
}
static RegisterList Intersection(const RegisterList& list_1,
const RegisterList& list_2,
const RegisterList& list_3) {
return Intersection(list_1, Intersection(list_2, list_3));
}
static RegisterList Intersection(const RegisterList& list_1,
const RegisterList& list_2,
const RegisterList& list_3,
const RegisterList& list_4) {
return Intersection(Intersection(list_1, list_2),
Intersection(list_3, list_4));
}
private:
static U16 RegisterToList(RegisterA32& reg) {
if (reg.getCode() == UnknowRegiser.getCode()) {
return 0;
} else {
return static_cast<U16>(UINT16_C(1) << reg.getCode());
}
}
// Bitfield representation of all registers in the list
// (1 for r0, 2 for r1, 4 for r2, ...).
U16 list_;
};
inline uint32_t GetRegisterListEncoding(const RegisterList& registers,
int first,
int count) {
return (registers.GetList() >> first) & ((1 << count) - 1);
}
inline bool isThumbCode(Addr codeAddr) {
return (codeAddr & 0x1) == 0x1;
}
inline bool isThumb32(InstT16 code) {
return ((code & 0xF000) == 0xF000) || ((code & 0xF800) == 0xE800);
}
inline void* getThumbCodeAddress(void* code) {
Addr addr = reinterpret_cast<Addr>(code) & (~0x1);
return reinterpret_cast<void*>(addr);
}
inline void* getThumbPC(void* code) {
Addr addr = reinterpret_cast<Addr>(code) & (~0x1);
return reinterpret_cast<void*>(addr + 1);
}
std::ostream& operator<<(std::ostream& os, RegisterList registers);
}
}
#endif //SANDHOOK_ARM32_BASE_H
//
// 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/16.
//
#ifndef SANDHOOK_INST_CODE_ARM32_H
#define SANDHOOK_INST_CODE_ARM32_H
enum class InstCodeA32 {
};
enum class InstCodeT16 {
UNKNOW,
BASE_SASMC,
DATA_PROC,
SPDIABE,
MISC,
B,
B_COND,
BX_BLX,
CBZ_CBNZ,
LDR_LIT,
ADD_IMM_RDN,
//rn = pc
ADR,
ADD_REG,
CMP_REG,
CMP_REG_EXT,
MOV_IMM,
MOV_REG,
POP,
PUSH
};
enum class InstCodeT32 {
UNKNOW,
B32,
LDR_LIT,
LDR_IMM,
LDR_UIMM,
MOV_MOVT_IMM
};
#endif //SANDHOOK_INST_CODE_ARM32_H
//
// Created by swift on 2019/5/12.
//
#ifndef SANDHOOK_NH_INST_STRUCT_ARM32_H
#define SANDHOOK_NH_INST_STRUCT_ARM32_H
#include "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.
//
#ifndef SANDHOOK_NH_INST_STRUCT_T16_H
#define SANDHOOK_NH_INST_STRUCT_T16_H
#include "instruction.h"
#include "inst_code_arm32.h"
#define STRUCT_T16(X) T16_STRUCT_##X
#define OPCODE_T16(X) T16_OPCODE_##X
#define DEFINE_OPCODE_T16(X, V) const U32 OPCODE_T16(X) = V;
#define DEFINE_STRUCT_T16(X) struct STRUCT_T16(X) : public Base
#define DEFINE_STRCUT_BASE_T16(w_base, w_op) \
InstT16 opcode:w_op; \
InstT16 opcode_base:w_base;
//Shift (immediate), add, subtract, move, and compare
//opcode_base == 0b00
DEFINE_OPCODE_T16(BASE_SASMC, 0b00)
//Data-processing
DEFINE_OPCODE_T16(DATA_PROC, 0b010000)
DEFINE_OPCODE_T16(SPDIABE, 0b010001)
DEFINE_OPCODE_T16(MISC, 0b1011)
#define DATA_PROC_FIELDS DEFINE_STRCUT_BASE_T16(6, 4)
#define T16_REG_WIDE 3
//unknow inst
DEFINE_STRUCT_T16(UNKNOW) {
InstT16 raw;
};
DEFINE_OPCODE_T16(B, 0b11100)
DEFINE_STRUCT_T16(B) {
InstT16 imm11:11;
InstT16 opcode:5;
};
DEFINE_OPCODE_T16(B_COND, 0b1101)
DEFINE_STRUCT_T16(B_COND) {
InstT16 imm8:8;
InstT16 cond:4;
InstT16 opcode:4;
};
DEFINE_OPCODE_T16(BX_BLX_1, 0b01000111)
DEFINE_OPCODE_T16(BX_BLX_2, 0b000)
DEFINE_STRUCT_T16(BX_BLX) {
InstT16 opcode2:3;
InstT16 rm:4;
InstT16 op:1;
InstT16 opcode1:8;
};
DEFINE_OPCODE_T16(CBZ_CBNZ_1, 0b1011)
DEFINE_OPCODE_T16(CBZ_CBNZ_2, 0b0)
DEFINE_OPCODE_T16(CBZ_CBNZ_3, 0b1)
DEFINE_STRUCT_T16(CBZ_CBNZ) {
InstT16 rn:T16_REG_WIDE;
InstT16 imm5:5;
InstT16 opcode3:1;
InstT16 i:1;
InstT16 opcode2:1;
InstT16 op:1;
InstT16 opcode1:4;
};
DEFINE_OPCODE_T16(LDR_LIT, 0b01001)
DEFINE_STRUCT_T16(LDR_LIT) {
InstT16 imm8:8;
InstT16 rt:T16_REG_WIDE;
InstT16 opcode:5;
};
DEFINE_OPCODE_T16(ADD_IMM_RDN, 0b00110)
DEFINE_STRUCT_T16(ADD_IMM_RDN) {
InstT16 imm8:8;
InstT16 rdn:T16_REG_WIDE;
InstT16 opcode:5;
};
DEFINE_OPCODE_T16(ADR, 0b10100)
DEFINE_STRUCT_T16(ADR) {
InstT16 imm8:8;
InstT16 rd:T16_REG_WIDE;
InstT16 opcode:5;
};
DEFINE_OPCODE_T16(CMP_REG, 0b1010)
DEFINE_STRUCT_T16(CMP_REG) {
InstT16 rn:T16_REG_WIDE;
InstT16 rm:T16_REG_WIDE;
DATA_PROC_FIELDS
};
DEFINE_OPCODE_T16(CMP_REG_EXT, 0b1010)
DEFINE_STRUCT_T16(CMP_REG_EXT) {
InstT16 rn:4;
InstT16 rm:4;
InstT16 N:1;
InstT16 opcode:8;
};
DEFINE_OPCODE_T16(MOV_REG, 0b10)
DEFINE_STRUCT_T16(MOV_REG) {
InstT16 rd:T16_REG_WIDE;
InstT16 rm:4;
InstT16 D:1;
DEFINE_STRCUT_BASE_T16(6, 2)
};
DEFINE_OPCODE_T16(MOV_IMM, 0b00100)
DEFINE_STRUCT_T16(MOV_IMM) {
InstT16 imm8:8;
InstT16 rd:T16_REG_WIDE;
InstT16 opcode:5;
};
DEFINE_OPCODE_T16(ADD_REG, 0b0001100)
DEFINE_STRUCT_T16(ADD_REG) {
InstT16 rd:T16_REG_WIDE;
InstT16 rn:T16_REG_WIDE;
InstT16 rm:T16_REG_WIDE;
InstT16 opcode:7;
};
DEFINE_OPCODE_T16(POP, 0b1011110)
DEFINE_STRUCT_T16(POP) {
InstT16 regs:8;
InstT16 P:1;
InstT16 opcode:7;
};
DEFINE_OPCODE_T16(PUSH, 0b1011010)
DEFINE_STRUCT_T16(PUSH) {
InstT16 regs:8;
InstT16 M:1;
InstT16 opcode:7;
};
#endif //SANDHOOK_NH_INST_STRUCT_T16_H
//
// Created by swift on 2019/5/12.
//
#ifndef SANDHOOK_NH_INST_STRUCT_T32_H
#define SANDHOOK_NH_INST_STRUCT_T32_H
#include "instruction.h"
#define STRUCT_T32(X) T32_STRUCT_##X
#define OPCODE_T32(X) T32_OPCODE_##X
#define DEFINE_OPCODE_T32(X, V) const U32 OPCODE_T32(X) = V;
#define DEFINE_STRUCT_T32(X) struct STRUCT_T32(X) : public Base
#define T32_REG_WIDE 4
//unknow inst
DEFINE_STRUCT_T32(UNKNOW) {
InstT32 raw;
};
DEFINE_OPCODE_T32(B32, 0b11110)
DEFINE_STRUCT_T32(B32) {
InstT32 imm10:10;
InstT32 S:1;
InstT32 opcode:5;
InstT32 imm11:11;
InstT32 J2:1;
InstT32 X:1;
InstT32 J1:1;
InstT32 op:2;
};
DEFINE_OPCODE_T32(LDR_LIT, 0b1111100)
DEFINE_STRUCT_T32(LDR_LIT) {
InstT32 op:7;
InstT32 U:1;
InstT32 S:1;
InstT32 opcode:7;
InstT32 imm12:12;
InstT32 rt:T32_REG_WIDE;
};
//ldr imm T3
DEFINE_OPCODE_T32(LDR_UIMM, 0b111110001101)
DEFINE_STRUCT_T32(LDR_UIMM) {
InstT32 rn:T32_REG_WIDE;
InstT32 opcode:12;
InstT32 imm12:12;
InstT32 rt:T32_REG_WIDE;
};
//ldr imm T4
DEFINE_OPCODE_T32(LDR_IMM_1, 0b11111000)
DEFINE_OPCODE_T32(LDR_IMM_2, 0b1)
DEFINE_STRUCT_T32(LDR_IMM) {
InstT32 rn:T32_REG_WIDE;
InstT32 op:4;
InstT32 opcode1:8;
InstT32 imm8:8;
InstT32 W:1;
InstT32 U:1;
InstT32 P:1;
InstT32 opcode2:1;
InstT32 rt:T32_REG_WIDE;
};
DEFINE_OPCODE_T32(MOV_MOVT_IMM_1, 0b11110)
DEFINE_OPCODE_T32(MOV_MOVT_IMM_2, 0b0)
DEFINE_STRUCT_T32(MOV_MOVT_IMM) {
InstT32 imm4:4;
InstT32 op:6;
InstT32 i:1;
InstT32 opcode1:5;
InstT32 imm8:8;
InstT32 rd:4;
InstT32 imm3:3;
InstT32 opcode2:1;
};
#endif //SANDHOOK_NH_INST_STRUCT_T32_H
//
// Created by swift on 2019/5/16.
//
#include "inst_t16.h"
#include "arm32_base.h"
#include "register_list_arm32.h"
#define SET_BASE_OPCODE(X) get()->opcode_base = OPCODE_T16(X)
#define SET_OPCODE(X) get()->opcode = OPCODE_T16(X)
#define SET_OPCODE_MULTI(X, INDEX) get()->opcode##INDEX = OPCODE_T16(X##_##INDEX)
using namespace SandHook::AsmA32;
using namespace SandHook::RegistersA32;
//Unknow
T16_UNKNOW::T16_UNKNOW(STRUCT_T16(UNKNOW) &inst) : InstructionT16(&inst) {
decode(&inst);
}
void T16_UNKNOW::decode(T16_STRUCT_UNKNOW *inst) {
inst_backup = *inst;
}
void T16_UNKNOW::assembler() {
set(inst_backup);
}
//B
T16_B::T16_B() {}
T16_B::T16_B(T16_STRUCT_B *inst) : T16_INST_PC_REL(inst) {
decode(inst);
}
T16_B::T16_B(Off offset) : offset(offset) {}
T16_B::T16_B(Label &label) {
bindLabel(label);
}
Off T16_B::getImmPCOffset() {
return DECODE_OFFSET(11, 1);
}
void T16_B::decode(T16_STRUCT_B *inst) {
offset = getImmPCOffset();
}
void T16_B::assembler() {
SET_OPCODE(B);
DECODE_OFFSET(11, 1);
}
void T16_B::onOffsetApply(Off offset) {
this->offset = offset;
DECODE_OFFSET(11, 1);
}
//B Cond
T16_B_COND::T16_B_COND() {}
T16_B_COND::T16_B_COND(STRUCT_T16(B_COND) *inst) : T16_INST_PC_REL(inst) {
decode(inst);
}
T16_B_COND::T16_B_COND(Condition condition, Off offset) : condition(condition), offset(offset) {}
T16_B_COND::T16_B_COND(Condition condition, Label &label) {
bindLabel(label);
}
void T16_B_COND::decode(STRUCT_T16(B_COND) *inst) {
DECODE_COND;
offset = getImmPCOffset();
}
void T16_B_COND::assembler() {
SET_OPCODE(B_COND);
ENCODE_COND;
ENCODE_OFFSET(8, 1);
}
void T16_B_COND::onOffsetApply(Off offset) {
this->offset = offset;
ENCODE_OFFSET(8, 1);
}
Off T16_B_COND::getImmPCOffset() {
return DECODE_OFFSET(8, 1);
}
//BX BLX
T16_BX_BLX::T16_BX_BLX(T16_BX_BLX::OP op, RegisterA32 &rm) : op(op), rm(&rm) {}
T16_BX_BLX::T16_BX_BLX(T16_STRUCT_BX_BLX *inst) : T16_INST_PC_REL(inst) {
decode(inst);
}
void T16_BX_BLX::decode(STRUCT_T16(BX_BLX) *inst) {
DECODE_OP;
DECODE_RM(Reg);
}
void T16_BX_BLX::assembler() {
SET_OPCODE_MULTI(BX_BLX, 1);
SET_OPCODE_MULTI(BX_BLX, 2);
ENCODE_OP;
ENCODE_RM;
}
//CBZ CBNZ
T16_CBZ_CBNZ::T16_CBZ_CBNZ(T16_STRUCT_CBZ_CBNZ *inst) : T16_INST_PC_REL(inst) {
decode(inst);
}
T16_CBZ_CBNZ::T16_CBZ_CBNZ(T16_CBZ_CBNZ::OP op, Off offset, RegisterA32 &rn) : op(op), offset(offset),
rn(&rn) {}
T16_CBZ_CBNZ::T16_CBZ_CBNZ(T16_CBZ_CBNZ::OP op, Label& label, RegisterA32 &rn) : op(op),
rn(&rn) {
bindLabel(label);
}
Off T16_CBZ_CBNZ::getImmPCOffset() {
return COMBINE(get()->i, get()->imm5, 5) << 2;
}
void T16_CBZ_CBNZ::decode(T16_STRUCT_CBZ_CBNZ *inst) {
offset = getImmPCOffset();
DECODE_RN(Reg);
DECODE_OP;
}
void T16_CBZ_CBNZ::assembler() {
SET_OPCODE_MULTI(CBZ_CBNZ, 1);
SET_OPCODE_MULTI(CBZ_CBNZ, 2);
SET_OPCODE_MULTI(CBZ_CBNZ, 3);
ENCODE_OP;
ENCODE_RN;
ENCODE_OFFSET(5, 2);
}
void T16_CBZ_CBNZ::onOffsetApply(Off offset) {
this->offset = offset;
ENCODE_OFFSET(5, 2);
}
//LDR_LIT
T16_LDR_LIT::T16_LDR_LIT(T16_STRUCT_LDR_LIT *inst) : T16_INST_PC_REL(inst) {
decode(inst);
}
T16_LDR_LIT::T16_LDR_LIT(Off offset, RegisterA32 &rt) : offset(offset), rt(&rt) {
}
Off T16_LDR_LIT::getImmPCOffset() {
return get()->imm8 << 2;
}
Addr T16_LDR_LIT::getImmPCOffsetTarget() {
return ALIGN((Addr) getPC() + offset, 4);
}
void T16_LDR_LIT::onOffsetApply(Off offset) {
this->offset = offset;
ENCODE_OFFSET(8, 2);
}
void T16_LDR_LIT::decode(T16_STRUCT_LDR_LIT *inst) {
DECODE_RT(Reg);
offset = getImmPCOffset();
}
void T16_LDR_LIT::assembler() {
SET_OPCODE(LDR_LIT);
ENCODE_RT;
ENCODE_OFFSET(8, 2);
}
//ADD IMM RD = RN
T16_ADD_IMM_RDN::T16_ADD_IMM_RDN(T16_STRUCT_ADD_IMM_RDN *inst) : InstructionT16(inst) {
decode(inst);
}
T16_ADD_IMM_RDN::T16_ADD_IMM_RDN(RegisterA32 *rdn, U8 imm8) : rdn(rdn), imm8(imm8) {}
void T16_ADD_IMM_RDN::decode(T16_STRUCT_ADD_IMM_RDN *inst) {
rdn = Reg(inst->rdn);
imm8 = inst->imm8;
}
void T16_ADD_IMM_RDN::assembler() {
SET_OPCODE(ADD_IMM_RDN);
get()->imm8 = imm8;
get()->rdn = rdn->getCode();
}
//ADR
T16_ADR::T16_ADR(T16_STRUCT_ADR *inst) : T16_INST_PC_REL(inst) {
decode(inst);
}
T16_ADR::T16_ADR(RegisterA32 &rd, Off offset) : rd(&rd), offset(offset) {}
T16_ADR::T16_ADR(RegisterA32 &rd, Label &label) : rd(&rd) {
bindLabel(label);
}
Off T16_ADR::getImmPCOffset() {
return COMBINE(get()->imm8, 0 ,2);
}
Addr T16_ADR::getImmPCOffsetTarget() {
return RoundDown((Addr) getPC() + offset, 4);
}
void T16_ADR::onOffsetApply(Off offset) {
this->offset = offset;
get()->imm8 = (U32)offset >> 2;
}
void T16_ADR::decode(T16_STRUCT_ADR *inst) {
offset = getImmPCOffset();
DECODE_RD(Reg);
}
void T16_ADR::assembler() {
SET_OPCODE(ADR);
ENCODE_RD;
get()->imm8 = (U32)offset >> 2;
}
T16_CMP_REG::T16_CMP_REG() {}
T16_CMP_REG::T16_CMP_REG(T16_STRUCT_CMP_REG *inst) : InstructionT16(inst) {
decode(inst);
}
T16_CMP_REG::T16_CMP_REG(RegisterA32 &rm, RegisterA32 &rn) : rm(&rm), rn(&rn) {}
void T16_CMP_REG::decode(T16_STRUCT_CMP_REG *inst) {
DECODE_RM(Reg);
DECODE_RN(Reg);
}
void T16_CMP_REG::assembler() {
SET_BASE_OPCODE(DATA_PROC);
SET_OPCODE(CMP_REG);
ENCODE_RM;
ENCODE_RN;
}
//MOV REG
T16_MOV_REG::T16_MOV_REG(T16_STRUCT_MOV_REG *inst) : InstructionT16(inst) {
decode(inst);
}
T16_MOV_REG::T16_MOV_REG(RegisterA32 &rd, RegisterA32 &rm) : rm(&rm), rd(&rd) {
}
void T16_MOV_REG::decode(T16_STRUCT_MOV_REG *inst) {
DECODE_RM(Reg);
rd = Reg(static_cast<U8>(COMBINE(inst->D, inst->rd, 3)));
}
void T16_MOV_REG::assembler() {
SET_BASE_OPCODE(DATA_PROC);
SET_OPCODE(MOV_REG);
ENCODE_RM;
get()->rd = BITS(rd->getCode(), 0, 2);
get()->D = BIT(rd->getCode(), 3);
}
bool T16_MOV_REG::pcRelate() {
return rd == &PC || rm == &PC;
}
T16_ADD_REG::T16_ADD_REG() {}
T16_ADD_REG::T16_ADD_REG(T16_STRUCT_ADD_REG *inst) : InstructionT16(inst) {
decode(inst);
}
T16_ADD_REG::T16_ADD_REG(RegisterA32 *rd, RegisterA32 *rn, RegisterA32 *rm) : rd(rd), rn(rn),
rm(rm) {}
void T16_ADD_REG::decode(T16_STRUCT_ADD_REG *inst) {
DECODE_RD(Reg);
DECODE_RN(Reg);
DECODE_RM(Reg);
}
void T16_ADD_REG::assembler() {
SET_OPCODE(ADD_REG);
INST_ASSERT(rd->getCode() > 7);
INST_ASSERT(rn->getCode() > 7);
INST_ASSERT(rm->getCode() > 7);
ENCODE_RD;
ENCODE_RN;
ENCODE_RM;
}
T16_CMP_REG_EXT::T16_CMP_REG_EXT(T16_STRUCT_CMP_REG_EXT *inst) : InstructionT16(inst) {
decode(inst);
}
T16_CMP_REG_EXT::T16_CMP_REG_EXT(RegisterA32 &rn, RegisterA32 &rm) : rn(&rn), rm(&rm) {}
void T16_CMP_REG_EXT::decode(T16_STRUCT_CMP_REG_EXT *inst) {
rn = Reg(COMBINE(inst->N, inst->rn, 3));
DECODE_RM(Reg);
}
void T16_CMP_REG_EXT::assembler() {
SET_OPCODE(CMP_REG_EXT);
ENCODE_RM;
get()->rn = BITS(rn->getCode(), 0, 2);
get()->N = BIT(rn->getCode(), 3);
}
//POP
T16_POP::T16_POP(T16_STRUCT_POP *inst) : InstructionT16(inst) {
decode(inst);
}
T16_POP::T16_POP(const RegisterList &registerList) : registerList(registerList) {}
void T16_POP::decode(T16_STRUCT_POP *inst) {
registerList.SetList(COMBINE(inst->P << 7, inst->regs, 8));
}
void T16_POP::assembler() {
SET_OPCODE(POP);
U16 regs = registerList.GetList();
get()->regs = BITS(regs, 0, 7);
get()->P = BIT(regs, 15);
}
//PUSH
T16_PUSH::T16_PUSH(T16_STRUCT_PUSH *inst) : InstructionT16(inst) {
decode(inst);
}
T16_PUSH::T16_PUSH(const RegisterList &registerList) : registerList(registerList) {}
void T16_PUSH::decode(T16_STRUCT_PUSH *inst) {
registerList.SetList(COMBINE(inst->M << 6, inst->regs, 8));
}
void T16_PUSH::assembler() {
SET_OPCODE(PUSH);
U16 regs = registerList.GetList();
get()->regs = BITS(regs, 0, 7);
get()->M = BIT(regs, 14);
}
\ No newline at end of file
This diff is collapsed.
//
// Created by swift on 2019/5/16.
//
#include "inst_t32.h"
#include "inst_struct_t32.h"
#define SET_BASE_OPCODE(X) get()->opcode_base = OPCODE_T32(X)
#define SET_OPCODE(X) get()->opcode = OPCODE_T32(X)
#define SET_OPCODE_MULTI(X, INDEX) get()->opcode##INDEX = OPCODE_T32(X##_##INDEX)
using namespace SandHook::Asm;
using namespace SandHook::AsmA32;
//Unknow
T32_UNKNOW::T32_UNKNOW(STRUCT_T32(UNKNOW) &inst) : InstructionT32(&inst) {
decode(&inst);
}
void T32_UNKNOW::decode(T32_STRUCT_UNKNOW *inst) {
inst_backup = *inst;
}
void T32_UNKNOW::assembler() {
set(inst_backup);
}
T32_B32::T32_B32(T32_STRUCT_B32 *inst) : T32_INST_PC_REL(inst) {
decode(inst);
}
T32_B32::T32_B32(T32_B32::OP op, T32_B32::X x, Off offset) : op(op), x(x), offset(offset) {}
T32_B32::T32_B32(T32_B32::OP op, T32_B32::X x, Label &label) : op(op), x(x) {
bindLabel(label);
}
Off T32_B32::getImmPCOffset() {
U32 S = get()->S;
U32 imm21 = COMBINE(get()->imm10, get()->imm11, 11);
if (get()->X == 0) {
imm21 &= ~(1 << 0);
}
U32 i1 = !(get()->J1 ^ S);
U32 i2 = !(get()->J2 ^ S);
U32 i1i2 = COMBINE(i1, i2, 1);
U32 Si1i2 = COMBINE(-S, i1i2, 2);
return signExtend32(25, COMBINE(Si1i2, imm21, 21) << 1);
}
void T32_B32::decode(T32_STRUCT_B32 *inst) {
DECODE_OP;
x = X(inst->X);
offset = getImmPCOffset();
}
void T32_B32::assembler() {
SET_OPCODE(B32);
ENCODE_OP;
get()->X = x;
U32 imm24 = TruncateToUint25(offset) >> 1;
get()->imm11 = BITS(imm24, 0, 10);
get()->imm10 = BITS(imm24, 11, 20);
if (get()->X == 0) {
get()->imm11 |= (1 << 0);
}
get()->S = BIT(imm24, 23);
U32 i1 = BIT(imm24, 22);
U32 i2 = BIT(imm24, 21);
if (i1 == 1) {
get()->J1 = get()->S;
} else {
get()->J1 = !get()->S;
}
if (i2 == 1) {
get()->J2 = get()->S;
} else {
get()->J2 = !get()->S;
}
}
Addr T32_B32::getImmPCOffsetTarget() {
if (x == arm) {
void* base = reinterpret_cast<void *>(ALIGN((Addr) getPC(), 4));
return offset + reinterpret_cast<Addr>(base);
} else {
return T32_INST_PC_REL::getImmPCOffsetTarget();
}
}
T32_LDR_UIMM::T32_LDR_UIMM(T32_STRUCT_LDR_UIMM *inst) : InstructionT32(inst) {}
T32_LDR_UIMM::T32_LDR_UIMM(RegisterA32 &rt, RegisterA32 &rn, U32 offset) : rt(&rt), rn(&rn),
offset(offset) {}
void T32_LDR_UIMM::decode(T32_STRUCT_LDR_UIMM *inst) {
DECODE_RN(Reg);
DECODE_RT(Reg);
INST_ASSERT(rn == &PC);
offset = inst->imm12;
}
void T32_LDR_UIMM::assembler() {
SET_OPCODE(LDR_UIMM);
ENCODE_RN;
ENCODE_RT;
INST_ASSERT(rn == &PC);
get()->imm12 = offset;
}
T32_LDR_LIT::T32_LDR_LIT() {}
T32_LDR_LIT::T32_LDR_LIT(T32_STRUCT_LDR_LIT *inst) : T32_INST_PC_REL(inst) {
decode(inst);
}
T32_LDR_LIT::T32_LDR_LIT(OP op, S s, RegisterA32 &rt, Off offset) : op(op), s(s), rt(&rt), offset(offset) {}
T32_LDR_LIT::T32_LDR_LIT(OP op, S s, RegisterA32 &rt, Label& label) : op(op), s(s), rt(&rt) {
bindLabel(label);
}
Off T32_LDR_LIT::getImmPCOffset() {
return get()->U == add ? get()->imm12 : -get()->imm12;
}
void T32_LDR_LIT::onOffsetApply(Off offset) {
this->offset = offset;
if (offset >= 0) {
get()->U = add;
get()->imm12 = static_cast<InstT32>(offset);
} else {
get()->U = cmp;
get()->imm12 = static_cast<InstT32>(-offset);
}
}
void T32_LDR_LIT::decode(T32_STRUCT_LDR_LIT *inst) {
DECODE_OP;
DECODE_RT(Reg);
s = S(inst->S);
offset = getImmPCOffset();
}
void T32_LDR_LIT::assembler() {
SET_OPCODE(LDR_LIT);
ENCODE_OP;
ENCODE_RT;
get()->S = s;
if (offset >= 0) {
get()->U = add;
get()->imm12 = static_cast<InstT32>(offset);
} else {
get()->U = cmp;
get()->imm12 = static_cast<InstT32>(-offset);
}
}
T32_MOV_MOVT_IMM::T32_MOV_MOVT_IMM() {}
T32_MOV_MOVT_IMM::T32_MOV_MOVT_IMM(T32_STRUCT_MOV_MOVT_IMM *inst) : InstructionT32(inst) {
decode(inst);
}
T32_MOV_MOVT_IMM::T32_MOV_MOVT_IMM(T32_MOV_MOVT_IMM::OP op, RegisterA32 &rd, U16 imm16) : op(op),
rd(&rd),
imm16(imm16) {}
void T32_MOV_MOVT_IMM::decode(T32_STRUCT_MOV_MOVT_IMM *inst) {
DECODE_OP;
DECODE_RD(Reg);
U16 imm4i = COMBINE(inst->imm4, inst->i, 1);
U16 imm38 = COMBINE(inst->imm3, inst->imm8, 8);
imm16 = COMBINE(imm4i, imm38, 11);
}
void T32_MOV_MOVT_IMM::assembler() {
SET_OPCODE_MULTI(MOV_MOVT_IMM, 1);
SET_OPCODE_MULTI(MOV_MOVT_IMM, 2);
ENCODE_OP;
ENCODE_RD;
get()->imm8 = BITS(imm16, 0, 7);
get()->imm3 = BITS(imm16, 8 ,10);
get()->i = BIT(imm16, 11);
get()->imm4 = BITS(imm16, 12, 15);
}
T32_LDR_IMM::T32_LDR_IMM(T32_STRUCT_LDR_IMM *inst) : InstructionT32(inst) {
decode(inst);
}
T32_LDR_IMM::T32_LDR_IMM(T32_LDR_IMM::OP op, RegisterA32 &rt, const MemOperand &operand) : op(op),
rt(&rt),
operand(operand) {}
void T32_LDR_IMM::decode(T32_STRUCT_LDR_IMM *inst) {
DECODE_OP;
DECODE_RT(Reg);
operand.rn = Reg(static_cast<U8>(inst->rn));
if (inst->P == 1 && inst->U == 0 && inst->W == 0) {
operand.addr_mode = Offset;
} else if (inst->P == 0 && inst->W == 1) {
operand.addr_mode = PostIndex;
} else if (inst->P == 1 && inst->W == 1) {
operand.addr_mode = PreIndex;
} else {
valid = false;
}
operand.offset = inst->U == 0 ? -inst->imm8 : inst->imm8;
}
void T32_LDR_IMM::assembler() {
SET_OPCODE_MULTI(LDR_IMM, 1);
SET_OPCODE_MULTI(LDR_IMM, 2);
ENCODE_OP;
get()->rn = operand.rn->getCode();
if (operand.offset < 0) {
get()->imm8 = static_cast<InstT32>(-operand.offset);
get()->U = 0;
} else {
get()->imm8 = static_cast<InstT32>(operand.offset);
get()->U = 1;
}
switch (operand.addr_mode) {
case Offset:
get()->P = 1;
get()->U = 0;
get()->W = 0;
break;
case PostIndex:
get()->P = 0;
get()->W = 1;
break;
case PreIndex:
get()->P = 1;
get()->W = 1;
break;
default:
valid = false;
}
}
//
// Created by swift on 2019/5/16.
//
#ifndef SANDHOOK_INST_T32_H
#define SANDHOOK_INST_T32_H
#include "arm_base.h"
#include "arm32_base.h"
#include "register_list_arm32.h"
#include "inst_struct_t16.h"
#include "inst_code_arm32.h"
#include "inst_struct_t32.h"
#define INST_T32(X) T32_##X
#define IS_OPCODE_T32(RAW,OP) INST_T32(OP)::is(RAW)
#define DEFINE_IS_EXT(X, COND) \
inline static bool is(InstT32& inst) { \
union { \
InstT32 raw; \
STRUCT_T32(X) inst; \
} inst_test; \
inst_test.raw = inst; \
return COND; \
}
#define DEFINE_IS(X) DEFINE_IS_EXT(X, TEST_INST_FIELD(opcode,OPCODE_T32(X)))
#define TEST_INST_FIELD(F,V) inst_test.inst.F == V
#define INST_FIELD(F) inst_test.inst.F
#define TEST_INST_OPCODE(X, INDEX) inst_test.inst.opcode##INDEX == OPCODE_T32(X##_##INDEX)
#define DEFINE_INST_CODE(X) \
inline U32 instCode() override { \
return ENUM_VALUE(InstCodeT32, InstCodeT32::X); \
}
using namespace SandHook::RegistersA32;
namespace SandHook {
namespace AsmA32 {
template<typename Inst>
class InstructionT32 : public Instruction<Inst> {
public:
InstructionT32() {}
InstructionT32(Inst *inst) : Instruction<Inst>(inst) {}
Inst mask(Inst raw) {
return raw & *(this->get());
}
U32 size() override {
return 4;
}
void *getPC() override {
return reinterpret_cast<void *>((Addr) Instruction<Inst>::getPC() + 2 * 2);
}
Addr getVPC() override {
return Instruction<Inst>::getVPC() + 2 * 2;
}
static inline S32 signExtend32(unsigned int bits, U32 value) {
return ExtractSignedBitfield32(bits - 1, 0, value);
}
InstType instType() override {
return thumb32;
}
Arch arch() override {
return arm32;
}
};
template <typename Inst>
class T32_INST_PC_REL : public InstructionT32<Inst> {
public:
T32_INST_PC_REL() {};
T32_INST_PC_REL(Inst *inst) : InstructionT32<Inst>(inst) {};
virtual Off getImmPCOffset() {
return 0;
};
virtual Addr getImmPCOffsetTarget() {
return (Addr) this->getPC() + getImmPCOffset();
};
inline bool pcRelate() override {
return true;
};
};
class INST_T32(UNKNOW) : public InstructionT32<STRUCT_T32(UNKNOW)> {
public:
T32_UNKNOW(STRUCT_T32(UNKNOW) &inst);
DEFINE_INST_CODE(UNKNOW)
inline bool unknow() override {
return true;
}
void decode(T32_STRUCT_UNKNOW *inst) override;
void assembler() override;
private:
STRUCT_T32(UNKNOW) inst_backup;
};
class INST_T32(B32) : public T32_INST_PC_REL<STRUCT_T32(B32)> {
public:
enum OP {
B = 0b10,
BL = 0b11
};
enum X {
arm = 0b0,
thumb = 0b1
};
T32_B32(T32_STRUCT_B32 *inst);
T32_B32(OP op, X x, Off offset);
T32_B32(OP op, X x, Label& label);
DEFINE_INST_CODE(B32)
DEFINE_IS(B32)
Addr getImmPCOffsetTarget() override;
Off getImmPCOffset() override;
void decode(T32_STRUCT_B32 *inst) override;
void assembler() override;
public:
OP op;
X x;
Off offset;
};
class INST_T32(LDR_UIMM) : public InstructionT32<STRUCT_T32(LDR_UIMM)> {
public:
T32_LDR_UIMM(T32_STRUCT_LDR_UIMM *inst);
T32_LDR_UIMM(RegisterA32 &rt, RegisterA32 &rn, U32 offset);
DEFINE_INST_CODE(LDR_UIMM)
DEFINE_IS(LDR_UIMM)
void decode(T32_STRUCT_LDR_UIMM *inst) override;
void assembler() override;
public:
RegisterA32* rt;
RegisterA32* rn;
U32 offset;
};
class INST_T32(LDR_LIT) : public T32_INST_PC_REL<STRUCT_T32(LDR_LIT)> {
public:
enum OP {
LDR = 0b1011111,
LDRB = 0b0011111,
LDRH = 0b0111111
};
enum U {
cmp = 0b0,
add = 0b1
};
enum S {
UnSign = 0b0,
Sign = 0b1
};
T32_LDR_LIT();
T32_LDR_LIT(T32_STRUCT_LDR_LIT *inst);
T32_LDR_LIT(OP op, S s, RegisterA32 &rt, Off offset);
T32_LDR_LIT(OP op, S s, RegisterA32 &rt, Label& label);
DEFINE_IS(LDR_LIT)
DEFINE_INST_CODE(LDR_LIT)
Off getImmPCOffset() override;
void onOffsetApply(Off offset) override;
void decode(T32_STRUCT_LDR_LIT *inst) override;
void assembler() override;
public:
OP op;
S s;
RegisterA32* rt;
Off offset;
};
class INST_T32(MOV_MOVT_IMM) : public InstructionT32<STRUCT_T32(MOV_MOVT_IMM)> {
public:
enum OP {
MOV = 0b100100,
MOVT = 0b101100
};
T32_MOV_MOVT_IMM();
T32_MOV_MOVT_IMM(T32_STRUCT_MOV_MOVT_IMM *inst);
T32_MOV_MOVT_IMM(OP op, RegisterA32 &rd, U16 imm16);
DEFINE_IS_EXT(MOV_MOVT_IMM, TEST_INST_OPCODE(MOV_MOVT_IMM, 1) && TEST_INST_OPCODE(MOV_MOVT_IMM, 2))
DEFINE_INST_CODE(MOV_MOVT_IMM)
void decode(T32_STRUCT_MOV_MOVT_IMM *inst) override;
void assembler() override;
public:
OP op;
RegisterA32* rd;
U16 imm16;
};
class INST_T32(LDR_IMM) : public InstructionT32<STRUCT_T32(LDR_IMM)> {
public:
enum OP {
LDR = 0b0101,
LDRB = 0b1001,
LDRH = 0b1011,
LDRSB = 0b0001,
LDRSH = 0b0011
};
T32_LDR_IMM(T32_STRUCT_LDR_IMM *inst);
T32_LDR_IMM(OP op, RegisterA32 &rt, const MemOperand &operand);
DEFINE_IS_EXT(LDR_IMM, TEST_INST_OPCODE(LDR_IMM, 1) && TEST_INST_OPCODE(LDR_IMM, 2))
DEFINE_INST_CODE(LDR_IMM)
void decode(T32_STRUCT_LDR_IMM *inst) override;
void assembler() override;
public:
OP op;
RegisterA32* rt;
MemOperand operand;
};
}
}
#undef DEFINE_IS_EXT
#undef DEFINE_IS
#undef TEST_INST_FIELD
#undef TEST_INST_OPCODE
#undef DEFINE_INST_CODE
#endif //SANDHOOK_INST_T32_H
//
// Created by swift on 2019/5/12.
//
#include "register_arm32.h"
#include "register_list_arm32.h"
using namespace SandHook::RegistersA32;
SandHook::Asm::RegisterA32::RegisterA32(U8 code) : Register(code) {
}
SandHook::Asm::RegisterA32::RegisterA32() {
}
U8 SandHook::Asm::RegisterA32::getWide() {
return 4;
}
RegisterA32* RegisterA32::registers[ARM32_REGISTER_COUNT] = {
#define DEFINE_REGISTERS_X(N) \
&R##N,
ARM32_REGISTER_CODE_LIST(DEFINE_REGISTERS_X)
#undef DEFINE_REGISTERS_X
};
\ No newline at end of file
//
// 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 {
union A32RegisterStruct {
struct {
U8 b3;
U8 b2;
U8 b1;
U8 b0;
} u8;
struct {
U16 h;
U16 l;
} u16;
};
class RegisterA32 : public Register<A32RegisterStruct> {
public:
RegisterA32();
RegisterA32(U8 code);
U8 getWide() override;
virtual bool isUnkonw () {
return getCode() == 38;
}
static RegisterA32* get(U8 code) {
return registers[code];
}
private:
static RegisterA32* registers[];
};
}
}
#endif //SANDHOOK_NH_REGISTER_A32_H
//
// Created by swift on 2019/5/16.
//
#include "register_list_arm32.h"
namespace SandHook {
namespace RegistersA32 {
#define INIT_REGISTERS(N) \
RegisterA32 R##N = RegisterA32(N);
ARM32_REGISTER_CODE_LIST(INIT_REGISTERS)
#undef INIT_REGISTERS
enum RegNum {
kIPRegNum = 12, kSPRegNum = 13, kLRRegNum = 14, kPCRegNum = 15
};
RegisterA32 SP = *Reg(kSPRegNum);
RegisterA32 IP = *Reg(kIPRegNum);
RegisterA32 LR = *Reg(kLRRegNum);
RegisterA32 PC = *Reg(kPCRegNum);
RegisterA32 UnknowRegiser = RegisterA32(38);
}}
\ No newline at end of file
//
// Created by swift on 2019/5/8.
//
#ifndef SANDHOOK_NH_REGISTER_LIST_A32_H
#define SANDHOOK_NH_REGISTER_LIST_A32_H
#include "register_arm32.h"
using namespace SandHook::Asm;
// clang-format off
#define ARM32_REGISTER_COUNT 16
#define ARM32_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)
namespace SandHook {
namespace RegistersA32 {
#define DEFINE_REGISTERS(N) \
extern RegisterA32 R##N;
ARM32_REGISTER_CODE_LIST(DEFINE_REGISTERS)
#undef DEFINE_REGISTERS
extern RegisterA32 SP;
extern RegisterA32 IP;
extern RegisterA32 LR;
extern RegisterA32 PC;
extern RegisterA32 UnknowRegiser;
}}
#define Reg(N) RegisterA32::get(N)
#endif //SANDHOOK_NH_REGISTER_LIST_A32_H
//
// Created by swift on 2019/5/23.
//
#include "code_relocate_arm32.h"
#include "decoder.h"
#include "lock.h"
using namespace SandHook::RegistersA32;
using namespace SandHook::AsmA32;
using namespace SandHook::Utils;
using namespace SandHook::Decoder;
#define __ assemblerA32->
#define IMPL_RELOCATE(T, X) void CodeRelocateA32::relocate_##T##_##X (INST_##T(X)* inst, void* toPc) throw(ErrorCodeException)
#define CASE(T, X) \
case ENUM_VALUE(InstCode##T, InstCode##T::X): \
relocate_##T##_##X(reinterpret_cast<INST_##T(X)*>(instruction), toPc); \
break;
CodeRelocateA32::CodeRelocateA32(AssemblerA32 &assembler) : CodeRelocate(assembler.codeContainer) {
this->assemblerA32 = &assembler;
}
bool CodeRelocateA32::visit(Unit<Base> *unit, void *pc) {
relocate(reinterpret_cast<Instruction<Base> *>(unit), __ getPC());
curOffset += unit->size();
if (unit->refcount() == 0) {
delete unit;
}
return true;
}
void* CodeRelocateA32::relocate(void *startPc, Addr len, void *toPc = nullptr) throw(ErrorCodeException) {
AutoLock autoLock(relocateLock);
startAddr = reinterpret_cast<Addr>(startPc);
if (isThumbCode(startAddr)) {
startAddr = reinterpret_cast<Addr>(getThumbCodeAddress(startPc));
}
length = len;
curOffset = 0;
__ allocBufferFirst(static_cast<U32>(len * 8));
void* curPc = __ getPC();
if (toPc == nullptr) {
Disassembler::get()->decode(startPc, len, *this);
} else {
//TODO
}
return curPc;
}
void* CodeRelocateA32::relocate(Instruction<Base> *instruction, void *toPc) throw(ErrorCodeException) {
void* curPc = __ getPC();
//insert later bind labels
__ Emit(getLaterBindLabel(curOffset));
if (!instruction->pcRelate()) {
__ Emit(instruction);
instruction->ref();
return curPc;
}
if (instruction->instType() == thumb32) {
switch (instruction->instCode()) {
CASE(T32, B32)
CASE(T32, LDR_LIT)
default:
__ Emit(instruction);
instruction->ref();
}
} else if (instruction->instType() == thumb16) {
switch (instruction->instCode()) {
CASE(T16, B)
CASE(T16, B_COND)
CASE(T16, BX_BLX)
CASE(T16, CBZ_CBNZ)
CASE(T16, ADR)
CASE(T16, LDR_LIT)
default:
__ Emit(instruction);
instruction->ref();
}
} else {
__ Emit(instruction);
instruction->ref();
}
return curPc;
}
IMPL_RELOCATE(T16, B_COND) {
if (inRelocateRange(CODE_OFFSET(inst), sizeof(InstT16))) {
__ B(inst->condition, getLaterBindLabel(CODE_OFFSET(inst) + curOffset));
return;
}
Addr targetAddr = inst->getImmPCOffsetTarget();
if (inst->condition == al) {
Label* target_label = new Label;
__ Ldr(PC, target_label);
__ Emit(target_label);
__ Emit(targetAddr);
} else {
Label* true_label = new Label();
Label* false_label = new Label();
Label* target_label = new Label;
__ B(inst->condition, true_label);
__ B(false_label);
__ Emit(true_label);
__ Ldr(PC, target_label);
__ Emit(target_label);
__ Emit(targetAddr);
__ Emit(false_label);
}
}
IMPL_RELOCATE(T16, B) {
if (inRelocateRange(CODE_OFFSET(inst), sizeof(InstT16))) {
__ B(getLaterBindLabel(CODE_OFFSET(inst) + curOffset));
return;
}
Addr targetAddr = inst->getImmPCOffsetTarget();
Label* target_label = new Label();
__ Ldr(PC, target_label);
__ Emit(target_label);
__ Emit((Addr) getThumbPC(reinterpret_cast<void *>(targetAddr)));
}
IMPL_RELOCATE(T16, BX_BLX) {
__ Emit(reinterpret_cast<Instruction<Base>*>(inst));
inst->ref();
}
IMPL_RELOCATE(T16, CBZ_CBNZ) {
inst->ref();
if (inRelocateRange(CODE_OFFSET(inst), sizeof(InstT16))) {
inst->bindLabel(*getLaterBindLabel(CODE_OFFSET(inst) + curOffset));
__ Emit(reinterpret_cast<Instruction<Base>*>(inst));
return;
}
Addr targetAddr = inst->getImmPCOffsetTarget();
Label* true_label = new Label;
Label* false_label = new Label;
Label* target_label = new Label();
inst->bindLabel(*true_label);
__ Emit(reinterpret_cast<Instruction<Base>*>(inst));
__ B(false_label);
__ Emit(true_label);
__ Ldr(PC, target_label);
__ Emit(target_label);
__ Emit((Addr) getThumbPC(reinterpret_cast<void *>(targetAddr)));
__ Emit(false_label);
}
IMPL_RELOCATE(T16, LDR_LIT) {
if (inRelocateRange(CODE_OFFSET(inst), inst->rt->getWide())) {
inst->ref();
inst->bindLabel(*getLaterBindLabel(CODE_OFFSET(inst) + curOffset));
__ Emit(reinterpret_cast<Instruction<Base>*>(inst));
return;
}
Addr targetAddr = inst->getImmPCOffsetTarget();
__ Mov(*inst->rt, targetAddr);
__ Ldr(*inst->rt, MemOperand(inst->rt, 0));
}
IMPL_RELOCATE(T16, ADR) {
if (inRelocateRange(CODE_OFFSET(inst), inst->rd->getWide())) {
inst->ref();
inst->bindLabel(*getLaterBindLabel(CODE_OFFSET(inst) + curOffset));
__ Emit(reinterpret_cast<Instruction<Base>*>(inst));
return;
}
Addr targetAddr = inst->getImmPCOffsetTarget();
__ Mov(*inst->rd, targetAddr);
}
IMPL_RELOCATE(T32, B32) {
if (inRelocateRange(CODE_OFFSET(inst), sizeof(InstT16))) {
inst->ref();
inst->bindLabel(*getLaterBindLabel(CODE_OFFSET(inst) + curOffset));
__ Emit(reinterpret_cast<Instruction<Base>*>(inst));
return;
}
Addr targetAddr = inst->getImmPCOffsetTarget();
if (inst->x == T32_B32::thumb) {
//Thumb mode
if (inst->op == T32_B32::BL) {
__ Mov(LR, U32((Addr) toPc + inst->size() + 2 * 2));
}
targetAddr = reinterpret_cast<Addr>(getThumbPC(reinterpret_cast<void *>(targetAddr)));
Label* target_label = new Label();
__ Ldr(PC, target_label);
__ Emit(target_label);
__ Emit(reinterpret_cast<Addr>(targetAddr));
} else {
//to A32 mode
__ Mov(IP, targetAddr);
if (inst->op == T32_B32::BL) {
__ Blx(IP);
} else {
__ Bx(IP);
}
}
}
IMPL_RELOCATE(T32, LDR_LIT) {
if (inRelocateRange(CODE_OFFSET(inst), sizeof(InstT16))) {
inst->ref();
inst->bindLabel(*getLaterBindLabel(CODE_OFFSET(inst) + curOffset));
__ Emit(reinterpret_cast<Instruction<Base>*>(inst));
return;
}
Addr targetAddr = inst->getImmPCOffsetTarget();
__ Mov(*inst->rt, targetAddr);
switch (inst->op) {
case T32_LDR_LIT::LDR:
__ Ldr(*inst->rt, MemOperand(inst->rt, 0));
break;
case T32_LDR_LIT::LDRB:
if (inst->s == T32_LDR_LIT::UnSign) {
__ Ldrb(*inst->rt, MemOperand(inst->rt, 0));
} else {
__ Ldrsb(*inst->rt, MemOperand(inst->rt, 0));
}
break;
case T32_LDR_LIT::LDRH:
if (inst->s == T32_LDR_LIT::UnSign) {
__ Ldrh(*inst->rt, MemOperand(inst->rt, 0));
} else {
__ Ldrsh(*inst->rt, MemOperand(inst->rt, 0));
}
break;
default:
inst->ref();
__ Emit(reinterpret_cast<Instruction<Base>*>(inst));
}
}
\ No newline at end of file
//
// Created by swift on 2019/5/23.
//
#ifndef SANDHOOK_CODE_RELOCATE_ARM32_H
#define SANDHOOK_CODE_RELOCATE_ARM32_H
#include <mutex>
#include <map>
#include "code_relocate.h"
#include "assembler_arm32.h"
using namespace SandHook::Assembler;
using namespace SandHook::Decoder;
using namespace SandHook::AsmA32;
#define DEFINE_RELOCATE(T, X) void relocate_##T##_##X (INST_##T(X)* inst, void* toPc) throw(ErrorCodeException);
namespace SandHook {
namespace Asm {
class CodeRelocateA32 : public CodeRelocate {
public:
CodeRelocateA32(AssemblerA32 &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(T16, B_COND)
DEFINE_RELOCATE(T16, B)
DEFINE_RELOCATE(T16, BX_BLX)
DEFINE_RELOCATE(T16, CBZ_CBNZ)
DEFINE_RELOCATE(T16, LDR_LIT)
DEFINE_RELOCATE(T16, ADR)
DEFINE_RELOCATE(T32, B32)
DEFINE_RELOCATE(T32, LDR_LIT)
private:
AssemblerA32* assemblerA32;
};
}
}
#undef DEFINE_RELOCATE
#endif //SANDHOOK_CODE_RELOCATE_ARM32_H
//
// Created by swift on 2019/5/11.
//
#include "assembler_arm64.h"
using namespace SandHook::Assembler;
using namespace SandHook::RegistersA64;
using namespace SandHook::AsmA64;
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(RegisterA64 &rt, Label* label) {
Emit(reinterpret_cast<Unit<Base> *>(new INST_A64(LDR_LIT)(INST_A64(LDR_LIT)::LDR_SW, 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)));
}
}
// If the current stack pointer is sp, then it must be aligned to 16 bytes
// on entry and the total size of the specified registers must also be a
// multiple of 16 bytes.
void AssemblerA64::Pop(RegisterA64 &rd) {
if (rd.isX()) {
Ldr(rd, MemOperand(&SP, 16, PostIndex));
} else {
Ldr(rd, MemOperand(&WSP, 16, PostIndex));
}
}
// If the current stack pointer is sp, then it must be aligned to 16 bytes
// on entry and the total size of the specified registers must also be a
// multiple of 16 bytes.
void AssemblerA64::Push(RegisterA64 &rt) {
if (rt.isX()) {
Str(rt, MemOperand(&SP, -16, PreIndex));
} else {
Str(rt, MemOperand(&WSP, -16, PreIndex));
}
}
void AssemblerA64::Cmp(RegisterA64 &rn, const Operand &operand) {
Subs(*zeroRegFor(rn), rn, operand);
}
void AssemblerA64::Subs(RegisterA64 &rd, RegisterA64 &rn, const Operand &operand) {
Emit(reinterpret_cast<Unit<Base> *>(new INST_A64(SUB_EXT_REG)(rd, rn, operand, SetFlags)));
}
//
// Created by swift on 2019/5/11.
//
#ifndef SANDHOOK_NH_ASSEMBLER_A64_H
#define SANDHOOK_NH_ASSEMBLER_A64_H
#include "assembler.h"
#include "register_arm64.h"
#include "inst_arm64.h"
using namespace SandHook::AsmA64;
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(RegisterA64 &rt, Label* label);
void Ldrsw(XRegister& rt, const MemOperand& memOperand);
void Pop(RegisterA64& rt);
void Push(RegisterA64& rt);
void Subs(RegisterA64& rd, RegisterA64& rn, const Operand& operand);
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;
using namespace SandHook::AsmA64;
#define CASE(X) \
if (IS_OPCODE_A64(*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; \
}
Arm64Decoder* Arm64Decoder::instant = new Arm64Decoder();
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_UIMM)
CASE(STR_IMM)
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 INST_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;
public:
static Arm64Decoder* instant;
};
}
}
#endif //SANDHOOK_NH_DECODER_ARM64_H
//
// Created by swift on 2019/5/23.
//
#include "hook_arm64.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_arm64.h"
#include "code_relocate_arm64.h"
using namespace SandHook::RegistersA64;
void *InlineHookArm64Android::inlineHook(void *origin, void *replace) {
AutoLock lock(hookLock);
void* backup = nullptr;
AssemblerA64 assemblerBackup(backupBuffer);
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((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((Addr) origin + codeContainerInline->size());
__ finish();
#undef __
//commit inline trampoline
assemblerInline.finish();
return backup;
}
\ No newline at end of file
//
// Created by swift on 2019/5/23.
//
#ifndef SANDHOOK_HOOK_ARM64_H
#define SANDHOOK_HOOK_ARM64_H
#include "hook.h"
namespace SandHook {
namespace Hook {
class InlineHookArm64Android : public 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_HOOK_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 class 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"
#include "arm_base.h"
#define STRUCT_A64(X) A64_STRUCT_##X
#define OPCODE_A64(X) A64_OPCODE_##X
#define DEFINE_OPCODE_A64(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
};
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_A64(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_A64(MOV_WIDE, 0b100101)
DEFINE_STRUCT_A64(MOV_WIDE) {
InstA64 rd:WideReg;
InstA64 imm16:16;
InstA64 hw:2;
InstA64 opcode:6;
InstA64 op:2;
InstA64 sf:1;
};
DEFINE_OPCODE_A64(MOV_REG_1, 0b0101010000)
DEFINE_OPCODE_A64(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_A64(B_BL, 0b00101)
DEFINE_STRUCT_A64(B_BL) {
InstA64 imm26:26;
InstA64 opcode:5;
InstA64 op:1;
};
DEFINE_OPCODE_A64(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_A64(B_COND, 0b01010100)
DEFINE_STRUCT_A64(B_COND) {
InstA64 cond:4;
InstA64 unkown_0:1;
InstA64 imm19:19;
InstA64 opcode:8;
};
DEFINE_OPCODE_A64(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_A64(LDR_LIT, 0b011000)
DEFINE_STRUCT_A64(LDR_LIT) {
InstA64 rt:WideReg;
InstA64 imm19:19;
InstA64 opcode:6;
InstA64 op:2;
};
DEFINE_OPCODE_A64(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_A64(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_A64(LDRSW_UIMM, 0b11100110)
struct STRUCT_A64(LDRSW_UIMM) : public STRUCT_A64(LDR_UIMM) {
};
DEFINE_OPCODE_A64(LDRSW_IMM, 0b111000100)
struct STRUCT_A64(LDRSW_IMM) : public STRUCT_A64(LDR_IMM) {
};
DEFINE_OPCODE_A64(BR_BLR_RET_1, 0b110101100)
DEFINE_OPCODE_A64(BR_BLR_RET_2, 0b11111000000)
DEFINE_OPCODE_A64(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_A64(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_A64(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_A64(SUB_EXT_REG_1, 0b1)
DEFINE_OPCODE_A64(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_A64(EXCEPTION_GEN_1, 0b11010100)
DEFINE_OPCODE_A64(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_arm64.h"
#include "register_list_arm64.h"
using namespace SandHook::Asm;
using namespace SandHook::RegistersA64;
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;
}
This diff is collapsed.
//
// Created by swift on 2019/5/16.
//
#ifndef SANDHOOK_PLACE_HOLDER_H
#define SANDHOOK_PLACE_HOLDER_H
#endif //SANDHOOK_PLACE_HOLDER_H
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
//
// Created by swift on 2019/5/23.
//
#ifndef SANDHOOK_MEMORY_H
#define SANDHOOK_MEMORY_H
namespace SandHook {
namespace VM {
class Memory {
};
}
}
#endif //SANDHOOK_MEMORY_H
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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