├── .gitmodules ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── f │ │ └── qbdi │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── cpp │ │ ├── CMakeLists.txt │ │ └── native-lib.cpp │ ├── java │ │ └── com │ │ │ └── f │ │ │ └── qbdi │ │ │ └── MainActivity.java │ └── res │ │ ├── drawable │ │ ├── ic_launcher_background.xml │ │ └── ic_launcher_foreground.xml │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── values-night │ │ └── themes.xml │ │ ├── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── themes.xml │ │ └── xml │ │ ├── backup_rules.xml │ │ └── data_extraction_rules.xml │ └── test │ └── java │ └── com │ └── f │ └── qbdi │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── nativelib ├── .gitignore ├── build.gradle ├── consumer-rules.pro ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── f │ │ └── nativelib │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── cpp │ │ ├── CMakeLists.txt │ │ ├── hook │ │ │ ├── HookUtils.cpp │ │ │ ├── HookUtils.h │ │ │ ├── linkerHandler.cpp │ │ │ └── linkerHandler.h │ │ ├── include │ │ │ ├── logger.h │ │ │ ├── nativelib.h │ │ │ ├── version.h │ │ │ └── vm.h │ │ ├── nativelib.cpp │ │ ├── qdbi-arm64 │ │ │ ├── bin │ │ │ │ ├── qbdi-frida-template-AARCH64 │ │ │ │ └── qbdi-template-AARCH64 │ │ │ ├── include │ │ │ │ ├── QBDI.h │ │ │ │ └── QBDI │ │ │ │ │ ├── Bitmask.h │ │ │ │ │ ├── Callback.h │ │ │ │ │ ├── Config.h │ │ │ │ │ ├── Errors.h │ │ │ │ │ ├── InstAnalysis.h │ │ │ │ │ ├── Logs.h │ │ │ │ │ ├── Memory.h │ │ │ │ │ ├── Memory.hpp │ │ │ │ │ ├── Options.h │ │ │ │ │ ├── Platform.h │ │ │ │ │ ├── Range.h │ │ │ │ │ ├── State.h │ │ │ │ │ ├── VM.h │ │ │ │ │ ├── VM_C.h │ │ │ │ │ └── Version.h │ │ │ ├── lib │ │ │ │ ├── libQBDI.a │ │ │ │ └── libQBDI.so │ │ │ ├── libQBDI.so │ │ │ └── share │ │ │ │ └── qbdiAARCH64 │ │ │ │ ├── LICENSE.txt │ │ │ │ ├── cmake │ │ │ │ ├── QBDIAARCH64Config-release.cmake │ │ │ │ ├── QBDIAARCH64Config.cmake │ │ │ │ ├── QBDIConfig-release.cmake │ │ │ │ └── QBDIConfig.cmake │ │ │ │ ├── frida-qbdi.js │ │ │ │ ├── qbdi_frida_template │ │ │ │ ├── CMakeLists.txt │ │ │ │ ├── FridaQBDI_sample.js │ │ │ │ └── SimpleXOR.c │ │ │ │ └── qbdi_template │ │ │ │ ├── CMakeLists.txt │ │ │ │ ├── README.txt │ │ │ │ └── qbdi_template.c │ │ ├── record │ │ │ ├── HookInfo.cpp │ │ │ ├── HookInfo.h │ │ │ ├── fileRecord.cpp │ │ │ └── fileRecord.h │ │ ├── utils │ │ │ ├── json.hpp │ │ │ ├── jsonbean.cpp │ │ │ ├── jsonbean.h │ │ │ ├── mongoose.c │ │ │ ├── mongoose.h │ │ │ ├── socketUtils.cpp │ │ │ └── socketUtils.h │ │ └── vm.cpp │ └── java │ │ └── com │ │ └── f │ │ └── nativelib │ │ └── NativeLib.java │ └── test │ └── java │ └── com │ └── f │ └── nativelib │ └── ExampleUnitTest.java └── settings.gradle /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "nativelib/src/main/cpp/Dobby"] 2 | path = nativelib/src/main/cpp/Dobby 3 | url = https://github.com/Fangg3/Dobby 4 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.application' 3 | } 4 | 5 | android { 6 | namespace 'com.f.qbdi' 7 | compileSdk 33 8 | 9 | defaultConfig { 10 | applicationId "com.f.qbdi" 11 | minSdk 24 12 | targetSdk 33 13 | versionCode 1 14 | versionName "1.0" 15 | ndk{ 16 | abiFilters "arm64-v8a" 17 | } 18 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 19 | } 20 | 21 | buildTypes { 22 | release { 23 | minifyEnabled false 24 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 25 | } 26 | } 27 | compileOptions { 28 | sourceCompatibility JavaVersion.VERSION_1_8 29 | targetCompatibility JavaVersion.VERSION_1_8 30 | } 31 | externalNativeBuild { 32 | cmake { 33 | path file('src/main/cpp/CMakeLists.txt') 34 | version '3.22.1' 35 | 36 | } 37 | } 38 | buildFeatures { 39 | viewBinding true 40 | } 41 | } 42 | 43 | dependencies { 44 | 45 | implementation 'androidx.appcompat:appcompat:1.6.1' 46 | implementation 'com.google.android.material:material:1.8.0' 47 | implementation 'androidx.constraintlayout:constraintlayout:2.1.4' 48 | implementation project(path: ':nativelib') 49 | testImplementation 'junit:junit:4.13.2' 50 | androidTestImplementation 'androidx.test.ext:junit:1.1.5' 51 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' 52 | } -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /app/src/androidTest/java/com/f/qbdi/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.f.qbdi; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.test.platform.app.InstrumentationRegistry; 6 | import androidx.test.ext.junit.runners.AndroidJUnit4; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | /** 14 | * Instrumented test, which will execute on an Android device. 15 | * 16 | * @see Testing documentation 17 | */ 18 | @RunWith(AndroidJUnit4.class) 19 | public class ExampleInstrumentedTest { 20 | @Test 21 | public void useAppContext() { 22 | // Context of the app under test. 23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 24 | assertEquals("com.f.qbdi", appContext.getPackageName()); 25 | } 26 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 17 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/cpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # For more information about using CMake with Android Studio, read the 2 | # documentation: https://d.android.com/studio/projects/add-native-code.html. 3 | # For more examples on how to use CMake, see https://github.com/android/ndk-samples. 4 | 5 | # Sets the minimum CMake version required for this project. 6 | cmake_minimum_required(VERSION 3.22.1) 7 | 8 | # Declares the project name. The project name can be accessed via ${ PROJECT_NAME}, 9 | # Since this is the top level CMakeLists.txt, the project name is also accessible 10 | # with ${CMAKE_PROJECT_NAME} (both CMake variables are in-sync within the top level 11 | # build script scope). 12 | project("test") 13 | 14 | # Creates and names a library, sets it as either STATIC 15 | # or SHARED, and provides the relative paths to its source code. 16 | # You can define multiple libraries, and CMake builds them for you. 17 | # Gradle automatically packages shared libraries with your APK. 18 | # 19 | # In this top level CMakeLists.txt, ${CMAKE_PROJECT_NAME} is used to define 20 | # the target library name; in the sub-module's CMakeLists.txt, ${PROJECT_NAME} 21 | # is preferred for the same purpose. 22 | # 23 | # In order to load a library into your app from Java/Kotlin, you must call 24 | # System.loadLibrary() and pass the name of the library defined here; 25 | # for GameActivity/NativeActivity derived applications, the same library name must be 26 | # used in the AndroidManifest.xml file. 27 | add_library(${CMAKE_PROJECT_NAME} SHARED 28 | # List C/C++ source files with relative paths to this CMakeLists.txt. 29 | native-lib.cpp) 30 | 31 | # Specifies libraries CMake should link to your target library. You 32 | # can link libraries from various origins, such as libraries defined in this 33 | # build script, prebuilt third-party libraries, or Android system libraries. 34 | target_link_libraries(${CMAKE_PROJECT_NAME} 35 | # List libraries link to the target library 36 | android 37 | log) -------------------------------------------------------------------------------- /app/src/main/cpp/native-lib.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | extern "C" JNIEXPORT jstring JNICALL 5 | Java_com_f_qbdi_MainActivity_stringFromJNI( 6 | JNIEnv* env, 7 | jobject /* this */) { 8 | std::string hello = "Hello from C++"; 9 | return env->NewStringUTF(hello.c_str()); 10 | } 11 | extern "C" 12 | JNIEXPORT jint JNICALL 13 | Java_com_f_qbdi_MainActivity_add(JNIEnv *env, jobject thiz, jint a, jint b) { 14 | 15 | return a+b; 16 | } -------------------------------------------------------------------------------- /app/src/main/java/com/f/qbdi/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.f.qbdi; 2 | 3 | import androidx.appcompat.app.AppCompatActivity; 4 | 5 | import android.os.Bundle; 6 | import android.util.Log; 7 | import android.widget.TextView; 8 | 9 | import com.f.nativelib.NativeLib; 10 | import com.f.qbdi.databinding.ActivityMainBinding; 11 | 12 | public class MainActivity extends AppCompatActivity { 13 | 14 | // Used to load the 'qbdi' library on application startup. 15 | static { 16 | System.loadLibrary("nativelib"); 17 | 18 | } 19 | 20 | private ActivityMainBinding binding; 21 | 22 | @Override 23 | protected void onCreate(Bundle savedInstanceState) { 24 | super.onCreate(savedInstanceState); 25 | new NativeLib().stringFromJNI(); 26 | binding = ActivityMainBinding.inflate(getLayoutInflater()); 27 | setContentView(binding.getRoot()); 28 | 29 | // Example of a call to a native method 30 | TextView tv = binding.sampleText; 31 | System.loadLibrary("test"); 32 | tv.setText(stringFromJNI()); 33 | Log.i("qbdi", String.valueOf(add(1,3))); 34 | 35 | 36 | } 37 | 38 | /** 39 | * A native method that is implemented by the 'qbdi' native library, 40 | * which is packaged with this application. 41 | */ 42 | public native String stringFromJNI(); 43 | public native int add(int a, int b); 44 | 45 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FANGG3/DobbyWithQBDI/8a7abff6fd39c61d01e02f7a74704bab052b27d5/app/src/main/res/mipmap-hdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FANGG3/DobbyWithQBDI/8a7abff6fd39c61d01e02f7a74704bab052b27d5/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FANGG3/DobbyWithQBDI/8a7abff6fd39c61d01e02f7a74704bab052b27d5/app/src/main/res/mipmap-mdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FANGG3/DobbyWithQBDI/8a7abff6fd39c61d01e02f7a74704bab052b27d5/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FANGG3/DobbyWithQBDI/8a7abff6fd39c61d01e02f7a74704bab052b27d5/app/src/main/res/mipmap-xhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FANGG3/DobbyWithQBDI/8a7abff6fd39c61d01e02f7a74704bab052b27d5/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FANGG3/DobbyWithQBDI/8a7abff6fd39c61d01e02f7a74704bab052b27d5/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FANGG3/DobbyWithQBDI/8a7abff6fd39c61d01e02f7a74704bab052b27d5/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FANGG3/DobbyWithQBDI/8a7abff6fd39c61d01e02f7a74704bab052b27d5/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FANGG3/DobbyWithQBDI/8a7abff6fd39c61d01e02f7a74704bab052b27d5/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/values-night/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFBB86FC 4 | #FF6200EE 5 | #FF3700B3 6 | #FF03DAC5 7 | #FF018786 8 | #FF000000 9 | #FFFFFFFF 10 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | qbdi 3 | -------------------------------------------------------------------------------- /app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/xml/backup_rules.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/xml/data_extraction_rules.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 12 | 13 | 19 | -------------------------------------------------------------------------------- /app/src/test/java/com/f/qbdi/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.f.qbdi; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | plugins { 3 | id 'com.android.application' version '8.1.2' apply false 4 | id 'com.android.library' version '8.1.2' apply false 5 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app's APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Enables namespacing of each library's R class so that its R class includes only the 19 | # resources declared in the library itself and none from the library's dependencies, 20 | # thereby reducing the size of the R class for that library 21 | android.nonTransitiveRClass=true -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FANGG3/DobbyWithQBDI/8a7abff6fd39c61d01e02f7a74704bab052b27d5/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Dec 22 10:41:20 CST 2023 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip 5 | zipStoreBase=GRADLE_USER_HOME 6 | zipStorePath=wrapper/dists 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | 86 | # Determine the Java command to use to start the JVM. 87 | if [ -n "$JAVA_HOME" ] ; then 88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 89 | # IBM's JDK on AIX uses strange locations for the executables 90 | JAVACMD="$JAVA_HOME/jre/sh/java" 91 | else 92 | JAVACMD="$JAVA_HOME/bin/java" 93 | fi 94 | if [ ! -x "$JAVACMD" ] ; then 95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 96 | 97 | Please set the JAVA_HOME variable in your environment to match the 98 | location of your Java installation." 99 | fi 100 | else 101 | JAVACMD="java" 102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 103 | 104 | Please set the JAVA_HOME variable in your environment to match the 105 | location of your Java installation." 106 | fi 107 | 108 | # Increase the maximum file descriptors if we can. 109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 110 | MAX_FD_LIMIT=`ulimit -H -n` 111 | if [ $? -eq 0 ] ; then 112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 113 | MAX_FD="$MAX_FD_LIMIT" 114 | fi 115 | ulimit -n $MAX_FD 116 | if [ $? -ne 0 ] ; then 117 | warn "Could not set maximum file descriptor limit: $MAX_FD" 118 | fi 119 | else 120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 121 | fi 122 | fi 123 | 124 | # For Darwin, add options to specify how the application appears in the dock 125 | if $darwin; then 126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 127 | fi 128 | 129 | # For Cygwin or MSYS, switch paths to Windows format before running java 130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 133 | 134 | JAVACMD=`cygpath --unix "$JAVACMD"` 135 | 136 | # We build the pattern for arguments to be converted via cygpath 137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 138 | SEP="" 139 | for dir in $ROOTDIRSRAW ; do 140 | ROOTDIRS="$ROOTDIRS$SEP$dir" 141 | SEP="|" 142 | done 143 | OURCYGPATTERN="(^($ROOTDIRS))" 144 | # Add a user-defined pattern to the cygpath arguments 145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 147 | fi 148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 149 | i=0 150 | for arg in "$@" ; do 151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 153 | 154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 156 | else 157 | eval `echo args$i`="\"$arg\"" 158 | fi 159 | i=`expr $i + 1` 160 | done 161 | case $i in 162 | 0) set -- ;; 163 | 1) set -- "$args0" ;; 164 | 2) set -- "$args0" "$args1" ;; 165 | 3) set -- "$args0" "$args1" "$args2" ;; 166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 172 | esac 173 | fi 174 | 175 | # Escape application args 176 | save () { 177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 178 | echo " " 179 | } 180 | APP_ARGS=`save "$@"` 181 | 182 | # Collect all arguments for the java command, following the shell quoting and substitution rules 183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 184 | 185 | exec "$JAVACMD" "$@" 186 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /nativelib/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /nativelib/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.library' 3 | } 4 | 5 | android { 6 | namespace 'com.f.nativelib' 7 | compileSdk 33 8 | packagingOptions { 9 | exclude '**/libdobby.so' 10 | 11 | } 12 | defaultConfig { 13 | minSdk 24 14 | 15 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 16 | consumerProguardFiles "consumer-rules.pro" 17 | externalNativeBuild { 18 | cmake { 19 | cppFlags "" 20 | } 21 | 22 | } 23 | ndk{ 24 | abiFilters "arm64-v8a" 25 | } 26 | } 27 | 28 | buildTypes { 29 | release { 30 | minifyEnabled false 31 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 32 | } 33 | 34 | } 35 | externalNativeBuild { 36 | cmake { 37 | path "src/main/cpp/CMakeLists.txt" 38 | version "3.22.1" 39 | 40 | 41 | } 42 | } 43 | compileOptions { 44 | sourceCompatibility JavaVersion.VERSION_1_8 45 | targetCompatibility JavaVersion.VERSION_1_8 46 | } 47 | } 48 | 49 | dependencies { 50 | 51 | implementation 'androidx.appcompat:appcompat:1.6.1' 52 | implementation 'com.google.android.material:material:1.8.0' 53 | testImplementation 'junit:junit:4.13.2' 54 | androidTestImplementation 'androidx.test.ext:junit:1.1.5' 55 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' 56 | } -------------------------------------------------------------------------------- /nativelib/consumer-rules.pro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FANGG3/DobbyWithQBDI/8a7abff6fd39c61d01e02f7a74704bab052b27d5/nativelib/consumer-rules.pro -------------------------------------------------------------------------------- /nativelib/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /nativelib/src/androidTest/java/com/f/nativelib/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.f.nativelib; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.test.platform.app.InstrumentationRegistry; 6 | import androidx.test.ext.junit.runners.AndroidJUnit4; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | /** 14 | * Instrumented test, which will execute on an Android device. 15 | * 16 | * @see Testing documentation 17 | */ 18 | @RunWith(AndroidJUnit4.class) 19 | public class ExampleInstrumentedTest { 20 | @Test 21 | public void useAppContext() { 22 | // Context of the app under test. 23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 24 | assertEquals("com.f.nativelib.test", appContext.getPackageName()); 25 | } 26 | } -------------------------------------------------------------------------------- /nativelib/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /nativelib/src/main/cpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # For more information about using CMake with Android Studio, read the 2 | # documentation: https://d.android.com/studio/projects/add-native-code.html. 3 | # For more examples on how to use CMake, see https://github.com/android/ndk-samples. 4 | 5 | # Sets the minimum CMake version required for this project. 6 | cmake_minimum_required(VERSION 3.22.1) 7 | project("nativelib") 8 | set(CMAKE_CXX_STANDARD 20) 9 | set(CMAKE_ANDROID_ARCH_ABI arm64-v8a) 10 | 11 | include_directories( 12 | Dobby/include 13 | Dobby/source 14 | Dobby/builtin-plugin 15 | Dobby/builtin-plugin/AndroidRestriction 16 | Dobby/builtin-plugin/SymbolResolver 17 | Dobby/external/logging 18 | ) 19 | macro(SET_OPTION option value) 20 | set(${option} ${value} CACHE INTERNAL "" FORCE) 21 | endmacro() 22 | # 关闭DobbyDebug日志 23 | SET_OPTION(DOBBY_DEBUG OFF) 24 | # 关闭shared库,和我们的so 集成到一起。 25 | SET_OPTION(DOBBY_GENERATE_SHARED OFF) 26 | #是否加载linker加载so的回调 27 | SET_OPTION(Plugin.LinkerLoadCallback ON) 28 | SET_OPTION(Plugin.Android.BionicLinkerUtil ON) 29 | 30 | add_subdirectory(Dobby dobby.build) 31 | 32 | 33 | INCLUDE_DIRECTORIES( 34 | Dobby/include 35 | qdbi-arm64/include 36 | include 37 | utils 38 | hook 39 | record 40 | #dobby_c 41 | ) 42 | 43 | # find local Installed QBDI 44 | set(CMAKE_FIND_ROOT_PATH "/usr/local") 45 | 46 | find_package(QBDIAARCH64 REQUIRED) 47 | 48 | add_library(qdbi-arm64 STATIC IMPORTED) 49 | add_library(qdbi-arm64-share SHARED IMPORTED) 50 | set_target_properties(qdbi-arm64 PROPERTIES IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/qdbi-arm64/lib/libQBDI.a) 51 | set_target_properties(qdbi-arm64-share PROPERTIES IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/qdbi-arm64/libQBDI.so) 52 | 53 | 54 | aux_source_directory(hook hook_src_list) 55 | aux_source_directory(utils utils_src_list) 56 | aux_source_directory(record record_src_list) 57 | 58 | add_library(${CMAKE_PROJECT_NAME} SHARED 59 | nativelib.cpp 60 | vm.cpp 61 | ${hook_src_list} 62 | ${utils_src_list} 63 | ${record_src_list} 64 | ) 65 | 66 | 67 | target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE 68 | dobby_static 69 | qdbi-arm64-share 70 | # QBDI::AARCH64::QBDI 71 | android 72 | log) -------------------------------------------------------------------------------- /nativelib/src/main/cpp/hook/HookUtils.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by fang on 2024/1/3. 3 | // 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "logger.h" 16 | #include "HookUtils.h" 17 | 18 | MapItemInfo getSoBaseAddress(const char *name) { 19 | MapItemInfo info{0}; 20 | if (name == nullptr) { 21 | return info; 22 | } 23 | size_t start = 0; 24 | size_t end = 0; 25 | bool isFirst = true; 26 | size_t len = 0; 27 | char buffer[PATH_MAX]; 28 | memset(buffer, 0, PATH_MAX); 29 | 30 | 31 | //找不到用原始文件 32 | FILE *fp = fopen("/proc/self/maps", "r"); 33 | 34 | if (fp == nullptr) { 35 | LOGD("找不到用原始文件"); 36 | return info; 37 | } 38 | 39 | char *line = nullptr; 40 | while (getline(&line, &len, fp) != -1) { 41 | //LOGD("%s",line); 42 | if (line != nullptr && strstr(line, name)) { 43 | sscanf(line, "%lx-%lx", &start, &end); 44 | // LOGD("%s",line); 45 | //start 只有第一次赋值 46 | if (isFirst) { 47 | info.start = start; 48 | isFirst = false; 49 | } 50 | } 51 | } 52 | info.end = end; 53 | syscall(__NR_close, fp); 54 | //LOGE("get maps info start -> 0x%zx end -> 0x%zx ",info.start,info.end); 55 | return info; 56 | } 57 | 58 | static _Unwind_Reason_Code unwindCallback(struct _Unwind_Context* context, void* arg) 59 | { 60 | std::vector<_Unwind_Word> &stack = *(std::vector<_Unwind_Word>*)arg; 61 | stack.push_back(_Unwind_GetIP(context)); 62 | return _URC_NO_REASON; 63 | } 64 | 65 | void callstackDump(std::string &dump) { 66 | std::vector<_Unwind_Word> stack; 67 | _Unwind_Backtrace(unwindCallback, (void*)&stack); 68 | dump.append(" \n" 69 | "*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n" 70 | "pid: 17980, tid: 17980, name: callstack.dump >>> callstack.dump <<<\n" 71 | "signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0\n" 72 | "r0 00000000 r1 00000000 r2 00000001 r3 00000001\n" 73 | "r4 e8efe008 r5 e0537b99 r6 ff970b88 r7 ff970a98\n" 74 | "r8 ff970de0 r9 e7904400 sl e790448c fp ff970b14\n" 75 | "ip e8ef985c sp ff970a60 lr e8eca00f pc e0537d86 cpsr 200b0030\n" 76 | "backtrace:\n"); 77 | 78 | char buff[256]; 79 | for (size_t i = 0; i < stack.size(); i++) { 80 | Dl_info info; 81 | if (!dladdr((void*)stack[i], &info)) { 82 | continue; 83 | } 84 | int addr = (char*)stack[i] - (char*)info.dli_fbase - 1; 85 | if (info.dli_sname == NULL || strlen(info.dli_sname) == 0) { 86 | sprintf(buff, "#%02x pc %08x %s\n", i, addr, info.dli_fname); 87 | } else { 88 | sprintf(buff, "#%02x pc %08x %s (%s+00)\n", i, addr, info.dli_fname, info.dli_sname); 89 | } 90 | dump.append(buff); 91 | } 92 | } 93 | 94 | void callstackLogcat(const char* tag) { 95 | std::string dump; 96 | callstackDump(dump); 97 | __android_log_print(ANDROID_LOG_DEBUG, tag, "%s", dump.c_str()); 98 | } 99 | 100 | char* appName = nullptr; 101 | char* getAppName(){ 102 | if (appName != NULL){ 103 | LOGD("get appName %s",appName); 104 | return appName; 105 | } 106 | FILE* f = fopen("/proc/self/cmdline","r"); 107 | size_t len; 108 | char* line = nullptr; 109 | if(getline(&line,&len,f)==-1){ 110 | perror("can't get app name"); 111 | } 112 | appName = line; 113 | LOGD("get appName %s",appName); 114 | return appName; 115 | } 116 | 117 | char privatePath[PATH_MAX]; 118 | char* getPrivatePath(){ 119 | if (privatePath[0] != 0 ){ 120 | return privatePath; 121 | } 122 | // std::string ret= std::string("/data/data"); 123 | // ret.append(getAppName()); 124 | sprintf(privatePath,"%s%s%s","/data/data/",getAppName(),"/"); 125 | return privatePath; 126 | } -------------------------------------------------------------------------------- /nativelib/src/main/cpp/hook/HookUtils.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by fang on 2024/1/3. 3 | // 4 | 5 | #ifndef QBDI_HOOKUTILS_H 6 | #define QBDI_HOOKUTILS_H 7 | #include "dobby.h" 8 | #define HOOK_DEF(ret, func, ...) \ 9 | ret (*orig_##func)(__VA_ARGS__)=nullptr; \ 10 | ret new_##func(__VA_ARGS__) 11 | typedef size_t Size; 12 | struct MapAddresInfo { 13 | /** 14 | * 函数的符号 15 | */ 16 | char *sym = nullptr; 17 | /** 18 | * 函数在文件路径 19 | */ 20 | char *fname = nullptr; 21 | 22 | /** 23 | * 所在函数的基地址 24 | */ 25 | size_t sym_base = 0; 26 | /** 27 | * 文件基地址 28 | */ 29 | size_t fbase = 0; 30 | 31 | /** 32 | * 传入地址,相对于so的偏移 33 | */ 34 | size_t offset = 0; 35 | }; 36 | 37 | struct MapItemInfo { 38 | /** 39 | * item开始位置 40 | */ 41 | size_t start; 42 | 43 | /** 44 | * item结束位置 45 | */ 46 | size_t end; 47 | }; 48 | 49 | MapItemInfo getSoBaseAddress(const char *name); 50 | void callstackLogcat(const char* tag); 51 | char* getAppName(); 52 | char* getPrivatePath(); 53 | #endif //QBDI_HOOKUTILS_H 54 | -------------------------------------------------------------------------------- /nativelib/src/main/cpp/hook/linkerHandler.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by fang on 2024/1/3. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include "linkerHandler.h" 15 | #include "logger.h" 16 | #include "version.h" 17 | #include "vm.h" 18 | #include "HookInfo.h" 19 | #include 20 | 21 | 22 | #if defined(__arm__) 23 | typedef Elf32_Word elf_word; 24 | typedef Elf32_Half elf_half; 25 | typedef Elf32_Ehdr elf_ehdr; 26 | typedef Elf32_Shdr elf_shdr; 27 | typedef Elf32_Sym elf_sym; 28 | #elif defined(__i386__) 29 | typedef Elf32_Word elf_word; 30 | typedef Elf32_Half elf_half; 31 | typedef Elf32_Ehdr elf_ehdr; 32 | typedef Elf32_Shdr elf_shdr; 33 | typedef Elf32_Sym elf_sym; 34 | #elif defined(__aarch64__) 35 | typedef Elf64_Word elf_word; 36 | typedef Elf64_Half elf_half; 37 | typedef Elf64_Ehdr elf_ehdr; 38 | typedef Elf64_Shdr elf_shdr; 39 | typedef Elf64_Sym elf_sym; 40 | #else 41 | #error "Unsupported architecture" 42 | #endif 43 | using namespace std; 44 | static std::ofstream *hookStrHandlerOs; 45 | static bool isSave = false; 46 | 47 | 48 | VM_BEFORE(sig) 49 | //LOGD("VM_BEFORE %lx", ctx->general.x[0]); 50 | //LOGD("VM_BEFORE %lx", ctx->general.x[1]); 51 | VM_AFTER 52 | //LOGD("VM_AFTER %lx", ctx->general.x[0]); 53 | //VM_END(sig) 54 | } 55 | 56 | int aaa = 0; 57 | 58 | void onSoLoadedAfter(const char *filename,void *ret){ 59 | auto mapInfo = getSoBaseAddress(filename); 60 | char buffer[PATH_MAX]; 61 | sprintf(buffer, "linker load %s start-> 0x%zx end-> 0x%zx size -> %lu", 62 | filename, mapInfo.start, mapInfo.end, (mapInfo.end - mapInfo.start)); 63 | LOGI("%s ", buffer); 64 | 65 | // if (isSave) { 66 | // if (hookStrHandlerOs != nullptr) { 67 | // (*hookStrHandlerOs) << buffer; 68 | // } 69 | // } 70 | string f = string(filename); 71 | if ( f.find("nep") != -1 && aaa == 0){ 72 | HookInfo::getInstance().set_module(filename,mapInfo.start,mapInfo.end); 73 | recordToFile("name:%s\nbase:%zx\nend:%zx",filename,mapInfo.start,mapInfo.end); 74 | 75 | aaa = 1; 76 | auto base = get_addr(filename); 77 | //int offset = 0x20068C;//get 78 | int offset = 0x200b0c; 79 | // int offset = 0x1DB0C4; 80 | auto symbol = (void*)(base+offset); 81 | 82 | DobbyInstrumentQBDI(symbol,vm_handle_sig); 83 | } 84 | } 85 | HOOK_DEF(void *, dlopen_CI, const char *filename, int flag) { 86 | char temp[PATH_MAX]; 87 | void *ret = orig_dlopen_CI(filename, flag); 88 | onSoLoadedAfter(filename, ret); 89 | return ret; 90 | } 91 | 92 | HOOK_DEF(void*, do_dlopen_CIV, const char *filename, int flag, const void *extinfo) { 93 | char temp[PATH_MAX]; 94 | void *ret = orig_do_dlopen_CIV(filename, flag, extinfo); 95 | onSoLoadedAfter(filename, ret); 96 | return ret; 97 | } 98 | 99 | HOOK_DEF(void*, do_dlopen_CIVV, const char *name, int flags, const void *extinfo, 100 | void *caller_addr) { 101 | char temp[PATH_MAX]; 102 | void *ret = orig_do_dlopen_CIVV(name, flags, extinfo, caller_addr); 103 | onSoLoadedAfter(name,ret); 104 | return ret; 105 | } 106 | 107 | 108 | static int resolve_symbol_from_symtab(FILE *fp, elf_shdr *symtab, char *strtab, 109 | size_t strtab_size, const char *symname, intptr_t *symval) { 110 | elf_word i, num_syms; 111 | elf_sym sym; 112 | long cur_off; 113 | 114 | int r = -1; 115 | 116 | cur_off = ftell(fp); 117 | 118 | if (fseek(fp, symtab->sh_offset, SEEK_SET) != 0) { 119 | perror("resolve_symbol_from_symtab: fseek"); 120 | goto _ret; 121 | } 122 | 123 | num_syms = symtab->sh_size / sizeof(elf_sym); 124 | 125 | for (i = 0; i < num_syms; i++) { 126 | if (fread(&sym, sizeof(elf_sym), 1, fp) != 1) { 127 | perror("resolve_symbol_from_symtab: fread"); 128 | goto _ret; 129 | } 130 | if (sym.st_name < strtab_size && 131 | strcmp(&strtab[sym.st_name], symname) == 0) { 132 | *symval = sym.st_value; 133 | break; 134 | } 135 | } 136 | 137 | if (fseek(fp, cur_off, SEEK_SET) != 0) { 138 | perror("resolve_symbol_from_symtab: fseek"); 139 | goto _ret; 140 | } 141 | 142 | if (i < num_syms) 143 | r = 0; 144 | 145 | _ret: 146 | return r; 147 | } 148 | 149 | static ssize_t read_strtab(FILE *fp, elf_shdr *shdr, char **datap) { 150 | elf_word sh_size; 151 | long cur_off; 152 | char *data; 153 | 154 | 155 | sh_size = shdr->sh_size; 156 | 157 | if ((size_t) sh_size > SIZE_MAX - 1) { 158 | fprintf(stderr, "read_strtab: %s", strerror(EFBIG)); 159 | goto _ret; 160 | } 161 | 162 | 163 | cur_off = ftell(fp); 164 | 165 | if (fseek(fp, shdr->sh_offset, SEEK_SET) != 0) { 166 | perror("read_strtab: fseek"); 167 | goto _ret; 168 | } 169 | 170 | if ((data = (char *) malloc(sh_size + 1)) == NULL) { 171 | perror("read_strtab: malloc"); 172 | goto _ret; 173 | } 174 | 175 | if (fread(data, 1, sh_size, fp) != sh_size) { 176 | perror("read_strtab: fread"); 177 | goto _free; 178 | } 179 | 180 | data[sh_size] = 0; 181 | 182 | if (fseek(fp, cur_off, SEEK_SET) != 0) { 183 | perror("read_strtab: fseek"); 184 | goto _free; 185 | } 186 | 187 | *datap = data; 188 | 189 | return (ssize_t) sh_size; 190 | 191 | _free: 192 | free(data); 193 | 194 | _ret: 195 | return -1; 196 | } 197 | 198 | 199 | static int resolve_symbol_from_sections(FILE *fp, elf_shdr *shdrs, 200 | elf_half num_sects, const char *symname, intptr_t *symval) { 201 | elf_half i; 202 | elf_shdr *shdr, *strtab_shdr; 203 | char *strtab; 204 | ssize_t strtab_size; 205 | 206 | int r = -1; 207 | 208 | for (i = 0; i < num_sects; i++) { 209 | shdr = &shdrs[i]; 210 | 211 | if (shdr->sh_type == SHT_SYMTAB && shdr->sh_link < num_sects) { 212 | strtab_shdr = &shdrs[shdr->sh_link]; 213 | 214 | if ((strtab_size = read_strtab(fp, strtab_shdr, &strtab)) < 0) 215 | goto _ret; 216 | 217 | r = resolve_symbol_from_symtab(fp, shdr, strtab, (size_t) strtab_size, 218 | symname, symval); 219 | 220 | free(strtab); 221 | 222 | if (r == 0) 223 | goto _ret; 224 | } 225 | 226 | } 227 | 228 | _ret: 229 | return r; 230 | } 231 | 232 | 233 | int resolve_symbol(const char *filename, const char *symname, intptr_t *symval) { 234 | FILE *fp; 235 | elf_ehdr ehdr; 236 | elf_shdr *shdrs; 237 | elf_half shnum; 238 | 239 | int r = -1; 240 | 241 | if ((fp = fopen(filename, "r")) == NULL) { 242 | perror("resolve_symbol: fopen"); 243 | goto _ret; 244 | } 245 | 246 | if (fread(&ehdr, sizeof(ehdr), 1, fp) != 1) { 247 | perror("resolve_symbol: fread"); 248 | goto _close; 249 | } 250 | 251 | if (fseek(fp, ehdr.e_shoff, SEEK_SET) != 0) { 252 | perror("resolve_symbol: fseek"); 253 | goto _close; 254 | } 255 | 256 | shnum = ehdr.e_shnum; 257 | 258 | if ((shdrs = (elf_shdr *) (calloc(shnum, sizeof(elf_shdr)))) == NULL) { 259 | perror("resolve_symbol: calloc"); 260 | goto _close; 261 | } 262 | 263 | if (fread(shdrs, sizeof(elf_shdr), shnum, fp) != shnum) { 264 | perror("resolve_symbol: fread"); 265 | goto _free; 266 | } 267 | 268 | r = resolve_symbol_from_sections(fp, shdrs, shnum, symname, symval); 269 | 270 | _free: 271 | free(shdrs); 272 | 273 | _close: 274 | fclose(fp); 275 | 276 | _ret: 277 | return r; 278 | } 279 | intptr_t get_addr(const char *name) { 280 | char buf[BUFSIZ], *tok[6]; 281 | int i; 282 | FILE *fp; 283 | intptr_t r = NULL; 284 | 285 | 286 | fp = fopen("/proc/self/maps", "r"); 287 | if(fp == NULL) { 288 | perror("get_linker_addr: fopen"); 289 | goto ret; 290 | } 291 | 292 | 293 | while (fgets(buf, sizeof(buf), fp)) { 294 | i = strlen(buf); 295 | if (i > 0 && buf[i - 1] == '\n') 296 | buf[i - 1] = 0; 297 | 298 | tok[0] = strtok(buf, " "); 299 | for (i = 1; i < 6; i++) 300 | tok[i] = strtok(NULL, " "); 301 | 302 | if (tok[5] && strstr(tok[5], name) != NULL) { 303 | LOGE("get linker maps item -> %s ",buf); 304 | 305 | r = (intptr_t) strtoul(tok[0], NULL, 16); 306 | goto close; 307 | } 308 | } 309 | 310 | close: 311 | fclose(fp); 312 | 313 | ret: 314 | return r; 315 | } 316 | 317 | 318 | bool relocate_linker(const char *linker_path){ 319 | intptr_t linker_addr, dlopen_off, symbol; 320 | if ((linker_addr = get_addr(linker_path)) == 0) { 321 | LOGE("cannot found linker addr %s", linker_path); 322 | return false; 323 | } 324 | if (resolve_symbol(linker_path, "__dl__Z9do_dlopenPKciPK17android_dlextinfoPKv", 325 | &dlopen_off) == 0) { 326 | symbol = linker_addr + dlopen_off; 327 | DobbyHook((void *) symbol, (void *) new_do_dlopen_CIVV, 328 | (void **) &orig_do_dlopen_CIVV); 329 | return true; 330 | } else if (resolve_symbol(linker_path, "__dl__Z9do_dlopenPKciPK17android_dlextinfoPv", 331 | &dlopen_off) == 0) { 332 | symbol = linker_addr + dlopen_off; 333 | DobbyHook((void *) symbol, (void *) new_do_dlopen_CIVV, 334 | (void **) &orig_do_dlopen_CIVV); 335 | return true; 336 | } else if (resolve_symbol(linker_path, "__dl__ZL10dlopen_extPKciPK17android_dlextinfoPv", 337 | &dlopen_off) == 0) { 338 | symbol = linker_addr + dlopen_off; 339 | DobbyHook((void *) symbol, (void *) new_do_dlopen_CIVV, 340 | (void **) &orig_do_dlopen_CIVV); 341 | return true; 342 | } else if ( 343 | resolve_symbol(linker_path, "__dl__Z20__android_dlopen_extPKciPK17android_dlextinfoPKv", 344 | &dlopen_off) == 0) { 345 | symbol = linker_addr + dlopen_off; 346 | DobbyHook((void *) symbol, (void *) new_do_dlopen_CIVV, 347 | (void **) &orig_do_dlopen_CIVV); 348 | return true; 349 | } else if ( 350 | resolve_symbol(linker_path, "__dl___loader_android_dlopen_ext", 351 | &dlopen_off) == 0) { 352 | symbol = linker_addr + dlopen_off; 353 | DobbyHook((void *) symbol, (void *) new_do_dlopen_CIVV, 354 | (void **) &orig_do_dlopen_CIVV); 355 | return true; 356 | } else if (resolve_symbol(linker_path, "__dl__Z9do_dlopenPKciPK17android_dlextinfo", 357 | &dlopen_off) == 0) { 358 | symbol = linker_addr + dlopen_off; 359 | DobbyHook((void *) symbol, (void *) new_do_dlopen_CIV, 360 | (void **) &orig_do_dlopen_CIV); 361 | return true; 362 | } else if (resolve_symbol(linker_path, "__dl__Z8__dlopenPKciPKv", 363 | &dlopen_off) == 0) { 364 | symbol = linker_addr + dlopen_off; 365 | DobbyHook((void *) symbol, (void *) new_do_dlopen_CIV, 366 | (void **) &orig_do_dlopen_CIV); 367 | return true; 368 | } else if (resolve_symbol(linker_path, "__dl___loader_dlopen", 369 | &dlopen_off) == 0) { 370 | symbol = linker_addr + dlopen_off; 371 | DobbyHook((void *) symbol, (void *) new_do_dlopen_CIV, 372 | (void **) &orig_do_dlopen_CIV); 373 | return true; 374 | } else if (resolve_symbol(linker_path, "__dl_dlopen", 375 | &dlopen_off) == 0) { 376 | symbol = linker_addr + dlopen_off; 377 | DobbyHook((void *) symbol, (void *) new_dlopen_CI, 378 | (void **) &orig_dlopen_CI); 379 | return true; 380 | } 381 | return false; 382 | } 383 | 384 | HOOK_DEF(void,call_array,const char* array_name, 385 | void* functions, 386 | size_t count, 387 | bool reverse, 388 | const char* realpath){ 389 | 390 | LOGD("call init function: %s %s ",array_name,realpath); 391 | orig_call_array(array_name,functions,count,reverse,realpath); 392 | 393 | } 394 | 395 | bool relocate_call_array(const char* linker_path){ 396 | //_dl__ZL10call_arrayIPFviPPcS1_EEvPKcPT_mbS5_ 397 | intptr_t linker_addr, dlopen_off, symbol; 398 | if ((linker_addr = get_addr(linker_path)) == 0) { 399 | LOGE("cannot found linker addr %s", linker_path); 400 | return false; 401 | } 402 | 403 | if (resolve_symbol(linker_path, "__dl__ZL10call_arrayIPFviPPcS1_EEvPKcPT_mbS5_", 404 | &dlopen_off) == 0) { 405 | symbol = linker_addr + dlopen_off; 406 | LOGI("_dl__ZL10call_arrayIPFviPPcS1_EEvPKcPT_mbS5_ %p",symbol); 407 | DobbyHook((void *) symbol, (void *) new_call_array, 408 | (void **) &orig_call_array); 409 | return true; 410 | } 411 | return false; 412 | } 413 | 414 | //art12_GLOBAL__N_111ScopedCheck5CheckERNS_18ScopedObjectAccessEbPKcPNS0_12JniValueTypeE.__uniq.99033978352804627313491551960229047428 415 | 416 | HOOK_DEF(bool ,artcheck){ 417 | return true; 418 | } 419 | 420 | bool relocate_artcheck(const char* libart_path){ 421 | //_dl__ZL10call_arrayIPFviPPcS1_EEvPKcPT_mbS5_ 422 | intptr_t linker_addr, dlopen_off, symbol; 423 | if ((linker_addr = get_addr(libart_path)) == 0) { 424 | LOGE("cannot found libart.so addr %s", libart_path); 425 | return false; 426 | } 427 | 428 | if (resolve_symbol(libart_path, "art12_GLOBAL__N_111ScopedCheck5CheckERNS_18ScopedObjectAccessEbPKcPNS0_12JniValueTypeE", 429 | &dlopen_off) == 0) { 430 | symbol = linker_addr + dlopen_off; 431 | LOGI("_dl__ZL10call_arrayIPFviPPcS1_EEvPKcPT_mbS5_ %p",symbol); 432 | DobbyHook((void *) symbol, (void *) new_artcheck, 433 | (void **) &orig_artcheck); 434 | return true; 435 | }else{ 436 | //238894 437 | DobbyHook((void *) (linker_addr+0x238894), (void *) new_artcheck, 438 | (void **) &orig_artcheck); 439 | return true; 440 | }; 441 | return false; 442 | } 443 | 444 | 445 | static int SDK_INT = -1; 446 | 447 | int get_sdk_level() { 448 | if (SDK_INT > 0) { 449 | return SDK_INT; 450 | } 451 | char sdk[PROP_VALUE_MAX] = {0}; 452 | __system_property_get("ro.build.version.sdk", sdk); 453 | SDK_INT = atoi(sdk); 454 | return SDK_INT; 455 | } 456 | 457 | char *getLinkerPath() { 458 | char *linker; 459 | 460 | //get_sdk_level 是dlfc自己实现的方法 461 | //android_get_device_api_level是系统方法,低版本的NDK没有此方法。 462 | #if defined(__aarch64__) 463 | if (get_sdk_level() >= ANDROID_R) { 464 | linker = (char*)"/apex/com.android.runtime/bin/linker64"; 465 | } else if (get_sdk_level() >= ANDROID_Q) { 466 | linker = (char*)"/apex/com.android.runtime/bin/linker64"; 467 | } else { 468 | linker = (char*)"/system/bin/linker64"; 469 | } 470 | #else 471 | if (get_sdk_level() >= ANDROID_R) { 472 | linker = (char*)"/apex/com.android.runtime/bin/linker"; 473 | } else if (get_sdk_level() >= ANDROID_Q) { 474 | linker = (char*)"/apex/com.android.runtime/bin/linker"; 475 | } else { 476 | linker = (char*)"/system/bin/linker"; 477 | } 478 | #endif 479 | 480 | return linker; 481 | } 482 | void linkerHandler_init() { 483 | 484 | bool isSuccess = relocate_linker(getLinkerPath()); 485 | 486 | LOGE(">>>>>>>>> linker handler init ! %s",(isSuccess?"true":"false")); 487 | 488 | isSuccess = relocate_call_array(getLinkerPath()); 489 | LOGE(">>>>>>>>> linker handler relocate_call_array ! %s",(isSuccess?"true":"false")); 490 | 491 | isSuccess = relocate_artcheck("/apex/com.android.art/lib64/libart.so"); 492 | LOGE(">>>>>>>>> art handler relocate_artcheck ! %s",(isSuccess?"true":"false")); 493 | } 494 | 495 | 496 | -------------------------------------------------------------------------------- /nativelib/src/main/cpp/hook/linkerHandler.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by fang on 2024/1/3. 3 | // 4 | 5 | #ifndef QBDI_LINKERHANDLER_H 6 | #define QBDI_LINKERHANDLER_H 7 | #include "HookUtils.h" 8 | void linkerHandler_init(); 9 | int resolve_symbol(const char *filename, const char *symname, intptr_t *symval); 10 | intptr_t get_addr(const char *name); 11 | #endif //QBDI_LINKERHANDLER_H 12 | -------------------------------------------------------------------------------- /nativelib/src/main/cpp/include/logger.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by fang on 23-12-19. 3 | // 4 | 5 | #ifndef QBDIRECORDER_LOGGER_H 6 | #define QBDIRECORDER_LOGGER_H 7 | #include 8 | 9 | 10 | 11 | // 日志 12 | #define LOG_TAG "SSAGEHOOK" 13 | #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) 14 | #define LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__) 15 | #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) 16 | #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) 17 | #endif //QBDIRECORDER_LOGGER_H 18 | -------------------------------------------------------------------------------- /nativelib/src/main/cpp/include/nativelib.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by fang on 2023/12/22. 3 | // 4 | 5 | #ifndef QBDI_NATIVELIB_H 6 | #define QBDI_NATIVELIB_H 7 | #include 8 | #include "logger.h" 9 | #include "dobby.h" 10 | #include "QBDI.h" 11 | #include "socketUtils.h" 12 | #include "BionicLinkerUtil/bionic_linker_util.h" 13 | #include "HookUtils.h" 14 | #include "linkerHandler.h" 15 | extern JavaVM *mVm; 16 | extern JNIEnv *mEnv; 17 | 18 | extern "C"{ 19 | #include "mongoose.h" 20 | 21 | }; 22 | 23 | 24 | #endif //QBDI_NATIVELIB_H 25 | -------------------------------------------------------------------------------- /nativelib/src/main/cpp/include/version.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by zhenxi on 2022/4/30. 3 | // 4 | 5 | #ifndef QCONTAINER_PRO_VERSION_H 6 | #define QCONTAINER_PRO_VERSION_H 7 | 8 | #define ANDROID_K 19 9 | #define ANDROID_L 21 10 | #define ANDROID_L2 22 11 | #define ANDROID_M 23 12 | #define ANDROID_N 24 13 | #define ANDROID_N2 25 14 | //Android 8.0 15 | #define ANDROID_O 26 16 | //Android 8.1 17 | #define ANDROID_O2 27 18 | //Android 9.0 19 | #define ANDROID_P 28 20 | //Android 10.0 21 | #define ANDROID_Q 29 22 | //Android 11.0 23 | #define ANDROID_R 30 24 | //Android 12.0 25 | #define ANDROID_S 31 26 | 27 | 28 | #endif //QCONTAINER_PRO_VERSION_H -------------------------------------------------------------------------------- /nativelib/src/main/cpp/include/vm.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by fang on 23-12-19. 3 | // 4 | 5 | #ifndef QBDIRECORDER_VM_H 6 | #define QBDIRECORDER_VM_H 7 | #include "QBDI.h" 8 | #include "QBDI/State.h" 9 | #include "dobby.h" 10 | #include "mongoose.h" 11 | //#include "socketUtils.h" 12 | #include "fileRecord.h" 13 | 14 | #include "json.hpp" 15 | #include "jsonbean.h" 16 | #define STACK_SIZE 0x800000 17 | void syn_regs(DobbyRegisterContext *ctx,QBDI::GPRState *state,bool D2Q); 18 | class vm { 19 | 20 | public: 21 | QBDI::VM init(void* address); 22 | private: 23 | 24 | }; 25 | 26 | 27 | #define VM_BEFORE(addr) \ 28 | void vm_handle_##addr(void* address,DobbyRegisterContext *ctx,addr_t * relocated_addr){\ 29 | LOGD("vm address %p ",address);\ 30 | DobbyDestroy(address);\ 31 | auto vm_ = new vm();\ 32 | auto qvm = vm_->init(address);\ 33 | auto state = qvm.getGPRState();\ 34 | QBDI::rword retval;\ 35 | syn_regs(ctx,state, true); \ 36 | uint8_t *fakestack; \ 37 | QBDI::allocateVirtualStack(state, STACK_SIZE, &fakestack); \ 38 | 39 | 40 | 41 | #define VM_AFTER \ 42 | qvm.call(nullptr, (uint64_t) address);\ 43 | syn_regs(ctx,state, false); \ 44 | QBDI::alignedFree(fakestack);\ 45 | 46 | 47 | #define VM_END(addr) \ 48 | DobbyInstrumentQBDI(address,vm_handle_##addr);\ 49 | }\ 50 | 51 | #endif //QBDIRECORDER_VM_H 52 | -------------------------------------------------------------------------------- /nativelib/src/main/cpp/nativelib.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "vm.h" 6 | #include "nativelib.h" 7 | #include "HookUtils.h" 8 | #include "HookInfo.h" 9 | 10 | using namespace std; 11 | #define HOOK_ADDR_DOBBY(func) \ 12 | DobbyHook((void*)func, (void*) new_##func, (void**) &orig_##func); \ 13 | 14 | 15 | void aaa(); 16 | 17 | extern "C" JNIEXPORT jstring JNICALL 18 | Java_com_f_nativelib_NativeLib_stringFromJNI( 19 | JNIEnv *env, 20 | jobject /* this */) { 21 | std::string hello = "Hello from C++"; 22 | auto a = env->NewStringUTF("123123"); 23 | env->DeleteLocalRef(a); 24 | //aaa(); 25 | return env->NewStringUTF(hello.c_str()); 26 | } 27 | 28 | int sub(int a, int b) { 29 | return a + b; 30 | } 31 | 32 | int add(int a, int b) { 33 | int c = sub(5, 6); 34 | return a + b + c; 35 | } 36 | 37 | 38 | 39 | //void add_handle2(void* address,DobbyRegisterContext *ctx,addr_t * relocated_addr){ 40 | // LOGD("address %p ",address); 41 | // LOGD("Java_com_f_nativelib_NativeLib_stringFromJNI %p ,lr %lx ",Java_com_f_nativelib_NativeLib_stringFromJNI,ctx->lr); 42 | // LOGD("%lx %lx",ctx->dmmpy_0,ctx->dmmpy_1); 43 | // LOGD("relocated_addr %p",relocated_addr); 44 | // DobbyDestroy(address); 45 | // auto vm_ = new vm(); 46 | // auto qvm = vm_->init(address); 47 | // auto state = qvm.getGPRState(); 48 | // QBDI::rword retval; 49 | // syn_regs(ctx,state, true); 50 | // 51 | // qvm.call(&retval, (uint64_t) address); 52 | // syn_regs(ctx,state, false); 53 | // DobbyInstrumentQBDI(address,add_handle); 54 | //} 55 | 56 | 57 | VM_BEFORE(add) 58 | LOGD("VM_BEFORE %lx", ctx->general.x[0]); 59 | LOGD("VM_BEFORE %lx", ctx->general.x[1]); 60 | VM_AFTER 61 | LOGD("VM_AFTER %lx", ctx->general.x[0]); 62 | VM_END(add) 63 | 64 | 65 | void aaa() { 66 | DobbyInstrumentQBDI((void *) (add), vm_handle_add); 67 | LOGD("%d", add(1, 2)); 68 | LOGD("%d", add(1, 2)); 69 | LOGD("%d", add(1, 2)); 70 | } 71 | 72 | 73 | void init() { 74 | linkerHandler_init(); 75 | } 76 | 77 | JavaVM *mVm; 78 | JNIEnv *mEnv; 79 | 80 | jint JNICALL 81 | JNI_OnLoad(JavaVM *vm, void *reversed) { 82 | LOGD("JNI_ONLOAD start"); 83 | mVm = vm; 84 | JNIEnv *env = nullptr; 85 | if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) == JNI_OK) { 86 | mEnv = env; 87 | 88 | //init(); 89 | return JNI_VERSION_1_6; 90 | } 91 | return JNI_ERR; 92 | } 93 | 94 | 95 | // you can do something here 96 | VM_BEFORE(sig1) 97 | 98 | LOGD("ctx->lr %zx",ctx->lr); 99 | 100 | VM_AFTER 101 | LOGD("vm end"); 102 | } 103 | 104 | 105 | extern "C" void _init(void) { 106 | LOGD("getPrivatePath %s", getPrivatePath()); 107 | //aaa(); 108 | init(); 109 | 110 | } 111 | 112 | __unused __attribute__((constructor)) void init_main() { 113 | // add hook 114 | DobbyInstrumentQBDI((void*)Java_com_f_nativelib_NativeLib_stringFromJNI, vm_handle_sig1); 115 | } -------------------------------------------------------------------------------- /nativelib/src/main/cpp/qdbi-arm64/bin/qbdi-frida-template-AARCH64: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | cp /usr/local/share/qbdiAARCH64/qbdi_frida_template/* . 3 | cp /usr/local/share/qbdiAARCH64/frida-qbdi.js . 4 | 5 | -------------------------------------------------------------------------------- /nativelib/src/main/cpp/qdbi-arm64/bin/qbdi-template-AARCH64: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | cp /usr/local/share/qbdiAARCH64/qbdi_template/* . 3 | -------------------------------------------------------------------------------- /nativelib/src/main/cpp/qdbi-arm64/include/QBDI.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of QBDI. 3 | * 4 | * Copyright 2017 - 2023 Quarkslab 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | #ifndef QBDI_H_ 19 | #define QBDI_H_ 20 | 21 | #ifdef __cplusplus 22 | #include "QBDI/Memory.hpp" 23 | #include "QBDI/VM.h" 24 | #else 25 | #include "QBDI/Memory.h" 26 | #include "QBDI/VM_C.h" 27 | #endif 28 | 29 | #include "QBDI/Logs.h" 30 | #include "QBDI/Version.h" 31 | 32 | #endif // QBDI_H_ 33 | -------------------------------------------------------------------------------- /nativelib/src/main/cpp/qdbi-arm64/include/QBDI/Bitmask.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of QBDI. 3 | * 4 | * Copyright 2017 - 2023 Quarkslab 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | #ifndef QBDI_BITMASK_H_ 19 | #define QBDI_BITMASK_H_ 20 | 21 | #ifdef __cplusplus 22 | #include 23 | 24 | namespace QBDI { 25 | 26 | template 27 | struct EnableBitMaskOperators { 28 | static const bool enable = false; 29 | }; 30 | 31 | template 32 | typename std::enable_if::enable, Enum>::type 33 | operator|(Enum lhs, Enum rhs) { 34 | using underlying = typename std::underlying_type::type; 35 | return static_cast(static_cast(lhs) | 36 | static_cast(rhs)); 37 | } 38 | 39 | template 40 | typename std::enable_if::enable, Enum>::type & 41 | operator|=(Enum &lhs, Enum rhs) { 42 | using underlying = typename std::underlying_type::type; 43 | lhs = static_cast(static_cast(lhs) | 44 | static_cast(rhs)); 45 | return lhs; 46 | } 47 | 48 | #define _QBDI_ENABLE_BITMASK_OPERATORS(x) \ 49 | template <> \ 50 | struct EnableBitMaskOperators { \ 51 | static const bool enable = true; \ 52 | }; 53 | 54 | } // namespace QBDI 55 | #else 56 | #define _QBDI_ENABLE_BITMASK_OPERATORS(x) 57 | #endif 58 | 59 | #endif // QBDI_BITMASK_H_ 60 | -------------------------------------------------------------------------------- /nativelib/src/main/cpp/qdbi-arm64/include/QBDI/Callback.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of QBDI. 3 | * 4 | * Copyright 2017 - 2023 Quarkslab 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | #ifndef QBDI_CALLBACK_H_ 19 | #define QBDI_CALLBACK_H_ 20 | 21 | #include "QBDI/Bitmask.h" 22 | #include "QBDI/InstAnalysis.h" 23 | #include "QBDI/Platform.h" 24 | #include "QBDI/State.h" 25 | #ifdef __cplusplus 26 | #include 27 | #include 28 | 29 | namespace QBDI { 30 | #endif 31 | 32 | /*! The callback results. 33 | */ 34 | typedef enum { 35 | _QBDI_EI(CONTINUE) = 0, /*!< The execution of the basic block continues. */ 36 | _QBDI_EI(SKIP_INST) = 1, /*!< Available only with PREINST InstCallback. 37 | * The instruction and the remained PREINST 38 | * callbacks are skip. The execution continue 39 | * with the POSTINST instruction. 40 | * 41 | * We recommand to used this result with a low 42 | * priority PREINST callback in order to emulate 43 | * the instruction without skipping the POSTINST 44 | * callback. 45 | */ 46 | _QBDI_EI(SKIP_PATCH) = 2, /*!< Available only with InstCallback. The current 47 | * instruction and the reminding callback (PRE 48 | * and POST) are skip. The execution continues to 49 | * the next instruction. 50 | * 51 | * For instruction that change the instruction 52 | * pointer (jump/call/ret), BREAK_TO_VM must be 53 | * used insted of SKIP. 54 | * 55 | * SKIP can break the record of MemoryAccess for 56 | * the current instruction. 57 | */ 58 | _QBDI_EI(BREAK_TO_VM) = 3, /*!< The execution breaks and returns to the VM 59 | * causing a complete reevaluation of the 60 | * execution state. A BREAK_TO_VM is needed to 61 | * ensure that modifications of the Program 62 | * Counter or the program code are taken 63 | * into account. 64 | */ 65 | _QBDI_EI(STOP) = 4, /*!< Stops the execution of the program. This 66 | * causes the run function to return early. 67 | */ 68 | } VMAction; 69 | 70 | typedef void *VMInstance; 71 | 72 | #ifdef __cplusplus 73 | class VM; 74 | using VMInstanceRef = VM *; 75 | #else 76 | typedef VMInstance *VMInstanceRef; 77 | #endif 78 | 79 | /*! Instruction callback function type. 80 | * 81 | * @param[in] vm VM instance of the callback. 82 | * @param[in] gprState A structure containing the state of the 83 | * General Purpose Registers. Modifying 84 | * it affects the VM execution accordingly. 85 | * @param[in] fprState A structure containing the state of the 86 | * Floating Point Registers. Modifying 87 | * it affects the VM execution accordingly. 88 | * @param[in] data User defined data which can be defined when 89 | * registering the callback. 90 | * 91 | * @return The callback result used to signal subsequent 92 | * actions the VM needs to take. 93 | */ 94 | typedef VMAction (*InstCallback)(VMInstanceRef vm, GPRState *gprState, 95 | FPRState *fprState, void *data); 96 | #ifdef __cplusplus 97 | /*! Instruction callback lambda type. 98 | * 99 | * @param[in] vm VM instance of the callback. 100 | * @param[in] gprState A structure containing the state of the 101 | * General Purpose Registers. Modifying 102 | * it affects the VM execution accordingly. 103 | * @param[in] fprState A structure containing the state of the 104 | * Floating Point Registers. Modifying 105 | * it affects the VM execution accordingly. 106 | * 107 | * @return The callback result used to signal subsequent 108 | * actions the VM needs to take. 109 | */ 110 | typedef std::function 112 | InstCbLambda; 113 | #endif 114 | 115 | /*! Position relative to an instruction. 116 | */ 117 | typedef enum { 118 | _QBDI_EI(PREINST) = 0, /*!< Positioned before the instruction.*/ 119 | _QBDI_EI(POSTINST) /*!< Positioned after the instruction.*/ 120 | } InstPosition; 121 | 122 | /*! Priority of callback 123 | * 124 | * A callback with an higher priority will be call before a callback with a 125 | * lower priority. 126 | * 127 | * ie: 128 | * 129 | * 1. CBpre(p = 10) 130 | * 2. CBpre(p = 0) 131 | * 3. CBpre(p = -10) 132 | * 4. instrumented instruction 133 | * 5. CBpost(p = 10) 134 | * 6. CBpost(p = 0) 135 | * 7. CBpost(p = -10) 136 | * 137 | * When the MemoryAccess API is used in a callback, the priority of the callback 138 | * must not be greater than PRIORITY_MEMACCESS_LIMIT 139 | */ 140 | typedef enum { 141 | _QBDI_EI(PRIORITY_DEFAULT) = 0, /*!< Default priority for callback */ 142 | _QBDI_EI(PRIORITY_MEMACCESS_LIMIT) = 143 | 0x1000000, /*!< Maximum priority if getInstMemoryAccess 144 | * is used in the callback */ 145 | } CallbackPriority; 146 | 147 | typedef enum { 148 | _QBDI_EI(NO_EVENT) = 0, 149 | _QBDI_EI(SEQUENCE_ENTRY) = 1, /*!< Triggered when the execution 150 | * enters a sequence. 151 | */ 152 | _QBDI_EI(SEQUENCE_EXIT) = 1 << 1, /*!< Triggered when the execution 153 | * exits from the current sequence. 154 | */ 155 | _QBDI_EI(BASIC_BLOCK_ENTRY) = 1 << 2, /*!< Triggered when the execution 156 | * enters a basic block. 157 | */ 158 | _QBDI_EI(BASIC_BLOCK_EXIT) = 1 << 3, /*!< Triggered when the execution 159 | * exits from the current 160 | * basic block. 161 | */ 162 | _QBDI_EI(BASIC_BLOCK_NEW) = 1 << 4, /*!< Triggered when the execution 163 | * enters a new (~unknown) 164 | * basic block. 165 | */ 166 | _QBDI_EI(EXEC_TRANSFER_CALL) = 1 << 5, /*!< Triggered when the ExecBroker 167 | * executes an execution transfer. 168 | */ 169 | _QBDI_EI(EXEC_TRANSFER_RETURN) = 1 << 6, /*!< Triggered when the ExecBroker 170 | * returns from an execution 171 | * transfer. 172 | */ 173 | _QBDI_EI(SYSCALL_ENTRY) = 1 << 7, /*!< Not implemented.*/ 174 | _QBDI_EI(SYSCALL_EXIT) = 1 << 8, /*!< Not implemented.*/ 175 | _QBDI_EI(SIGNAL) = 1 << 9, /*!< Not implemented.*/ 176 | } VMEvent; 177 | 178 | _QBDI_ENABLE_BITMASK_OPERATORS(VMEvent) 179 | 180 | /*! 181 | * Structure describing the current VM state 182 | */ 183 | typedef struct { 184 | VMEvent event; /*!< The event(s) which triggered the callback (must 185 | * be checked using a mask: 186 | * event & BASIC_BLOCK_ENTRY). 187 | */ 188 | rword basicBlockStart; /*!< The current basic block start address which can 189 | * also be the execution transfer destination. 190 | */ 191 | rword basicBlockEnd; /*!< The current basic block end address which can 192 | * also be the execution transfer destination. 193 | */ 194 | rword sequenceStart; /*!< The current sequence start address which can also 195 | * be the execution transfer destination. 196 | */ 197 | rword sequenceEnd; /*!< The current sequence end address which can also 198 | * be the execution transfer destination. 199 | */ 200 | rword lastSignal; /*!< Not implemented.*/ 201 | } VMState; 202 | 203 | /*! VM callback function type. 204 | * 205 | * @param[in] vm VM instance of the callback. 206 | * @param[in] vmState A structure containing the current state of the VM. 207 | * @param[in] gprState A structure containing the state of the 208 | * General Purpose Registers. Modifying 209 | * it affects the VM execution accordingly. 210 | * @param[in] fprState A structure containing the state of the 211 | * Floating Point Registers. Modifying 212 | * it affects the VM execution accordingly. 213 | * @param[in] data User defined data which can be defined when 214 | * registering the callback. 215 | * 216 | * @return The callback result used to signal subsequent 217 | * actions the VM needs to take. 218 | */ 219 | typedef VMAction (*VMCallback)(VMInstanceRef vm, const VMState *vmState, 220 | GPRState *gprState, FPRState *fprState, 221 | void *data); 222 | #ifdef __cplusplus 223 | /*! VM callback lambda type. 224 | * 225 | * @param[in] vm VM instance of the callback. 226 | * @param[in] vmState A structure containing the current state of the VM. 227 | * @param[in] gprState A structure containing the state of the 228 | * General Purpose Registers. Modifying 229 | * it affects the VM execution accordingly. 230 | * @param[in] fprState A structure containing the state of the 231 | * Floating Point Registers. Modifying 232 | * it affects the VM execution accordingly. 233 | * 234 | * @return The callback result used to signal subsequent 235 | * actions the VM needs to take. 236 | */ 237 | typedef std::function 239 | VMCbLambda; 240 | #endif 241 | 242 | static const uint16_t NO_REGISTRATION = 0xFFFF; 243 | static const uint16_t NOT_FOUND = 0xFFFF; 244 | static const uint16_t ANY = 0xFFFF; 245 | 246 | /*! Memory access type (read / write / ...) 247 | */ 248 | typedef enum { 249 | _QBDI_EI(MEMORY_READ) = 1, /*!< Memory read access */ 250 | _QBDI_EI(MEMORY_WRITE) = 1 << 1, /*!< Memory write access */ 251 | _QBDI_EI(MEMORY_READ_WRITE) = 3 /*!< Memory read/write access */ 252 | } MemoryAccessType; 253 | 254 | _QBDI_ENABLE_BITMASK_OPERATORS(MemoryAccessType); 255 | 256 | /*! Memory access flags 257 | */ 258 | typedef enum { 259 | _QBDI_EI(MEMORY_NO_FLAGS) = 0, 260 | _QBDI_EI(MEMORY_UNKNOWN_SIZE) = 1 << 0, /*!< The size of the access isn't 261 | * known. 262 | */ 263 | _QBDI_EI(MEMORY_MINIMUM_SIZE) = 1 << 1, /*!< The given size is a minimum 264 | * size. 265 | */ 266 | _QBDI_EI(MEMORY_UNKNOWN_VALUE) = 1 << 2, /*!< The value of the access is 267 | * unknown or hasn't been retrived. 268 | */ 269 | } MemoryAccessFlags; 270 | 271 | _QBDI_ENABLE_BITMASK_OPERATORS(MemoryAccessFlags); 272 | 273 | /*! Describe a memory access 274 | */ 275 | typedef struct { 276 | rword instAddress; /*!< Address of instruction making the access */ 277 | rword accessAddress; /*!< Address of accessed memory */ 278 | rword value; /*!< Value read from / written to memory */ 279 | uint16_t size; /*!< Size of memory access (in bytes) */ 280 | MemoryAccessType type; /*!< Memory access type (READ / WRITE) */ 281 | MemoryAccessFlags flags; /*!< Memory access flags */ 282 | } MemoryAccess; 283 | 284 | #ifdef __cplusplus 285 | struct InstrRuleDataCBK { 286 | InstPosition position; /*!< Relative position of the event callback (PREINST / 287 | * POSTINST). 288 | */ 289 | InstCallback cbk; /*!< Address of the function to call when the 290 | * instruction is executed. 291 | */ 292 | void *data; /*!< User defined data which will be forward to cbk */ 293 | 294 | InstCbLambda 295 | lambdaCbk; /*!< Lambda callback. Replace cbk and data if not nullptr */ 296 | 297 | int priority; /*!< Priority of the callback */ 298 | 299 | InstrRuleDataCBK(InstPosition position, InstCallback cbk, void *data, 300 | int priority = PRIORITY_DEFAULT) 301 | : position(position), cbk(cbk), data(data), lambdaCbk(nullptr), 302 | priority(priority) {} 303 | InstrRuleDataCBK(InstPosition position, const InstCbLambda &cbk, 304 | int priority = PRIORITY_DEFAULT) 305 | : position(position), cbk(nullptr), data(nullptr), lambdaCbk(cbk), 306 | priority(priority) {} 307 | InstrRuleDataCBK(InstPosition position, InstCbLambda &&cbk, 308 | int priority = PRIORITY_DEFAULT) 309 | : position(position), cbk(nullptr), data(nullptr), 310 | lambdaCbk(std::move(cbk)), priority(priority) {} 311 | }; 312 | 313 | using InstrRuleDataVec = std::vector *; 314 | #else 315 | typedef void *InstrRuleDataVec; 316 | #endif 317 | 318 | /*! Instrumentation rule callback function type for C API. 319 | * 320 | * @param[in] vm VM instance of the callback. 321 | * @param[in] inst AnalysisType of the current instrumented Instruction. 322 | * @param[in] cbks An object to add the callback to apply for this 323 | * instruction. InstCallback can be add with 324 | * qbdi_addInstrRuleData. 325 | * @param[in] data User defined data which can be defined when registering 326 | * the callback. 327 | */ 328 | typedef void (*InstrRuleCallbackC)(VMInstanceRef vm, const InstAnalysis *inst, 329 | InstrRuleDataVec cbks, void *data); 330 | 331 | #ifdef __cplusplus 332 | 333 | /*! Instrumentation rule callback function type. 334 | * 335 | * @param[in] vm VM instance of the callback. 336 | * @param[in] inst AnalysisType of the current instrumented Instruction. 337 | * @param[in] data User defined data which can be defined when registering 338 | * the callback. 339 | * 340 | * @return Return cbk to call when this instruction is run. 341 | */ 342 | typedef std::vector (*InstrRuleCallback)( 343 | VMInstanceRef vm, const InstAnalysis *inst, void *data); 344 | 345 | /*! Instrumentation rule callback lambda type. 346 | * 347 | * @param[in] vm VM instance of the callback. 348 | * @param[in] inst AnalysisType of the current instrumented Instruction. 349 | * 350 | * @return Return cbk to call when this instruction is run. 351 | */ 352 | typedef std::function(VMInstanceRef vm, 353 | const InstAnalysis *inst)> 354 | InstrRuleCbLambda; 355 | 356 | } // QBDI:: 357 | #endif 358 | 359 | #endif 360 | -------------------------------------------------------------------------------- /nativelib/src/main/cpp/qdbi-arm64/include/QBDI/Config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of QBDI. 3 | * 4 | * Copyright 2017 - 2023 Quarkslab 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | #ifndef QBDI_CONFIG_H_ 19 | #define QBDI_CONFIG_H_ 20 | 21 | /* #undef QBDI_ARCH_ARM */ 22 | #define QBDI_ARCH_AARCH64 1 23 | /* #undef QBDI_ARCH_X86 */ 24 | /* #undef QBDI_ARCH_X86_64 */ 25 | 26 | /* #undef QBDI_PLATFORM_WINDOWS */ 27 | /* #undef QBDI_PLATFORM_LINUX */ 28 | #define QBDI_PLATFORM_ANDROID 1 29 | /* #undef QBDI_PLATFORM_OSX */ 30 | /* #undef QBDI_PLATFORM_IOS */ 31 | 32 | /* #undef QBDI_NOT_AVX_SUPPORT */ 33 | 34 | /* #undef QBDI_BITS_32 */ 35 | #define QBDI_BITS_64 1 36 | 37 | /* #undef QBDI_LOG_DEBUG */ 38 | 39 | /* #undef QBDI_EXPORT_SYM */ 40 | 41 | #ifdef __cplusplus 42 | namespace QBDI { 43 | 44 | static constexpr bool is_android = 1; 45 | static constexpr bool is_linux = 0; 46 | static constexpr bool is_osx = 0; 47 | static constexpr bool is_ios = 0; 48 | static constexpr bool is_windows = 0; 49 | 50 | 51 | static constexpr bool is_arm = 0; 52 | static constexpr bool is_aarch64 = 1; 53 | static constexpr bool is_x86 = 0; 54 | static constexpr bool is_x86_64 = 0; 55 | 56 | static constexpr bool it_bits_32 = 0; 57 | static constexpr bool is_bits_64 = 1; 58 | 59 | static constexpr bool has_debug_log = 0; 60 | } 61 | #endif // __cplusplus 62 | 63 | #endif // QBDI_CONFIG_H_ 64 | -------------------------------------------------------------------------------- /nativelib/src/main/cpp/qdbi-arm64/include/QBDI/Errors.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of QBDI. 3 | * 4 | * Copyright 2017 - 2023 Quarkslab 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | #ifndef QBDI_ERRORS_H_ 19 | #define QBDI_ERRORS_H_ 20 | 21 | #include "QBDI/Platform.h" 22 | 23 | #ifdef __cplusplus 24 | namespace QBDI { 25 | #endif 26 | 27 | /*! QBDI Error values 28 | */ 29 | typedef enum { 30 | _QBDI_EI(INVALID_EVENTID) = 0xffffffff, /*!< Mark a returned event id as 31 | * invalid 32 | */ 33 | } VMError; 34 | 35 | #ifdef __cplusplus 36 | } 37 | #endif 38 | 39 | #endif // QBDI_ERRORS_H_ 40 | -------------------------------------------------------------------------------- /nativelib/src/main/cpp/qdbi-arm64/include/QBDI/InstAnalysis.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of QBDI. 3 | * 4 | * Copyright 2017 - 2023 Quarkslab 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | #ifndef QBDI_INSTANALYSIS_H_ 19 | #define QBDI_INSTANALYSIS_H_ 20 | 21 | #include 22 | 23 | #include "QBDI/Bitmask.h" 24 | #include "QBDI/Platform.h" 25 | #include "QBDI/State.h" 26 | 27 | #ifdef __cplusplus 28 | namespace QBDI { 29 | #endif 30 | 31 | /*! Access type (R/W/RW) of a register operand 32 | */ 33 | typedef enum { 34 | _QBDI_EI(REGISTER_UNUSED) = 0, /*!< Unused register */ 35 | _QBDI_EI(REGISTER_READ) = 1, /*!< Register read access */ 36 | _QBDI_EI(REGISTER_WRITE) = 1 << 1, /*!< Register write access */ 37 | _QBDI_EI(REGISTER_READ_WRITE) = 3, /*!< Register read/write access */ 38 | } RegisterAccessType; 39 | 40 | _QBDI_ENABLE_BITMASK_OPERATORS(RegisterAccessType) 41 | 42 | /*! Instruction Condition 43 | */ 44 | typedef enum { 45 | _QBDI_EI(CONDITION_NONE) = 0x0, /*!< The instruction is unconditionnal */ 46 | // ConditionType ^ 0x1 reverse the condition, except for CONDITION_NONE 47 | _QBDI_EI(CONDITION_ALWAYS) = 0x2, /*!< The instruction is always true */ 48 | _QBDI_EI(CONDITION_NEVER) = 0x3, /*!< The instruction is always false 49 | */ 50 | _QBDI_EI(CONDITION_EQUALS) = 0x4, /*!< Equals ('==') */ 51 | _QBDI_EI(CONDITION_NOT_EQUALS) = 0x5, /*!< Not Equals ('!=') */ 52 | _QBDI_EI(CONDITION_ABOVE) = 0x6, /*!< Above ('>' unsigned) */ 53 | _QBDI_EI(CONDITION_BELOW_EQUALS) = 0x7, /*!< Below or Equals ('<=' unsigned) 54 | */ 55 | _QBDI_EI(CONDITION_ABOVE_EQUALS) = 0x8, /*!< Above or Equals ('>=' unsigned) 56 | */ 57 | _QBDI_EI(CONDITION_BELOW) = 0x9, /*!< Below ('<' unsigned) */ 58 | _QBDI_EI(CONDITION_GREAT) = 0xa, /*!< Great ('>' signed) */ 59 | _QBDI_EI(CONDITION_LESS_EQUALS) = 0xb, /*!< Less or Equals ('<=' signed) */ 60 | _QBDI_EI(CONDITION_GREAT_EQUALS) = 0xc, /*!< Great or Equals ('>=' signed) */ 61 | _QBDI_EI(CONDITION_LESS) = 0xd, /*!< Less ('<' signed) */ 62 | _QBDI_EI(CONDITION_EVEN) = 0xe, /*!< Even */ 63 | _QBDI_EI(CONDITION_ODD) = 0xf, /*!< Odd */ 64 | _QBDI_EI(CONDITION_OVERFLOW) = 0x10, /*!< Overflow */ 65 | _QBDI_EI(CONDITION_NOT_OVERFLOW) = 0x11, /*!< Not Overflow */ 66 | _QBDI_EI(CONDITION_SIGN) = 0x12, /*!< Sign */ 67 | _QBDI_EI(CONDITION_NOT_SIGN) = 0x13, /*!< Not Sign */ 68 | } ConditionType; 69 | 70 | /*! Operand type 71 | */ 72 | typedef enum { 73 | _QBDI_EI(OPERAND_INVALID) = 0, /*!< Invalid operand */ 74 | _QBDI_EI(OPERAND_IMM), /*!< Immediate operand */ 75 | _QBDI_EI(OPERAND_GPR), /*!< Register operand */ 76 | _QBDI_EI(OPERAND_PRED), /*!< Predicate operand */ 77 | _QBDI_EI(OPERAND_FPR), /*!< Float register operand */ 78 | _QBDI_EI(OPERAND_SEG), /*!< Segment or unsupported register operand */ 79 | } OperandType; 80 | 81 | typedef enum { 82 | _QBDI_EI(OPERANDFLAG_NONE) = 0, /*!< No flag */ 83 | _QBDI_EI(OPERANDFLAG_ADDR) = 1 << 0, /*!< The operand is used to 84 | * compute an address 85 | */ 86 | _QBDI_EI(OPERANDFLAG_PCREL) = 1 << 1, /*!< The value of the 87 | * operand is PC relative 88 | */ 89 | _QBDI_EI(OPERANDFLAG_UNDEFINED_EFFECT) = 1 << 2, /*!< The operand role isn't 90 | * fully defined 91 | */ 92 | _QBDI_EI(OPERANDFLAG_IMPLICIT) = 1 << 3, /*!< The operand is implicit 93 | */ 94 | } OperandFlag; 95 | 96 | _QBDI_ENABLE_BITMASK_OPERATORS(OperandFlag) 97 | 98 | /*! Structure containing analysis results of an operand provided by the VM. 99 | */ 100 | typedef struct { 101 | // Common fields 102 | OperandType type; /*!< Operand type */ 103 | OperandFlag flag; /*!< Operand flag */ 104 | sword value; /*!< Operand value (if immediate), or register Id */ 105 | uint8_t size; /*!< Operand size (in bytes) */ 106 | // Register specific fields 107 | uint8_t regOff; /*!< Sub-register offset in register (in bits) */ 108 | int16_t regCtxIdx; /*!< Register index in VM state (< 0 if not know) */ 109 | const char *regName; /*!< Register name */ 110 | RegisterAccessType regAccess; /*!< Register access type (r, w, rw) */ 111 | } OperandAnalysis; 112 | 113 | /*! Instruction analysis type 114 | */ 115 | typedef enum { 116 | _QBDI_EI(ANALYSIS_INSTRUCTION) = 1, /*!< Instruction analysis (address, 117 | * mnemonic, ...) 118 | */ 119 | _QBDI_EI(ANALYSIS_DISASSEMBLY) = 1 << 1, /*!< Instruction disassembly */ 120 | _QBDI_EI(ANALYSIS_OPERANDS) = 1 << 2, /*!< Instruction operands analysis */ 121 | _QBDI_EI(ANALYSIS_SYMBOL) = 1 << 3, /*!< Instruction symbol */ 122 | } AnalysisType; 123 | 124 | _QBDI_ENABLE_BITMASK_OPERATORS(AnalysisType) 125 | 126 | /*! Structure containing analysis results of an instruction provided by the VM. 127 | */ 128 | typedef struct { 129 | // ANALYSIS_INSTRUCTION 130 | const char *mnemonic; /*!< LLVM mnemonic 131 | * (warning: NULL if !ANALYSIS_INSTRUCTION) 132 | */ 133 | rword address; /*!< Instruction address */ 134 | uint32_t instSize; /*!< Instruction size (in bytes) */ 135 | CPUMode cpuMode; /*!< Instruction CPU mode */ 136 | bool affectControlFlow; /*!< true if instruction affects control flow */ 137 | bool isBranch; /*!< true if instruction acts like a 'jump' */ 138 | bool isCall; /*!< true if instruction acts like a 'call' */ 139 | bool isReturn; /*!< true if instruction acts like a 'return' */ 140 | bool isCompare; /*!< true if instruction is a comparison */ 141 | bool isPredicable; /*!< true if instruction contains a predicate 142 | * (~is conditional) 143 | */ 144 | bool isMoveImm; /*!< true if this instruction is a move immediate 145 | * (including conditional moves) instruction. 146 | */ 147 | bool mayLoad; /*!< true if QBDI detects a load for this instruction */ 148 | bool mayStore; /*!< true if QBDI detects a store for this instruction */ 149 | uint32_t loadSize; /*!< size of the expected read access, 150 | * may be 0 with mayLoad if the size isn't 151 | * determined 152 | */ 153 | uint32_t storeSize; /*!< size of the expected write access, 154 | * may be 0 with mayStore if the size isn't 155 | * determined 156 | */ 157 | ConditionType condition; /*!< Condition associated with the instruction */ 158 | bool mayLoad_LLVM; // mayLoad of 0.7.1 159 | bool mayStore_LLVM; // mayStore of 0.7.1 160 | // ANALYSIS_DISASSEMBLY 161 | char *disassembly; /*!< Instruction disassembly 162 | * (warning: NULL if !ANALYSIS_DISASSEMBLY) */ 163 | // ANALYSIS_OPERANDS 164 | RegisterAccessType flagsAccess; /*!< Flag access type (noaccess, r, w, rw) 165 | * (warning: REGISTER_UNUSED if 166 | * !ANALYSIS_OPERANDS) 167 | */ 168 | uint8_t numOperands; /*!< Number of operands used by the 169 | * instruction 170 | */ 171 | OperandAnalysis *operands; /*!< Structure containing analysis results 172 | * of an operand provided by the VM. 173 | * (warning: NULL if !ANALYSIS_OPERANDS) */ 174 | // ANALYSIS_SYMBOL 175 | const char *symbol; /*!< Instruction symbol 176 | * (warning: NULL if !ANALYSIS_SYMBOL or not found) 177 | */ 178 | uint32_t symbolOffset; /*!< Instruction symbol offset */ 179 | const char *module; /*!< Instruction module name 180 | * (warning: NULL if !ANALYSIS_SYMBOL or not found) 181 | */ 182 | // INTERNAL 183 | uint32_t analysisType; /*!< INTERNAL: Instruction analysis type 184 | * (this should NOT be used) 185 | */ 186 | } InstAnalysis; 187 | 188 | #ifdef __cplusplus 189 | } 190 | #endif 191 | 192 | #endif // QBDI_INSTANALYSIS_H_ 193 | -------------------------------------------------------------------------------- /nativelib/src/main/cpp/qdbi-arm64/include/QBDI/Logs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of QBDI. 3 | * 4 | * Copyright 2017 - 2023 Quarkslab 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | #ifndef QBDI_LOGS_H_ 19 | #define QBDI_LOGS_H_ 20 | 21 | #include 22 | #include "QBDI/Platform.h" 23 | 24 | #ifdef __cplusplus 25 | #include 26 | #endif 27 | 28 | #ifdef __cplusplus 29 | namespace QBDI { 30 | extern "C" { 31 | #endif 32 | 33 | /*! Each log has a priority (or level) which can be used to control verbosity. 34 | * In production builds, only Warning and Error logs are kept. 35 | */ 36 | typedef enum { 37 | _QBDI_EI(DEBUG) = 0, /*!< Debug logs */ 38 | _QBDI_EI(INFO), /*!< Info logs (default) */ 39 | _QBDI_EI(WARNING), /*!< Warning logs */ 40 | _QBDI_EI(ERROR), /*!< Error logs */ 41 | _QBDI_EI(DISABLE) = 0xff, /*!< Disable logs message */ 42 | } LogPriority; 43 | 44 | /*! Redirect logs to a file. 45 | * 46 | * @param[in] filename the path of the file to append the log 47 | * @param[in] truncate Set to true to clear the file before append the log 48 | */ 49 | QBDI_EXPORT void qbdi_setLogFile(const char *filename, bool truncate); 50 | 51 | /*! Write log to the console (stderr) 52 | */ 53 | QBDI_EXPORT void qbdi_setLogConsole(); 54 | 55 | /*! Write log to the default location (stderr for linux, android_logger for 56 | * android) 57 | */ 58 | QBDI_EXPORT void qbdi_setLogDefault(); 59 | 60 | /*! Enable logs matching priority. 61 | * 62 | * @param[in] priority Filter logs with greater or equal priority. 63 | */ 64 | QBDI_EXPORT void qbdi_setLogPriority(LogPriority priority); 65 | 66 | #ifdef __cplusplus 67 | 68 | /* 69 | * C API C++ bindings 70 | */ 71 | 72 | /*! Redirect logs to a file. 73 | * 74 | * @param[in] filename the path of the file to append the log 75 | * @param[in] truncate Set to true to clear the file before append the log 76 | */ 77 | QBDI_EXPORT void setLogFile(const std::string &filename, bool truncate = false); 78 | 79 | /*! Enable logs matching priority. 80 | * 81 | * @param[in] priority Filter logs with greater or equal priority. 82 | */ 83 | inline void setLogPriority(LogPriority priority = LogPriority::INFO) { 84 | return qbdi_setLogPriority(priority); 85 | } 86 | 87 | /*! Write log to the console (stderr) 88 | */ 89 | inline void setLogConsole() { return qbdi_setLogConsole(); } 90 | 91 | /*! Write log to the default location (stderr for linux, android_logger for 92 | * android) 93 | */ 94 | inline void setLogDefault() { return qbdi_setLogDefault(); } 95 | 96 | } // "C" 97 | 98 | } // QBDI:: 99 | #endif 100 | 101 | #endif // QBDI_LOGS_H_ 102 | -------------------------------------------------------------------------------- /nativelib/src/main/cpp/qdbi-arm64/include/QBDI/Memory.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of QBDI. 3 | * 4 | * Copyright 2017 - 2023 Quarkslab 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | #ifndef QBDI_MEMORY_H_ 19 | #define QBDI_MEMORY_H_ 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | #include "QBDI/Platform.h" 26 | #include "QBDI/State.h" 27 | 28 | #ifdef __cplusplus 29 | namespace QBDI { 30 | extern "C" { 31 | #endif 32 | 33 | /*! Memory access rights. 34 | */ 35 | typedef enum { 36 | QBDI_PF_NONE = 0, /*!< No access */ 37 | QBDI_PF_READ = 1, /*!< Read access */ 38 | QBDI_PF_WRITE = 2, /*!< Write access */ 39 | QBDI_PF_EXEC = 4 /*!< Execution access */ 40 | } qbdi_Permission; 41 | 42 | /*! Map of a memory area (region). 43 | */ 44 | typedef struct { 45 | rword start; /*!< Range start value. */ 46 | rword end; /*!< Range end value (always excluded). */ 47 | qbdi_Permission permission; /*!< Region access rights 48 | * (PF_READ, PF_WRITE, PF_EXEC). 49 | */ 50 | char *name; /*!< Region name or path (useful when a region 51 | * is mapping a module). 52 | */ 53 | } qbdi_MemoryMap; 54 | 55 | /*! Get a list of all the memory maps (regions) of a process. 56 | * 57 | * @param[in] pid The identifier of the process. 58 | * @param[in] full_path Return the full path of the module in name field 59 | * @param[out] size Will be set to the number of strings in the returned array. 60 | * 61 | * @return An array of MemoryMap object. 62 | */ 63 | QBDI_EXPORT qbdi_MemoryMap *qbdi_getRemoteProcessMaps(rword pid, bool full_path, 64 | size_t *size); 65 | 66 | /*! Get a list of all the memory maps (regions) of the current process. 67 | * 68 | * @param[in] full_path Return the full path of the module in name field 69 | * @param[out] size Will be set to the number of strings in the returned array. 70 | * 71 | * @return An array of MemoryMap object. 72 | */ 73 | QBDI_EXPORT qbdi_MemoryMap *qbdi_getCurrentProcessMaps(bool full_path, 74 | size_t *size); 75 | 76 | /*! Free an array of memory maps objects. 77 | * 78 | * @param[in] arr An array of MemoryMap object. 79 | * @param[in] size Number of elements in the array. 80 | */ 81 | QBDI_EXPORT void qbdi_freeMemoryMapArray(qbdi_MemoryMap *arr, size_t size); 82 | 83 | /*! Get a list of all the module names loaded in the process memory. 84 | * If no modules are found, size is set to 0 and this function returns NULL. 85 | * 86 | * @param[out] size Will be set to the number of strings in the returned 87 | * array. 88 | * 89 | * @return An array of C strings, each one containing the name of a loaded 90 | * module. This array needs to be free'd by the caller by repetively 91 | * calling free() on each of its element then finally on the array 92 | * itself. 93 | */ 94 | QBDI_EXPORT char **qbdi_getModuleNames(size_t *size); 95 | 96 | /*! Allocate a block of memory of a specified sized with an aligned base 97 | * address. 98 | * 99 | * @param[in] size Allocation size in bytes. 100 | * @param[in] align Base address alignement in bytes. 101 | * 102 | * @return Pointer to the allocated memory or NULL in case an error was 103 | * encountered. 104 | * 105 | */ 106 | QBDI_EXPORT void *qbdi_alignedAlloc(size_t size, size_t align); 107 | 108 | /*! Free a block of aligned memory allocated with alignedAlloc. 109 | * 110 | * @param[in] ptr Pointer to the allocated memory. 111 | * 112 | */ 113 | QBDI_EXPORT void qbdi_alignedFree(void *ptr); 114 | 115 | /*! Allocate a new stack and setup the GPRState accordingly. 116 | * The allocated stack needs to be freed with alignedFree(). 117 | * 118 | * @param[in] ctx GPRState which will be setup to use the new stack. 119 | * @param[in] stackSize Size of the stack to be allocated. 120 | * @param[out] stack The newly allocated stack pointer will be returned 121 | * in the variable pointed by stack. 122 | * 123 | * @return True if stack allocation was successfull. 124 | */ 125 | QBDI_EXPORT bool qbdi_allocateVirtualStack(GPRState *ctx, uint32_t stackSize, 126 | uint8_t **stack); 127 | 128 | /*! Simulate a call by modifying the stack and registers accordingly. 129 | * 130 | * @param[in] ctx GPRState where the simulated call will be setup. 131 | * The state needs to point to a valid stack for 132 | * example setup with allocateVirtualStack(). 133 | * @param[in] returnAddress Return address of the call to simulate. 134 | * @param[in] argNum The number of arguments in the variadic list. 135 | * @param[in] ... A variadic list of arguments. 136 | */ 137 | QBDI_EXPORT void qbdi_simulateCall(GPRState *ctx, rword returnAddress, 138 | uint32_t argNum, ...); 139 | 140 | /*! Simulate a call by modifying the stack and registers accordingly 141 | * (stdarg version). 142 | * 143 | * @param[in] ctx GPRState where the simulated call will be setup. 144 | * The state needs to point to a valid stack 145 | * for example setup with allocateVirtualStack(). 146 | * @param[in] returnAddress Return address of the call to simulate. 147 | * @param[in] argNum The number of arguments in the va_list object. 148 | * @param[in] ap An stdarg va_list object. 149 | */ 150 | QBDI_EXPORT void qbdi_simulateCallV(GPRState *ctx, rword returnAddress, 151 | uint32_t argNum, va_list ap); 152 | 153 | /*! Simulate a call by modifying the stack and registers accordingly 154 | * (C array version). 155 | * 156 | * @param[in] ctx GPRState where the simulated call will be setup. 157 | * The state needs to point to a valid stack for 158 | * example setup with allocateVirtualStack(). 159 | * @param[in] returnAddress Return address of the call to simulate. 160 | * @param[in] argNum The number of arguments in the array args. 161 | * @param[in] args An array or arguments. 162 | */ 163 | QBDI_EXPORT void qbdi_simulateCallA(GPRState *ctx, rword returnAddress, 164 | uint32_t argNum, const rword *args); 165 | 166 | #ifdef __cplusplus 167 | } 168 | } 169 | #endif 170 | 171 | #endif // QBDI_MEMORY_H_ 172 | -------------------------------------------------------------------------------- /nativelib/src/main/cpp/qdbi-arm64/include/QBDI/Memory.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of QBDI. 3 | * 4 | * Copyright 2017 - 2023 Quarkslab 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | #ifndef QBDI_MEMORY_HPP_ 19 | #define QBDI_MEMORY_HPP_ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "QBDI/Bitmask.h" 28 | #include "QBDI/Platform.h" 29 | #include "QBDI/Range.h" 30 | #include "QBDI/State.h" 31 | 32 | namespace QBDI { 33 | 34 | /*! Memory access rights. 35 | */ 36 | typedef enum { 37 | PF_NONE = 0, /*!< No access */ 38 | PF_READ = 1, /*!< Read access */ 39 | PF_WRITE = 2, /*!< Write access */ 40 | PF_EXEC = 4 /*!< Execution access */ 41 | } Permission; 42 | 43 | _QBDI_ENABLE_BITMASK_OPERATORS(Permission) 44 | 45 | /*! Map of a memory area (region). 46 | */ 47 | struct MemoryMap { 48 | 49 | Range range; /*!< A range of memory (region), delimited between 50 | * a start and an (excluded) end address. 51 | */ 52 | Permission permission; /*!< Region access rights 53 | * (PF_READ, PF_WRITE, PF_EXEC). 54 | */ 55 | std::string name; /*!< Region name or path (useful when a region 56 | * is mapping a module). 57 | */ 58 | 59 | /* Construct a new (empty) MemoryMap. 60 | */ 61 | MemoryMap() : range(0, 0), permission(QBDI::PF_NONE){}; 62 | 63 | /*! Construct a new MemoryMap (given some properties). 64 | * 65 | * @param[in] start Range start value. 66 | * @param[in] end Range end value (always excluded). 67 | * @param[in] permission Region access rights (PF_READ, PF_WRITE, PF_EXEC). 68 | * @param[in] name Region name (useful when a region is mapping 69 | * a module). 70 | */ 71 | MemoryMap(rword start, rword end, Permission permission, std::string name) 72 | : range(start, end), permission(permission), name(name) {} 73 | 74 | /*! Construct a new MemoryMap (given some properties). 75 | * 76 | * @param[in] range A range of memory (region), delimited between 77 | * a start and an (excluded) end address. 78 | * @param[in] permission Region access rights (PF_READ, PF_WRITE, PF_EXEC). 79 | * @param[in] name Region name (useful when a region is mapping 80 | * a module). 81 | */ 82 | MemoryMap(Range range, Permission permission, std::string name) 83 | : range(range), permission(permission), name(name) {} 84 | }; 85 | 86 | /*! Get a list of all the memory maps (regions) of a process. 87 | * 88 | * @param[in] pid The identifier of the process. 89 | * @param[in] full_path Return the full path of the module in name field 90 | * 91 | * @return A vector of MemoryMap object. 92 | */ 93 | QBDI_EXPORT std::vector getRemoteProcessMaps(QBDI::rword pid, 94 | bool full_path = false); 95 | 96 | /*! Get a list of all the memory maps (regions) of the current process. 97 | * 98 | * @param[in] full_path Return the full path of the module in name field 99 | * @return A vector of MemoryMap object. 100 | */ 101 | QBDI_EXPORT std::vector 102 | getCurrentProcessMaps(bool full_path = false); 103 | 104 | /*! Get a list of all the module names loaded in the process memory. 105 | * 106 | * @return A vector of string of module names. 107 | */ 108 | QBDI_EXPORT std::vector getModuleNames(); 109 | 110 | /*! Allocate a block of memory of a specified sized with an aligned base 111 | * address. 112 | * 113 | * @param[in] size Allocation size in bytes. 114 | * @param[in] align Base address alignement in bytes. 115 | * 116 | * @return Pointer to the allocated memory or NULL in case an error was 117 | * encountered. 118 | * 119 | */ 120 | QBDI_EXPORT void *alignedAlloc(size_t size, size_t align); 121 | 122 | /*! Free a block of aligned memory allocated with alignedAlloc. 123 | * 124 | * @param[in] ptr Pointer to the allocated memory. 125 | * 126 | */ 127 | QBDI_EXPORT void alignedFree(void *ptr); 128 | 129 | /*! Allocate a new stack and setup the GPRState accordingly. 130 | * The allocated stack needs to be freed with alignedFree(). 131 | * 132 | * @param[in] ctx GPRState which will be setup to use the new stack. 133 | * @param[in] stackSize Size of the stack to be allocated. 134 | * @param[out] stack The newly allocated stack pointer will be returned in 135 | * the variable pointed by stack. 136 | * 137 | * @return True if stack allocation was successfull. 138 | */ 139 | QBDI_EXPORT bool allocateVirtualStack(GPRState *ctx, uint32_t stackSize, 140 | uint8_t **stack); 141 | 142 | /*! Simulate a call by modifying the stack and registers accordingly 143 | * (std::vector version). 144 | * 145 | * @param[in] ctx GPRState where the simulated call will be setup. 146 | * The state needs to point to a valid stack for 147 | * example setup with allocateVirtualStack(). 148 | * @param[in] returnAddress Return address of the call to simulate. 149 | * @param[in] args A list of arguments. 150 | */ 151 | QBDI_EXPORT void simulateCall(GPRState *ctx, rword returnAddress, 152 | const std::vector &args = {}); 153 | 154 | /*! Simulate a call by modifying the stack and registers accordingly 155 | * (stdarg version). 156 | * 157 | * @param[in] ctx GPRState where the simulated call will be setup. 158 | * The state needs to point to a valid stack for 159 | * example setup with allocateVirtualStack(). 160 | * @param[in] returnAddress Return address of the call to simulate. 161 | * @param[in] argNum The number of arguments in the va_list object. 162 | * @param[in] ap An stdarg va_list object. 163 | */ 164 | QBDI_EXPORT void simulateCallV(GPRState *ctx, rword returnAddress, 165 | uint32_t argNum, va_list ap); 166 | 167 | /*! Simulate a call by modifying the stack and registers accordingly 168 | * (C array version). 169 | * 170 | * @param[in] ctx GPRState where the simulated call will be setup. 171 | * The state needs to point to a valid stack for 172 | * example setup with allocateVirtualStack(). 173 | * @param[in] returnAddress Return address of the call to simulate. 174 | * @param[in] argNum The number of arguments in the array args. 175 | * @param[in] args An array or arguments. 176 | */ 177 | QBDI_EXPORT void simulateCallA(GPRState *ctx, rword returnAddress, 178 | uint32_t argNum, const rword *args); 179 | 180 | } // namespace QBDI 181 | 182 | #endif // QBDI_MEMORY_HPP_ 183 | -------------------------------------------------------------------------------- /nativelib/src/main/cpp/qdbi-arm64/include/QBDI/Options.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of QBDI. 3 | * 4 | * Copyright 2017 - 2023 Quarkslab 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | #ifndef QBDI_OPTION_AARCH64_H_ 19 | #define QBDI_OPTION_AARCH64_H_ 20 | 21 | #include 22 | 23 | #include "QBDI/Bitmask.h" 24 | #include "QBDI/Platform.h" 25 | 26 | #ifdef __cplusplus 27 | namespace QBDI { 28 | #endif 29 | 30 | typedef enum { 31 | _QBDI_EI(NO_OPT) = 0, /*!< Default value */ 32 | // general options between 0 and 23 33 | _QBDI_EI(OPT_DISABLE_FPR) = 1 << 0, /*!< Disable all operation on FPU 34 | * (SSE, AVX, SIMD). May break 35 | * the execution if the target 36 | * use the FPU 37 | */ 38 | _QBDI_EI(OPT_DISABLE_OPTIONAL_FPR) = 1 << 1, /*!< Disable context switch 39 | * optimisation when the target 40 | * execblock doesn't used FPR 41 | */ 42 | // architecture specific option between 24 and 31 43 | _QBDI_EI(OPT_DISABLE_LOCAL_MONITOR) = 44 | 1 << 24, /*!< Disable the local monitor for instruction like stxr */ 45 | _QBDI_EI(OPT_BYPASS_PAUTH) = 1 << 25, /*!< Disable pointeur authentication */ 46 | _QBDI_EI(OPT_ENABLE_BTI) = 1 << 26, /*!< Enable BTI on instrumented code*/ 47 | } Options; 48 | 49 | _QBDI_ENABLE_BITMASK_OPERATORS(Options) 50 | 51 | #ifdef __cplusplus 52 | } 53 | #endif 54 | 55 | #endif /* QBDI_OPTION_AARCH64_H_ */ 56 | -------------------------------------------------------------------------------- /nativelib/src/main/cpp/qdbi-arm64/include/QBDI/Platform.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of QBDI. 3 | * 4 | * Copyright 2017 - 2023 Quarkslab 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | #ifndef QBDI_PLATFORM_H_ 19 | #define QBDI_PLATFORM_H_ 20 | 21 | #include "QBDI/Config.h" 22 | 23 | #ifdef QBDI_PLATFORM_WINDOWS 24 | #define QBDI_ALIGNED(n) __declspec(align(n)) 25 | #define QBDI_NOINLINE __declspec(noinline) 26 | #define QBDI_NOSTACKPROTECTOR 27 | #define _QBDI_FORCE_USE 28 | #define _QBDI_UNREACHABLE() __assume(0) 29 | #define QBDI_DISABLE_ASAN __declspec(no_sanitize_address) 30 | #define QBDI_FORCE_EXPORT __declspec(dllexport) 31 | #else 32 | #define QBDI_ALIGNED(n) __attribute__((aligned(n))) 33 | #define QBDI_NOINLINE __attribute__((noinline)) 34 | #define QBDI_NOSTACKPROTECTOR __attribute__((no_stack_protector)) 35 | #define _QBDI_FORCE_USE __attribute__((__used__)) 36 | #define _QBDI_UNREACHABLE() __builtin_unreachable() 37 | #define QBDI_DISABLE_ASAN __attribute__((no_sanitize_address)) 38 | #define QBDI_FORCE_EXPORT __attribute__((visibility("default"))) 39 | #endif 40 | 41 | #ifdef QBDI_EXPORT_SYM 42 | #define QBDI_EXPORT QBDI_FORCE_EXPORT 43 | #else 44 | #define QBDI_EXPORT 45 | #endif 46 | 47 | #if defined(__has_feature) 48 | #if __has_feature(address_sanitizer) 49 | #define _QBDI_ASAN_ENABLED_ 50 | #endif 51 | #endif 52 | 53 | #ifdef __cplusplus 54 | #define _QBDI_EI(X) X 55 | #else 56 | #define _QBDI_EI(X) QBDI_##X 57 | #endif 58 | 59 | #endif // QBDI_PLATFORM_H_ 60 | -------------------------------------------------------------------------------- /nativelib/src/main/cpp/qdbi-arm64/include/QBDI/Range.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of QBDI. 3 | * 4 | * Copyright 2017 - 2023 Quarkslab 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | #ifndef QBDI_RANGE_H_ 19 | #define QBDI_RANGE_H_ 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | namespace QBDI { 26 | template 27 | class Range { 28 | 29 | private: 30 | T min(const T a, const T b) const { return a < b ? a : b; } 31 | 32 | T max(const T a, const T b) const { return a > b ? a : b; } 33 | 34 | T _start; /*!< Range start value. */ 35 | T _end; /*!< Range end value (always excluded). */ 36 | 37 | public: 38 | inline T start() const { return _start; } 39 | inline T end() const { return _end; } 40 | inline void setStart(const T start) { 41 | _start = start; 42 | if (_end < _start) 43 | _end = _start; 44 | } 45 | inline void setEnd(const T end) { 46 | _end = end; 47 | if (_end < _start) 48 | _start = _end; 49 | } 50 | 51 | /*! Construct a new range. 52 | * @param[in] start Range start value. 53 | * @param[in] end Range end value (excluded). 54 | */ 55 | Range(const T start, const T end) { 56 | if (start < end) { 57 | this->_start = start; 58 | this->_end = end; 59 | } else { 60 | this->_end = this->_start = start; 61 | } 62 | } 63 | 64 | /*! Return the total length of a range. 65 | */ 66 | T size() const { return end() - start(); } 67 | 68 | /*! Return True if two ranges are equal (same boundaries). 69 | * 70 | * @param[in] r Range to check. 71 | * 72 | * @return True if equal. 73 | */ 74 | bool operator==(const Range &r) const { 75 | return r.start() == start() && r.end() == end(); 76 | } 77 | 78 | /*! Return True if an value is inside current range boundaries. 79 | * 80 | * @param[in] t Value to check. 81 | * 82 | * @return True if contained. 83 | */ 84 | bool contains(const T t) const { return (start() <= t) && (t < end()); } 85 | 86 | /*! Return True if a range is inside current range boundaries. 87 | * 88 | * @param[in] r Range to check. 89 | * 90 | * @return True if contained. 91 | */ 92 | bool contains(const Range &r) const { 93 | return (start() <= r.start()) && (r.end() <= end()); 94 | } 95 | 96 | /*! Return True if a range is overlapping current range lower 97 | * or/and upper boundary. 98 | * 99 | * @param[in] r Range to check. 100 | * 101 | * @return True if overlapping. 102 | */ 103 | bool overlaps(const Range &r) const { 104 | return start() < r.end() && r.start() < end(); 105 | } 106 | 107 | /*! Pretty print a range 108 | * 109 | * @param[in] os An output stream. 110 | */ 111 | void display(std::ostream &os) const { 112 | os << "(0x" << std::hex << start() << ", 0x" << end() << ")"; 113 | } 114 | 115 | /*! Return the intersection of two ranges. 116 | * 117 | * @param[in] r Range to intersect with current range. 118 | * 119 | * @return A new range. 120 | */ 121 | Range intersect(const Range &r) const { 122 | return Range(max(start(), r.start()), min(end(), r.end())); 123 | } 124 | }; 125 | 126 | template 127 | std::ostream &operator<<(std::ostream &os, const Range &obj) { 128 | obj.display(os); 129 | return os; 130 | } 131 | 132 | template 133 | class RangeSet { 134 | 135 | private: 136 | std::vector> ranges; 137 | 138 | public: 139 | RangeSet() {} 140 | 141 | const std::vector> &getRanges() const { return ranges; } 142 | 143 | T size() const { 144 | T sum = 0; 145 | for (const Range &r : ranges) { 146 | sum += r.size(); 147 | } 148 | return sum; 149 | } 150 | 151 | const Range *getElementRange(const T &t) const { 152 | auto lower = std::lower_bound( 153 | ranges.cbegin(), ranges.cend(), t, 154 | [](const Range &r, const T &value) { return r.end() <= value; }); 155 | if (lower == ranges.cend() || (!lower->contains(t))) { 156 | return nullptr; 157 | } else { 158 | return &*lower; 159 | } 160 | } 161 | 162 | bool contains(const T &t) const { return getElementRange(t) != nullptr; } 163 | 164 | bool contains(const Range &t) const { 165 | if (t.end() <= t.start()) { 166 | return true; 167 | } 168 | auto lower = std::lower_bound( 169 | ranges.cbegin(), ranges.cend(), t.start(), 170 | [](const Range &r, const T &value) { return r.end() <= value; }); 171 | if (lower == ranges.cend()) { 172 | return false; 173 | } else { 174 | return lower->contains(t); 175 | } 176 | } 177 | 178 | bool overlaps(const Range &t) const { 179 | if (t.end() <= t.start()) { 180 | return true; 181 | } 182 | auto lower = std::lower_bound( 183 | ranges.cbegin(), ranges.cend(), t.start(), 184 | [](const Range &r, const T &value) { return r.end() <= value; }); 185 | if (lower == ranges.cend()) { 186 | return false; 187 | } else { 188 | return lower->overlaps(t); 189 | } 190 | } 191 | 192 | void add(const Range &t) { 193 | // Exception for empty ranges 194 | if (t.end() <= t.start()) { 195 | return; 196 | } 197 | 198 | // Find lower element in sorted range list 199 | auto lower = std::lower_bound( 200 | ranges.begin(), ranges.end(), t.start(), 201 | [](const Range &r, const T &value) { return r.end() < value; }); 202 | 203 | // if no range match, push the new range at the end of the list 204 | if (lower == ranges.end()) { 205 | ranges.push_back(t); 206 | return; 207 | } 208 | 209 | // if t is strictly before lower, just insert it before lower 210 | if (t.end() < lower->start()) { 211 | ranges.insert(lower, t); 212 | return; 213 | } 214 | 215 | // lower and t either intersect, or t is right before lower 216 | // Extend the start of lower 217 | if (t.start() < lower->start()) { 218 | lower->setStart(t.start()); 219 | } 220 | // Extend the end of lower 221 | if (lower->end() < t.end()) { 222 | lower->setEnd(t.end()); 223 | } 224 | 225 | // we extend the end of lower, but we must verify that the new end isn't 226 | // overlapsed nested element 227 | auto endEraseList = lower + 1; 228 | while (endEraseList != ranges.end()) { 229 | if (lower->end() < endEraseList->start()) { 230 | break; 231 | } 232 | if (lower->end() < endEraseList->end()) { 233 | lower->setEnd(endEraseList->end()); 234 | } 235 | endEraseList++; 236 | } 237 | ranges.erase(lower + 1, endEraseList); 238 | } 239 | 240 | void add(const RangeSet &t) { 241 | for (const Range &r : t.ranges) { 242 | add(r); 243 | } 244 | } 245 | 246 | void remove(const Range &t) { 247 | // Exception for empty ranges 248 | if (t.end() <= t.start()) { 249 | return; 250 | } 251 | 252 | // Find lower element in sorted range list 253 | auto lower = std::lower_bound( 254 | ranges.begin(), ranges.end(), t.start(), 255 | [](const Range &r, const T &value) { return r.end() <= value; }); 256 | 257 | // if no range match, do nothing 258 | if (lower == ranges.end()) { 259 | return; 260 | } 261 | 262 | // if t is before lower, do nothing 263 | if (t.end() <= lower->start()) { 264 | return; 265 | } 266 | // lower and t intersect 267 | 268 | // managed case where t begin inside a range 269 | if (lower->start() < t.start()) { 270 | 271 | if (t.end() < lower->end()) { 272 | // t is a part of lower, but with extra both at the start and the end 273 | // -> split lower in two 274 | Range preRange = {lower->start(), t.start()}; 275 | lower->setStart(t.end()); 276 | ranges.insert(lower, preRange); 277 | return; 278 | } 279 | 280 | // lower begins before t, but end inside t (or has the same end). 281 | // => reduce lower 282 | lower->setEnd(t.start()); 283 | 284 | // lower is not longuer inside t, go to the next element; 285 | lower++; 286 | } 287 | 288 | // Erase all range that are inside t 289 | auto beginEraseList = lower; 290 | while (lower != ranges.end()) { 291 | // lower is after t, exit 292 | if (t.end() <= lower->start()) { 293 | break; 294 | } 295 | 296 | // lower overlaps t but the end 297 | if (t.end() < lower->end()) { 298 | lower->setStart(t.end()); 299 | break; 300 | } 301 | 302 | // lower is included in t, erase it at the end 303 | lower++; 304 | } 305 | ranges.erase(beginEraseList, lower); 306 | } 307 | 308 | void remove(const RangeSet &t) { 309 | for (const Range &r : t.ranges) { 310 | remove(r); 311 | } 312 | } 313 | 314 | void intersect(const RangeSet &t) { 315 | RangeSet intersected; 316 | auto itThis = ranges.cbegin(); 317 | auto itOther = t.ranges.cbegin(); 318 | while (itThis != ranges.cend() && itOther != t.ranges.cend()) { 319 | if (itThis->overlaps(*itOther)) { 320 | intersected.add(itThis->intersect(*itOther)); 321 | } 322 | // select the iterator to step 323 | if (itThis->end() < itOther->end()) { 324 | itThis++; 325 | } else if (itThis->end() == itOther->end()) { 326 | itThis++; 327 | itOther++; 328 | } else { 329 | itOther++; 330 | } 331 | } 332 | ranges.swap(intersected.ranges); 333 | } 334 | 335 | void intersect(const Range &t) { 336 | auto lower = std::lower_bound( 337 | ranges.cbegin(), ranges.cend(), t.start(), 338 | [](const Range &r, const T &value) { return r.end() <= value; }); 339 | 340 | if (lower == ranges.cend()) { 341 | clear(); 342 | return; 343 | } 344 | 345 | RangeSet intersected; 346 | while (lower != ranges.cend() && t.overlaps(*lower)) { 347 | intersected.add(t.intersect(*lower)); 348 | lower++; 349 | } 350 | 351 | ranges.swap(intersected.ranges); 352 | } 353 | 354 | void clear() { ranges.clear(); } 355 | 356 | void display(std::ostream &os) const { 357 | os << "["; 358 | for (const Range &r : ranges) { 359 | r.display(os); 360 | os << ", "; 361 | } 362 | os << "]"; 363 | } 364 | 365 | bool operator==(const RangeSet &r) const { 366 | const std::vector> &ranges = r.ranges; 367 | 368 | if (this->ranges.size() != ranges.size()) { 369 | return false; 370 | } 371 | 372 | for (size_t i = 0; i < ranges.size(); i++) { 373 | if (!(this->ranges[i] == ranges[i])) { 374 | return false; 375 | } 376 | } 377 | 378 | return true; 379 | } 380 | }; 381 | 382 | template 383 | std::ostream &operator<<(std::ostream &os, const RangeSet &obj) { 384 | obj.display(os); 385 | return os; 386 | } 387 | 388 | } // namespace QBDI 389 | 390 | #endif // QBDI_RANGE_H_ 391 | -------------------------------------------------------------------------------- /nativelib/src/main/cpp/qdbi-arm64/include/QBDI/State.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of QBDI. 3 | * 4 | * Copyright 2017 - 2023 Quarkslab 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | #ifndef QBDI_STATE_AARCH64_H_ 19 | #define QBDI_STATE_AARCH64_H_ 20 | 21 | #ifdef __cplusplus 22 | #include 23 | #endif 24 | #include 25 | #include 26 | #include "QBDI/Platform.h" 27 | 28 | // ============================================================================ 29 | // AARCH64 Context 30 | // ============================================================================ 31 | 32 | #define PRIRWORD PRIx64 33 | 34 | #define QBDI_NUM_FPR 32 35 | 36 | #ifdef __cplusplus 37 | namespace QBDI { 38 | #endif // __cplusplus 39 | 40 | /*! ARM CPU modes. 41 | */ 42 | typedef enum { AARCH64 = 0, DEFAULT = 0, COUNT } CPUMode; 43 | 44 | typedef uint64_t rword; 45 | typedef int64_t sword; 46 | 47 | // SPHINX_AARCH64_FPRSTATE_BEGIN 48 | /*! ARM Floating Point Register context. 49 | */ 50 | typedef struct QBDI_ALIGNED(8) { 51 | __uint128_t v0; 52 | __uint128_t v1; 53 | __uint128_t v2; 54 | __uint128_t v3; 55 | 56 | __uint128_t v4; 57 | __uint128_t v5; 58 | __uint128_t v6; 59 | __uint128_t v7; 60 | 61 | __uint128_t v8; 62 | __uint128_t v9; 63 | __uint128_t v10; 64 | __uint128_t v11; 65 | 66 | __uint128_t v12; 67 | __uint128_t v13; 68 | __uint128_t v14; 69 | __uint128_t v15; 70 | 71 | __uint128_t v16; 72 | __uint128_t v17; 73 | __uint128_t v18; 74 | __uint128_t v19; 75 | 76 | __uint128_t v20; 77 | __uint128_t v21; 78 | __uint128_t v22; 79 | __uint128_t v23; 80 | 81 | __uint128_t v24; 82 | __uint128_t v25; 83 | __uint128_t v26; 84 | __uint128_t v27; 85 | 86 | __uint128_t v28; 87 | __uint128_t v29; 88 | __uint128_t v30; 89 | __uint128_t v31; 90 | 91 | rword fpcr; 92 | rword fpsr; 93 | } FPRState; 94 | // SPHINX_AARCH64_FPRSTATE_END 95 | 96 | // SPHINX_AARCH64_GPRSTATE_BEGIN 97 | /*! ARM General Purpose Register context. 98 | */ 99 | typedef struct QBDI_ALIGNED(8) { 100 | rword x0; 101 | rword x1; 102 | rword x2; 103 | rword x3; 104 | rword x4; 105 | rword x5; 106 | rword x6; 107 | rword x7; 108 | rword x8; 109 | rword x9; 110 | rword x10; 111 | rword x11; 112 | rword x12; 113 | rword x13; 114 | rword x14; 115 | rword x15; 116 | rword x16; 117 | rword x17; 118 | rword x18; 119 | rword x19; 120 | rword x20; 121 | rword x21; 122 | rword x22; 123 | rword x23; 124 | rword x24; 125 | rword x25; 126 | rword x26; 127 | rword x27; 128 | rword x28; 129 | rword x29; // FP (x29) 130 | rword lr; // LR (x30) 131 | 132 | rword sp; 133 | rword nzcv; 134 | rword pc; 135 | // ? rword daif; ? 136 | 137 | /* Internal CPU state 138 | * Local monitor state for exclusive load/store instruction 139 | */ 140 | struct { 141 | rword addr; 142 | rword enable; /* 0=>disable, 1=>exclusive state, use a rword to not break 143 | align */ 144 | } localMonitor; 145 | 146 | } GPRState; 147 | // SPHINX_AARCH64_GPRSTATE_END 148 | 149 | static const char *const GPR_NAMES[] = { 150 | "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", 151 | "X10", "X11", "X12", "X13", "X14", "X15", "X16", "X17", "X18", "X19", 152 | "X20", "X21", "X22", "X23", "X24", "X25", "X26", "X27", "X28", 153 | "X29", // FP 154 | "LR", 155 | 156 | "SP", "NZCV", "PC", 157 | }; 158 | 159 | static const unsigned int NUM_GPR = 32; 160 | static const unsigned int AVAILABLE_GPR = 28; 161 | static const unsigned int REG_RETURN = 0; 162 | static const unsigned int REG_BP = 29; 163 | static const unsigned int REG_LR = 30; 164 | static const unsigned int REG_SP = 31; 165 | static const unsigned int REG_PC = 33; 166 | static const unsigned int REG_FLAG = 32; 167 | 168 | #ifdef __cplusplus 169 | #define QBDI_GPR_GET(state, i) (reinterpret_cast(state)[i]) 170 | #define QBDI_GPR_SET(state, i, v) \ 171 | (reinterpret_cast(state)[i] = v) 172 | #else 173 | #define QBDI_GPR_GET(state, i) (((rword *)state)[i]) 174 | #define QBDI_GPR_SET(state, i, v) (((rword *)state)[i] = v) 175 | #endif 176 | 177 | #ifdef __cplusplus 178 | } // namespace QBDI 179 | #endif // __cplusplus 180 | 181 | #endif // QBDI_STATE_AARCH64_H_ 182 | -------------------------------------------------------------------------------- /nativelib/src/main/cpp/qdbi-arm64/include/QBDI/VM_C.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of QBDI. 3 | * 4 | * Copyright 2017 - 2023 Quarkslab 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | #ifndef QBDI_VM_C_H_ 19 | #define QBDI_VM_C_H_ 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | #include "QBDI/Callback.h" 26 | #include "QBDI/Errors.h" 27 | #include "QBDI/InstAnalysis.h" 28 | #include "QBDI/Options.h" 29 | #include "QBDI/Platform.h" 30 | #include "QBDI/State.h" 31 | 32 | #ifdef __cplusplus 33 | namespace QBDI { 34 | extern "C" { 35 | #endif 36 | 37 | /*! Create and initialize a VM instance. 38 | * 39 | * @param[out] instance VM instance created. 40 | * @param[in] cpu A C string naming the CPU model to use. 41 | * If NULL, the default architecture CPU model is used 42 | * (see LLVM documentation for more details). 43 | * @param[in] mattrs A NULL terminated array of C strings specifying the 44 | * attributes of the cpu model. 45 | * If NULL, no additional features are specified. 46 | * @param[in] opts The options to enable in the VM 47 | */ 48 | QBDI_EXPORT void qbdi_initVM(VMInstanceRef *instance, const char *cpu, 49 | const char **mattrs, Options opts); 50 | 51 | /*! Destroy an instance of VM. 52 | * This method mustn't be called when the VM runs. 53 | * 54 | * @param[in] instance VM instance. 55 | */ 56 | QBDI_EXPORT void qbdi_terminateVM(VMInstanceRef instance); 57 | 58 | /*! Add an address range to the set of instrumented address ranges. 59 | * 60 | * @param[in] instance VM instance. 61 | * @param[in] start Start address of the range (included). 62 | * @param[in] end End address of the range (excluded). 63 | */ 64 | QBDI_EXPORT void qbdi_addInstrumentedRange(VMInstanceRef instance, rword start, 65 | rword end); 66 | 67 | /*! Add the executable address ranges of a module to the set of instrumented 68 | * address ranges. 69 | * 70 | * @param[in] instance VM instance. 71 | * @param[in] name The module's name. 72 | * 73 | * @return True if at least one range was added to the instrumented ranges. 74 | */ 75 | QBDI_EXPORT bool qbdi_addInstrumentedModule(VMInstanceRef instance, 76 | const char *name); 77 | 78 | /*! Add the executable address ranges of a module to the set of instrumented 79 | * address ranges using an address belonging to the module. 80 | * 81 | * @param[in] instance VM instance. 82 | * @param[in] addr An address contained by module's range. 83 | * 84 | * @return True if at least one range was added to the instrumented ranges. 85 | */ 86 | QBDI_EXPORT bool qbdi_addInstrumentedModuleFromAddr(VMInstanceRef instance, 87 | rword addr); 88 | 89 | /*! Adds all the executable memory maps to the instrumented range set. 90 | * 91 | * @param[in] instance VM instance. 92 | * 93 | * @return True if at least one range was added to the instrumented ranges. 94 | */ 95 | QBDI_EXPORT bool qbdi_instrumentAllExecutableMaps(VMInstanceRef instance); 96 | 97 | /*! Remove an address range from the set of instrumented address ranges. 98 | * 99 | * @param[in] instance VM instance. 100 | * @param[in] start Start address of the range (included). 101 | * @param[in] end End address of the range (excluded). 102 | */ 103 | QBDI_EXPORT void qbdi_removeInstrumentedRange(VMInstanceRef instance, 104 | rword start, rword end); 105 | 106 | /*! Remove the executable address ranges of a module from the set of 107 | * instrumented address ranges. 108 | * 109 | * @param[in] instance VM instance. 110 | * @param[in] name The module's name. 111 | * 112 | * @return True if at least one range was removed from the instrumented ranges. 113 | */ 114 | QBDI_EXPORT bool qbdi_removeInstrumentedModule(VMInstanceRef instance, 115 | const char *name); 116 | 117 | /*! Remove the executable address ranges of a module from the set of 118 | * instrumented address ranges using an address belonging to the module. 119 | * 120 | * @param[in] instance VM instance. 121 | * @param[in] addr An address contained by module's range. 122 | * 123 | * @return True if at least one range was removed from the instrumented ranges. 124 | */ 125 | QBDI_EXPORT bool qbdi_removeInstrumentedModuleFromAddr(VMInstanceRef instance, 126 | rword addr); 127 | 128 | /*! Remove all instrumented ranges. 129 | * 130 | * @param[in] instance VM instance. 131 | */ 132 | QBDI_EXPORT void qbdi_removeAllInstrumentedRanges(VMInstanceRef instance); 133 | 134 | /*! Start the execution by the DBI from a given address (and stop when another 135 | * is reached). This method mustn't be called when the VM already runs. 136 | * 137 | * @param[in] instance VM instance. 138 | * @param[in] start Address of the first instruction to execute. 139 | * @param[in] stop Stop the execution when this instruction is reached. 140 | * 141 | * @return True if at least one block has been executed. 142 | */ 143 | QBDI_EXPORT bool qbdi_run(VMInstanceRef instance, rword start, rword stop); 144 | 145 | /*! Call a function using the DBI (and its current state). 146 | * This method mustn't be called when the VM already runs. 147 | * 148 | * @param[in] instance VM instance. 149 | * @param[in] [retval] Pointer to the returned value (optional). 150 | * @param[in] function Address of the function start instruction. 151 | * @param[in] argNum The number of arguments in the variadic list. 152 | * @param[in] ... A variadic list of arguments. 153 | * 154 | * @return True if at least one block has been executed. 155 | * 156 | * @details Example: 157 | * 158 | * // perform (with QBDI) a call similar to (*funcPtr)(42); 159 | * uint8_t *fakestack = NULL; 160 | * VMInstanceRef vm; 161 | * qbdi_initVM(&vm, NULL, NULL); 162 | * GPRState* gprState = qbdi_getGPRState(vm); 163 | * qbdi_allocateVirtualStack(gprState, 0x1000000, &fakestack); 164 | * qbdi_addInstrumentedModuleFromAddr(vm, funcPtr); 165 | * rword retVal; 166 | * qbdi_call(vm, &retVal, funcPtr, 1, 42); 167 | * 168 | */ 169 | QBDI_EXPORT bool qbdi_call(VMInstanceRef instance, rword *retval, 170 | rword function, uint32_t argNum, ...); 171 | 172 | /*! Call a function using the DBI (and its current state). 173 | * This method mustn't be called when the VM already runs. 174 | * 175 | * @param[in] instance VM instance. 176 | * @param[in] [retval] Pointer to the returned value (optional). 177 | * @param[in] function Address of the function start instruction. 178 | * @param[in] argNum The number of arguments in the variadic list. 179 | * @param[in] ap An stdarg va_list object. 180 | * 181 | * @return True if at least one block has been executed. 182 | */ 183 | QBDI_EXPORT bool qbdi_callV(VMInstanceRef instance, rword *retval, 184 | rword function, uint32_t argNum, va_list ap); 185 | 186 | /*! Call a function using the DBI (and its current state). 187 | * This method mustn't be called when the VM already runs. 188 | * 189 | * @param[in] instance VM instance. 190 | * @param[in] [retval] Pointer to the returned value (optional). 191 | * @param[in] function Address of the function start instruction. 192 | * @param[in] argNum The number of arguments in the variadic list. 193 | * @param[in] args Arguments as an array of rword values. 194 | * 195 | * @return True if at least one block has been executed. 196 | */ 197 | QBDI_EXPORT bool qbdi_callA(VMInstanceRef instance, rword *retval, 198 | rword function, uint32_t argNum, const rword *args); 199 | 200 | /*! Obtain the current general purpose register state. 201 | * 202 | * @param[in] instance VM instance. 203 | * 204 | * @return A structure containing the General Purpose Registers state. 205 | */ 206 | QBDI_EXPORT GPRState *qbdi_getGPRState(VMInstanceRef instance); 207 | 208 | /*! Obtain the current floating point register state. 209 | * 210 | * @param[in] instance VM instance. 211 | * 212 | * @return A structure containing the Floating Point Registers state. 213 | */ 214 | QBDI_EXPORT FPRState *qbdi_getFPRState(VMInstanceRef instance); 215 | 216 | /*! Set the GPR state 217 | * 218 | * @param[in] instance VM instance. 219 | * @param[in] gprState A structure containing the General Purpose Registers 220 | * state. 221 | */ 222 | QBDI_EXPORT void qbdi_setGPRState(VMInstanceRef instance, GPRState *gprState); 223 | 224 | /*! Set the FPR state 225 | * 226 | * @param[in] instance VM instance. 227 | * @param[in] fprState A structure containing the Floating Point Registers 228 | * state. 229 | */ 230 | QBDI_EXPORT void qbdi_setFPRState(VMInstanceRef instance, FPRState *fprState); 231 | 232 | /*! Get the current Options 233 | * 234 | * @param[in] instance VM instance. 235 | * 236 | * @return The current options of the VM 237 | */ 238 | QBDI_EXPORT Options qbdi_getOptions(VMInstanceRef instance); 239 | 240 | /*! Set the Options 241 | * This method mustn't be called when the VM runs. 242 | * 243 | * @param[in] instance VM instance. 244 | * @param[in] options The new options of the VM. 245 | */ 246 | QBDI_EXPORT void qbdi_setOptions(VMInstanceRef instance, Options options); 247 | 248 | /*! Add a custom instrumentation rule to the VM. 249 | * 250 | * @param[in] instance VM instance. 251 | * @param[in] cbk A function pointer to the callback 252 | * @param[in] type Analyse type needed for this instruction function 253 | * pointer to the callback 254 | * @param[in] data User defined data passed to the callback. 255 | * 256 | * @return The id of the registered instrumentation (or VMError::INVALID_EVENTID 257 | * in case of failure). 258 | */ 259 | QBDI_EXPORT uint32_t qbdi_addInstrRule(VMInstanceRef instance, 260 | InstrRuleCallbackC cbk, 261 | AnalysisType type, void *data); 262 | 263 | /*! Add a custom instrumentation rule to the VM for a range of address 264 | * 265 | * @param[in] instance VM instance. 266 | * @param[in] start Begin of the range of address where apply the rule 267 | * @param[in] end End of the range of address where apply the rule 268 | * @param[in] cbk A function pointer to the callback 269 | * @param[in] type Analyse type needed for this instruction function 270 | * pointer to the callback 271 | * @param[in] data User defined data passed to the callback. 272 | * 273 | * @return The id of the registered instrumentation (or VMError::INVALID_EVENTID 274 | * in case of failure). 275 | */ 276 | QBDI_EXPORT uint32_t qbdi_addInstrRuleRange(VMInstanceRef instance, rword start, 277 | rword end, InstrRuleCallbackC cbk, 278 | AnalysisType type, void *data); 279 | 280 | /*! Add a callback for the current instruction 281 | * 282 | * @param[in] cbks InstrRuleDataVec given in argument 283 | * @param[in] position Relative position of the callback 284 | * (QBDI_PREINST / QBDI_POSTINST). 285 | * @param[in] cbk A function pointer to the callback 286 | * @param[in] data User defined data passed to the callback. 287 | * @param[in] priority Priority of the callback 288 | */ 289 | QBDI_EXPORT void qbdi_addInstrRuleData(InstrRuleDataVec cbks, 290 | InstPosition position, InstCallback cbk, 291 | void *data, int priority); 292 | 293 | /*! Register a callback event for every memory access matching the type bitfield 294 | * made by the instructions. 295 | * 296 | * @param[in] instance VM instance. 297 | * @param[in] type A mode bitfield: either QBDI_MEMORY_READ, 298 | * QBDI_MEMORY_WRITE or both (QBDI_MEMORY_READ_WRITE). 299 | * @param[in] cbk A function pointer to the callback. 300 | * @param[in] data User defined data passed to the callback. 301 | * @param[in] priority The priority of the callback. 302 | * 303 | * @return The id of the registered instrumentation (or QBDI_INVALID_EVENTID 304 | * in case of failure). 305 | */ 306 | QBDI_EXPORT uint32_t qbdi_addMemAccessCB(VMInstanceRef instance, 307 | MemoryAccessType type, 308 | InstCallback cbk, void *data, 309 | int priority); 310 | 311 | /*! Add a virtual callback which is triggered for any memory access at a 312 | * specific address matching the access type. Virtual callbacks are called via 313 | * callback forwarding by a gate callback triggered on every memory access. This 314 | * incurs a high performance cost. 315 | * 316 | * @param[in] instance VM instance. 317 | * @param[in] address Code address which will trigger the callback. 318 | * @param[in] type A mode bitfield: either QBDI_MEMORY_READ, 319 | * QBDI_MEMORY_WRITE or both (QBDI_MEMORY_READ_WRITE). 320 | * @param[in] cbk A function pointer to the callback. 321 | * @param[in] data User defined data passed to the callback. 322 | * 323 | * @return The id of the registered instrumentation (or QBDI_INVALID_EVENTID 324 | * in case of failure). 325 | */ 326 | QBDI_EXPORT uint32_t qbdi_addMemAddrCB(VMInstanceRef instance, rword address, 327 | MemoryAccessType type, InstCallback cbk, 328 | void *data); 329 | 330 | /*! Add a virtual callback which is triggered for any memory access in a 331 | * specific address range matching the access type. Virtual callbacks are called 332 | * via callback forwarding by a gate callback triggered on every memory access. 333 | * This incurs a high performance cost. 334 | * 335 | * @param[in] instance VM instance. 336 | * @param[in] start Start of the address range which will trigger the 337 | * callback. 338 | * @param[in] end End of the address range which will trigger the callback. 339 | * @param[in] type A mode bitfield: either QBDI_MEMORY_READ, 340 | * QBDI_MEMORY_WRITE or both (QBDI_MEMORY_READ_WRITE). 341 | * @param[in] cbk A function pointer to the callback. 342 | * @param[in] data User defined data passed to the callback. 343 | * 344 | * @return The id of the registered instrumentation (or QBDI_INVALID_EVENTID 345 | * in case of failure). 346 | */ 347 | QBDI_EXPORT uint32_t qbdi_addMemRangeCB(VMInstanceRef instance, rword start, 348 | rword end, MemoryAccessType type, 349 | InstCallback cbk, void *data); 350 | 351 | /*! Register a callback event if the instruction matches the mnemonic. 352 | * 353 | * @param[in] instance VM instance. 354 | * @param[in] mnemonic Mnemonic to match. 355 | * @param[in] pos Relative position of the event callback 356 | * (QBDI_PREINST / QBDI_POSTINST). 357 | * @param[in] cbk A function pointer to the callback. 358 | * @param[in] data User defined data passed to the callback. 359 | * @param[in] priority The priority of the callback. 360 | * 361 | * @return The id of the registered instrumentation (or QBDI_INVALID_EVENTID 362 | * in case of failure). 363 | */ 364 | QBDI_EXPORT uint32_t qbdi_addMnemonicCB(VMInstanceRef instance, 365 | const char *mnemonic, InstPosition pos, 366 | InstCallback cbk, void *data, 367 | int priority); 368 | 369 | /*! Register a callback event for a specific instruction event. 370 | * 371 | * @param[in] instance VM instance. 372 | * @param[in] pos Relative position of the event callback 373 | * (QBDI_PREINST / QBDI_POSTINST). 374 | * @param[in] cbk A function pointer to the callback. 375 | * @param[in] data User defined data passed to the callback. 376 | * @param[in] priority The priority of the callback. 377 | * 378 | * @return The id of the registered instrumentation (or QBDI_INVALID_EVENTID 379 | * in case of failure). 380 | */ 381 | QBDI_EXPORT uint32_t qbdi_addCodeCB(VMInstanceRef instance, InstPosition pos, 382 | InstCallback cbk, void *data, int priority); 383 | 384 | /*! Register a callback for when a specific address is executed. 385 | * 386 | * @param[in] instance VM instance. 387 | * @param[in] address Code address which will trigger the callback. 388 | * @param[in] pos Relative position of the callback 389 | * (QBDI_PREINST / QBDI_POSTINST). 390 | * @param[in] cbk A function pointer to the callback. 391 | * @param[in] data User defined data passed to the callback. 392 | * @param[in] priority The priority of the callback. 393 | * 394 | * @return The id of the registered instrumentation (or QBDI_INVALID_EVENTID 395 | * in case of failure). 396 | */ 397 | QBDI_EXPORT uint32_t qbdi_addCodeAddrCB(VMInstanceRef instance, rword address, 398 | InstPosition pos, InstCallback cbk, 399 | void *data, int priority); 400 | 401 | /*! Register a callback for when a specific address range is executed. 402 | * 403 | * @param[in] instance VM instance. 404 | * @param[in] start Start of the address range which will trigger the callback. 405 | * @param[in] end End of the address range which will trigger the callback. 406 | * @param[in] pos Relative position of the callback 407 | * (QBDI_PREINST / QBDI_POSTINST). 408 | * @param[in] cbk A function pointer to the callback. 409 | * @param[in] data User defined data passed to the callback. 410 | * @param[in] priority The priority of the callback. 411 | * 412 | * @return The id of the registered instrumentation (or QBDI_INVALID_EVENTID 413 | * in case of failure). 414 | */ 415 | QBDI_EXPORT uint32_t qbdi_addCodeRangeCB(VMInstanceRef instance, rword start, 416 | rword end, InstPosition pos, 417 | InstCallback cbk, void *data, 418 | int priority); 419 | 420 | /*! Register a callback event for a specific VM event. 421 | * 422 | * @param[in] instance VM instance. 423 | * @param[in] mask A mask of VM event type which will trigger the callback. 424 | * @param[in] cbk A function pointer to the callback. 425 | * @param[in] data User defined data passed to the callback. 426 | * 427 | * @return The id of the registered instrumentation (or QBDI_INVALID_EVENTID 428 | * in case of failure). 429 | */ 430 | QBDI_EXPORT uint32_t qbdi_addVMEventCB(VMInstanceRef instance, VMEvent mask, 431 | VMCallback cbk, void *data); 432 | 433 | /*! Remove an instrumentation. 434 | * 435 | * @param[in] instance VM instance. 436 | * @param[in] id The id of the instrumentation to remove. 437 | * 438 | * @return True if instrumentation has been removed. 439 | */ 440 | QBDI_EXPORT bool qbdi_deleteInstrumentation(VMInstanceRef instance, 441 | uint32_t id); 442 | 443 | /*! Remove all the registered instrumentations. 444 | * 445 | * @param[in] instance VM instance. 446 | */ 447 | QBDI_EXPORT void qbdi_deleteAllInstrumentations(VMInstanceRef instance); 448 | 449 | /*! Obtain the analysis of the current instruction. Analysis results are cached 450 | * in the VM. The validity of the returned pointer is only guaranteed until the 451 | * end of the callback, else a deepcopy of the structure is required. This 452 | * method must only be used in an InstCallback. 453 | * 454 | * @param[in] instance VM instance. 455 | * @param[in] type Properties to retrieve during analysis. 456 | * 457 | * @return A InstAnalysis structure containing the analysis result. 458 | */ 459 | QBDI_EXPORT const InstAnalysis * 460 | qbdi_getInstAnalysis(const VMInstanceRef instance, AnalysisType type); 461 | 462 | /*! Obtain the analysis of a cached instruction. Analysis results are cached in 463 | * the VM. The validity of the returned pointer is only guaranteed until the end 464 | * of the callback or a call to a noconst method of the VM instance. 465 | * 466 | * @param[in] instance VM instance. 467 | * @param[in] address The address of the instruction to analyse. 468 | * @param[in] type Properties to retrieve during analysis. 469 | * 470 | * @return A InstAnalysis structure containing the analysis result. 471 | * null if the instruction isn't in the cache. 472 | */ 473 | QBDI_EXPORT const InstAnalysis * 474 | qbdi_getCachedInstAnalysis(const VMInstanceRef instance, rword address, 475 | AnalysisType type); 476 | 477 | /*! Add instrumentation rules to log memory access using inline instrumentation 478 | and 479 | * instruction shadows. 480 | 481 | * @param[in] instance VM instance. 482 | * @param[in] type Memory mode bitfield to activate the logging for: 483 | * either QBDI_MEMORY_READ, QBDI_MEMORY_WRITE 484 | * or both (QBDI_MEMORY_READ_WRITE). 485 | * 486 | * @return True if inline memory logging is supported, False if not or in case 487 | of error. 488 | */ 489 | QBDI_EXPORT bool qbdi_recordMemoryAccess(VMInstanceRef instance, 490 | MemoryAccessType type); 491 | 492 | /*! Obtain the memory accesses made by the last executed instruction. 493 | * The method should be called in an InstCallback. 494 | * Return NULL and a size of 0 if the instruction made no memory access. 495 | * 496 | * @param[in] instance VM instance. 497 | * @param[out] size Will be set to the number of elements in the 498 | * returned array. 499 | * 500 | * @return An array of memory accesses made by the instruction. 501 | */ 502 | QBDI_EXPORT MemoryAccess *qbdi_getInstMemoryAccess(VMInstanceRef instance, 503 | size_t *size); 504 | 505 | /*! Obtain the memory accesses made by the last executed basic block. 506 | * The method should be called in a VMCallback with QBDI_SEQUENCE_EXIT. 507 | * Return NULL and a size of 0 if the basic block made no memory access. 508 | * 509 | * @param[in] instance VM instance. 510 | * @param[out] size Will be set to the number of elements in the 511 | * returned array. 512 | * 513 | * @return An array of memory accesses made by the basic block. 514 | */ 515 | QBDI_EXPORT MemoryAccess *qbdi_getBBMemoryAccess(VMInstanceRef instance, 516 | size_t *size); 517 | 518 | /*! Pre-cache a known basic block 519 | * This method mustn't be called when the VM runs. 520 | * 521 | * @param[in] instance VM instance. 522 | * @param[in] pc Start address of a basic block 523 | * 524 | * @return True if basic block has been inserted in cache. 525 | */ 526 | QBDI_EXPORT bool qbdi_precacheBasicBlock(VMInstanceRef instance, rword pc); 527 | 528 | /*! Clear a specific address range from the translation cache. 529 | * 530 | * @param[in] instance VM instance. 531 | * @param[in] start Start of the address range to clear from the cache. 532 | * @param[in] end End of the address range to clear from the cache. 533 | * 534 | */ 535 | QBDI_EXPORT void qbdi_clearCache(VMInstanceRef instance, rword start, 536 | rword end); 537 | 538 | /*! Clear the entire translation cache. 539 | * 540 | * @param[in] instance VM instance. 541 | */ 542 | QBDI_EXPORT void qbdi_clearAllCache(VMInstanceRef instance); 543 | 544 | #ifdef __cplusplus 545 | } // "C" 546 | } // QBDI:: 547 | #endif 548 | 549 | #endif // QBDI_VM_C_H_ 550 | -------------------------------------------------------------------------------- /nativelib/src/main/cpp/qdbi-arm64/include/QBDI/Version.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of QBDI. 3 | * 4 | * Copyright 2017 - 2023 Quarkslab 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | #ifndef QBDI_VERSION_H_ 19 | #define QBDI_VERSION_H_ 20 | 21 | #include 22 | #include "QBDI/Platform.h" 23 | 24 | #ifdef __cplusplus 25 | namespace QBDI { 26 | extern "C" { 27 | #endif 28 | 29 | #define QBDI_VERSION ((0 << 16 ) | \ 30 | (10 << 8 ) | \ 31 | (0 << 0 )) 32 | #define QBDI_VERSION_STRING "0.10.0" 33 | 34 | #define QBDI_VERSION_MAJOR 0 35 | #define QBDI_VERSION_MINOR 10 36 | #define QBDI_VERSION_PATCH 0 37 | #define QBDI_VERSION_DEV 0 38 | 39 | #define QBDI_ARCHITECTURE_STRING "AARCH64" 40 | #define QBDI_PLATFORM_STRING "android" 41 | 42 | /*! Return QBDI version. 43 | * 44 | * @param[out] version QBDI version encoded as an unsigned integer (0xMMmmpp). 45 | * @return QBDI version as a string (major.minor.patch). 46 | */ 47 | QBDI_EXPORT const char* qbdi_getVersion(uint32_t* version); 48 | 49 | #ifdef __cplusplus 50 | /*! Return QBDI version. 51 | * 52 | * @param[out] version QBDI version encoded as an unsigned integer (0xMMmmpp). 53 | * @return QBDI version as a string (major.minor.patch). 54 | */ 55 | inline const char* getVersion(uint32_t* version) { 56 | return qbdi_getVersion(version); 57 | } 58 | 59 | } // "C" 60 | } // QBDI:: 61 | #endif 62 | 63 | #endif // QBDI_VERSION_H_ 64 | -------------------------------------------------------------------------------- /nativelib/src/main/cpp/qdbi-arm64/lib/libQBDI.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FANGG3/DobbyWithQBDI/8a7abff6fd39c61d01e02f7a74704bab052b27d5/nativelib/src/main/cpp/qdbi-arm64/lib/libQBDI.a -------------------------------------------------------------------------------- /nativelib/src/main/cpp/qdbi-arm64/lib/libQBDI.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FANGG3/DobbyWithQBDI/8a7abff6fd39c61d01e02f7a74704bab052b27d5/nativelib/src/main/cpp/qdbi-arm64/lib/libQBDI.so -------------------------------------------------------------------------------- /nativelib/src/main/cpp/qdbi-arm64/libQBDI.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FANGG3/DobbyWithQBDI/8a7abff6fd39c61d01e02f7a74704bab052b27d5/nativelib/src/main/cpp/qdbi-arm64/libQBDI.so -------------------------------------------------------------------------------- /nativelib/src/main/cpp/qdbi-arm64/share/qbdiAARCH64/LICENSE.txt: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | QBDI package license 3 | ################################################################################ 4 | 5 | QBDI binaries and packages can be statically linked with the followed source: 6 | 7 | - QBDI under the Apache License v2.0 8 | - LLVM under the Apache License v2.0 with LLVM Exceptions 9 | https://releases.llvm.org/10.0.0/LICENSE.TXT 10 | - spdlog under the MIT License 11 | https://github.com/gabime/spdlog/blob/v1.x/LICENSE 12 | - fmtlib under the MIT License 13 | https://github.com/fmtlib/fmt/blob/master/LICENSE.rst 14 | - Catch2 under the Boost Software License 1.0 15 | https://github.com/catchorg/Catch2/blob/devel/LICENSE.txt 16 | - Pybind11 under a BSD-style license 17 | https://github.com/pybind/pybind11/blob/master/LICENSE 18 | - A sha256 implementation under GPLv3 / Apache License v2.0 19 | https://github.com/aguinet/sha256_literal#licensing 20 | 21 | ################################################################################ 22 | QBDI source code is under the Apache License v2.0 23 | ################################################################################ 24 | 25 | Apache License 26 | Version 2.0, January 2004 27 | http://www.apache.org/licenses/ 28 | 29 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 30 | 31 | 1. Definitions. 32 | 33 | "License" shall mean the terms and conditions for use, reproduction, 34 | and distribution as defined by Sections 1 through 9 of this document. 35 | 36 | "Licensor" shall mean the copyright owner or entity authorized by 37 | the copyright owner that is granting the License. 38 | 39 | "Legal Entity" shall mean the union of the acting entity and all 40 | other entities that control, are controlled by, or are under common 41 | control with that entity. For the purposes of this definition, 42 | "control" means (i) the power, direct or indirect, to cause the 43 | direction or management of such entity, whether by contract or 44 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 45 | outstanding shares, or (iii) beneficial ownership of such entity. 46 | 47 | "You" (or "Your") shall mean an individual or Legal Entity 48 | exercising permissions granted by this License. 49 | 50 | "Source" form shall mean the preferred form for making modifications, 51 | including but not limited to software source code, documentation 52 | source, and configuration files. 53 | 54 | "Object" form shall mean any form resulting from mechanical 55 | transformation or translation of a Source form, including but 56 | not limited to compiled object code, generated documentation, 57 | and conversions to other media types. 58 | 59 | "Work" shall mean the work of authorship, whether in Source or 60 | Object form, made available under the License, as indicated by a 61 | copyright notice that is included in or attached to the work 62 | (an example is provided in the Appendix below). 63 | 64 | "Derivative Works" shall mean any work, whether in Source or Object 65 | form, that is based on (or derived from) the Work and for which the 66 | editorial revisions, annotations, elaborations, or other modifications 67 | represent, as a whole, an original work of authorship. For the purposes 68 | of this License, Derivative Works shall not include works that remain 69 | separable from, or merely link (or bind by name) to the interfaces of, 70 | the Work and Derivative Works thereof. 71 | 72 | "Contribution" shall mean any work of authorship, including 73 | the original version of the Work and any modifications or additions 74 | to that Work or Derivative Works thereof, that is intentionally 75 | submitted to Licensor for inclusion in the Work by the copyright owner 76 | or by an individual or Legal Entity authorized to submit on behalf of 77 | the copyright owner. For the purposes of this definition, "submitted" 78 | means any form of electronic, verbal, or written communication sent 79 | to the Licensor or its representatives, including but not limited to 80 | communication on electronic mailing lists, source code control systems, 81 | and issue tracking systems that are managed by, or on behalf of, the 82 | Licensor for the purpose of discussing and improving the Work, but 83 | excluding communication that is conspicuously marked or otherwise 84 | designated in writing by the copyright owner as "Not a Contribution." 85 | 86 | "Contributor" shall mean Licensor and any individual or Legal Entity 87 | on behalf of whom a Contribution has been received by Licensor and 88 | subsequently incorporated within the Work. 89 | 90 | 2. Grant of Copyright License. Subject to the terms and conditions of 91 | this License, each Contributor hereby grants to You a perpetual, 92 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 93 | copyright license to reproduce, prepare Derivative Works of, 94 | publicly display, publicly perform, sublicense, and distribute the 95 | Work and such Derivative Works in Source or Object form. 96 | 97 | 3. Grant of Patent License. Subject to the terms and conditions of 98 | this License, each Contributor hereby grants to You a perpetual, 99 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 100 | (except as stated in this section) patent license to make, have made, 101 | use, offer to sell, sell, import, and otherwise transfer the Work, 102 | where such license applies only to those patent claims licensable 103 | by such Contributor that are necessarily infringed by their 104 | Contribution(s) alone or by combination of their Contribution(s) 105 | with the Work to which such Contribution(s) was submitted. If You 106 | institute patent litigation against any entity (including a 107 | cross-claim or counterclaim in a lawsuit) alleging that the Work 108 | or a Contribution incorporated within the Work constitutes direct 109 | or contributory patent infringement, then any patent licenses 110 | granted to You under this License for that Work shall terminate 111 | as of the date such litigation is filed. 112 | 113 | 4. Redistribution. You may reproduce and distribute copies of the 114 | Work or Derivative Works thereof in any medium, with or without 115 | modifications, and in Source or Object form, provided that You 116 | meet the following conditions: 117 | 118 | (a) You must give any other recipients of the Work or 119 | Derivative Works a copy of this License; and 120 | 121 | (b) You must cause any modified files to carry prominent notices 122 | stating that You changed the files; and 123 | 124 | (c) You must retain, in the Source form of any Derivative Works 125 | that You distribute, all copyright, patent, trademark, and 126 | attribution notices from the Source form of the Work, 127 | excluding those notices that do not pertain to any part of 128 | the Derivative Works; and 129 | 130 | (d) If the Work includes a "NOTICE" text file as part of its 131 | distribution, then any Derivative Works that You distribute must 132 | include a readable copy of the attribution notices contained 133 | within such NOTICE file, excluding those notices that do not 134 | pertain to any part of the Derivative Works, in at least one 135 | of the following places: within a NOTICE text file distributed 136 | as part of the Derivative Works; within the Source form or 137 | documentation, if provided along with the Derivative Works; or, 138 | within a display generated by the Derivative Works, if and 139 | wherever such third-party notices normally appear. The contents 140 | of the NOTICE file are for informational purposes only and 141 | do not modify the License. You may add Your own attribution 142 | notices within Derivative Works that You distribute, alongside 143 | or as an addendum to the NOTICE text from the Work, provided 144 | that such additional attribution notices cannot be construed 145 | as modifying the License. 146 | 147 | You may add Your own copyright statement to Your modifications and 148 | may provide additional or different license terms and conditions 149 | for use, reproduction, or distribution of Your modifications, or 150 | for any such Derivative Works as a whole, provided Your use, 151 | reproduction, and distribution of the Work otherwise complies with 152 | the conditions stated in this License. 153 | 154 | 5. Submission of Contributions. Unless You explicitly state otherwise, 155 | any Contribution intentionally submitted for inclusion in the Work 156 | by You to the Licensor shall be under the terms and conditions of 157 | this License, without any additional terms or conditions. 158 | Notwithstanding the above, nothing herein shall supersede or modify 159 | the terms of any separate license agreement you may have executed 160 | with Licensor regarding such Contributions. 161 | 162 | 6. Trademarks. This License does not grant permission to use the trade 163 | names, trademarks, service marks, or product names of the Licensor, 164 | except as required for reasonable and customary use in describing the 165 | origin of the Work and reproducing the content of the NOTICE file. 166 | 167 | 7. Disclaimer of Warranty. Unless required by applicable law or 168 | agreed to in writing, Licensor provides the Work (and each 169 | Contributor provides its Contributions) on an "AS IS" BASIS, 170 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 171 | implied, including, without limitation, any warranties or conditions 172 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 173 | PARTICULAR PURPOSE. You are solely responsible for determining the 174 | appropriateness of using or redistributing the Work and assume any 175 | risks associated with Your exercise of permissions under this License. 176 | 177 | 8. Limitation of Liability. In no event and under no legal theory, 178 | whether in tort (including negligence), contract, or otherwise, 179 | unless required by applicable law (such as deliberate and grossly 180 | negligent acts) or agreed to in writing, shall any Contributor be 181 | liable to You for damages, including any direct, indirect, special, 182 | incidental, or consequential damages of any character arising as a 183 | result of this License or out of the use or inability to use the 184 | Work (including but not limited to damages for loss of goodwill, 185 | work stoppage, computer failure or malfunction, or any and all 186 | other commercial damages or losses), even if such Contributor 187 | has been advised of the possibility of such damages. 188 | 189 | 9. Accepting Warranty or Additional Liability. While redistributing 190 | the Work or Derivative Works thereof, You may choose to offer, 191 | and charge a fee for, acceptance of support, warranty, indemnity, 192 | or other liability obligations and/or rights consistent with this 193 | License. However, in accepting such obligations, You may act only 194 | on Your own behalf and on Your sole responsibility, not on behalf 195 | of any other Contributor, and only if You agree to indemnify, 196 | defend, and hold each Contributor harmless for any liability 197 | incurred by, or claims asserted against, such Contributor by reason 198 | of your accepting any such warranty or additional liability. 199 | 200 | END OF TERMS AND CONDITIONS 201 | 202 | APPENDIX: How to apply the Apache License to your work. 203 | 204 | To apply the Apache License to your work, attach the following 205 | boilerplate notice, with the fields enclosed by brackets "[]" 206 | replaced with your own identifying information. (Don't include 207 | the brackets!) The text should be enclosed in the appropriate 208 | comment syntax for the file format. We also recommend that a 209 | file or class name and description of purpose be included on the 210 | same "printed page" as the copyright notice for easier 211 | identification within third-party archives. 212 | 213 | Copyright 2017 - 2023 Quarkslab 214 | 215 | Licensed under the Apache License, Version 2.0 (the "License"); 216 | you may not use this file except in compliance with the License. 217 | You may obtain a copy of the License at 218 | 219 | http://www.apache.org/licenses/LICENSE-2.0 220 | 221 | Unless required by applicable law or agreed to in writing, software 222 | distributed under the License is distributed on an "AS IS" BASIS, 223 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 224 | See the License for the specific language governing permissions and 225 | limitations under the License. 226 | -------------------------------------------------------------------------------- /nativelib/src/main/cpp/qdbi-arm64/share/qbdiAARCH64/cmake/QBDIAARCH64Config-release.cmake: -------------------------------------------------------------------------------- 1 | #---------------------------------------------------------------- 2 | # Generated CMake target import file for configuration "Release". 3 | #---------------------------------------------------------------- 4 | 5 | # Commands may need to know the format version. 6 | set(CMAKE_IMPORT_FILE_VERSION 1) 7 | 8 | # Import target "QBDI::AARCH64::QBDI_static" for configuration "Release" 9 | set_property(TARGET QBDI::AARCH64::QBDI_static APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) 10 | set_target_properties(QBDI::AARCH64::QBDI_static PROPERTIES 11 | IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "C" 12 | IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/libQBDI.a" 13 | ) 14 | 15 | list(APPEND _cmake_import_check_targets QBDI::AARCH64::QBDI_static ) 16 | list(APPEND _cmake_import_check_files_for_QBDI::AARCH64::QBDI_static "${_IMPORT_PREFIX}/lib/libQBDI.a" ) 17 | 18 | # Import target "QBDI::AARCH64::QBDI" for configuration "Release" 19 | set_property(TARGET QBDI::AARCH64::QBDI APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) 20 | set_target_properties(QBDI::AARCH64::QBDI PROPERTIES 21 | IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/libQBDI.so" 22 | IMPORTED_SONAME_RELEASE "libQBDI.so" 23 | ) 24 | 25 | list(APPEND _cmake_import_check_targets QBDI::AARCH64::QBDI ) 26 | list(APPEND _cmake_import_check_files_for_QBDI::AARCH64::QBDI "${_IMPORT_PREFIX}/lib/libQBDI.so" ) 27 | 28 | # Commands beyond this point should not need to know the version. 29 | set(CMAKE_IMPORT_FILE_VERSION) 30 | -------------------------------------------------------------------------------- /nativelib/src/main/cpp/qdbi-arm64/share/qbdiAARCH64/cmake/QBDIAARCH64Config.cmake: -------------------------------------------------------------------------------- 1 | # Generated by CMake 2 | 3 | if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.8) 4 | message(FATAL_ERROR "CMake >= 2.8.0 required") 5 | endif() 6 | if(CMAKE_VERSION VERSION_LESS "2.8.3") 7 | message(FATAL_ERROR "CMake >= 2.8.3 required") 8 | endif() 9 | cmake_policy(PUSH) 10 | cmake_policy(VERSION 2.8.3...3.23) 11 | #---------------------------------------------------------------- 12 | # Generated CMake target import file. 13 | #---------------------------------------------------------------- 14 | 15 | # Commands may need to know the format version. 16 | set(CMAKE_IMPORT_FILE_VERSION 1) 17 | 18 | # Protect against multiple inclusion, which would fail when already imported targets are added once more. 19 | set(_cmake_targets_defined "") 20 | set(_cmake_targets_not_defined "") 21 | set(_cmake_expected_targets "") 22 | foreach(_cmake_expected_target IN ITEMS QBDI::AARCH64::QBDI_static QBDI::AARCH64::QBDI) 23 | list(APPEND _cmake_expected_targets "${_cmake_expected_target}") 24 | if(TARGET "${_cmake_expected_target}") 25 | list(APPEND _cmake_targets_defined "${_cmake_expected_target}") 26 | else() 27 | list(APPEND _cmake_targets_not_defined "${_cmake_expected_target}") 28 | endif() 29 | endforeach() 30 | unset(_cmake_expected_target) 31 | if(_cmake_targets_defined STREQUAL _cmake_expected_targets) 32 | unset(_cmake_targets_defined) 33 | unset(_cmake_targets_not_defined) 34 | unset(_cmake_expected_targets) 35 | unset(CMAKE_IMPORT_FILE_VERSION) 36 | cmake_policy(POP) 37 | return() 38 | endif() 39 | if(NOT _cmake_targets_defined STREQUAL "") 40 | string(REPLACE ";" ", " _cmake_targets_defined_text "${_cmake_targets_defined}") 41 | string(REPLACE ";" ", " _cmake_targets_not_defined_text "${_cmake_targets_not_defined}") 42 | message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_cmake_targets_defined_text}\nTargets not yet defined: ${_cmake_targets_not_defined_text}\n") 43 | endif() 44 | unset(_cmake_targets_defined) 45 | unset(_cmake_targets_not_defined) 46 | unset(_cmake_expected_targets) 47 | 48 | 49 | # Compute the installation prefix relative to this file. 50 | get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH) 51 | get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) 52 | get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) 53 | get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) 54 | if(_IMPORT_PREFIX STREQUAL "/") 55 | set(_IMPORT_PREFIX "") 56 | endif() 57 | 58 | # Create imported target QBDI::AARCH64::QBDI_static 59 | add_library(QBDI::AARCH64::QBDI_static STATIC IMPORTED) 60 | 61 | set_target_properties(QBDI::AARCH64::QBDI_static PROPERTIES 62 | INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include" 63 | INTERFACE_LINK_LIBRARIES "dl;m;log" 64 | ) 65 | 66 | # Create imported target QBDI::AARCH64::QBDI 67 | add_library(QBDI::AARCH64::QBDI SHARED IMPORTED) 68 | 69 | set_target_properties(QBDI::AARCH64::QBDI PROPERTIES 70 | INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include" 71 | ) 72 | 73 | if(CMAKE_VERSION VERSION_LESS 2.8.12) 74 | message(FATAL_ERROR "This file relies on consumers using CMake 2.8.12 or greater.") 75 | endif() 76 | 77 | # Load information for each installed configuration. 78 | file(GLOB _cmake_config_files "${CMAKE_CURRENT_LIST_DIR}/QBDIAARCH64Config-*.cmake") 79 | foreach(_cmake_config_file IN LISTS _cmake_config_files) 80 | include("${_cmake_config_file}") 81 | endforeach() 82 | unset(_cmake_config_file) 83 | unset(_cmake_config_files) 84 | 85 | # Cleanup temporary variables. 86 | set(_IMPORT_PREFIX) 87 | 88 | # Loop over all imported files and verify that they actually exist 89 | foreach(_cmake_target IN LISTS _cmake_import_check_targets) 90 | foreach(_cmake_file IN LISTS "_cmake_import_check_files_for_${_cmake_target}") 91 | if(NOT EXISTS "${_cmake_file}") 92 | message(FATAL_ERROR "The imported target \"${_cmake_target}\" references the file 93 | \"${_cmake_file}\" 94 | but this file does not exist. Possible reasons include: 95 | * The file was deleted, renamed, or moved to another location. 96 | * An install or uninstall procedure did not complete successfully. 97 | * The installation package was faulty and contained 98 | \"${CMAKE_CURRENT_LIST_FILE}\" 99 | but not all the files it references. 100 | ") 101 | endif() 102 | endforeach() 103 | unset(_cmake_file) 104 | unset("_cmake_import_check_files_for_${_cmake_target}") 105 | endforeach() 106 | unset(_cmake_target) 107 | unset(_cmake_import_check_targets) 108 | 109 | # This file does not depend on other imported targets which have 110 | # been exported from the same project but in a separate export set. 111 | 112 | # Commands beyond this point should not need to know the version. 113 | set(CMAKE_IMPORT_FILE_VERSION) 114 | cmake_policy(POP) 115 | -------------------------------------------------------------------------------- /nativelib/src/main/cpp/qdbi-arm64/share/qbdiAARCH64/cmake/QBDIConfig-release.cmake: -------------------------------------------------------------------------------- 1 | #---------------------------------------------------------------- 2 | # Generated CMake target import file for configuration "Release". 3 | #---------------------------------------------------------------- 4 | 5 | # Commands may need to know the format version. 6 | set(CMAKE_IMPORT_FILE_VERSION 1) 7 | 8 | # Import target "QBDI::QBDI_static" for configuration "Release" 9 | set_property(TARGET QBDI::QBDI_static APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) 10 | set_target_properties(QBDI::QBDI_static PROPERTIES 11 | IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "C" 12 | IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/libQBDI.a" 13 | ) 14 | 15 | list(APPEND _cmake_import_check_targets QBDI::QBDI_static ) 16 | list(APPEND _cmake_import_check_files_for_QBDI::QBDI_static "${_IMPORT_PREFIX}/lib/libQBDI.a" ) 17 | 18 | # Import target "QBDI::QBDI" for configuration "Release" 19 | set_property(TARGET QBDI::QBDI APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) 20 | set_target_properties(QBDI::QBDI PROPERTIES 21 | IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/libQBDI.so" 22 | IMPORTED_SONAME_RELEASE "libQBDI.so" 23 | ) 24 | 25 | list(APPEND _cmake_import_check_targets QBDI::QBDI ) 26 | list(APPEND _cmake_import_check_files_for_QBDI::QBDI "${_IMPORT_PREFIX}/lib/libQBDI.so" ) 27 | 28 | # Commands beyond this point should not need to know the version. 29 | set(CMAKE_IMPORT_FILE_VERSION) 30 | -------------------------------------------------------------------------------- /nativelib/src/main/cpp/qdbi-arm64/share/qbdiAARCH64/cmake/QBDIConfig.cmake: -------------------------------------------------------------------------------- 1 | # Generated by CMake 2 | 3 | if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.8) 4 | message(FATAL_ERROR "CMake >= 2.8.0 required") 5 | endif() 6 | if(CMAKE_VERSION VERSION_LESS "2.8.3") 7 | message(FATAL_ERROR "CMake >= 2.8.3 required") 8 | endif() 9 | cmake_policy(PUSH) 10 | cmake_policy(VERSION 2.8.3...3.23) 11 | #---------------------------------------------------------------- 12 | # Generated CMake target import file. 13 | #---------------------------------------------------------------- 14 | 15 | # Commands may need to know the format version. 16 | set(CMAKE_IMPORT_FILE_VERSION 1) 17 | 18 | # Protect against multiple inclusion, which would fail when already imported targets are added once more. 19 | set(_cmake_targets_defined "") 20 | set(_cmake_targets_not_defined "") 21 | set(_cmake_expected_targets "") 22 | foreach(_cmake_expected_target IN ITEMS QBDI::QBDI_static QBDI::QBDI) 23 | list(APPEND _cmake_expected_targets "${_cmake_expected_target}") 24 | if(TARGET "${_cmake_expected_target}") 25 | list(APPEND _cmake_targets_defined "${_cmake_expected_target}") 26 | else() 27 | list(APPEND _cmake_targets_not_defined "${_cmake_expected_target}") 28 | endif() 29 | endforeach() 30 | unset(_cmake_expected_target) 31 | if(_cmake_targets_defined STREQUAL _cmake_expected_targets) 32 | unset(_cmake_targets_defined) 33 | unset(_cmake_targets_not_defined) 34 | unset(_cmake_expected_targets) 35 | unset(CMAKE_IMPORT_FILE_VERSION) 36 | cmake_policy(POP) 37 | return() 38 | endif() 39 | if(NOT _cmake_targets_defined STREQUAL "") 40 | string(REPLACE ";" ", " _cmake_targets_defined_text "${_cmake_targets_defined}") 41 | string(REPLACE ";" ", " _cmake_targets_not_defined_text "${_cmake_targets_not_defined}") 42 | message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_cmake_targets_defined_text}\nTargets not yet defined: ${_cmake_targets_not_defined_text}\n") 43 | endif() 44 | unset(_cmake_targets_defined) 45 | unset(_cmake_targets_not_defined) 46 | unset(_cmake_expected_targets) 47 | 48 | 49 | # Compute the installation prefix relative to this file. 50 | get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH) 51 | get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) 52 | get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) 53 | get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) 54 | if(_IMPORT_PREFIX STREQUAL "/") 55 | set(_IMPORT_PREFIX "") 56 | endif() 57 | 58 | # Create imported target QBDI::QBDI_static 59 | add_library(QBDI::QBDI_static STATIC IMPORTED) 60 | 61 | set_target_properties(QBDI::QBDI_static PROPERTIES 62 | INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include" 63 | INTERFACE_LINK_LIBRARIES "dl;m;log" 64 | ) 65 | 66 | # Create imported target QBDI::QBDI 67 | add_library(QBDI::QBDI SHARED IMPORTED) 68 | 69 | set_target_properties(QBDI::QBDI PROPERTIES 70 | INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include" 71 | ) 72 | 73 | if(CMAKE_VERSION VERSION_LESS 2.8.12) 74 | message(FATAL_ERROR "This file relies on consumers using CMake 2.8.12 or greater.") 75 | endif() 76 | 77 | # Load information for each installed configuration. 78 | file(GLOB _cmake_config_files "${CMAKE_CURRENT_LIST_DIR}/QBDIConfig-*.cmake") 79 | foreach(_cmake_config_file IN LISTS _cmake_config_files) 80 | include("${_cmake_config_file}") 81 | endforeach() 82 | unset(_cmake_config_file) 83 | unset(_cmake_config_files) 84 | 85 | # Cleanup temporary variables. 86 | set(_IMPORT_PREFIX) 87 | 88 | # Loop over all imported files and verify that they actually exist 89 | foreach(_cmake_target IN LISTS _cmake_import_check_targets) 90 | foreach(_cmake_file IN LISTS "_cmake_import_check_files_for_${_cmake_target}") 91 | if(NOT EXISTS "${_cmake_file}") 92 | message(FATAL_ERROR "The imported target \"${_cmake_target}\" references the file 93 | \"${_cmake_file}\" 94 | but this file does not exist. Possible reasons include: 95 | * The file was deleted, renamed, or moved to another location. 96 | * An install or uninstall procedure did not complete successfully. 97 | * The installation package was faulty and contained 98 | \"${CMAKE_CURRENT_LIST_FILE}\" 99 | but not all the files it references. 100 | ") 101 | endif() 102 | endforeach() 103 | unset(_cmake_file) 104 | unset("_cmake_import_check_files_for_${_cmake_target}") 105 | endforeach() 106 | unset(_cmake_target) 107 | unset(_cmake_import_check_targets) 108 | 109 | # This file does not depend on other imported targets which have 110 | # been exported from the same project but in a separate export set. 111 | 112 | # Commands beyond this point should not need to know the version. 113 | set(CMAKE_IMPORT_FILE_VERSION) 114 | cmake_policy(POP) 115 | -------------------------------------------------------------------------------- /nativelib/src/main/cpp/qdbi-arm64/share/qbdiAARCH64/qbdi_frida_template/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.2) 2 | project(qbdi-frida-template) 3 | add_executable(demo.bin SimpleXOR.c) 4 | -------------------------------------------------------------------------------- /nativelib/src/main/cpp/qdbi-arm64/share/qbdiAARCH64/qbdi_frida_template/FridaQBDI_sample.js: -------------------------------------------------------------------------------- 1 | // QBDI 2 | import { VM, InstPosition, VMAction } from "./frida-qbdi.js"; 3 | 4 | // Initialize QBDI 5 | var vm = new VM(); 6 | var state = vm.getGPRState(); 7 | var stack = vm.allocateVirtualStack(state, 0x100000); 8 | 9 | // Instrument "Secret" function from demo.bin 10 | var funcPtr = Module.findExportByName(null, "Secret"); 11 | if (!funcPtr) { 12 | funcPtr = DebugSymbol.fromName("Secret").address; 13 | } 14 | vm.addInstrumentedModuleFromAddr(funcPtr); 15 | 16 | // Callback on every instruction 17 | // This callback will print context and display current instruction address and dissassembly 18 | // We choose to print only XOR instructions 19 | var icbk = vm.newInstCallback(function(vm, gpr, fpr, data) { 20 | var inst = vm.getInstAnalysis(); 21 | if (inst.mnemonic.search("XOR")){ 22 | return VMAction.CONTINUE; 23 | } 24 | gpr.dump(); // Display context 25 | console.log("0x" + inst.address.toString(16) + " " + inst.disassembly); // Display instruction dissassembly 26 | return VMAction.CONTINUE; 27 | }); 28 | var iid = vm.addCodeCB(InstPosition.PREINST, icbk); 29 | 30 | // Allocate a string in remote process memory 31 | var strP = Memory.allocUtf8String("Hello world !"); 32 | // Call the Secret function using QBDI and with our string as argument 33 | vm.call(funcPtr, [strP]); 34 | -------------------------------------------------------------------------------- /nativelib/src/main/cpp/qdbi-arm64/share/qbdiAARCH64/qbdi_frida_template/SimpleXOR.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #if defined(_MSC_VER) 7 | #define EXPORT __declspec(dllexport) 8 | #else // _MSC_VER 9 | #define EXPORT __attribute__((visibility("default"))) 10 | #endif 11 | 12 | EXPORT int Secret(char *str) { 13 | int i; 14 | unsigned char XOR[] = {0x51, 0x42, 0x44, 0x49, 0x46, 0x72, 0x69, 0x64, 0x61}; 15 | size_t len = strlen(str); 16 | 17 | printf("Input string is : %s\nEncrypted string is : \n", str); 18 | 19 | for (i = 0; i < len; i++) { 20 | printf("0x%x,", str[i] ^ XOR[i % sizeof(XOR)]); 21 | } 22 | printf("\n"); 23 | fflush(stdout); 24 | return 0; 25 | } 26 | 27 | void Hello() { Secret("Hello world !"); } 28 | 29 | int main() { Hello(); } 30 | -------------------------------------------------------------------------------- /nativelib/src/main/cpp/qdbi-arm64/share/qbdiAARCH64/qbdi_template/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.2) 2 | project(QBDITemplate) 3 | 4 | find_package(QBDIAARCH64 REQUIRED) 5 | 6 | add_executable(qbdi_template qbdi_template.c) 7 | 8 | # Easier to build using QBDI static library on Windows 9 | if(MSVC) 10 | target_link_libraries(qbdi_template QBDI::AARCH64::QBDI_static) 11 | else() 12 | target_link_libraries(qbdi_template QBDI::AARCH64::QBDI) 13 | endif() 14 | -------------------------------------------------------------------------------- /nativelib/src/main/cpp/qdbi-arm64/share/qbdiAARCH64/qbdi_template/README.txt: -------------------------------------------------------------------------------- 1 | Introduction 2 | ============ 3 | 4 | A simple template to easily create an instrumentation tool 5 | linking QBDI at compile time. 6 | 7 | 8 | Compilation 9 | =========== 10 | 11 | Linux / macOS 12 | ------------- 13 | 14 | $ # unix 15 | $ mkdir build 16 | $ cd build 17 | $ cmake .. 18 | $ make 19 | 20 | 21 | Windows 22 | ------- 23 | 24 | $ # win 25 | $ mkdir build 26 | $ cd build 27 | $ cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_BUILD_TYPE=Release .. 28 | $ MSBuild.exe /p:Configuration=Release ALL_BUILD.vcxproj 29 | 30 | If compilation is successful, test binary will be in Release directory. 31 | If compiled dynamically, it will need QBDI.dll (from lib directory). 32 | 33 | Note 1: Visual Studio version must match the one installed on your system. 34 | Note 2: under cygwin, QBDI.dll needs to have executable bit set. 35 | -------------------------------------------------------------------------------- /nativelib/src/main/cpp/qdbi-arm64/share/qbdiAARCH64/qbdi_template/qbdi_template.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #define STACK_SIZE 0x100000 8 | 9 | QBDI_NOINLINE int secretFunc(unsigned int value) { return value ^ 0x5c; } 10 | 11 | VMAction showInstruction(VMInstanceRef vm, GPRState *gprState, 12 | FPRState *fprState, void *data) { 13 | // Obtain an analysis of the instruction from the VM 14 | const InstAnalysis *instAnalysis = qbdi_getInstAnalysis( 15 | vm, QBDI_ANALYSIS_INSTRUCTION | QBDI_ANALYSIS_DISASSEMBLY); 16 | // Printing disassembly 17 | printf("0x%" PRIRWORD ": %s\n", instAnalysis->address, 18 | instAnalysis->disassembly); 19 | return QBDI_CONTINUE; 20 | } 21 | 22 | int main(int argc, char **argv) { 23 | VMInstanceRef vm = NULL; 24 | uint8_t *fakestack = NULL; 25 | 26 | // init VM 27 | qbdi_initVM(&vm, NULL, NULL, 0); 28 | 29 | // Get a pointer to the GPR state of the VM 30 | GPRState *state = qbdi_getGPRState(vm); 31 | assert(state != NULL); 32 | 33 | // Setup initial GPR state, this fakestack will produce a ret NULL at the end 34 | // of the execution 35 | bool res = qbdi_allocateVirtualStack(state, STACK_SIZE, &fakestack); 36 | assert(res == true); 37 | 38 | // Add callback on our instruction range 39 | uint32_t uid = 40 | qbdi_addCodeRangeCB(vm, (rword)&secretFunc, (rword)&secretFunc + 100, 41 | QBDI_PREINST, showInstruction, vm, 0); 42 | assert(uid != QBDI_INVALID_EVENTID); 43 | 44 | // add executable code range 45 | res = qbdi_addInstrumentedModuleFromAddr(vm, (rword)&main); 46 | assert(res == true); 47 | 48 | // call secretFunc using VM, custom state and fake stack 49 | // eq: secretFunc(666); 50 | rword retval; 51 | res = qbdi_call(vm, &retval, (rword)secretFunc, 1, 666); 52 | assert(res == true); 53 | 54 | // get return value from current state 55 | printf("[*] retval=0x%" PRIRWORD "\n", retval); 56 | 57 | // free everything 58 | qbdi_alignedFree(fakestack); 59 | qbdi_terminateVM(vm); 60 | 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /nativelib/src/main/cpp/record/HookInfo.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by fang on 2024/1/4. 3 | // 4 | 5 | #include "HookInfo.h" 6 | #include 7 | 8 | 9 | static ModuleInfo moduleInfo; 10 | 11 | ModuleInfo HookInfo::get_module() { 12 | return moduleInfo; 13 | } 14 | 15 | void HookInfo::set_module(const char* name,size_t base, size_t end) { 16 | moduleInfo.name = name; 17 | moduleInfo.end = end; 18 | moduleInfo.base = base; 19 | } 20 | -------------------------------------------------------------------------------- /nativelib/src/main/cpp/record/HookInfo.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by fang on 2024/1/4. 3 | // 4 | 5 | #ifndef QBDI_HOOKINFO_H 6 | #define QBDI_HOOKINFO_H 7 | 8 | #include 9 | 10 | struct ModuleInfo{ 11 | const char* name; 12 | size_t base; 13 | size_t end; 14 | }; 15 | 16 | class HookInfo { 17 | public: 18 | // 获取单例实例的静态方法 19 | static HookInfo& getInstance() { 20 | static HookInfo instance; // Guaranteed to be destroyed. Instantiated on first use. 21 | return instance; 22 | } 23 | ModuleInfo get_module(); 24 | void set_module(const char* name ,size_t base,size_t size); 25 | 26 | private: 27 | // 隐藏构造函数,防止外部代码创建实例 28 | HookInfo() {} 29 | 30 | // 删除复制构造函数和赋值运算符 31 | HookInfo(const HookInfo&) = delete; 32 | HookInfo& operator=(const HookInfo&) = delete; 33 | }; 34 | 35 | #endif //QBDI_HOOKINFO_H 36 | -------------------------------------------------------------------------------- /nativelib/src/main/cpp/record/fileRecord.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by fang on 2024/1/4. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "fileRecord.h" 12 | #include "logger.h" 13 | using namespace std; 14 | static fstream* mFs ; 15 | 16 | 17 | void fileRecordOpen(){ 18 | 19 | if (mFs != nullptr) return; 20 | 21 | char* private_path = getPrivatePath(); 22 | string p = private_path; 23 | p.append("record.txt"); 24 | char* recode_path = const_cast(p.c_str()); 25 | if(access(recode_path,F_OK) !=-1 ){ 26 | remove(recode_path); 27 | } 28 | static fstream fs(recode_path,ios_base::app); 29 | LOGD("File record path: %s %p %d",recode_path,&fs,fs.is_open()); 30 | mFs = &fs; 31 | } 32 | 33 | void write(fstream* fs_, char* buff,size_t len){ 34 | 35 | *fs_ << buff << endl; 36 | //fs_->flush(); 37 | } 38 | 39 | void recordToFile(const char *fmt, ...) { 40 | if (mFs == nullptr) fileRecordOpen(); 41 | va_list args; 42 | size_t len; 43 | int LEN = 1024; 44 | char *dst = (char *) malloc(LEN); 45 | memset(dst, 0, LEN); 46 | va_start(args, fmt); 47 | len = vsnprintf(dst, LEN - 1, fmt, args); 48 | va_end(args); 49 | LOGD("%p %d %s",mFs, len, dst); 50 | write(mFs,dst,len); 51 | free(dst); 52 | } 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /nativelib/src/main/cpp/record/fileRecord.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by fang on 2024/1/4. 3 | // 4 | 5 | #ifndef QBDI_FILERECORD_H 6 | #define QBDI_FILERECORD_H 7 | #define MODE_FILE 8 | #include "HookUtils.h" 9 | void fileRecordOpen(); 10 | void recordToFile(const char *fmt, ...); 11 | #endif //QBDI_FILERECORD_H 12 | -------------------------------------------------------------------------------- /nativelib/src/main/cpp/utils/jsonbean.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by fang on 2023/12/29. 3 | // 4 | 5 | #include "jsonbean.h" 6 | #include 7 | #include 8 | 9 | static uint64_t getThreadID() 10 | { 11 | std::stringstream ss; 12 | ss << std::this_thread::get_id(); 13 | return std::stoull(ss.str()); 14 | } 15 | 16 | jsonbean::jsonbean(jsonbean::TYPE type) { 17 | json["type"] = type; 18 | 19 | json["tid"] = getThreadID(); 20 | } 21 | 22 | jsonbean jsonbean::setData(string data) { 23 | json["data"] = data; 24 | return *this; 25 | } 26 | 27 | jsonbean jsonbean::setData(nlohmann::ordered_json data) { 28 | json["data"] = data; 29 | return *this; 30 | } 31 | 32 | string jsonbean::dump(){ 33 | return json.dump(); 34 | } 35 | nlohmann::ordered_json jsonbean::getJson(){ 36 | return json; 37 | } 38 | 39 | 40 | -------------------------------------------------------------------------------- /nativelib/src/main/cpp/utils/jsonbean.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by fang on 2023/12/29. 3 | // 4 | 5 | #ifndef QBDI_JSONBEAN_H 6 | #define QBDI_JSONBEAN_H 7 | #include "json.hpp" 8 | using namespace std; 9 | class jsonbean { 10 | public: 11 | 12 | enum TYPE{ 13 | REG = 1, 14 | MEM = 2, 15 | ASM = 3 16 | }; 17 | jsonbean(TYPE type); 18 | jsonbean setData(string); 19 | jsonbean setData(nlohmann::ordered_json); 20 | string dump(); 21 | nlohmann::ordered_json getJson(); 22 | 23 | private: 24 | nlohmann::ordered_json json; 25 | 26 | 27 | }; 28 | #endif //QBDI_JSONBEAN_H 29 | -------------------------------------------------------------------------------- /nativelib/src/main/cpp/utils/socketUtils.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by fang on 2023/12/29. 3 | // 4 | 5 | 6 | #include 7 | #include "socketUtils.h" 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | using namespace std; 14 | socketUtils *socketUtils::instance = nullptr; 15 | mg_connection *socketUtils::connection = nullptr; 16 | struct mg_mgr socketUtils::mgr; 17 | static vector clients; 18 | 19 | void send(mg_connection *c, const char *data, size_t len) { 20 | mg_ws_send(c, data, len, WEBSOCKET_OP_TEXT); 21 | } 22 | 23 | void sendAllClient(const char *data) { 24 | string d = data; 25 | sendAllClient(data, d.length()); 26 | } 27 | 28 | bool isTryWS = false; 29 | void sendAllClient_sn(const char *fmt, ...) { 30 | // if (clients.size() == 0 && isTryWS == false){ 31 | // isTryWS = true; 32 | // socketUtils::getInstance()->startServer(); 33 | // sleep(5); 34 | // } 35 | 36 | LOGD("client size:%lu",clients.size()); 37 | va_list args; 38 | size_t len; 39 | //char dst [512]; 40 | int LEN = 1024; 41 | char *dst = (char *) malloc(LEN); 42 | memset(dst, 0, LEN); 43 | va_start(args, fmt); 44 | len = vsnprintf(dst, LEN - 1, fmt, args); 45 | va_end(args); 46 | LOGD("%d %s", len, dst); 47 | 48 | sendAllClient(dst, len); 49 | free(dst); 50 | } 51 | 52 | 53 | void sendAllClient(const char *data, size_t len) { 54 | 55 | try { 56 | if (clients.size()!=0){ 57 | for (mg_connection *c: clients) { 58 | if (c->is_accepted) { 59 | send(c, data, len); 60 | } 61 | } 62 | }else{ 63 | 64 | 65 | } 66 | 67 | } catch (exception &e) { 68 | 69 | LOGE("%s", e.what()); 70 | } 71 | } 72 | 73 | 74 | 75 | 76 | void *eventloop(void *mgr) { 77 | 78 | for (;;) mg_mgr_poll((mg_mgr *) mgr, 1000); 79 | 80 | } 81 | 82 | char log_buf[256]; 83 | int log_index = 0; 84 | 85 | void log_fn(char ch, void *param) { 86 | log_buf[log_index] = ch; 87 | log_index++; 88 | if (ch == '\0' || ch == '\n' || log_index == 255) { 89 | LOGD("%s", log_buf); 90 | log_index = 0; 91 | memset(log_buf, '\0', 256); 92 | } 93 | 94 | } 95 | 96 | static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) { 97 | if (ev == MG_EV_OPEN) { 98 | // c->is_hexdumping = 1; 99 | } else if (ev == MG_EV_HTTP_MSG) { 100 | struct mg_http_message *hm = (struct mg_http_message *) ev_data; 101 | if (mg_http_match_uri(hm, "/websocket")) { 102 | // Upgrade to websocket. From now on, a connection is a full-duplex 103 | // Websocket connection, which will receive MG_EV_WS_MSG events. 104 | mg_ws_upgrade(c, hm, NULL); 105 | } 106 | } else if (ev == MG_EV_WS_MSG) { 107 | // Got websocket frame. Received data is wm->data. Echo it back! 108 | struct mg_ws_message *wm = (struct mg_ws_message *) ev_data; 109 | string msg = string((const char *) wm->data.ptr, wm->data.len); 110 | LOGD("socket recv %s", msg.c_str()); 111 | mg_ws_send(c, wm->data.ptr, wm->data.len, WEBSOCKET_OP_TEXT); 112 | } else if (ev == MG_EV_WS_OPEN) { 113 | clients.emplace_back(c); 114 | LOGD("client conn size: %lu",clients.size()); 115 | mg_ws_send(c, "conn", 4, WEBSOCKET_OP_TEXT); 116 | } 117 | (void) fn_data; 118 | } 119 | 120 | bool socketUtils::startServer() { 121 | 122 | mg_log_set(MG_LL_DEBUG); 123 | mg_log_set_fn(log_fn, nullptr); 124 | mg_mgr_init(&mgr); 125 | 126 | socketUtils::connection = mg_http_listen(&mgr, "ws://localhost:8765", fn, 127 | nullptr); // Setup listener 128 | if (socketUtils::connection == nullptr) { 129 | LOGE("socket creat fail"); 130 | return false; 131 | } 132 | pthread_t socket_t; 133 | int ret = pthread_create(&socket_t, nullptr, reinterpret_cast(eventloop), 134 | &mgr); 135 | LOGD("socket_t %d", ret); 136 | return true; 137 | } 138 | 139 | bool socketUtils::sendMsg(struct mg_connection *c, void *buff, size_t len) { 140 | //mg_send(c,buff,len); 141 | mg_ws_send(c, buff, len, WEBSOCKET_OP_TEXT); 142 | } 143 | 144 | bool socketUtils::sendMsg(struct mg_connection *c, const std::string data) { 145 | //mg_send(c,data.c_str(),data.length()); 146 | mg_ws_send(c, data.c_str(), data.length(), WEBSOCKET_OP_TEXT); 147 | 148 | } 149 | 150 | void socketUtils::close() { 151 | mg_mgr_free(&mgr); 152 | } 153 | -------------------------------------------------------------------------------- /nativelib/src/main/cpp/utils/socketUtils.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by fang on 2023/12/29. 3 | // 4 | 5 | #ifndef QBDI_SOCKETUTILS_H 6 | #define QBDI_SOCKETUTILS_H 7 | #define MODE_SOCKET 8 | #include "mongoose.h" 9 | #include "logger.h" 10 | #include 11 | class socketUtils { 12 | 13 | 14 | public: 15 | static socketUtils* getInstance(){ 16 | if (instance == nullptr){ 17 | instance = new socketUtils(); 18 | } 19 | return instance; 20 | }; 21 | 22 | bool startServer(); 23 | static bool sendMsg(struct mg_connection *c,std::string data); 24 | static bool sendMsg(struct mg_connection *c,void *buff, size_t len); 25 | 26 | void close(); 27 | private: 28 | static socketUtils* instance ; 29 | static mg_connection* connection; 30 | static struct mg_mgr mgr; 31 | 32 | }; 33 | void sendAllClient(const char* data,size_t len); 34 | void sendAllClient(const char* data); 35 | void sendAllClient_sn(const char* fmt,...); 36 | 37 | 38 | #endif //QBDI_SOCKETUTILS_H 39 | -------------------------------------------------------------------------------- /nativelib/src/main/cpp/vm.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by fang on 23-12-19. 3 | // 4 | 5 | 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "vm.h" 13 | #include "logger.h" 14 | #include "dobby_symbol_resolver.h" 15 | #include "HookInfo.h" 16 | 17 | using namespace std; 18 | using namespace QBDI; 19 | 20 | 21 | string prinitGPR(QBDI::GPRState *gprState){ 22 | stringstream info; 23 | int i = 0; 24 | nlohmann::ordered_json j; 25 | auto bean = new jsonbean(jsonbean::TYPE::REG); 26 | for (string reg_name: QBDI::GPR_NAMES) { 27 | 28 | j[reg_name] = QBDI_GPR_GET(gprState,i); 29 | info << reg_name<<"=" << QBDI_GPR_GET(gprState,i) << setbase(16)<< " | "; 30 | i++; 31 | } 32 | bean->setData(j); 33 | //LOGD("%s",info.str().c_str()); 34 | return bean->dump(); 35 | return info.str(); 36 | } 37 | #define IFNULL_P(obj,d) (obj == nullptr)? d : obj 38 | #define IFNULL_I(obj,d) (obj == 0)? d : obj 39 | string printASM(const QBDI::InstAnalysis *instAnalysis){ 40 | auto bean = new jsonbean(jsonbean::ASM); 41 | nlohmann::ordered_json data; 42 | data["symbol"] = IFNULL_P(instAnalysis->symbol,""); 43 | data["address"] = IFNULL_I(instAnalysis->address - HookInfo::getInstance().get_module().base,0); 44 | data["symbolOffset"] = IFNULL_I(instAnalysis->symbolOffset,0); 45 | data["disassembly"] = IFNULL_P(instAnalysis->disassembly,""); 46 | data["module"] = IFNULL_P(instAnalysis->module,""); 47 | bean->setData(data); 48 | return bean->dump(); 49 | } 50 | 51 | string printMemAcc(QBDI::MemoryAccess memoryAccess){ 52 | auto bean = new jsonbean(jsonbean::MEM); 53 | nlohmann::ordered_json data; 54 | data["accessAddress"] = memoryAccess.accessAddress; 55 | data["type"] = memoryAccess.type; 56 | data["instAddress"] = memoryAccess.instAddress; 57 | data["value"] = memoryAccess.value; 58 | data["size"] = memoryAccess.size; 59 | bean->setData(data); 60 | return bean->dump(); 61 | } 62 | 63 | 64 | 65 | QBDI::VMAction showInstruction(QBDI::VM *vm, QBDI::GPRState *gprState, QBDI::FPRState *fprState, void *data) { 66 | 67 | const QBDI::InstAnalysis *instAnalysis = vm->getInstAnalysis(QBDI::ANALYSIS_INSTRUCTION 68 | | QBDI::ANALYSIS_SYMBOL 69 | | QBDI::ANALYSIS_DISASSEMBLY 70 | | QBDI::ANALYSIS_OPERANDS 71 | ); 72 | LOGD("%s[0x%x]:%lx %-16s",instAnalysis->symbol,instAnalysis->symbolOffset, instAnalysis->address, instAnalysis->disassembly); 73 | 74 | //sendAllClient_sn("%s[0x%x]:%lx %-16s",instAnalysis->symbol,instAnalysis->symbolOffset, instAnalysis->address, instAnalysis->disassembly); 75 | 76 | #ifdef MODE_SOCKET 77 | sendAllClient_sn("%s", printASM(instAnalysis).c_str()); 78 | sendAllClient_sn("%s",prinitGPR(gprState).c_str()); 79 | #endif 80 | #ifdef MODE_FILE 81 | recordToFile("%s",printASM(instAnalysis).c_str()); 82 | recordToFile("%s", prinitGPR(gprState).c_str()); 83 | #endif 84 | 85 | // if (instAnalysis->mayLoad || instAnalysis->mayStore){ 86 | // vector memAccVector = vm->getInstMemoryAccess(); 87 | // for (int i = 0; i < memAccVector.size(); ++i) { 88 | // 89 | // #ifdef MODE_SOCKET 90 | // sendAllClient_sn("%s",printMemAcc(memAccVector.at(i)).c_str()); 91 | // #endif 92 | // 93 | // 94 | // } 95 | // } 96 | 97 | 98 | 99 | return QBDI::VMAction::CONTINUE; 100 | } 101 | QBDI::VMCbLambda event_cb = [](VMInstanceRef vm, const VMState *vmState, 102 | GPRState *gprState, FPRState *fprState){ 103 | 104 | 105 | 106 | return VMAction::CONTINUE; 107 | }; 108 | 109 | QBDI::VM vm::init(void* address) { 110 | uint32_t cid; 111 | QBDI::GPRState *state; 112 | QBDI::VM qvm{}; 113 | // Get a pointer to the GPR state of the VM 114 | state = qvm.getGPRState(); 115 | assert(state != nullptr); 116 | qvm.recordMemoryAccess(QBDI::MEMORY_READ_WRITE); 117 | cid = qvm.addCodeCB(QBDI::PREINST, showInstruction, nullptr); 118 | //qvm.addVMEventCB(QBDI::VMEvent::EXEC_TRANSFER_CALL,) 119 | assert(cid != QBDI::INVALID_EVENTID); 120 | bool ret = qvm.addInstrumentedModuleFromAddr(reinterpret_cast(address)); 121 | // bool ret = qvm.instrumentAllExecutableMaps(); 122 | assert(ret == true); 123 | 124 | return qvm; 125 | } 126 | void syn_regs(DobbyRegisterContext *ctx,QBDI::GPRState *state,bool D2Q){ 127 | if (D2Q){ 128 | for(int i = 0 ; i < 29; i++){ 129 | QBDI_GPR_SET(state,i,ctx->general.x[i]); 130 | } 131 | state->lr = ctx->lr; 132 | state->x29 = ctx->fp; 133 | state->sp = ctx->sp; 134 | 135 | // state->sp = ctx->sp; 136 | 137 | }else{ 138 | for(int i = 0 ; i < 29; i++){ 139 | //QBDI_GPR_SET(state,i,ctx->general.x[i]); 140 | ctx->general.x[i] = QBDI_GPR_GET(state,i); 141 | } 142 | ctx->lr = state->lr; 143 | ctx->fp = state->x29; 144 | ctx->sp = state->sp; 145 | 146 | } 147 | //state->sp = ctx->sp; 148 | } 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | -------------------------------------------------------------------------------- /nativelib/src/main/java/com/f/nativelib/NativeLib.java: -------------------------------------------------------------------------------- 1 | package com.f.nativelib; 2 | 3 | public class NativeLib { 4 | 5 | // Used to load the 'nativelib' library on application startup. 6 | static { 7 | System.loadLibrary("nativelib"); 8 | } 9 | 10 | /** 11 | * A native method that is implemented by the 'nativelib' native library, 12 | * which is packaged with this application. 13 | */ 14 | public native String stringFromJNI(); 15 | } -------------------------------------------------------------------------------- /nativelib/src/test/java/com/f/nativelib/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.f.nativelib; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | google() 4 | mavenCentral() 5 | gradlePluginPortal() 6 | } 7 | } 8 | dependencyResolutionManagement { 9 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 10 | repositories { 11 | google() 12 | mavenCentral() 13 | } 14 | } 15 | 16 | rootProject.name = "qbdi" 17 | include ':app' 18 | include ':nativelib' 19 | --------------------------------------------------------------------------------