diff --git a/build.gradle b/build.gradle index ddd888e9..6ace8209 100644 --- a/build.gradle +++ b/build.gradle @@ -24,6 +24,7 @@ allprojects { templateLib64Path = templateRootPath + "/system/lib64/" templateEtcPath = templateRootPath + "/system/etc/" hiddenApiStubJarFilePath = project(":hiddenapi-stubs").buildDir.absolutePath + "/libs/framework-stub.jar" + zipPathMagiskReleasePath = project(":edxp-core").projectDir.path + "/build/tmp/release/magisk" } repositories { google() @@ -34,8 +35,3 @@ allprojects { task clean(type: Delete) { delete rootProject.buildDir } - -ext { - minSdkVersion = 23 - targetSdkVersion = 28 -} diff --git a/edxp-common/build.gradle b/edxp-common/build.gradle index 28713379..01a708ed 100644 --- a/edxp-common/build.gradle +++ b/edxp-common/build.gradle @@ -4,8 +4,8 @@ android { compileSdkVersion androidCompileSdkVersion.toInteger() defaultConfig { - minSdkVersion 26 - targetSdkVersion 28 + minSdkVersion minSdkVersion + targetSdkVersion targetSdkVersion versionCode 1 versionName "1.0" } diff --git a/edxp-core/build.gradle b/edxp-core/build.gradle index e3f9b3dc..20aa1baf 100644 --- a/edxp-core/build.gradle +++ b/edxp-core/build.gradle @@ -41,7 +41,6 @@ ext { sandhook_authors = "solohsu, MlgmXyysd & ganyao114" riruModuleId = "edxp" - zipPathMagiskRelease = "$buildDir/tmp/release/magisk" moduleMinRiruApiVersion = 10 moduleMinRiruVersionName = "v23.0" @@ -120,13 +119,16 @@ afterEvaluate { def variantLowered = variant.name.toLowerCase() backends.each { backend -> - def backendLowered = backend.toLowerCase() def backendCapped = backendLowered.capitalize() def authorList = property("${backendLowered}" + "_authors") def magiskModuleId = property("${backendLowered}" + "_module_id") + project.logger.lifecycle("delete file") + delete file(zipPathMagiskReleasePath) + def prepareJarsTask = task("prepareJars${backendCapped}${variantCapped}") { + project.logger.lifecycle("prepareJarsTask") dependsOn cleanTemplate dependsOn tasks.getByPath(":dexmaker:copyDex${variantCapped}") dependsOn tasks.getByPath(":dalvikdx:copyDex${variantCapped}") @@ -136,7 +138,6 @@ afterEvaluate { def prepareMagiskFilesTask = task("prepareMagiskFiles${backendCapped}${variantCapped}", type: Delete) { dependsOn prepareJarsTask, "assemble${variantCapped}" - delete file(zipPathMagiskRelease) doFirst { copy { from "${projectDir}/tpl/edconfig.tpl" @@ -169,12 +170,12 @@ afterEvaluate { doLast { copy { from "${projectDir}/template_override" - into zipPathMagiskRelease + into zipPathMagiskReleasePath exclude exclude_list } copy { from "${projectDir}/template_override" - into zipPathMagiskRelease + into zipPathMagiskReleasePath include 'riru.sh' filter { line -> line.replaceAll('%%%RIRU_MODULE_ID%%%', riruModuleId) @@ -185,23 +186,27 @@ afterEvaluate { eol: FixCrLfFilter.CrLf.newInstance("lf")) } copy { + include "libriru_edxp.so" from "$libPathRelease/armeabi-v7a" - into "$zipPathMagiskRelease/system/lib" + into "$zipPathMagiskReleasePath/system/lib" } copy { + include "libriru_edxp.so" from "$libPathRelease/arm64-v8a" - into "$zipPathMagiskRelease/system/lib64" + into "$zipPathMagiskReleasePath/system/lib64" } copy { + include "libriru_edxp.so" from "$libPathRelease/x86" - into "$zipPathMagiskRelease/system_x86/lib" + into "$zipPathMagiskReleasePath/system_x86/lib" } copy { + include "libriru_edxp.so" from "$libPathRelease/x86_64" - into "$zipPathMagiskRelease/system_x86/lib64" + into "$zipPathMagiskReleasePath/system_x86/lib64" } // generate sha1sum - fileTree(zipPathMagiskRelease).matching { + fileTree(zipPathMagiskReleasePath).matching { exclude "README.md", "META-INF" }.visit { f -> if (f.directory) return @@ -214,7 +219,7 @@ afterEvaluate { dependsOn prepareMagiskFilesTask archiveName "${module_name}-${backend}-${project.version}-${variantLowered}.zip" destinationDir file("$projectDir/release") - from "$zipPathMagiskRelease" + from "$zipPathMagiskReleasePath" } task("push${backendCapped}${variantCapped}", type: Exec) { diff --git a/edxp-sandhook/build.gradle b/edxp-sandhook/build.gradle index 3d4c0112..65a339e8 100644 --- a/edxp-sandhook/build.gradle +++ b/edxp-sandhook/build.gradle @@ -8,8 +8,8 @@ android { defaultConfig { applicationId "com.elderdrivers.riru.edxp.sandhook" - minSdkVersion 26 - targetSdkVersion 28 + minSdkVersion minSdkVersion + targetSdkVersion targetSdkVersion versionCode 1 versionName "1.0" multiDexEnabled false @@ -28,7 +28,7 @@ android { dependencies { compileOnly project(':hiddenapi-stubs') implementation project(':edxp-common') - implementation 'com.swift.sandhook:hooklib:4.2.1' + implementation project(':sandhook-hooklib') compileOnly files(project(":dexmaker").tasks.getByName("makeJarRelease").outputs) } @@ -62,21 +62,21 @@ afterEvaluate { task("copyDex${variantNameCapped}", type: Copy) { dependsOn "assemble${variantNameCapped}" dependsOn tasks.getByPath(":edxp-common:copyCommonProperties") + dependsOn tasks.getByPath(":sandhook-hooklib:copySandHook${variantNameCapped}LibraryToMagiskTemplate") def dexOutPath = variant.name.contains("release") ? "${buildDir}/intermediates/dex/${variantNameLowered}/minify${variantNameCapped}WithR8" : "${buildDir}/intermediates/dex/${variantNameLowered}/mergeDex${variantNameCapped}" from (dexOutPath){ rename("classes.dex", "edxp.dex") } - destinationDir file(templateRootPath + "system/framework/") + destinationDir file(zipPathMagiskReleasePath + "/system/framework/") outputs.upToDateWhen { false } doLast { copy { from file(myTemplatePath) - into file(templateRootPath) + into file(zipPathMagiskReleasePath) } } } - } } \ No newline at end of file diff --git a/edxp-sandhook/template_override/system/lib/libsandhook.edxp.so b/edxp-sandhook/template_override/system/lib/libsandhook.edxp.so deleted file mode 100644 index f8ff8905..00000000 Binary files a/edxp-sandhook/template_override/system/lib/libsandhook.edxp.so and /dev/null differ diff --git a/edxp-sandhook/template_override/system/lib64/libsandhook.edxp.so b/edxp-sandhook/template_override/system/lib64/libsandhook.edxp.so deleted file mode 100644 index 3e0cdc56..00000000 Binary files a/edxp-sandhook/template_override/system/lib64/libsandhook.edxp.so and /dev/null differ diff --git a/edxp-service/build.gradle b/edxp-service/build.gradle index fea020a2..b93169ce 100644 --- a/edxp-service/build.gradle +++ b/edxp-service/build.gradle @@ -8,8 +8,8 @@ android { defaultConfig { applicationId "com.elderdrivers.riru.edxp.yahfa" - minSdkVersion 26 - targetSdkVersion 28 + minSdkVersion minSdkVersion + targetSdkVersion targetSdkVersion versionCode 1 versionName "1.0" multiDexEnabled false diff --git a/edxp-yahfa/build.gradle b/edxp-yahfa/build.gradle index 890712a9..892c9c75 100644 --- a/edxp-yahfa/build.gradle +++ b/edxp-yahfa/build.gradle @@ -8,8 +8,8 @@ android { defaultConfig { applicationId "com.elderdrivers.riru.edxp.yahfa" - minSdkVersion 26 - targetSdkVersion 28 + minSdkVersion minSdkVersion + targetSdkVersion targetSdkVersion versionCode 1 versionName "1.0" multiDexEnabled false diff --git a/gradle.properties b/gradle.properties index e4fc85aa..0950a45a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,6 @@ androidCompileSdkVersion=30 androidCompileNdkVersion=22.0.6917172 android.prefabVersion=1.1.2 -apiCode=93 \ No newline at end of file +apiCode=93 +minSdkVersion=26 +targetSdkVersion=30 \ No newline at end of file diff --git a/sandhook-annotation/.gitignore b/sandhook-annotation/.gitignore new file mode 100644 index 00000000..796b96d1 --- /dev/null +++ b/sandhook-annotation/.gitignore @@ -0,0 +1 @@ +/build diff --git a/sandhook-annotation/build.gradle b/sandhook-annotation/build.gradle new file mode 100644 index 00000000..0e4c5e4a --- /dev/null +++ b/sandhook-annotation/build.gradle @@ -0,0 +1,8 @@ +apply plugin: 'java-library' + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) +} + +sourceCompatibility = "1.7" +targetCompatibility = "1.7" \ No newline at end of file diff --git a/sandhook-annotation/src/main/java/com/swift/sandhook/annotation/HookClass.java b/sandhook-annotation/src/main/java/com/swift/sandhook/annotation/HookClass.java new file mode 100644 index 00000000..199a3a15 --- /dev/null +++ b/sandhook-annotation/src/main/java/com/swift/sandhook/annotation/HookClass.java @@ -0,0 +1,12 @@ +package com.swift.sandhook.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface HookClass { + Class value(); +} diff --git a/sandhook-annotation/src/main/java/com/swift/sandhook/annotation/HookMethod.java b/sandhook-annotation/src/main/java/com/swift/sandhook/annotation/HookMethod.java new file mode 100644 index 00000000..1404649f --- /dev/null +++ b/sandhook-annotation/src/main/java/com/swift/sandhook/annotation/HookMethod.java @@ -0,0 +1,12 @@ +package com.swift.sandhook.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface HookMethod { + String value() default ""; +} diff --git a/sandhook-annotation/src/main/java/com/swift/sandhook/annotation/HookMethodBackup.java b/sandhook-annotation/src/main/java/com/swift/sandhook/annotation/HookMethodBackup.java new file mode 100644 index 00000000..4ae5769a --- /dev/null +++ b/sandhook-annotation/src/main/java/com/swift/sandhook/annotation/HookMethodBackup.java @@ -0,0 +1,12 @@ +package com.swift.sandhook.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD,ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface HookMethodBackup { + String value() default ""; +} diff --git a/sandhook-annotation/src/main/java/com/swift/sandhook/annotation/HookMode.java b/sandhook-annotation/src/main/java/com/swift/sandhook/annotation/HookMode.java new file mode 100644 index 00000000..503ee21a --- /dev/null +++ b/sandhook-annotation/src/main/java/com/swift/sandhook/annotation/HookMode.java @@ -0,0 +1,17 @@ +package com.swift.sandhook.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface HookMode { + + int AUTO = 0; + int INLINE = 1; + int REPLACE = 2; + + int value() default AUTO; +} diff --git a/sandhook-annotation/src/main/java/com/swift/sandhook/annotation/HookReflectClass.java b/sandhook-annotation/src/main/java/com/swift/sandhook/annotation/HookReflectClass.java new file mode 100644 index 00000000..d6cf8933 --- /dev/null +++ b/sandhook-annotation/src/main/java/com/swift/sandhook/annotation/HookReflectClass.java @@ -0,0 +1,12 @@ +package com.swift.sandhook.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface HookReflectClass { + String value(); +} diff --git a/sandhook-annotation/src/main/java/com/swift/sandhook/annotation/MethodParams.java b/sandhook-annotation/src/main/java/com/swift/sandhook/annotation/MethodParams.java new file mode 100644 index 00000000..351a441a --- /dev/null +++ b/sandhook-annotation/src/main/java/com/swift/sandhook/annotation/MethodParams.java @@ -0,0 +1,12 @@ +package com.swift.sandhook.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD,ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface MethodParams { + Class[] value(); +} \ No newline at end of file diff --git a/sandhook-annotation/src/main/java/com/swift/sandhook/annotation/MethodReflectParams.java b/sandhook-annotation/src/main/java/com/swift/sandhook/annotation/MethodReflectParams.java new file mode 100644 index 00000000..c40b039f --- /dev/null +++ b/sandhook-annotation/src/main/java/com/swift/sandhook/annotation/MethodReflectParams.java @@ -0,0 +1,22 @@ +package com.swift.sandhook.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD,ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface MethodReflectParams { + + String BOOLEAN = "boolean"; + String BYTE = "byte"; + String CHAR = "char"; + String DOUBLE = "double"; + String FLOAT = "float"; + String INT = "int"; + String LONG = "long"; + String SHORT = "short"; + + String[] value(); +} \ No newline at end of file diff --git a/sandhook-annotation/src/main/java/com/swift/sandhook/annotation/Param.java b/sandhook-annotation/src/main/java/com/swift/sandhook/annotation/Param.java new file mode 100644 index 00000000..de4eb55e --- /dev/null +++ b/sandhook-annotation/src/main/java/com/swift/sandhook/annotation/Param.java @@ -0,0 +1,12 @@ +package com.swift.sandhook.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +public @interface Param { + String value() default ""; +} diff --git a/sandhook-annotation/src/main/java/com/swift/sandhook/annotation/SkipParamCheck.java b/sandhook-annotation/src/main/java/com/swift/sandhook/annotation/SkipParamCheck.java new file mode 100644 index 00000000..7013d110 --- /dev/null +++ b/sandhook-annotation/src/main/java/com/swift/sandhook/annotation/SkipParamCheck.java @@ -0,0 +1,11 @@ +package com.swift.sandhook.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD, ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface SkipParamCheck { +} diff --git a/sandhook-annotation/src/main/java/com/swift/sandhook/annotation/ThisObject.java b/sandhook-annotation/src/main/java/com/swift/sandhook/annotation/ThisObject.java new file mode 100644 index 00000000..5550d898 --- /dev/null +++ b/sandhook-annotation/src/main/java/com/swift/sandhook/annotation/ThisObject.java @@ -0,0 +1,11 @@ +package com.swift.sandhook.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +public @interface ThisObject { +} diff --git a/sandhook-hooklib/.gitignore b/sandhook-hooklib/.gitignore new file mode 100644 index 00000000..9ff2a377 --- /dev/null +++ b/sandhook-hooklib/.gitignore @@ -0,0 +1,2 @@ +/build +/.cxx diff --git a/sandhook-hooklib/build.gradle b/sandhook-hooklib/build.gradle new file mode 100644 index 00000000..588010a4 --- /dev/null +++ b/sandhook-hooklib/build.gradle @@ -0,0 +1,66 @@ +apply plugin: 'com.android.library' + +android { + compileSdkVersion targetSdkVersion + + defaultConfig { + minSdkVersion minSdkVersion + targetSdkVersion targetSdkVersion + versionCode 1 + versionName "1.0" + + externalNativeBuild { + cmake { + //arguments "-DCMAKE_BUILD_TYPE=Release" + } + } + ndk { + abiFilters 'armeabi-v7a', 'arm64-v8a' + } + } + + externalNativeBuild { + cmake { + path "src/main/cpp/CMakeLists.txt" + } + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + +} + +dependencies { + implementation fileTree(include: ['*.jar'], dir: 'libs') + api project(':sandhook-annotation') +} + +afterEvaluate { + android.libraryVariants.all { variant -> + def variantNameCapped = variant.name.capitalize() + def variantNameLowered = variant.name.toLowerCase() + + task("copySandHook${variantNameCapped}LibraryToMagiskTemplate") { + def libPathRelease = "${buildDir}/intermediates/cmake/${variantNameLowered}/obj" + doLast { + project.logger.lifecycle(libPathRelease) + copy { + include "libsandhook.edxp.so" + from "${libPathRelease}/armeabi-v7a" + into "${zipPathMagiskReleasePath}/system/lib" + } + copy { + project.logger.lifecycle(zipPathMagiskReleasePath) + include "libsandhook.edxp.so" + from "${libPathRelease}/arm64-v8a" + into "${zipPathMagiskReleasePath}/system/lib64" + } + } + } + + } +} diff --git a/sandhook-hooklib/proguard-rules.pro b/sandhook-hooklib/proguard-rules.pro new file mode 100644 index 00000000..27d58c26 --- /dev/null +++ b/sandhook-hooklib/proguard-rules.pro @@ -0,0 +1,23 @@ +# 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 + +-keep class com.swift.sandhook.** { *; } diff --git a/sandhook-hooklib/src/main/AndroidManifest.xml b/sandhook-hooklib/src/main/AndroidManifest.xml new file mode 100644 index 00000000..5f32bcca --- /dev/null +++ b/sandhook-hooklib/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + diff --git a/sandhook-hooklib/src/main/cpp/CMakeLists.txt b/sandhook-hooklib/src/main/cpp/CMakeLists.txt new file mode 100644 index 00000000..7e62adef --- /dev/null +++ b/sandhook-hooklib/src/main/cpp/CMakeLists.txt @@ -0,0 +1,33 @@ +cmake_minimum_required(VERSION 3.4.1) +project(sandhook.edxp) + +ENABLE_LANGUAGE(ASM) + +add_definitions(-std=c++11) + +set(${PROJECT_NAME}_SOURCES + sandhook.cpp + trampoline/trampoline.cpp + trampoline/trampoline_manager.cpp + utils/dlfcn_nougat.cpp + utils/hide_api.cpp + utils/utils.cpp + utils/offset.cpp + utils/elf_util.cpp + casts/cast_art_method.cpp + casts/cast_compiler_options.cpp + art/art_method.cpp + art/art_compiler_options.cpp + art/art_classlinker.cpp + trampoline/arch/arm32.S + trampoline/arch/arm64.S + inst/insts_arm32.cpp + inst/insts_arm64.cpp + nativehook/native_hook.cpp + ) + +add_library(${PROJECT_NAME} + SHARED + ${${PROJECT_NAME}_SOURCES}) + +target_link_libraries(${PROJECT_NAME} log) \ No newline at end of file diff --git a/sandhook-hooklib/src/main/cpp/art/art_classlinker.cpp b/sandhook-hooklib/src/main/cpp/art/art_classlinker.cpp new file mode 100644 index 00000000..d54f50f2 --- /dev/null +++ b/sandhook-hooklib/src/main/cpp/art/art_classlinker.cpp @@ -0,0 +1,9 @@ +// +// Created by 双草酸酯 on 11/27/20. +// +#include "../includes/art_classlinker.h" + +using namespace art; +void ClassLinker::MakeInitializedClassesVisiblyInitialized(void* self, bool wait) { + +} \ No newline at end of file diff --git a/sandhook-hooklib/src/main/cpp/art/art_compiler_options.cpp b/sandhook-hooklib/src/main/cpp/art/art_compiler_options.cpp new file mode 100644 index 00000000..eaab2044 --- /dev/null +++ b/sandhook-hooklib/src/main/cpp/art/art_compiler_options.cpp @@ -0,0 +1,25 @@ +// +// Created by 甘尧 on 2019/2/24. +// + +#include "../includes/art_compiler_options.h" +#include "../includes/cast_compiler_options.h" +#include "../includes/hide_api.h" + +using namespace SandHook; +using namespace art; + +extern int SDK_INT; + +size_t CompilerOptions::getInlineMaxCodeUnits() { + if (SDK_INT < ANDROID_N) + return 0; + return CastCompilerOptions::inlineMaxCodeUnits->get(this); +} + +bool CompilerOptions::setInlineMaxCodeUnits(size_t units) { + if (SDK_INT < ANDROID_N) + return false; + CastCompilerOptions::inlineMaxCodeUnits->set(this, units); + return true; +} diff --git a/sandhook-hooklib/src/main/cpp/art/art_method.cpp b/sandhook-hooklib/src/main/cpp/art/art_method.cpp new file mode 100644 index 00000000..368b5faf --- /dev/null +++ b/sandhook-hooklib/src/main/cpp/art/art_method.cpp @@ -0,0 +1,197 @@ +// +// Created by swift on 2019/2/3. +// +#include +#include "../includes/art_method.h" +#include "../includes/cast_art_method.h" +#include "../includes/hide_api.h" +#include "../includes/utils.h" + +extern int SDK_INT; +extern bool DEBUG; + +using namespace art::mirror; +using namespace SandHook; + +// Non-intrinsics: Caches whether we can use fast-path in the interpreter invokes. +// Intrinsics: These bits are part of the intrinsic ordinal. +static constexpr uint32_t kAccFastInterpreterToInterpreterInvoke = 0x40000000; // method. + +void ArtMethod::tryDisableInline() { + if (SDK_INT < ANDROID_O) + return; + uint32_t accessFlag = getAccessFlags(); + accessFlag &= ~ 0x08000000; + setAccessFlags(accessFlag); +} + +void ArtMethod::disableInterpreterForO() { + if (SDK_INT >= ANDROID_O && SDK_INT < ANDROID_R && DEBUG) { + setNative(); + } +} + +void ArtMethod::disableFastInterpreterForQ() { + if (SDK_INT < ANDROID_Q) + return; + uint32_t accessFlag = getAccessFlags(); + accessFlag &= ~kAccFastInterpreterToInterpreterInvoke; + setAccessFlags(accessFlag); +} + +void ArtMethod::disableCompilable() { + if (SDK_INT < ANDROID_N) + return; + uint32_t accessFlag = getAccessFlags(); + if (SDK_INT >= ANDROID_O2) { + accessFlag |= 0x02000000; + accessFlag |= 0x00800000; + } else { + accessFlag |= 0x01000000; + } + setAccessFlags(accessFlag); +} + +bool ArtMethod::isAbstract() { + uint32_t accessFlags = getAccessFlags(); + return ((accessFlags & 0x0400) != 0); +} + +bool ArtMethod::isNative() { + uint32_t accessFlags = getAccessFlags(); + return ((accessFlags & 0x0100) != 0); +} + +bool ArtMethod::isStatic() { + uint32_t accessFlags = getAccessFlags(); + return ((accessFlags & 0x0008) != 0); +} + +bool ArtMethod::isCompiled() { + return getQuickCodeEntry() != CastArtMethod::quickToInterpreterBridge && + getQuickCodeEntry() != CastArtMethod::genericJniStub; +} + +bool ArtMethod::isThumbCode() { + #if defined(__arm__) + return (reinterpret_cast(getQuickCodeEntry()) & 0x1) == 0x1; + #else + return false; + #endif +} + +void ArtMethod::setAccessFlags(uint32_t flags) { + CastArtMethod::accessFlag->set(this, flags); +} + +void ArtMethod::setPrivate() { + uint32_t accessFlag = getAccessFlags(); + accessFlag &= ~ 0x0001; + accessFlag &= ~ 0x0004; + accessFlag |= 0x0002; + setAccessFlags(accessFlag); +} + +void ArtMethod::setStatic() { + uint32_t accessFlag = getAccessFlags(); + accessFlag |= 0x0008; + setAccessFlags(accessFlag); +}; + + +void ArtMethod::setNative() { + uint32_t accessFlag = getAccessFlags(); + accessFlag |= 0x0100; + setAccessFlags(accessFlag); +} + +uint32_t ArtMethod::getAccessFlags() { + return CastArtMethod::accessFlag->get(this); +} + +uint32_t ArtMethod::getDexMethodIndex() { + return CastArtMethod::dexMethodIndex->get(this); +} + +void* ArtMethod::getQuickCodeEntry() { + return CastArtMethod::entryPointQuickCompiled->get(this); +} + +void* ArtMethod::getInterpreterCodeEntry() { + return CastArtMethod::entryPointFromInterpreter->get(this); +} + +GCRoot ArtMethod::getDeclaringClass() { + return CastArtMethod::declaringClass->get(this); +} + +uint16_t ArtMethod::getHotnessCount() { + return CastArtMethod::hotnessCount->get(this); +} + +void ArtMethod::setQuickCodeEntry(void *entry) { + CastArtMethod::entryPointQuickCompiled->set(this, entry); +} + +void ArtMethod::setJniCodeEntry(void *entry) { + CastArtMethod::entryPointFromJNI->set(this, entry); +} + +void ArtMethod::setInterpreterCodeEntry(void *entry) { + CastArtMethod::entryPointFromInterpreter->set(this, entry); +} + +void ArtMethod::setDexCacheResolveList(void *list) { + CastArtMethod::dexCacheResolvedMethods->set(this, list); +} + +void ArtMethod::setDexCacheResolveItem(uint32_t index, void* item) { + CastArtMethod::dexCacheResolvedMethods->setElement(this, index, item); +} + +void ArtMethod::setDeclaringClass(GCRoot classPtr) { + CastArtMethod::declaringClass->set(this, classPtr); +} + +void ArtMethod::setHotnessCount(uint16_t count) { + CastArtMethod::hotnessCount->set(this, count); +} + +bool ArtMethod::compile(JNIEnv* env) { + if (isCompiled()) + return true; + //some unknown error when trigger jit for jni method manually + if (isNative()) + return false; + Size threadId = getAddressFromJavaByCallMethod(env, "com/swift/sandhook/SandHook", "getThreadId"); + if (threadId == 0) + return false; + return compileMethod(this, reinterpret_cast(threadId)) && isCompiled(); +} + +bool ArtMethod::deCompile() { + if (!isCompiled()) + return true; + if ((isNative() && CastArtMethod::canGetJniBridge) || (!isNative() && CastArtMethod::canGetInterpreterBridge)) { + setQuickCodeEntry(isNative() ? CastArtMethod::genericJniStub : CastArtMethod::quickToInterpreterBridge); + if (SDK_INT < ANDROID_N) { + //TODO SetEntryPointFromInterpreterCode + } + flushCache(); + return true; + } else { + return false; + } +} + +void ArtMethod::flushCache() { +// flushCacheExt(reinterpret_cast(this), size()); +} + +void ArtMethod::backup(ArtMethod *backup) { + memcpy(backup, this, size()); +} + +Size ArtMethod::size() { + return CastArtMethod::size; +} diff --git a/sandhook-hooklib/src/main/cpp/casts/cast_art_method.cpp b/sandhook-hooklib/src/main/cpp/casts/cast_art_method.cpp new file mode 100644 index 00000000..b67d70ed --- /dev/null +++ b/sandhook-hooklib/src/main/cpp/casts/cast_art_method.cpp @@ -0,0 +1,290 @@ +// +// Created by swift on 2019/2/3. +// + +#include "../includes/cast_art_method.h" +#include "../includes/utils.h" +#include "../includes/never_call.h" +#include "../includes/log.h" + +extern int SDK_INT; + +namespace SandHook { + + class CastDexCacheResolvedMethods : public ArrayMember { + protected: + Size calOffset(JNIEnv *jniEnv, art::mirror::ArtMethod *p) override { + if (SDK_INT >= ANDROID_P) + return getParentSize() + 1; + int offset = 0; + Size addr = getAddressFromJava(jniEnv, "com/swift/sandhook/SandHookMethodResolver", + "resolvedMethodsAddress"); + if (addr != 0) { + offset = findOffset(p, getParentSize(), 2, addr); + if (offset >= 0) { + return static_cast(offset); + } + } + if (SDK_INT == ANDROID_M) { + return 4; + } else if (SDK_INT >= ANDROID_L && SDK_INT <= ANDROID_L2) { + return 4 * 3; + } + return getParentSize() + 1; + } + + public: + Size arrayStart(mirror::ArtMethod *parent) override { + void *p = IMember::get(parent); + if (SDK_INT <= ANDROID_M) { + return reinterpret_cast(p) + 4 * 3; + } else { + return reinterpret_cast(p); + } + } + + }; + + class CastEntryPointFormInterpreter : public IMember { + protected: + Size calOffset(JNIEnv *jniEnv, art::mirror::ArtMethod *p) override { + if (SDK_INT == ANDROID_L2) { + return RoundUpToPtrSize(4 * 7 + 4 * 2); + } else if (SDK_INT == ANDROID_M) { + return getParentSize() - 3 * BYTE_POINT; + } else if (SDK_INT <= ANDROID_L) { + Size addr = getAddressFromJava(jniEnv, "com/swift/sandhook/SandHookMethodResolver", + "entryPointFromInterpreter"); + int offset = 0; + if (addr != 0) { + offset = findOffset(p, getParentSize(), 2, addr); + if (offset >= 0) { + return static_cast(offset); + } + } + return getParentSize() - 4 * 8 - 4 * 4; + } + else + return getParentSize() + 1; + } + }; + + class CastEntryPointQuickCompiled : public IMember { + protected: + Size calOffset(JNIEnv *jniEnv, art::mirror::ArtMethod *p) override { + if (SDK_INT >= ANDROID_M) { + return getParentSize() - BYTE_POINT; + } else if (SDK_INT <= ANDROID_L) { + Size addr = getAddressFromJava(jniEnv, "com/swift/sandhook/SandHookMethodResolver", + "entryPointFromCompiledCode"); + int offset = 0; + if (addr != 0) { + offset = findOffset(p, getParentSize(), 2, addr); + if (offset >= 0) { + return static_cast(offset); + } + } + return getParentSize() - 4 - 2 * BYTE_POINT; + } else { + return CastArtMethod::entryPointFromInterpreter->getOffset() + 2 * BYTE_POINT; + } + } + }; + + class CastEntryPointFromJni : public IMember { + protected: + Size calOffset(JNIEnv *jniEnv, art::mirror::ArtMethod *p) override { + Size jniAddr = reinterpret_cast(Java_com_swift_sandhook_ClassNeverCall_neverCallNative); + int offset = findOffset(p, getParentSize(), 2, jniAddr); + if (offset >= 0) { + return static_cast(offset); + } + if (SDK_INT >= ANDROID_L2 && SDK_INT <= ANDROID_N) { + return getParentSize() - 2 * BYTE_POINT; + } else { + return getParentSize() - 8 * 2 - 4 * 4; + } + } + }; + + + class CastAccessFlag : public IMember { + protected: + Size calOffset(JNIEnv *jniEnv, art::mirror::ArtMethod *p) override { + uint32_t accessFlag = getIntFromJava(jniEnv, "com/swift/sandhook/SandHook", + "testAccessFlag"); + if (accessFlag == 0) { + accessFlag = 524313; + //kAccPublicApi + if (SDK_INT >= ANDROID_Q) { + accessFlag |= 0x10000000; + } + } + int offset = findOffset(p, getParentSize(), 2, accessFlag); + if (offset < 0) { + if (SDK_INT >= ANDROID_N) { + return 4; + } else if (SDK_INT == ANDROID_L2) { + return 20; + } else if (SDK_INT == ANDROID_L) { + return 56; + } else { + return getParentSize() + 1; + } + } else { + return static_cast(offset); + } + } + }; + + class CastShadowClass : public IMember { + protected: + Size calOffset(JNIEnv *jniEnv, mirror::ArtMethod *p) override { + if (SDK_INT < ANDROID_N) + return getParentSize() + 1; + return 0; + } + }; + + + class CastDexMethodIndex : public IMember { + protected: + Size calOffset(JNIEnv *jniEnv, art::mirror::ArtMethod *p) override { + if (SDK_INT >= ANDROID_P) { + return CastArtMethod::accessFlag->getOffset() + + CastArtMethod::accessFlag->size() + + sizeof(uint32_t); + } + int offset = 0; + jint index = getIntFromJava(jniEnv, "com/swift/sandhook/SandHookMethodResolver", + "dexMethodIndex"); + if (index != 0) { + offset = findOffset(p, getParentSize(), 2, static_cast(index)); + if (offset >= 0) { + return static_cast(offset); + } + } + return getParentSize() + 1; + } + }; + + class CastHotnessCount : public IMember { + protected: + Size calOffset(JNIEnv *jniEnv, mirror::ArtMethod *p) override { + if (SDK_INT <= ANDROID_N) + return getParentSize() + 1; + return CastArtMethod::dexMethodIndex->getOffset() + + CastArtMethod::dexMethodIndex->size() + + sizeof(uint16_t); + } + }; + + + void CastArtMethod::init(JNIEnv *env) { + //init ArtMethodSize + jclass sizeTestClass = env->FindClass("com/swift/sandhook/ArtMethodSizeTest"); + jobject artMethod1 = getMethodObject(env, "com.swift.sandhook.ArtMethodSizeTest", "method1"); + jobject artMethod2 = getMethodObject(env, "com.swift.sandhook.ArtMethodSizeTest", "method2"); + + env->CallStaticVoidMethod(sizeTestClass, env->FromReflectedMethod(artMethod1)); + + std::atomic_thread_fence(std::memory_order_acquire); + + art::mirror::ArtMethod *m1 = getArtMethod(env, artMethod1); + art::mirror::ArtMethod *m2 = getArtMethod(env, artMethod2); + + size = m2 - m1; + + //init Members + + accessFlag = new CastAccessFlag(); + accessFlag->init(env, m1, size); + + entryPointFromInterpreter = new CastEntryPointFormInterpreter(); + entryPointFromInterpreter->init(env, m1, size); + + entryPointQuickCompiled = new CastEntryPointQuickCompiled(); + entryPointQuickCompiled->init(env, m1, size); + + dexMethodIndex = new CastDexMethodIndex(); + dexMethodIndex->init(env, m1, size); + + dexCacheResolvedMethods = new CastDexCacheResolvedMethods(); + dexCacheResolvedMethods->init(env, m1, size); + + declaringClass = new CastShadowClass(); + declaringClass->init(env, m1, size); + + + hotnessCount = new CastHotnessCount(); + hotnessCount->init(env, m1, size); + + auto neverCallTestClass = "com.swift.sandhook.ClassNeverCall"; + + art::mirror::ArtMethod *neverCall = getArtMethod(env, getMethodObject(env, + neverCallTestClass, + "neverCall")); + art::mirror::ArtMethod *neverCall2 = getArtMethod(env, getMethodObject(env, + neverCallTestClass, + "neverCall2")); + + bool beAot = entryPointQuickCompiled->get(neverCall) != entryPointQuickCompiled->get(neverCall2); + if (beAot) { + quickToInterpreterBridge = getInterpreterBridge(false); + if (quickToInterpreterBridge == nullptr) { + quickToInterpreterBridge = entryPointQuickCompiled->get(neverCall); + canGetInterpreterBridge = false; + } + } else { + quickToInterpreterBridge = entryPointQuickCompiled->get(neverCall); + } + + + art::mirror::ArtMethod *neverCallNative = getArtMethod(env, getMethodObject(env, + neverCallTestClass, + "neverCallNative")); + art::mirror::ArtMethod *neverCallNative2 = getArtMethod(env, getMethodObject(env, + neverCallTestClass, + "neverCallNative2")); + + beAot = entryPointQuickCompiled->get(neverCallNative) != entryPointQuickCompiled->get(neverCallNative2); + if (beAot) { + genericJniStub = getInterpreterBridge(true); + if (genericJniStub == nullptr) { + genericJniStub = entryPointQuickCompiled->get(neverCallNative); + canGetJniBridge = false; + } + } else { + genericJniStub = entryPointQuickCompiled->get(neverCallNative); + } + + entryPointFromJNI = new CastEntryPointFromJni(); + entryPointFromJNI->init(env, neverCallNative, size); + + art::mirror::ArtMethod *neverCallStatic = getArtMethod(env, getMethodObject(env, + neverCallTestClass, + "neverCallStatic")); + staticResolveStub = entryPointQuickCompiled->get(neverCallStatic); + + } + + void CastArtMethod::copy(art::mirror::ArtMethod *from, art::mirror::ArtMethod *to) { + memcpy(to, from, size); + } + + Size CastArtMethod::size = 0; + IMember *CastArtMethod::entryPointQuickCompiled = nullptr; + IMember *CastArtMethod::entryPointFromInterpreter = nullptr; + IMember *CastArtMethod::entryPointFromJNI = nullptr; + ArrayMember *CastArtMethod::dexCacheResolvedMethods = nullptr; + IMember *CastArtMethod::dexMethodIndex = nullptr; + IMember *CastArtMethod::accessFlag = nullptr; + IMember *CastArtMethod::declaringClass = nullptr; + IMember *CastArtMethod::hotnessCount = nullptr; + void *CastArtMethod::quickToInterpreterBridge = nullptr; + void *CastArtMethod::genericJniStub = nullptr; + void *CastArtMethod::staticResolveStub = nullptr; + bool CastArtMethod::canGetInterpreterBridge = true; + bool CastArtMethod::canGetJniBridge = true; + +} \ No newline at end of file diff --git a/sandhook-hooklib/src/main/cpp/casts/cast_compiler_options.cpp b/sandhook-hooklib/src/main/cpp/casts/cast_compiler_options.cpp new file mode 100644 index 00000000..b5bcb7e2 --- /dev/null +++ b/sandhook-hooklib/src/main/cpp/casts/cast_compiler_options.cpp @@ -0,0 +1,32 @@ +// +// Created by 甘尧 on 2019/2/24. +// + +#include "../includes/cast_compiler_options.h" +#include "../includes/hide_api.h" + +extern int SDK_INT; + +namespace SandHook { + + + class CastInlineMaxCodeUnits : public IMember { + protected: + Size calOffset(JNIEnv *jniEnv, art::CompilerOptions *p) override { + if (SDK_INT < ANDROID_N) + return getParentSize() + 1; + if (SDK_INT >= ANDROID_O) { + return BYTE_POINT + 5 * sizeof(size_t); + } else { + return BYTE_POINT + 6 * sizeof(size_t); + } + } + }; + + void CastCompilerOptions::init(JNIEnv *jniEnv) { + inlineMaxCodeUnits->init(jniEnv, nullptr, sizeof(art::CompilerOptions)); + } + + IMember* CastCompilerOptions::inlineMaxCodeUnits = new CastInlineMaxCodeUnits(); + +} diff --git a/sandhook-hooklib/src/main/cpp/includes/arch.h b/sandhook-hooklib/src/main/cpp/includes/arch.h new file mode 100644 index 00000000..d3843971 --- /dev/null +++ b/sandhook-hooklib/src/main/cpp/includes/arch.h @@ -0,0 +1,48 @@ +// +// Created by 甘尧 on 2019/1/12. +// + +#ifndef SANDHOOK_ARCH_H +#define SANDHOOK_ARCH_H + +#define BYTE_POINT sizeof(void*) + +typedef size_t Size; + +//32bit +#if defined(__i386__) || defined(__arm__) +//64bit +#elif defined(__aarch64__) || defined(__x86_64__) +#else +#endif + +#if defined(__arm__) +static void clearCacheArm32(char* begin, char *end) +{ + const int syscall = 0xf0002; + __asm __volatile ( + "mov r0, %0\n" + "mov r1, %1\n" + "mov r3, %2\n" + "mov r2, #0x0\n" + "svc 0x00000000\n" + : + : "r" (begin), "r" (end), "r" (syscall) + : "r0", "r1", "r3" + ); +} +#endif + +#define ANDROID_K 19 +#define ANDROID_L 21 +#define ANDROID_L2 22 +#define ANDROID_M 23 +#define ANDROID_N 24 +#define ANDROID_N2 25 +#define ANDROID_O 26 +#define ANDROID_O2 27 +#define ANDROID_P 28 +#define ANDROID_Q 29 +#define ANDROID_R 30 + +#endif //SANDHOOK_ARCH_H \ No newline at end of file diff --git a/sandhook-hooklib/src/main/cpp/includes/arch_base.h b/sandhook-hooklib/src/main/cpp/includes/arch_base.h new file mode 100644 index 00000000..34c05938 --- /dev/null +++ b/sandhook-hooklib/src/main/cpp/includes/arch_base.h @@ -0,0 +1,34 @@ +// +// Created by SwiftGan on 2019/1/17. +// + +#ifndef SANDHOOK_BASE_H +#define SANDHOOK_BASE_H + +#define FUNCTION_START(x) \ +.text; \ +.align 4; \ +.global x; \ +x: \ + +#define FUNCTION_START_T(x) \ +.syntax unified; \ +.text; \ +.align 4; \ +.thumb; \ +.thumb_func; \ +.global x; \ +x: \ + +#define FUNCTION_END(x) .size x, .-x + +#define REPLACEMENT_HOOK_TRAMPOLINE replacement_hook_trampoline +#define INLINE_HOOK_TRAMPOLINE inline_hook_trampoline +#define DIRECT_JUMP_TRAMPOLINE direct_jump_trampoline +#define CALL_ORIGIN_TRAMPOLINE call_origin_trampoline + +#define INLINE_HOOK_TRAMPOLINE_T inline_hook_trampoline_t +#define DIRECT_JUMP_TRAMPOLINE_T direct_jump_trampoline_t +#define CALL_ORIGIN_TRAMPOLINE_T call_origin_trampoline_t + +#endif //SANDHOOK_BASE_H diff --git a/sandhook-hooklib/src/main/cpp/includes/art_classlinker.h b/sandhook-hooklib/src/main/cpp/includes/art_classlinker.h new file mode 100644 index 00000000..18eaccd2 --- /dev/null +++ b/sandhook-hooklib/src/main/cpp/includes/art_classlinker.h @@ -0,0 +1,14 @@ +// +// Created by 双草酸酯 on 11/27/20. +// + +#ifndef SANDHOOK_ART_CLASSLINKER_H +#define SANDHOOK_ART_CLASSLINKER_H + +#endif //SANDHOOK_ART_CLASSLINKER_H +namespace art { +class ClassLinker { +public: + void MakeInitializedClassesVisiblyInitialized(void* self, bool wait); +}; +} \ No newline at end of file diff --git a/sandhook-hooklib/src/main/cpp/includes/art_compiler_options.h b/sandhook-hooklib/src/main/cpp/includes/art_compiler_options.h new file mode 100644 index 00000000..0a462353 --- /dev/null +++ b/sandhook-hooklib/src/main/cpp/includes/art_compiler_options.h @@ -0,0 +1,28 @@ +// +// Created by 甘尧 on 2019/2/23. +// + +#ifndef ART_COMPILER_OPTIONS_H +#define ART_COMPILER_OPTIONS_H + +#include + +namespace art { + class CompilerOptions { + public: + void* compiler_filter_; + size_t huge_method_threshold_; + size_t large_method_threshold_; + size_t small_method_threshold_; + size_t tiny_method_threshold_; + size_t num_dex_methods_threshold_; + size_t inline_depth_limit_; + size_t inline_max_code_units_; + + size_t getInlineMaxCodeUnits(); + bool setInlineMaxCodeUnits(size_t units); + + }; +} + +#endif //ART_COMPILER_OPTIONS_H diff --git a/sandhook-hooklib/src/main/cpp/includes/art_jit.h b/sandhook-hooklib/src/main/cpp/includes/art_jit.h new file mode 100644 index 00000000..c59f48cf --- /dev/null +++ b/sandhook-hooklib/src/main/cpp/includes/art_jit.h @@ -0,0 +1,28 @@ +// +// Created by 甘尧 on 2019/2/23. +// + +#ifndef SANDHOOK_ART_JIT_H +#define SANDHOOK_ART_JIT_H + +namespace art { + namespace jit { + + //7.0 - 9.0 + class JitCompiler { + public: + virtual ~JitCompiler(); + std::unique_ptr compilerOptions; + }; + + class Jit { + public: + //void* getCompilerOptions(); + }; + + + + }; +} + +#endif //SANDHOOK_ART_JIT_H diff --git a/sandhook-hooklib/src/main/cpp/includes/art_method.h b/sandhook-hooklib/src/main/cpp/includes/art_method.h new file mode 100644 index 00000000..58fb8ec4 --- /dev/null +++ b/sandhook-hooklib/src/main/cpp/includes/art_method.h @@ -0,0 +1,87 @@ +/* + * + * Copyright (c) 2011 The Android Open Source Project + * Copyright (c) 2015, alipay.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_H +#define ART_H + +#include +#include "arch.h" + +//7.0 - 10.0 +#define GCRoot uint32_t + +namespace art { +namespace mirror { +class Object { +public: +}; +class Class: public Object { +public: +}; + +class ArtField { +public: +}; + +class ArtMethod { +public: + + bool isAbstract(); + bool isNative(); + bool isStatic(); + bool isCompiled(); + bool isThumbCode(); + + void setAccessFlags(uint32_t flags); + void disableCompilable(); + void tryDisableInline(); + void disableInterpreterForO(); + void disableFastInterpreterForQ(); + void setPrivate(); + void setStatic(); + void setNative(); + + void setQuickCodeEntry(void* entry); + void setJniCodeEntry(void* entry); + void setInterpreterCodeEntry(void* entry); + void setDexCacheResolveList(void* list); + void setDexCacheResolveItem(uint32_t index, void* item); + void setDeclaringClass(GCRoot classPtr); + void setHotnessCount(uint16_t count); + + void* getQuickCodeEntry(); + void* getInterpreterCodeEntry(); + uint32_t getAccessFlags(); + uint32_t getDexMethodIndex(); + GCRoot getDeclaringClass(); + uint16_t getHotnessCount(); + + bool compile(JNIEnv* env); + bool deCompile(); + void flushCache(); + void backup(ArtMethod* backup); + + static Size size(); + +}; + +} + +} + +#endif //ART_H diff --git a/sandhook-hooklib/src/main/cpp/includes/art_runtime.h b/sandhook-hooklib/src/main/cpp/includes/art_runtime.h new file mode 100644 index 00000000..e27d68ae --- /dev/null +++ b/sandhook-hooklib/src/main/cpp/includes/art_runtime.h @@ -0,0 +1,18 @@ +// +// Created by 甘尧 on 2019/2/23. +// + +#ifndef SANDHOOK_ART_RUNTIME_H +#define SANDHOOK_ART_RUNTIME_H + +#include "art_jit.h" + +namespace art { + class Runtime { + + public: + jit::Jit* getJit(); + }; +} + +#endif //SANDHOOK_ART_RUNTIME_H diff --git a/sandhook-hooklib/src/main/cpp/includes/cast.h b/sandhook-hooklib/src/main/cpp/includes/cast.h new file mode 100644 index 00000000..6748c686 --- /dev/null +++ b/sandhook-hooklib/src/main/cpp/includes/cast.h @@ -0,0 +1,123 @@ +// +// Created by 甘尧 on 2019/1/12. +// + + +#ifndef SANDHOOK_ICAST_H +#define SANDHOOK_ICAST_H + +#include +#include +#include +#include "arch.h" +#include "utils.h" + + +namespace SandHook { + + template + class cast { + public: + cast(T t) { + this->origin = t; + }; + + virtual Size getSize() { return sizeof(T); }; + + private: + T origin; + }; + + template + class IMember { + public: + + virtual void init(JNIEnv *jniEnv, PType* p, Size size) { + this->parentSize = size; + offset = calOffset(jniEnv, p); + } + + Size size() { + return sizeof(MType); + } + + virtual Size getOffset() { + return offset; + } + + virtual Size getParentSize() { + return parentSize; + } + + virtual MType get(PType* p) { + if (offset > parentSize) + return 0; + return *reinterpret_cast((Size)p + getOffset()); + }; + + virtual void set(PType* p, MType t) { + if (offset > parentSize) + return; + memcpy(reinterpret_cast((Size)p + getOffset()), &t, size()); + }; + + template + int findOffset(void *start, size_t len, size_t step, T value) { + + if (nullptr == start) { + return -1; + } + + for (int i = 0; i <= len; i += step) { + T current_value = *reinterpret_cast((size_t) start + i); + if (value == current_value) { + return i; + } + } + return -1; + } + + private: + Size offset = 0; + protected: + Size parentSize = 0; + virtual Size calOffset(JNIEnv *jniEnv, PType* p) = 0; + + }; + + template + class ArrayMember : public IMember { + public: + + virtual void init(JNIEnv *jniEnv, PType* p, Size parentSize) override { + IMember::init(jniEnv, p, parentSize); + elementSize = calElementSize(jniEnv, p); + } + + virtual Size getElementSize() { + return elementSize; + } + + virtual Size arrayStart(PType* parent) { + void* p = IMember::get(parent); + return reinterpret_cast(p); + } + + using IMember::getParentSize; + + virtual void setElement(PType* parent, int position, ElementType elementPoint) { + Size array = arrayStart(parent); + memcpy(reinterpret_cast(array + position * getElementSize()), &elementPoint, getElementSize()); + } + + private: + Size elementSize = 0; + protected: + virtual Size calElementSize(JNIEnv *jniEnv, PType* p) { + return sizeof(ElementType); + }; + }; + +} + +#endif //SANDHOOK_ICAST_H \ No newline at end of file diff --git a/sandhook-hooklib/src/main/cpp/includes/cast_art_method.h b/sandhook-hooklib/src/main/cpp/includes/cast_art_method.h new file mode 100644 index 00000000..1cdb37bb --- /dev/null +++ b/sandhook-hooklib/src/main/cpp/includes/cast_art_method.h @@ -0,0 +1,39 @@ +// +// Created by 甘尧 on 2019/1/12. +// + +#ifndef SANDHOOK_CAST_ART_METHOD_H +#define SANDHOOK_CAST_ART_METHOD_H + +#include "cast.h" +#include "trampoline_manager.h" + +namespace SandHook { + + class CastArtMethod { + public: + static Size size; + static IMember* entryPointQuickCompiled; + static IMember* entryPointFromInterpreter; + static IMember* entryPointFromJNI; + static ArrayMember* dexCacheResolvedMethods; + static IMember* dexMethodIndex; + static IMember* accessFlag; + static IMember* declaringClass; + static IMember* hotnessCount; + static void* quickToInterpreterBridge; + static void* genericJniStub; + static void* staticResolveStub; + static bool canGetJniBridge; + static bool canGetInterpreterBridge; + + static void init(JNIEnv *env); + static void copy(art::mirror::ArtMethod* from, art::mirror::ArtMethod* to); + + }; + +} + +#endif //SANDHOOK_CAST_ART_METHOD_H + + diff --git a/sandhook-hooklib/src/main/cpp/includes/cast_compiler_options.h b/sandhook-hooklib/src/main/cpp/includes/cast_compiler_options.h new file mode 100644 index 00000000..5b98a9d4 --- /dev/null +++ b/sandhook-hooklib/src/main/cpp/includes/cast_compiler_options.h @@ -0,0 +1,24 @@ +// +// Created by 甘尧 on 2019/1/12. +// + +#ifndef SANDHOOK_CAST_COMPILER_OPTIONS_H +#define SANDHOOK_CAST_COMPILER_OPTIONS_H + +#include "cast.h" +#include "art_compiler_options.h" + +namespace SandHook { + + class CastCompilerOptions { + public: + static void init(JNIEnv *jniEnv); + static IMember* inlineMaxCodeUnits; + }; + + +} + +#endif //SANDHOOK_CAST_COMPILER_OPTIONS_H + + diff --git a/sandhook-hooklib/src/main/cpp/includes/dlfcn_nougat.h b/sandhook-hooklib/src/main/cpp/includes/dlfcn_nougat.h new file mode 100644 index 00000000..1fbaa5c4 --- /dev/null +++ b/sandhook-hooklib/src/main/cpp/includes/dlfcn_nougat.h @@ -0,0 +1,17 @@ +#ifndef DLFCN_NOUGAT_H +#define DLFCN_NOUGAT_H + +//see implementation in https://tech.meituan.com/2017/07/20/android-remote-debug.html +extern "C" { +int fake_dlclose(void *handle); + +void *fake_dlopen(const char *filename, int flags); + +void *fake_dlsym(void *handle, const char *name); + +const char *fake_dlerror(); + +void *getSymCompat(const char *filename, const char *name); +} + +#endif //DLFCN_NOUGAT_H diff --git a/sandhook-hooklib/src/main/cpp/includes/elf_util.h b/sandhook-hooklib/src/main/cpp/includes/elf_util.h new file mode 100644 index 00000000..79141764 --- /dev/null +++ b/sandhook-hooklib/src/main/cpp/includes/elf_util.h @@ -0,0 +1,72 @@ +// +// Created by Swift Gan on 2019/3/14. +// +#ifndef SANDHOOK_ELF_UTIL_H +#define SANDHOOK_ELF_UTIL_H + +#include + +#if defined(__LP64__) +typedef Elf64_Ehdr Elf_Ehdr; +typedef Elf64_Shdr Elf_Shdr; +typedef Elf64_Addr Elf_Addr; +typedef Elf64_Dyn Elf_Dyn; +typedef Elf64_Rela Elf_Rela; +typedef Elf64_Sym Elf_Sym; +typedef Elf64_Off Elf_Off; + +#define ELF_R_SYM(i) ELF64_R_SYM(i) +#else +typedef Elf32_Ehdr Elf_Ehdr; +typedef Elf32_Shdr Elf_Shdr; +typedef Elf32_Addr Elf_Addr; +typedef Elf32_Dyn Elf_Dyn; +typedef Elf32_Rel Elf_Rela; +typedef Elf32_Sym Elf_Sym; +typedef Elf32_Off Elf_Off; + +#define ELF_R_SYM(i) ELF32_R_SYM(i) +#endif + +namespace SandHook { + + class ElfImg { + public: + + ElfImg(const char* elf); + + Elf_Addr getSymbOffset(const char* name); + + void* getModuleBase(const char* name); + + Elf_Addr getSymbAddress(const char* name); + + ~ElfImg(); + + private: + const char* elf = nullptr; + void* base = nullptr; + char* buffer = nullptr; + off_t size = 0; + off_t bias = -4396; + Elf_Ehdr* header = nullptr; + Elf_Shdr* section_header = nullptr; + Elf_Shdr* symtab = nullptr; + Elf_Shdr* strtab = nullptr; + Elf_Shdr* dynsym = nullptr; + Elf_Off dynsym_count = 0; + Elf_Sym* symtab_start = nullptr; + Elf_Sym* dynsym_start = nullptr; + Elf_Sym* strtab_start = nullptr; + Elf_Off symtab_count = 0; + Elf_Off symstr_offset = 0; + Elf_Off symstr_offset_for_symtab = 0; + Elf_Off symtab_offset = 0; + Elf_Off dynsym_offset = 0; + Elf_Off symtab_size = 0; + Elf_Off dynsym_size = 0; + }; + +} + +#endif //SANDHOOK_ELF_UTIL_H diff --git a/sandhook-hooklib/src/main/cpp/includes/hide_api.h b/sandhook-hooklib/src/main/cpp/includes/hide_api.h new file mode 100644 index 00000000..4f8fba51 --- /dev/null +++ b/sandhook-hooklib/src/main/cpp/includes/hide_api.h @@ -0,0 +1,59 @@ +// +// Created by swift on 2019/1/21. +// + +#ifndef SANDHOOK_HIDE_API_H +#define SANDHOOK_HIDE_API_H + +#include +#include "dlfcn_nougat.h" +#include "dlfcn.h" +#include +#include "../includes/art_compiler_options.h" +#include "../includes/art_jit.h" +#include "../includes/art_method.h" + +#if defined(__aarch64__) +# define __get_tls() ({ void** __val; __asm__("mrs %0, tpidr_el0" : "=r"(__val)); __val; }) +#elif defined(__arm__) +# define __get_tls() ({ void** __val; __asm__("mrc p15, 0, %0, c13, c0, 3" : "=r"(__val)); __val; }) +#endif + +#define TLS_SLOT_ART_THREAD 7 + +using namespace art::mirror; + +extern "C" { + + void initHideApi(JNIEnv *env); + bool compileMethod(void *artMethod, void *thread); + + void suspendVM(); + void resumeVM(); + + bool canGetObject(); + jobject getJavaObject(JNIEnv* env, void* thread, void* address); + void *getCurrentThread(); + + art::jit::JitCompiler* getGlobalJitCompiler(); + + art::CompilerOptions* getCompilerOptions(art::jit::JitCompiler* compiler); + + art::CompilerOptions* getGlobalCompilerOptions(); + + bool disableJitInline(art::CompilerOptions* compilerOptions); + + void* getInterpreterBridge(bool isNative); + + bool replaceUpdateCompilerOptionsQ(); + + bool forceProcessProfiles(); + + bool hookClassInit(void(*callback)(void*)); + + JNIEnv *attachAndGetEvn(); + + ArtMethod* getArtMethod(JNIEnv *env, jobject method); +} + +#endif //SANDHOOK_HIDE_API_H diff --git a/sandhook-hooklib/src/main/cpp/includes/inst.h b/sandhook-hooklib/src/main/cpp/includes/inst.h new file mode 100644 index 00000000..0bc3f2a4 --- /dev/null +++ b/sandhook-hooklib/src/main/cpp/includes/inst.h @@ -0,0 +1,120 @@ +// +// Created by swift on 2019/2/3. +// + +#ifndef SANDHOOK_INST_VISTOR_H +#define SANDHOOK_INST_VISTOR_H + +#include +#include "arch.h" + +#define CASE(inst,mask,match,type) \ +if ((inst & mask) == match) { return type; } \ + +namespace SandHook { + + union Arm32Code { + uint32_t code; + struct { + uint32_t cond:4; + uint32_t empty:2; + uint32_t opcode:4; + uint32_t s:1; + uint32_t rn:4; + uint32_t rd:4; + uint32_t operand2:12; + } units; + }; + + union Arm16Code { + uint16_t code; + struct { + uint32_t cond:16; + } units; + }; + + enum InstArch { + ARM32 = 0, + Thumb16, + Thumb32, + Arm64, + X86, + X64 + }; + + enum class InstType_Thumb32 { + // BLX