├── .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 |
--------------------------------------------------------------------------------