├── .gitignore ├── .idea ├── .gitignore ├── .name ├── compiler.xml ├── gradle.xml └── misc.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── id │ │ └── kuro │ │ └── androidnativeguard │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── cpp │ │ ├── CMakeLists.txt │ │ ├── Modules │ │ │ ├── AntiDebug │ │ │ │ ├── AntiDebug.cpp │ │ │ │ └── AntiDebug.h │ │ │ ├── AntiDump │ │ │ │ ├── AntiDump.cpp │ │ │ │ └── AntiDump.h │ │ │ ├── AntiLibPatch │ │ │ │ ├── AntiLibPatch.cpp │ │ │ │ └── AntiLibPatch.h │ │ │ ├── FridaDetect │ │ │ │ ├── FridaDetect.cpp │ │ │ │ └── FridaDetect.h │ │ │ ├── IModule.h │ │ │ ├── RiGisk │ │ │ │ ├── RiGisk.cpp │ │ │ │ └── RiGisk.h │ │ │ └── RootDetect │ │ │ │ ├── RootDetect.cpp │ │ │ │ └── RootDetect.h │ │ ├── SecureAPI │ │ │ ├── SecureAPI.h │ │ │ └── syscall │ │ │ │ ├── arm64-v8a │ │ │ │ └── syscall_arch.h │ │ │ │ ├── armeabi-v7a │ │ │ │ └── syscall_arch.h │ │ │ │ ├── x86 │ │ │ │ └── syscall_arch.h │ │ │ │ └── x86_64 │ │ │ │ └── syscall_arch.h │ │ ├── Utils │ │ │ ├── ElfImg.cpp │ │ │ ├── ElfImg.h │ │ │ ├── Log.h │ │ │ └── obfuscate.h │ │ ├── constants.h │ │ └── main.cpp │ ├── java │ │ └── id │ │ │ └── kuro │ │ │ └── androidnativeguard │ │ │ └── MainActivity.java │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ ├── border_background.xml │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-anydpi-v33 │ │ └── ic_launcher.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 │ └── id │ └── kuro │ └── androidnativeguard │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea 5 | /.idea/* 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | .cxx 11 | local.properties 12 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | Android Native Guard -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 19 | 20 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # What is it? 2 | Android Native Guard is a proof of concepts on how to detect various threat that might harm your application's integrity. 3 | 4 | # How secure is it? 5 | Android Native Guard used what's called `Secure API` and low-level function call through inline `syscall` to prevent any bypass that could potentially break the security system. 6 | Android Native Guard used various open-source projects to implement a true-secure android application system. 7 | 8 | # Modules 9 | - Debugger Detection 10 | - Frida Detection 11 | - Riru & Zygisk Detection 12 | - Root Detection 13 | - Memory Access & Dump Detection 14 | - Library Patch & Hook Detection 15 | 16 | # TODO 17 | - Better documentation (codes & README) 18 | - App Tamper Detection (signature, checksum, etc) 19 | - Magisk-Hide Detection Module (e.g. Shamiko) 20 | - Blacklist for AntiLibPatch module 21 | 22 | # Notes 23 | - Don't forget to add `android:extractNativeLibs="true"` to your `AndroidManifest.xml` so that module _AntiLibPatch_ can work properly. 24 | 25 | # Credits 26 | https://github.com/darvincisec/AntiDebugandMemoryDump 27 | 28 | https://github.com/darvincisec/DetectFrida 29 | 30 | https://github.com/aimardcr/NativeDetector 31 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.application' 3 | } 4 | 5 | android { 6 | namespace 'id.kuro.androidnativeguard' 7 | compileSdk 33 8 | 9 | defaultConfig { 10 | applicationId "id.kuro.androidnativeguard" 11 | minSdk 24 12 | targetSdk 35 13 | versionCode 1 14 | versionName "1.0" 15 | multiDexEnabled true 16 | 17 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 18 | externalNativeBuild { 19 | cmake { 20 | 21 | } 22 | } 23 | } 24 | 25 | buildTypes { 26 | release { 27 | minifyEnabled false 28 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 29 | } 30 | } 31 | compileOptions { 32 | sourceCompatibility JavaVersion.VERSION_1_8 33 | targetCompatibility JavaVersion.VERSION_1_8 34 | } 35 | externalNativeBuild { 36 | cmake { 37 | path file('src/main/cpp/CMakeLists.txt') 38 | version '3.22.1' 39 | } 40 | } 41 | } 42 | 43 | dependencies { 44 | implementation 'com.android.support:multidex:1.0.0' 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 | testImplementation 'junit:junit:4.13.2' 49 | androidTestImplementation 'androidx.test.ext:junit:1.1.5' 50 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' 51 | } -------------------------------------------------------------------------------- /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/id/kuro/androidnativeguard/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package id.kuro.androidnativeguard; 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("id.kuro.androidnativeguard", appContext.getPackageName()); 25 | } 26 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 14 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/cpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.22.1) 2 | 3 | project(NativeGuard) 4 | 5 | set(CMAKE_CXX_STANDARD 20) 6 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 7 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-register") 8 | 9 | if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug") 10 | # Set visibility to hidden by default 11 | set(BUILD_CXX_AND_C_FLAGS "-fvisibility=hidden -fvisibility-inlines-hidden \ 12 | -fno-rtti -fno-exceptions") 13 | 14 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_RELEASE} ${BUILD_CXX_AND_C_FLAGS}") 15 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELEASE} ${BUILD_CXX_AND_C_FLAGS}") 16 | 17 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fdata-sections -ffunction-sections") 18 | else () 19 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 -g -DDEBUG") 20 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0 -g -DDEBUG") 21 | 22 | add_compile_definitions(DEBUG_BUILD) 23 | endif () 24 | 25 | if (${ANDROID_ABI} STREQUAL "armeabi-v7a") 26 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -marm") 27 | endif () 28 | 29 | # Add root directory reference for easier header includes, 30 | # It also let you avoid relative path e.g. #include "../include/header.h" 31 | include_directories(./) 32 | 33 | add_library(NativeGuard SHARED 34 | main.cpp 35 | Utils/ElfImg.cpp 36 | Modules/AntiDebug/AntiDebug.cpp 37 | Modules/FridaDetect/FridaDetect.cpp 38 | Modules/RiGisk/RiGisk.cpp 39 | Modules/RootDetect/RootDetect.cpp 40 | Modules/AntiDump/AntiDump.cpp 41 | Modules/AntiLibPatch/AntiLibPatch.cpp) 42 | 43 | target_include_directories(NativeGuard PRIVATE 44 | ${CMAKE_CURRENT_SOURCE_DIR}/SecureAPI 45 | ${CMAKE_CURRENT_SOURCE_DIR}/SecureAPI/syscall/${ANDROID_ABI} 46 | ${CMAKE_CURRENT_SOURCE_DIR}/Utils 47 | ${CMAKE_CURRENT_SOURCE_DIR}/Modules) 48 | 49 | target_link_libraries(NativeGuard log) -------------------------------------------------------------------------------- /app/src/main/cpp/Modules/AntiDebug/AntiDebug.cpp: -------------------------------------------------------------------------------- 1 | #include "AntiDebug.h" 2 | #include "SecureAPI.h" 3 | #include "Log.h" 4 | #include "obfuscate.h" 5 | 6 | #include 7 | #include 8 | 9 | AntiDebug::AntiDebug(void (*callback)()) : onDebuggerDetected(callback) { 10 | 11 | } 12 | 13 | const char *AntiDebug::getName() { 14 | return AY_OBFUSCATE("Debugger Detection"); 15 | } 16 | 17 | eSeverity AntiDebug::getSeverity() { 18 | return HIGH; 19 | } 20 | 21 | bool AntiDebug::execute() { 22 | LOGI("AntiDebug::execute"); 23 | if (scanStatus()) { 24 | return true; 25 | } 26 | if (scanTaskStatuses()) { 27 | return true; 28 | } 29 | LOGI("AntiDebug::execute false"); 30 | return false; 31 | } 32 | 33 | bool AntiDebug::scanStatus() { 34 | LOGI("AntiDebug::scanStatus"); 35 | int fd = SecureAPI::openat(AT_FDCWD, AY_OBFUSCATE("/proc/self/status"), O_RDONLY, 0); 36 | if (fd == -1) { 37 | return true; 38 | } 39 | LOGI("AntiDebug::scanStatus fd: %d", fd); 40 | 41 | if (checkTracerPid(fd)) { 42 | SecureAPI::close(fd); 43 | return true; 44 | } 45 | 46 | SecureAPI::close(fd); 47 | return false; 48 | } 49 | 50 | bool AntiDebug::scanTaskStatuses() { 51 | LOGI("AntiDebug::scanTaskStatuses"); 52 | int fd = SecureAPI::openat(AT_FDCWD, AY_OBFUSCATE("/proc/self/task"), O_RDONLY | O_DIRECTORY, 0); 53 | if (fd == -1) { 54 | return true; 55 | } 56 | 57 | struct linux_dirent64 *dirp; 58 | char buf[512]; 59 | int nread; 60 | 61 | while ((nread = SecureAPI::getdents64(fd, (struct linux_dirent64 *) buf, sizeof(buf))) > 0) { 62 | for (int bpos = 0; bpos < nread;) { 63 | dirp = (struct linux_dirent64 *) (buf + bpos); 64 | if (dirp->d_type == DT_DIR) { 65 | LOGI("AntiDebug::scanTaskStatuses dirp->d_name: %s", dirp->d_name); 66 | if (!SecureAPI::strcmp(dirp->d_name, AY_OBFUSCATE(".")) || !SecureAPI::strcmp(dirp->d_name, AY_OBFUSCATE(".."))) { 67 | bpos += dirp->d_reclen; 68 | continue; 69 | } 70 | 71 | char statusPath[512]; 72 | sprintf(statusPath, AY_OBFUSCATE("/proc/self/task/%s/status"), dirp->d_name); 73 | int statusFd = SecureAPI::openat(AT_FDCWD, statusPath, O_RDONLY, 0); 74 | LOGI("AntiDebug::scanTaskStatuses statusPath: %s | statusFd: %d", statusPath, statusFd); 75 | if (statusFd == -1) { 76 | bpos += dirp->d_reclen; 77 | continue; 78 | } 79 | 80 | if (checkTracerPid(statusFd)) { 81 | SecureAPI::close(statusFd); 82 | SecureAPI::close(fd); 83 | return true; 84 | } 85 | 86 | SecureAPI::close(statusFd); 87 | } 88 | bpos += dirp->d_reclen; 89 | } 90 | } 91 | 92 | SecureAPI::close(fd); 93 | return false; 94 | } 95 | 96 | bool AntiDebug::checkTracerPid(int fd) { 97 | char buf[512]; 98 | while (readLine(fd, buf, sizeof(buf)) > 0) { 99 | if (SecureAPI::strncmp(buf, AY_OBFUSCATE("TracerPid:"), 10) == 0) { 100 | int pid = atoi(buf + 10); 101 | LOGI("AntiDebug::checkTracerPid(%d) pid: %d", fd, pid); 102 | if (pid != 0) { 103 | if (this->onDebuggerDetected) { 104 | time_t now = time(0); 105 | if (std::find(this->m_debug_times.begin(), this->m_debug_times.end(), now) == this->m_debug_times.end()) { 106 | this->m_debug_times.push_back(now); 107 | this->onDebuggerDetected(); 108 | } 109 | } 110 | return true; 111 | } 112 | } 113 | } 114 | return false; 115 | } 116 | 117 | size_t AntiDebug::readLine(int fd, char *buf, size_t bufSize) { 118 | size_t i = 0, n; 119 | char c; 120 | while (i < bufSize - 1) { 121 | n = SecureAPI::read(fd, &c, 1); 122 | if (n == -1) { 123 | return -1; 124 | } 125 | 126 | if (n == 0 || c == '\n') { 127 | break; 128 | } 129 | 130 | buf[i++] = c; 131 | } 132 | buf[i] = '\0'; 133 | 134 | return i; 135 | } -------------------------------------------------------------------------------- /app/src/main/cpp/Modules/AntiDebug/AntiDebug.h: -------------------------------------------------------------------------------- 1 | #include "../IModule.h" 2 | 3 | class AntiDebug : public IModule { 4 | public: 5 | AntiDebug(void (*)()); 6 | const char *getName() override; 7 | eSeverity getSeverity() override; 8 | 9 | bool execute() override; 10 | private: 11 | bool scanStatus(); 12 | bool scanTaskStatuses(); 13 | 14 | bool checkTracerPid(int fd); 15 | size_t readLine(int fd, char *buf, size_t bufSize); 16 | 17 | std::vector m_debug_times; 18 | void (*onDebuggerDetected)(); 19 | }; -------------------------------------------------------------------------------- /app/src/main/cpp/Modules/AntiDump/AntiDump.cpp: -------------------------------------------------------------------------------- 1 | #include "AntiDump.h" 2 | #include "SecureAPI.h" 3 | #include "Log.h" 4 | #include "obfuscate.h" 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | AntiDump::AntiDump(void (*callback)()) : onDumpDetected(callback) { 13 | this->m_fd = SecureAPI::inotify_init1(0); 14 | if (this->m_fd == -1) { 15 | LOGI("AntiDump::execute inotify_init1 failed"); 16 | if (errno == EMFILE || errno == ENFILE) { 17 | LOGI("AntiDump::execute inotify_init1 probably failed because of max_user_watches being tampered."); 18 | } 19 | return; 20 | } 21 | 22 | this->m_wd[this->m_count++] = SecureAPI::inotify_add_watch(this->m_fd, AY_OBFUSCATE("/proc/self/maps"), IN_ACCESS | IN_OPEN); 23 | this->m_wd[this->m_count++] = SecureAPI::inotify_add_watch(this->m_fd, AY_OBFUSCATE("/proc/self/mem"), IN_ACCESS | IN_OPEN); 24 | this->m_wd[this->m_count++] = SecureAPI::inotify_add_watch(this->m_fd, AY_OBFUSCATE("/proc/self/pagemap"), IN_ACCESS | IN_OPEN); 25 | 26 | struct linux_dirent64 *dirp; 27 | char buf[512]; 28 | int nread; 29 | 30 | int task = SecureAPI::openat(AT_FDCWD, AY_OBFUSCATE("/proc/self/task"), O_RDONLY | O_DIRECTORY, 0); 31 | while ((nread = SecureAPI::getdents64(task, (struct linux_dirent64 *) buf, sizeof(buf))) > 0) { 32 | for (int bpos = 0; bpos < nread;) { 33 | dirp = (struct linux_dirent64 *) (buf + bpos); 34 | if (!SecureAPI::strcmp(dirp->d_name, AY_OBFUSCATE(".")) || 35 | !SecureAPI::strcmp(dirp->d_name, AY_OBFUSCATE(".."))) { 36 | bpos += dirp->d_reclen; 37 | continue; 38 | } 39 | if (dirp->d_type == DT_DIR) { 40 | char memPath[512], pagemapPath[512]; 41 | sprintf(memPath, AY_OBFUSCATE("/proc/self/task/%s/mem"), dirp->d_name); 42 | sprintf(pagemapPath, AY_OBFUSCATE("/proc/self/task/%s/pagemap"), dirp->d_name); 43 | 44 | this->m_wd[this->m_count++] = SecureAPI::inotify_add_watch(this->m_fd, memPath, IN_ACCESS | IN_OPEN); 45 | this->m_wd[this->m_count++] = SecureAPI::inotify_add_watch(this->m_fd, pagemapPath, IN_ACCESS | IN_OPEN); 46 | } 47 | bpos += dirp->d_reclen; 48 | } 49 | } 50 | SecureAPI::close(task); 51 | } 52 | 53 | const char *AntiDump::getName() { 54 | return AY_OBFUSCATE("Memory Dump Detection"); 55 | } 56 | 57 | eSeverity AntiDump::getSeverity() { 58 | return MEDIUM; 59 | } 60 | 61 | bool AntiDump::execute() { 62 | if (this->m_fd == -1) { 63 | return false; 64 | } 65 | 66 | char buf[4096]; 67 | int len = (int) SecureAPI::read(this->m_fd, buf, sizeof(buf)); 68 | if (len > 0) { 69 | LOGI("AntiDump::execute len: %d", len); 70 | struct inotify_event *event; 71 | for (char *ptr = buf; ptr < buf + len; ptr += sizeof(struct inotify_event) + event->len) { 72 | event = (struct inotify_event *) ptr; 73 | if (event->mask & IN_ACCESS || event->mask & IN_OPEN) { 74 | LOGI("AntiDump::execute event->mask: %d", event->mask); 75 | SecureAPI::close(this->m_fd); 76 | 77 | if (this->onDumpDetected) { 78 | time_t now = time(0); 79 | if (std::find(this->m_dump_times.begin(), this->m_dump_times.end(), now) == this->m_dump_times.end()) { 80 | this->m_dump_times.push_back(now); 81 | this->onDumpDetected(); 82 | } 83 | } 84 | return true; 85 | } 86 | } 87 | } 88 | return false; 89 | } -------------------------------------------------------------------------------- /app/src/main/cpp/Modules/AntiDump/AntiDump.h: -------------------------------------------------------------------------------- 1 | #include "../IModule.h" 2 | 3 | class AntiDump : public IModule { 4 | public: 5 | AntiDump(void (*)() = 0); 6 | const char *getName() override; 7 | eSeverity getSeverity() override; 8 | 9 | bool execute() override; 10 | private: 11 | int m_fd = -1; 12 | int m_wd[100]; 13 | int m_count = 0; 14 | 15 | std::vector m_dump_times; 16 | void (*onDumpDetected)(); 17 | }; -------------------------------------------------------------------------------- /app/src/main/cpp/Modules/AntiLibPatch/AntiLibPatch.cpp: -------------------------------------------------------------------------------- 1 | #include "AntiLibPatch.h" 2 | #include "SecureAPI.h" 3 | #include "Log.h" 4 | #include "obfuscate.h" 5 | #include "constants.h" 6 | #include "ElfImg.h" 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | static std::vector blacklists{ 18 | // Add your library here incase you don't want a certain library to be detected when it's tampered 19 | AY_OBFUSCATE("libclang_rt.ubsan_standalone-aarch64-android.so"), 20 | AY_OBFUSCATE("libart.so") 21 | }; 22 | 23 | _forceinline static uint32_t crc32(const uint8_t *data, size_t size) { 24 | uint32_t crc = 0xFFFFFFFF; 25 | for (size_t i = 0; i < size; i++) { 26 | crc ^= data[i]; 27 | for (size_t j = 0; j < 8; j++) { 28 | crc = (crc >> 1) ^ (0xEDB88320 & (-(crc & 1))); 29 | } 30 | } 31 | return ~crc; 32 | } 33 | 34 | AntiLibPatch::AntiLibPatch( 35 | void (*callback)(const char *libPath, 36 | uint32_t old_checksum, 37 | uint32_t new_checksum)) : onLibTampered(callback) { 38 | LOGI("AntiLibPatch::AntiLibPatch"); 39 | SandHook::ElfImg linker(AY_OBFUSCATE("/linker")); 40 | ElfW(Addr) soListAddress = linker.getSymbAddress( 41 | AY_OBFUSCATE("__dl__ZL6solist")); 42 | 43 | if (soListAddress == null) { 44 | return; 45 | } 46 | 47 | ElfW(Addr) soInfo = *(ElfW(Addr) *) (soListAddress); 48 | while (soInfo != null) { 49 | ElfW(Addr) next = *(ElfW(Addr) *) (soInfo + x32_64(0xA4, 0x28)); 50 | ElfW(Addr) baseAddress = *(ElfW(Addr) *) (soInfo + x32_64(0x104, 0xD0)); 51 | const char *soNameAddress = *(const char **) (soInfo + x32_64(0x108, 0xD8)); 52 | if (soNameAddress != nullptr) { 53 | struct dl_phdr_info info{}; 54 | info.dlpi_addr = baseAddress; 55 | info.dlpi_name = soNameAddress; 56 | info.dlpi_phdr = *(const ElfW(Phdr) **) (soInfo + x32_64(0x80, 0x0)); 57 | info.dlpi_phnum = *(ElfW(Half) *) (soInfo + x32_64(0x84, 0x8)); 58 | if (info.dlpi_phdr != nullptr) { 59 | LOGI("base %zx, libName %s\n", baseAddress, info.dlpi_name); 60 | 61 | bool blacklistedLibrary = false; 62 | for (auto &blacklistedName: blacklists) { 63 | if (SecureAPI::strstr(info.dlpi_name, blacklistedName.c_str())) { 64 | blacklistedLibrary = true; 65 | break; 66 | } 67 | } 68 | 69 | if (!blacklistedLibrary) { 70 | for (int i = 0; i < info.dlpi_phnum; ++i) { 71 | const ElfW(Phdr) *phdr = &info.dlpi_phdr[i]; 72 | if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_X) && 73 | (phdr->p_flags & PF_R)) { 74 | ElfW(Addr) start = phdr->p_vaddr; 75 | ElfW(Addr) end = start + phdr->p_memsz; 76 | 77 | auto regionAddress = reinterpret_cast(baseAddress + 78 | start); 79 | auto regionSize = end - start; 80 | uint32_t checksum = crc32(regionAddress, regionSize); 81 | 82 | if (checksum != 0) { 83 | regions.emplace_back(info.dlpi_name, 84 | info.dlpi_addr, 85 | std::pair(start, end), 86 | checksum); 87 | } 88 | } 89 | } 90 | } 91 | } 92 | } 93 | 94 | soInfo = next; 95 | } 96 | } 97 | 98 | const char *AntiLibPatch::getName() { 99 | return AY_OBFUSCATE("Lib. Patch & Hook Detection"); 100 | } 101 | 102 | eSeverity AntiLibPatch::getSeverity() { 103 | return HIGH; 104 | } 105 | 106 | bool AntiLibPatch::execute() { 107 | LOGI("AntiLibPatch::execute"); 108 | 109 | for (const auto ®ion: regions) { 110 | auto regionSize = region.chunkData.second - region.chunkData.first; 111 | auto *regionAddress = reinterpret_cast(region.baseAddress + 112 | region.chunkData.first); 113 | uint32_t currentChecksum = crc32(regionAddress, regionSize); 114 | if (currentChecksum != region.initialChecksum) { 115 | if (this->onLibTampered) { 116 | this->onLibTampered(region.libPath.c_str(), 117 | region.initialChecksum, 118 | currentChecksum); 119 | } 120 | 121 | return true; 122 | } 123 | } 124 | 125 | return false; 126 | } -------------------------------------------------------------------------------- /app/src/main/cpp/Modules/AntiLibPatch/AntiLibPatch.h: -------------------------------------------------------------------------------- 1 | #include "../IModule.h" 2 | #include "constants.h" 3 | 4 | struct ExecutableRegion { 5 | std::string libPath; 6 | Pointer baseAddress; 7 | std::pair chunkData; 8 | uint32_t initialChecksum; 9 | 10 | ExecutableRegion(std::string path, 11 | Pointer address, 12 | std::pair chunk, 13 | uint32_t initialChecksum) 14 | : libPath(std::move(path)), 15 | baseAddress(address), 16 | chunkData(std::move(chunk)), 17 | initialChecksum(initialChecksum) {} 18 | }; 19 | 20 | class AntiLibPatch : public IModule { 21 | using onLibTamperedCallbackType = void (*)(const char *libPath, 22 | uint32_t old_checksum, 23 | uint32_t new_checksum); 24 | onLibTamperedCallbackType onLibTampered; 25 | public: 26 | explicit AntiLibPatch(onLibTamperedCallbackType = nullptr); 27 | const char *getName() override; 28 | eSeverity getSeverity() override; 29 | 30 | bool execute() override; 31 | private: 32 | std::vector regions{}; 33 | }; -------------------------------------------------------------------------------- /app/src/main/cpp/Modules/FridaDetect/FridaDetect.cpp: -------------------------------------------------------------------------------- 1 | #include "FridaDetect.h" 2 | #include "SecureAPI.h" 3 | #include "Log.h" 4 | #include "obfuscate.h" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | FridaDetect::FridaDetect(void (*callback)()) : onFridaDetected(callback) { 18 | 19 | } 20 | 21 | const char *FridaDetect::getName() { 22 | return AY_OBFUSCATE("Frida Detection"); 23 | } 24 | 25 | eSeverity FridaDetect::getSeverity() { 26 | return HIGH; 27 | } 28 | 29 | bool FridaDetect::execute() { 30 | LOGI("FridaDetect::execute"); 31 | 32 | if (detectFridaAgent() || detectFridaPipe() || detectFridaListener()) { 33 | if (this->onFridaDetected) { 34 | time_t now = time(0); 35 | if (std::find(this->m_frida_times.begin(), this->m_frida_times.end(), now) == this->m_frida_times.end()) { 36 | this->m_frida_times.push_back(now); 37 | this->onFridaDetected(); 38 | } 39 | } 40 | return true; 41 | } 42 | return false; 43 | } 44 | 45 | bool FridaDetect::detectFridaAgent() { 46 | LOGI("FridaDetect::detectFridaAgent"); 47 | 48 | bool result = false; 49 | dl_iterate_phdr([](struct dl_phdr_info *info, size_t size, void *data) -> int { 50 | LOGI("FridaDetect::detectFridaAgent info->dlpi_name: %s", info->dlpi_name); 51 | if (SecureAPI::strstr(info->dlpi_name, AY_OBFUSCATE("frida-agent")) != nullptr) { 52 | LOGI("FridaDetect::detectFridaAgent found: %s", info->dlpi_name); 53 | *(bool *) data = true; 54 | return 1; 55 | } 56 | return 0; 57 | }, &result); 58 | return result; 59 | } 60 | 61 | bool FridaDetect::detectFridaPipe() { 62 | LOGI("FridaDetect::detectFridaPipe"); 63 | int fd = SecureAPI::openat(AT_FDCWD, AY_OBFUSCATE("/proc/self/fd"), O_RDONLY | O_DIRECTORY, 0); 64 | if (fd == -1) { 65 | return true; 66 | } 67 | LOGI("FridaDetect::detectFridaPipe fd: %d", fd); 68 | 69 | struct linux_dirent64 *dirp; 70 | char buf[512]; 71 | int nread; 72 | 73 | while ((nread = SecureAPI::getdents64(fd, (struct linux_dirent64 *) buf, sizeof(buf))) > 0) { 74 | for (int bpos = 0; bpos < nread;) { 75 | dirp = (struct linux_dirent64 *) (buf + bpos); 76 | if (dirp->d_type == DT_LNK) { 77 | LOGI("FridaDetect::detectFridaPipe dirp->d_name: %s", dirp->d_name); 78 | if (!SecureAPI::strcmp(dirp->d_name, AY_OBFUSCATE(".")) || !SecureAPI::strcmp(dirp->d_name, AY_OBFUSCATE(".."))) { 79 | bpos += dirp->d_reclen; 80 | continue; 81 | } 82 | 83 | char linkPath[512]; 84 | sprintf(linkPath, AY_OBFUSCATE("/proc/self/fd/%s"), dirp->d_name); 85 | char linkTarget[512]; 86 | int linkTargetLen = SecureAPI::readlinkat(fd, dirp->d_name, linkTarget, sizeof(linkTarget)); 87 | if (linkTargetLen == -1) { 88 | SecureAPI::close(fd); 89 | return true; 90 | } 91 | linkTarget[linkTargetLen] = '\0'; 92 | LOGI("FridaDetect::detectFridaPipe linkPath: %s | linkTarget: %s", linkPath, linkTarget); 93 | 94 | if (SecureAPI::strstr(linkTarget, AY_OBFUSCATE("linjector"))) { 95 | LOGI("FridaDetect::detectFridaPipe found: %s", linkTarget); 96 | SecureAPI::close(fd); 97 | return true; 98 | } 99 | } 100 | 101 | bpos += dirp->d_reclen; 102 | } 103 | } 104 | 105 | SecureAPI::close(fd); 106 | return false; 107 | } 108 | 109 | bool FridaDetect::detectFridaListener() { 110 | LOGI("FridaDetect::detectFridaListener"); 111 | struct sockaddr_in addr; 112 | addr.sin_family = AF_INET; 113 | addr.sin_addr.s_addr = htonl(INADDR_ANY); 114 | 115 | for (int i = 1; i < 65535; i++) { 116 | if (i == 39963) { // YouTube port (WTF???) 117 | continue; 118 | } 119 | 120 | int fd = SecureAPI::socket(AF_INET, SOCK_STREAM, 0); 121 | if (fd == -1) { 122 | LOGI("FridaDetect::detectFridaListener socket failed, errno: %d", errno); 123 | return true; 124 | } 125 | 126 | addr.sin_port = htons(i); 127 | int result = SecureAPI::connect(fd, (const struct sockaddr *) &addr, sizeof(addr)); 128 | if (result == -1 && errno != EINPROGRESS) { 129 | continue; 130 | } 131 | 132 | char req[1024]; 133 | sprintf(req, AY_OBFUSCATE("GET /ws HTTP/1.1\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Key: CpxD2C5REVLHvsUC9YAoqg==\r\nSec-WebSocket-Version: 13\r\nHost: %s:%d\r\nUser-Agent: Frida/16.1.7\r\n\r\n"), inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); 134 | SecureAPI::write(fd, req, SecureAPI::strlen(req)); 135 | 136 | char res[1024]; 137 | if (SecureAPI::read(fd, res, sizeof(res)) > 0) { 138 | if (SecureAPI::strstr(res, AY_OBFUSCATE("tyZql/Y8dNFFyopTrHadWzvbvRs="))) { 139 | LOGI("FridaDetect::detectFridaListener found fingerprint on port %d (WebSocket)", ntohs(addr.sin_port)); 140 | SecureAPI::close(fd); 141 | return true; 142 | } 143 | } 144 | 145 | SecureAPI::close(fd); 146 | } 147 | return false; 148 | } -------------------------------------------------------------------------------- /app/src/main/cpp/Modules/FridaDetect/FridaDetect.h: -------------------------------------------------------------------------------- 1 | #include "../IModule.h" 2 | 3 | class FridaDetect : public IModule { 4 | public: 5 | FridaDetect(void (*)()); 6 | const char *getName() override; 7 | eSeverity getSeverity() override; 8 | 9 | bool execute() override; 10 | private: 11 | bool detectFridaAgent(); 12 | bool detectFridaPipe(); 13 | bool detectFridaListener(); 14 | 15 | size_t readLine(int fd, char *buf, size_t bufSize); 16 | 17 | std::vector m_frida_times; 18 | void (*onFridaDetected)(); 19 | }; -------------------------------------------------------------------------------- /app/src/main/cpp/Modules/IModule.h: -------------------------------------------------------------------------------- 1 | #ifndef IMODULE 2 | #define IMODULE 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | enum eSeverity { 12 | HIGH, // Dangerous and might harm the application's integrity 13 | MEDIUM, // Not so dangerous but can be used to harm the application's integrity 14 | LOW // Common security issue and might not harm the application's integrity 15 | }; 16 | 17 | class IModule { 18 | public: 19 | virtual const char *getName() = 0; 20 | virtual eSeverity getSeverity() = 0; 21 | 22 | virtual bool execute() = 0; 23 | }; 24 | #endif -------------------------------------------------------------------------------- /app/src/main/cpp/Modules/RiGisk/RiGisk.cpp: -------------------------------------------------------------------------------- 1 | #include "RiGisk.h" 2 | #include "SecureAPI.h" 3 | #include "Log.h" 4 | #include "obfuscate.h" 5 | 6 | #include "ElfImg.h" 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | struct soinfo { 13 | #ifdef __LP64__ 14 | inline static size_t solist_next_offset = 0x30; 15 | constexpr static size_t solist_realpath_offset = 0x1a8; 16 | #else 17 | inline static size_t solist_next_offset = 0xa4; 18 | constexpr static size_t solist_realpath_offset = 0x174; 19 | #endif 20 | 21 | inline static const char *(*get_realpath_sym)(soinfo *) = nullptr; 22 | inline static const char *(*get_soname_sym)(soinfo *) = nullptr; 23 | 24 | soinfo *next() { 25 | return *(soinfo **) ((uintptr_t) this + solist_next_offset); 26 | } 27 | 28 | const char *get_realpath() { 29 | return get_realpath_sym ? get_realpath_sym(this) : 30 | ((std::string *) ((uintptr_t) this + solist_realpath_offset))->c_str(); 31 | } 32 | 33 | const char *get_soname() { 34 | return get_soname_sym ? get_soname_sym(this) : 35 | *((const char **) ((uintptr_t) this + solist_realpath_offset - sizeof(void *))); 36 | } 37 | }; 38 | 39 | soinfo *solist = nullptr; 40 | soinfo *somain = nullptr; 41 | std::vector *preloads = nullptr; 42 | 43 | template inline T *getStaticPointer(const SandHook::ElfImg &linker, std::string_view name) { 44 | auto *addr = reinterpret_cast(linker.getSymbAddress(name.data())); 45 | return addr == nullptr ? nullptr : *addr; 46 | } 47 | 48 | const char *RiGisk::getName() { 49 | return AY_OBFUSCATE("Riru & Zygisk Detection"); 50 | } 51 | 52 | eSeverity RiGisk::getSeverity() { 53 | return MEDIUM; 54 | } 55 | 56 | bool RiGisk::execute() { 57 | LOGI("RiGisk::execute"); 58 | 59 | SandHook::ElfImg linker(AY_OBFUSCATE("/linker")); 60 | solist = getStaticPointer(linker, AY_OBFUSCATE("__dl__ZL6solist")); 61 | somain = getStaticPointer(linker, AY_OBFUSCATE("__dl__ZL6somain")); 62 | preloads = reinterpret_cast *>(linker.getSymbAddress(AY_OBFUSCATE("__dl__ZL13g_ld_preloads"))); 63 | LOGI("RiGisk::execute solist: %p, somain: %p, preloads: %p", solist, somain, preloads); 64 | 65 | soinfo::get_realpath_sym = reinterpret_cast(linker.getSymbAddress(AY_OBFUSCATE("__dl__ZNK6soinfo12get_realpathEv"))); 66 | soinfo::get_soname_sym = reinterpret_cast(linker.getSymbAddress(AY_OBFUSCATE("__dl__ZNK6soinfo10get_sonameEv"))); 67 | LOGI("RiGisk::execute get_realpath_sym: %p, get_soname_sym: %p", soinfo::get_realpath_sym, soinfo::get_soname_sym); 68 | 69 | auto vsdo = getStaticPointer(linker, AY_OBFUSCATE("__dl__ZL4vdso")); 70 | LOGI("RiGisk::execute vsdo: %p", vsdo); 71 | for (size_t i = 0; i < 1024 / sizeof(void *); i++) { 72 | auto *possible_next = *(void **) ((uintptr_t) solist + i * sizeof(void *)); 73 | if (possible_next == somain || (vsdo != nullptr && possible_next == vsdo)) { 74 | soinfo::solist_next_offset = i * sizeof(void *); 75 | LOGI("RiGisk::execute solist_next_offset: %zu", soinfo::solist_next_offset); 76 | break; 77 | } 78 | } 79 | 80 | if (somain) { 81 | for (auto *iter = somain; iter; iter = iter->next()) { 82 | LOGI("RiGisk::execute somain so: %p, realpath: %s, soname: %s", iter, iter->get_realpath(), iter->get_soname()); 83 | if (iter->get_realpath() && iter->get_soname()) { 84 | if (SecureAPI::strstr(iter->get_realpath(), AY_OBFUSCATE("riru"))) { 85 | LOGI("RiGisk::execute riru detected"); 86 | return true; 87 | } else if (SecureAPI::strstr(iter->get_soname(), AY_OBFUSCATE("riru"))) { 88 | LOGI("RiGisk::execute riru detected"); 89 | return true; 90 | } 91 | } 92 | } 93 | } 94 | 95 | if (solist) { 96 | for (auto *iter = solist; iter; iter = iter->next()) { 97 | LOGI("RiGisk::execute solist so: %p, realpath: %s, soname: %s", iter, iter->get_realpath(), iter->get_soname()); 98 | if (iter->get_realpath() && iter->get_soname()) { 99 | if (SecureAPI::strstr(iter->get_realpath(), AY_OBFUSCATE("riru"))) { 100 | LOGI("RiGisk::execute riru detected"); 101 | return true; 102 | } else if (SecureAPI::strstr(iter->get_soname(), AY_OBFUSCATE("riru"))) { 103 | LOGI("RiGisk::execute riru detected"); 104 | return true; 105 | } 106 | } 107 | } 108 | } 109 | 110 | if (preloads) { 111 | for (auto so: *preloads) { 112 | LOGI("RiGisk::execute preloads so: %p, realpath: %s, soname: %s", so, so->get_realpath(), so->get_soname()); 113 | if (so->get_realpath() && so->get_soname()) { 114 | if (SecureAPI::strstr(so->get_realpath(), AY_OBFUSCATE("zygisk"))) { 115 | LOGI("RiGisk::execute zygisk detected"); 116 | return true; 117 | } else if (SecureAPI::strstr(so->get_soname(), AY_OBFUSCATE("zygisk"))) { 118 | LOGI("RiGisk::execute zygisk detected"); 119 | return true; 120 | } 121 | } 122 | } 123 | } 124 | 125 | return false; 126 | } -------------------------------------------------------------------------------- /app/src/main/cpp/Modules/RiGisk/RiGisk.h: -------------------------------------------------------------------------------- 1 | #include "../IModule.h" 2 | 3 | class RiGisk : public IModule { 4 | public: 5 | const char *getName() override; 6 | eSeverity getSeverity() override; 7 | 8 | bool execute() override; 9 | private: 10 | bool detectRiru(); 11 | bool detectZygisk(); 12 | 13 | size_t readLine(int fd, char *buf, size_t bufSize); 14 | }; -------------------------------------------------------------------------------- /app/src/main/cpp/Modules/RootDetect/RootDetect.cpp: -------------------------------------------------------------------------------- 1 | #include "RootDetect.h" 2 | #include "SecureAPI.h" 3 | #include "Log.h" 4 | #include "obfuscate.h" 5 | 6 | #include 7 | #include 8 | 9 | static const char *suBinaries[] = { 10 | AY_OBFUSCATE("/data/local/su"), 11 | AY_OBFUSCATE("/data/local/bin/su"), 12 | AY_OBFUSCATE("/data/local/xbin/su"), 13 | AY_OBFUSCATE("/sbin/su"), 14 | AY_OBFUSCATE("/su/bin/su"), 15 | AY_OBFUSCATE("/system/bin/su"), 16 | AY_OBFUSCATE("/system/bin/.ext/su"), 17 | AY_OBFUSCATE("/system/bin/failsafe/su"), 18 | AY_OBFUSCATE("/system/sd/xbin/su"), 19 | AY_OBFUSCATE("/system/usr/we-need-root/su"), 20 | AY_OBFUSCATE("/system/xbin/su"), 21 | AY_OBFUSCATE("/cache/su"), 22 | AY_OBFUSCATE("/data/su"), 23 | AY_OBFUSCATE("/dev/su") 24 | }; 25 | static const char *magiskMounts[] = { 26 | AY_OBFUSCATE("magisk"), 27 | AY_OBFUSCATE("core/mirror"), 28 | AY_OBFUSCATE("core/img") 29 | }; 30 | 31 | const char *RootDetect::getName() { 32 | return AY_OBFUSCATE("Root Detection"); 33 | } 34 | 35 | eSeverity RootDetect::getSeverity() { 36 | return LOW; 37 | } 38 | 39 | bool RootDetect::execute() { 40 | LOGI("RootDetect::execute"); 41 | if (detectSuBinaries()) { 42 | return true; 43 | } 44 | if (detectMagiskMount()) { 45 | return true; 46 | } 47 | return false; 48 | } 49 | 50 | bool RootDetect::detectSuBinaries() { 51 | for (const char *suBinary : suBinaries) { 52 | int fd = SecureAPI::openat(AT_FDCWD, suBinary, O_RDONLY, 0); 53 | if (fd > 0) { 54 | LOGI("RootDetect::execute su binary detected: %s", suBinary); 55 | SecureAPI::close(fd); 56 | return true; 57 | } 58 | 59 | if (SecureAPI::access(suBinary, F_OK) == 0) { 60 | LOGI("RootDetect::execute su binary detected: %s", suBinary); 61 | return true; 62 | } 63 | } 64 | return false; 65 | } 66 | 67 | bool RootDetect::detectMagiskMount() { 68 | int fd = SecureAPI::openat(AT_FDCWD, AY_OBFUSCATE("/proc/self/mounts"), O_RDONLY, 0); 69 | if (fd == -1) { 70 | return true; 71 | } 72 | 73 | char buf[512]; 74 | while (SecureAPI::read(fd, buf, sizeof(buf)) > 0) { 75 | for (const char *magiskMount : magiskMounts) { 76 | if (strstr(buf, magiskMount)) { 77 | LOGI("RootDetect::execute magisk mount detected: %s", magiskMount); 78 | SecureAPI::close(fd); 79 | return true; 80 | } 81 | } 82 | } 83 | 84 | SecureAPI::close(fd); 85 | return false; 86 | } -------------------------------------------------------------------------------- /app/src/main/cpp/Modules/RootDetect/RootDetect.h: -------------------------------------------------------------------------------- 1 | #include "../IModule.h" 2 | 3 | class RootDetect : public IModule { 4 | public: 5 | const char *getName() override; 6 | eSeverity getSeverity() override; 7 | 8 | bool execute() override; 9 | private: 10 | bool detectSuBinaries(); 11 | bool detectMagiskMount(); 12 | 13 | size_t readLine(int fd, char *buf, size_t bufSize); 14 | }; -------------------------------------------------------------------------------- /app/src/main/cpp/SecureAPI/SecureAPI.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #ifdef __arm__ 15 | #include "syscall/armeabi-v7a/syscall_arch.h" 16 | #elif defined(__aarch64__) 17 | #include "syscall/arm64-v8a/syscall_arch.h" 18 | #elif defined(__i386__) 19 | #include "syscall/x86/syscall_arch.h" 20 | #elif defined(__x86_64__) 21 | #include "syscall/x86_64/syscall_arch.h" 22 | #endif 23 | 24 | struct linux_dirent64 { 25 | unsigned long long d_ino; 26 | long long d_off; 27 | unsigned short d_reclen; 28 | unsigned char d_type; 29 | char d_name[]; 30 | }; 31 | 32 | namespace SecureAPI { 33 | __attribute__((always_inline)) inline int openat(int dirfd, const char *pathname, int flags, mode_t mode) { 34 | return (int) __syscall4(__NR_openat, dirfd, (long) pathname, flags, mode); 35 | } 36 | 37 | __attribute__((always_inline)) inline size_t read(int fd, void *buf, size_t count) { 38 | return (size_t) __syscall3(__NR_read, fd, (long) buf, count); 39 | } 40 | 41 | __attribute__((always_inline)) inline size_t write(int fd, const void *buf, size_t count) { 42 | return (size_t) __syscall3(__NR_write, fd, (long) buf, count); 43 | } 44 | 45 | __attribute__((always_inline)) inline off_t lseek(int fd, off_t offset, int whence) { 46 | return (off_t) __syscall3(__NR_lseek, fd, offset, whence); 47 | } 48 | 49 | __attribute__((always_inline)) inline int close(int fd) { 50 | return (int) __syscall1(__NR_close, fd); 51 | } 52 | 53 | __attribute__((always_inline)) inline int access(const char *pathname, int mode) { 54 | #ifdef __arm__ 55 | return (int) __syscall2(__NR_access, (long) pathname, mode); 56 | #else 57 | return (int) __syscall3(__NR_faccessat, AT_FDCWD, (long) pathname, mode); 58 | #endif 59 | } 60 | 61 | __attribute__((always_inline)) inline ssize_t getdents64(unsigned int fd, struct linux_dirent64 *dirp, unsigned int count) { 62 | return (ssize_t) __syscall3(__NR_getdents64, fd, (long) dirp, count); 63 | } 64 | 65 | __attribute__((always_inline)) inline int readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz) { 66 | return (int) __syscall4(__NR_readlinkat, dirfd, (long) pathname, (long) buf, bufsiz); 67 | } 68 | 69 | __attribute__((always_inline)) inline int inotify_init1(int flags) { 70 | return (int) __syscall1(__NR_inotify_init1, flags); 71 | } 72 | 73 | __attribute__((always_inline)) inline int inotify_add_watch(int fd, const char *pathname, uint32_t mask) { 74 | return (int) __syscall3(__NR_inotify_add_watch, fd, (long) pathname, mask); 75 | } 76 | 77 | __attribute__((always_inline)) inline int inotify_rm_watch(int fd, int wd) { 78 | return (int) __syscall2(__NR_inotify_rm_watch, fd, wd); 79 | } 80 | 81 | __attribute__((always_inline)) inline int socket(int domain, int type, int protocol) { 82 | return (int) __syscall3(__NR_socket, domain, type, protocol); 83 | } 84 | 85 | __attribute__((always_inline)) inline int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { 86 | return (int) __syscall3(__NR_connect, sockfd, (long) addr, addrlen); 87 | } 88 | 89 | __attribute__((always_inline)) inline int strcmp(const char *s1, const char *s2) { 90 | while (*s1 && (*s1 == *s2)) { 91 | s1++; 92 | s2++; 93 | } 94 | return *(const unsigned char *) s1 - *(const unsigned char *) s2; 95 | } 96 | 97 | __attribute__((always_inline)) inline int strncmp(const char *s1, const char *s2, size_t n) { 98 | if (n == 0) { 99 | return 0; 100 | } 101 | do { 102 | if (*s1 != *s2++) { 103 | return (*(const unsigned char *) s1 - *(const unsigned char *) --s2); 104 | } 105 | if (*s1++ == 0) { 106 | break; 107 | } 108 | } while (--n != 0); 109 | return 0; 110 | } 111 | 112 | __attribute__((always_inline)) inline char *strchr(const char *s, int c) { 113 | while (*s != (char) c) { 114 | if (!*s++) { 115 | return NULL; 116 | } 117 | } 118 | return (char *) s; 119 | } 120 | 121 | __attribute__((always_inline)) inline size_t strlen(const char *s) { 122 | const char *sc; 123 | for (sc = s; *sc != '\0'; ++sc) { 124 | } 125 | return sc - s; 126 | } 127 | 128 | __attribute__((always_inline)) inline int memcmp(const void *s1, const void *s2, size_t n) { 129 | const unsigned char *p1 = (const unsigned char *) s1, *p2 = (const unsigned char *) s2; 130 | while (n-- > 0) { 131 | if (*p1 != *p2) { 132 | return *p1 - *p2; 133 | } 134 | ++p1; 135 | ++p2; 136 | } 137 | return 0; 138 | } 139 | 140 | __attribute__((always_inline)) inline void *memcpy(void *dest, const void *src, size_t n) { 141 | char *dp = (char *) dest; 142 | const char *sp = (const char *) src; 143 | while (n-- > 0) { 144 | *dp++ = *sp++; 145 | } 146 | return dest; 147 | } 148 | 149 | __attribute__((always_inline)) inline void *memset(void *s, int c, size_t n) { 150 | unsigned char *p = (unsigned char *) s; 151 | while (n-- > 0) { 152 | *p++ = (unsigned char) c; 153 | } 154 | return s; 155 | } 156 | 157 | __attribute__((always_inline)) inline const char *strstr(const char *haystack, const char *needle) { 158 | size_t needle_len = SecureAPI::strlen(needle); 159 | if (!needle_len) { 160 | return haystack; 161 | } 162 | const char *p = haystack; 163 | while ((p = SecureAPI::strchr(p, *needle)) != NULL) { 164 | if (!SecureAPI::memcmp(p, needle, needle_len)) { 165 | return p; 166 | } 167 | p++; 168 | } 169 | return NULL; 170 | } 171 | } -------------------------------------------------------------------------------- /app/src/main/cpp/SecureAPI/syscall/arm64-v8a/syscall_arch.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------- 2 | Copyright © 2005-2020 Rich Felker, et al. 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining 5 | a copy of this software and associated documentation files (the 6 | "Software"), to deal in the Software without restriction, including 7 | without limitation the rights to use, copy, modify, merge, publish, 8 | distribute, sublicense, and/or sell copies of the Software, and to 9 | permit persons to whom the Software is furnished to do so, subject to 10 | the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | ----------------------------------------------------------------------*/ 23 | #define __SYSCALL_LL_E(x) (x) 24 | #define __SYSCALL_LL_O(x) (x) 25 | 26 | #define __asm_syscall(...) do { \ 27 | __asm__ __volatile__ ( "svc 0" \ 28 | : "=r"(x0) : __VA_ARGS__ : "memory", "cc"); \ 29 | return x0; \ 30 | } while (0) 31 | 32 | __attribute__((always_inline)) 33 | static inline long __syscall0(long n) 34 | { 35 | register long x8 __asm__("x8") = n; 36 | register long x0 __asm__("x0"); 37 | __asm_syscall("r"(x8)); 38 | } 39 | 40 | __attribute__((always_inline)) 41 | static inline long __syscall1(long n, long a) 42 | { 43 | register long x8 __asm__("x8") = n; 44 | register long x0 __asm__("x0") = a; 45 | __asm_syscall("r"(x8), "0"(x0)); 46 | } 47 | __attribute__((always_inline)) 48 | static inline long __syscall2(long n, long a, long b) 49 | { 50 | register long x8 __asm__("x8") = n; 51 | register long x0 __asm__("x0") = a; 52 | register long x1 __asm__("x1") = b; 53 | __asm_syscall("r"(x8), "0"(x0), "r"(x1)); 54 | } 55 | __attribute__((always_inline)) 56 | static inline long __syscall3(long n, long a, long b, long c) 57 | { 58 | register long x8 __asm__("x8") = n; 59 | register long x0 __asm__("x0") = a; 60 | register long x1 __asm__("x1") = b; 61 | register long x2 __asm__("x2") = c; 62 | __asm_syscall("r"(x8), "0"(x0), "r"(x1), "r"(x2)); 63 | } 64 | __attribute__((always_inline)) 65 | static inline long __syscall4(long n, long a, long b, long c, long d) 66 | { 67 | register long x8 __asm__("x8") = n; 68 | register long x0 __asm__("x0") = a; 69 | register long x1 __asm__("x1") = b; 70 | register long x2 __asm__("x2") = c; 71 | register long x3 __asm__("x3") = d; 72 | __asm_syscall("r"(x8), "0"(x0), "r"(x1), "r"(x2), "r"(x3)); 73 | } 74 | 75 | __attribute__((always_inline)) 76 | static inline long __syscall5(long n, long a, long b, long c, long d, long e) 77 | { 78 | register long x8 __asm__("x8") = n; 79 | register long x0 __asm__("x0") = a; 80 | register long x1 __asm__("x1") = b; 81 | register long x2 __asm__("x2") = c; 82 | register long x3 __asm__("x3") = d; 83 | register long x4 __asm__("x4") = e; 84 | __asm_syscall("r"(x8), "0"(x0), "r"(x1), "r"(x2), "r"(x3), "r"(x4)); 85 | } 86 | 87 | __attribute__((always_inline)) 88 | static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f) 89 | { 90 | register long x8 __asm__("x8") = n; 91 | register long x0 __asm__("x0") = a; 92 | register long x1 __asm__("x1") = b; 93 | register long x2 __asm__("x2") = c; 94 | register long x3 __asm__("x3") = d; 95 | register long x4 __asm__("x4") = e; 96 | register long x5 __asm__("x5") = f; 97 | __asm_syscall("r"(x8), "0"(x0), "r"(x1), "r"(x2), "r"(x3), "r"(x4), "r"(x5)); 98 | } 99 | 100 | #define VDSO_USEFUL 101 | #define VDSO_CGT_SYM "__kernel_clock_gettime" 102 | #define VDSO_CGT_VER "LINUX_2.6.39" 103 | 104 | #define IPC_64 0 105 | -------------------------------------------------------------------------------- /app/src/main/cpp/SecureAPI/syscall/armeabi-v7a/syscall_arch.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------- 2 | Copyright © 2005-2020 Rich Felker, et al. 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining 5 | a copy of this software and associated documentation files (the 6 | "Software"), to deal in the Software without restriction, including 7 | without limitation the rights to use, copy, modify, merge, publish, 8 | distribute, sublicense, and/or sell copies of the Software, and to 9 | permit persons to whom the Software is furnished to do so, subject to 10 | the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | ----------------------------------------------------------------------*/ 23 | #define __SYSCALL_LL_E(x) \ 24 | ((union { long long ll; long l[2]; }){ .ll = x }).l[0], \ 25 | ((union { long long ll; long l[2]; }){ .ll = x }).l[1] 26 | #define __SYSCALL_LL_O(x) 0, __SYSCALL_LL_E((x)) 27 | 28 | #ifdef __thumb__ 29 | 30 | /* Avoid use of r7 in asm constraints when producing thumb code, 31 | * since it's reserved as frame pointer and might not be supported. */ 32 | #define __ASM____R7__ 33 | #define __asm_syscall(...) do { \ 34 | __asm__ __volatile__ ( "mov %1,r7 ; mov r7,%2 ; svc 0 ; mov r7,%1" \ 35 | : "=r"(r0), "=&r"((int){0}) : __VA_ARGS__ : "memory"); \ 36 | return r0; \ 37 | } while (0) 38 | 39 | #else 40 | 41 | #define __ASM____R7__ __asm__("r7") 42 | #define __asm_syscall(...) do { \ 43 | __asm__ __volatile__ ( "svc 0" \ 44 | : "=r"(r0) : __VA_ARGS__ : "memory"); \ 45 | return r0; \ 46 | } while (0) 47 | #endif 48 | 49 | /* For thumb2, we can allow 8-bit immediate syscall numbers, saving a 50 | * register in the above dance around r7. Does not work for thumb1 where 51 | * only movs, not mov, supports immediates, and we can't use movs because 52 | * it doesn't support high regs. */ 53 | #ifdef __thumb2__ 54 | #define R7_OPERAND "rI"(r7) 55 | #else 56 | #define R7_OPERAND "r"(r7) 57 | #endif 58 | 59 | __attribute__((always_inline)) 60 | static inline long __syscall0(long n) 61 | { 62 | register long r7 __ASM____R7__ = n; 63 | register long r0 __asm__("r0"); 64 | __asm_syscall(R7_OPERAND); 65 | } 66 | 67 | __attribute__((always_inline)) 68 | static inline long __syscall1(long n, long a) 69 | { 70 | register long r7 __ASM____R7__ = n; 71 | register long r0 __asm__("r0") = a; 72 | __asm_syscall(R7_OPERAND, "0"(r0)); 73 | } 74 | 75 | __attribute__((always_inline)) 76 | static inline long __syscall2(long n, long a, long b) 77 | { 78 | register long r7 __ASM____R7__ = n; 79 | register long r0 __asm__("r0") = a; 80 | register long r1 __asm__("r1") = b; 81 | __asm_syscall(R7_OPERAND, "0"(r0), "r"(r1)); 82 | } 83 | 84 | __attribute__((always_inline)) 85 | static inline long __syscall3(long n, long a, long b, long c) 86 | { 87 | register long r7 __ASM____R7__ = n; 88 | register long r0 __asm__("r0") = a; 89 | register long r1 __asm__("r1") = b; 90 | register long r2 __asm__("r2") = c; 91 | __asm_syscall(R7_OPERAND, "0"(r0), "r"(r1), "r"(r2)); 92 | } 93 | 94 | __attribute__((always_inline)) 95 | static inline long __syscall4(long n, long a, long b, long c, long d) 96 | { 97 | register long r7 __ASM____R7__ = n; 98 | register long r0 __asm__("r0") = a; 99 | register long r1 __asm__("r1") = b; 100 | register long r2 __asm__("r2") = c; 101 | register long r3 __asm__("r3") = d; 102 | __asm_syscall(R7_OPERAND, "0"(r0), "r"(r1), "r"(r2), "r"(r3)); 103 | } 104 | 105 | __attribute__((always_inline)) 106 | static inline long __syscall5(long n, long a, long b, long c, long d, long e) 107 | { 108 | register long r7 __ASM____R7__ = n; 109 | register long r0 __asm__("r0") = a; 110 | register long r1 __asm__("r1") = b; 111 | register long r2 __asm__("r2") = c; 112 | register long r3 __asm__("r3") = d; 113 | register long r4 __asm__("r4") = e; 114 | __asm_syscall(R7_OPERAND, "0"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4)); 115 | } 116 | 117 | __attribute__((always_inline)) 118 | static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f) 119 | { 120 | register long r7 __ASM____R7__ = n; 121 | register long r0 __asm__("r0") = a; 122 | register long r1 __asm__("r1") = b; 123 | register long r2 __asm__("r2") = c; 124 | register long r3 __asm__("r3") = d; 125 | register long r4 __asm__("r4") = e; 126 | register long r5 __asm__("r5") = f; 127 | __asm_syscall(R7_OPERAND, "0"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r5)); 128 | } 129 | 130 | #define VDSO_USEFUL 131 | #define VDSO_CGT32_SYM "__vdso_clock_gettime" 132 | #define VDSO_CGT32_VER "LINUX_2.6" 133 | #define VDSO_CGT_SYM "__vdso_clock_gettime64" 134 | #define VDSO_CGT_VER "LINUX_2.6" 135 | 136 | #define SYSCALL_FADVISE_6_ARG 137 | 138 | #define SYSCALL_IPC_BROKEN_MODE 139 | -------------------------------------------------------------------------------- /app/src/main/cpp/SecureAPI/syscall/x86/syscall_arch.h: -------------------------------------------------------------------------------- 1 | //#define __SYSCALL_LL_E(x) (x) 2 | //#define __SYSCALL_LL_O(x) (x) 3 | // 4 | //#define __scc(X) sizeof(1?(X):0ULL) < 8 ? (unsigned long) (X) : (long long) (X) 5 | //typedef long long syscall_arg_t; 6 | // 7 | //static __inline long __syscall0(long long n) 8 | //{ 9 | // unsigned long ret; 10 | // __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n) : "rcx", "r11", "memory"); 11 | // return ret; 12 | //} 13 | // 14 | //static __inline long __syscall1(long long n, long long a1) 15 | //{ 16 | // unsigned long ret; 17 | // __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1) : "rcx", "r11", "memory"); 18 | // return ret; 19 | //} 20 | // 21 | //static __inline long __syscall2(long long n, long long a1, long long a2) 22 | //{ 23 | // unsigned long ret; 24 | // __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2) 25 | // : "rcx", "r11", "memory"); 26 | // return ret; 27 | //} 28 | // 29 | //static __inline long __syscall3(long long n, long long a1, long long a2, long long a3) 30 | //{ 31 | // unsigned long ret; 32 | // __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2), 33 | // "d"(a3) : "rcx", "r11", "memory"); 34 | // return ret; 35 | //} 36 | // 37 | //static __inline long __syscall4(long long n, long long a1, long long a2, long long a3, 38 | // long long a4_) 39 | //{ 40 | // unsigned long ret; 41 | // register long long a4 __asm__("r10") = a4_; 42 | // __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2), 43 | // "d"(a3), "r"(a4): "rcx", "r11", "memory"); 44 | // return ret; 45 | //} 46 | // 47 | //static __inline long __syscall5(long long n, long long a1, long long a2, long long a3, 48 | // long long a4_, long long a5_) 49 | //{ 50 | // unsigned long ret; 51 | // register long long a4 __asm__("r10") = a4_; 52 | // register long long a5 __asm__("r8") = a5_; 53 | // __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2), 54 | // "d"(a3), "r"(a4), "r"(a5) : "rcx", "r11", "memory"); 55 | // return ret; 56 | //} 57 | // 58 | //static __inline long __syscall6(long long n, long long a1, long long a2, long long a3, 59 | // long long a4_, long long a5_, long long a6_) 60 | //{ 61 | // unsigned long ret; 62 | // register long long a4 __asm__("r10") = a4_; 63 | // register long long a5 __asm__("r8") = a5_; 64 | // register long long a6 __asm__("r9") = a6_; 65 | // __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2), 66 | // "d"(a3), "r"(a4), "r"(a5), "r"(a6) : "rcx", "r11", "memory"); 67 | // return ret; 68 | //} 69 | // 70 | //#undef SYS_futimesat 71 | // 72 | //#define SYS_clock_gettime64 SYS_clock_gettime 73 | //#define SYS_clock_settime64 SYS_clock_settime 74 | //#define SYS_clock_adjtime64 SYS_clock_adjtime 75 | //#define SYS_clock_nanosleep_time64 SYS_clock_nanosleep 76 | //#define SYS_timer_gettime64 SYS_timer_gettime 77 | //#define SYS_timer_settime64 SYS_timer_settime 78 | //#define SYS_timerfd_gettime64 SYS_timerfd_gettime 79 | //#define SYS_timerfd_settime64 SYS_timerfd_settime 80 | //#define SYS_utimensat_time64 SYS_utimensat 81 | //#define SYS_pselect6_time64 SYS_pselect6 82 | //#define SYS_ppoll_time64 SYS_ppoll 83 | //#define SYS_recvmmsg_time64 SYS_recvmmsg 84 | //#define SYS_mq_timedsend_time64 SYS_mq_timedsend 85 | //#define SYS_mq_timedreceive_time64 SYS_mq_timedreceive 86 | //#define SYS_semtimedop_time64 SYS_semtimedop 87 | //#define SYS_rt_sigtimedwait_time64 SYS_rt_sigtimedwait 88 | //#define SYS_futex_time64 SYS_futex 89 | //#define SYS_sched_rr_get_interval_time64 SYS_sched_rr_get_interval 90 | //#define SYS_getrusage_time64 SYS_getrusage 91 | //#define SYS_wait4_time64 SYS_wait4 92 | // 93 | //#define IPC_64 0 94 | 95 | 96 | #define __SYSCALL_LL_E(x) \ 97 | ((union { long long ll; long l[2]; }){ .ll = x }).l[0], \ 98 | ((union { long long ll; long l[2]; }){ .ll = x }).l[1] 99 | #define __SYSCALL_LL_O(x) __SYSCALL_LL_E((x)) 100 | 101 | #if SYSCALL_NO_TLS 102 | #define SYSCALL_INSNS "int $128" 103 | #else 104 | #define SYSCALL_INSNS "call *%%gs:16" 105 | #endif 106 | 107 | #define SYSCALL_INSNS_12 "xchg %%ebx,%%edx ; " SYSCALL_INSNS " ; xchg %%ebx,%%edx" 108 | #define SYSCALL_INSNS_34 "xchg %%ebx,%%edi ; " SYSCALL_INSNS " ; xchg %%ebx,%%edi" 109 | 110 | static inline long __syscall0(long n) 111 | { 112 | unsigned long __ret; 113 | __asm__ __volatile__ (SYSCALL_INSNS : "=a"(__ret) : "a"(n) : "memory"); 114 | return __ret; 115 | } 116 | 117 | static inline long __syscall1(long n, long a1) 118 | { 119 | unsigned long __ret; 120 | __asm__ __volatile__ (SYSCALL_INSNS_12 : "=a"(__ret) : "a"(n), "d"(a1) : "memory"); 121 | return __ret; 122 | } 123 | 124 | static inline long __syscall2(long n, long a1, long a2) 125 | { 126 | unsigned long __ret; 127 | __asm__ __volatile__ (SYSCALL_INSNS_12 : "=a"(__ret) : "a"(n), "d"(a1), "c"(a2) : "memory"); 128 | return __ret; 129 | } 130 | 131 | static inline long __syscall3(long n, long a1, long a2, long a3) 132 | { 133 | unsigned long __ret; 134 | #if !defined(__PIC__) || !defined(BROKEN_EBX_ASM) 135 | __asm__ __volatile__ (SYSCALL_INSNS : "=a"(__ret) : "a"(n), "b"(a1), "c"(a2), "d"(a3) : "memory"); 136 | #else 137 | __asm__ __volatile__ (SYSCALL_INSNS_34 : "=a"(__ret) : "a"(n), "D"(a1), "c"(a2), "d"(a3) : "memory"); 138 | #endif 139 | return __ret; 140 | } 141 | 142 | static inline long __syscall4(long n, long a1, long a2, long a3, long a4) 143 | { 144 | unsigned long __ret; 145 | #if !defined(__PIC__) || !defined(BROKEN_EBX_ASM) 146 | __asm__ __volatile__ (SYSCALL_INSNS : "=a"(__ret) : "a"(n), "b"(a1), "c"(a2), "d"(a3), "S"(a4) : "memory"); 147 | #else 148 | __asm__ __volatile__ (SYSCALL_INSNS_34 : "=a"(__ret) : "a"(n), "D"(a1), "c"(a2), "d"(a3), "S"(a4) : "memory"); 149 | #endif 150 | return __ret; 151 | } 152 | 153 | static inline long __syscall5(long n, long a1, long a2, long a3, long a4, long a5) 154 | { 155 | unsigned long __ret; 156 | #if !defined(__PIC__) || !defined(BROKEN_EBX_ASM) 157 | __asm__ __volatile__ (SYSCALL_INSNS 158 | : "=a"(__ret) : "a"(n), "b"(a1), "c"(a2), "d"(a3), "S"(a4), "D"(a5) : "memory"); 159 | #else 160 | __asm__ __volatile__ ("pushl %2 ; push %%ebx ; mov 4(%%esp),%%ebx ; " SYSCALL_INSNS " ; pop %%ebx ; add $4,%%esp" 161 | : "=a"(__ret) : "a"(n), "g"(a1), "c"(a2), "d"(a3), "S"(a4), "D"(a5) : "memory"); 162 | #endif 163 | return __ret; 164 | } 165 | 166 | static inline long __syscall6(long n, long a1, long a2, long a3, long a4, long a5, long a6) 167 | { 168 | unsigned long __ret; 169 | #if !defined(__PIC__) || !defined(BROKEN_EBX_ASM) 170 | __asm__ __volatile__ ("pushl %7 ; push %%ebp ; mov 4(%%esp),%%ebp ; " SYSCALL_INSNS " ; pop %%ebp ; add $4,%%esp" 171 | : "=a"(__ret) : "a"(n), "b"(a1), "c"(a2), "d"(a3), "S"(a4), "D"(a5), "g"(a6) : "memory"); 172 | #else 173 | unsigned long a1a6[2] = { a1, a6 }; 174 | __asm__ __volatile__ ("pushl %1 ; push %%ebx ; push %%ebp ; mov 8(%%esp),%%ebx ; mov 4(%%ebx),%%ebp ; mov (%%ebx),%%ebx ; " SYSCALL_INSNS " ; pop %%ebp ; pop %%ebx ; add $4,%%esp" 175 | : "=a"(__ret) : "g"(&a1a6), "a"(n), "c"(a2), "d"(a3), "S"(a4), "D"(a5) : "memory"); 176 | #endif 177 | return __ret; 178 | } 179 | 180 | #define VDSO_USEFUL 181 | #define VDSO_CGT32_SYM "__vdso_clock_gettime" 182 | #define VDSO_CGT32_VER "LINUX_2.6" 183 | #define VDSO_CGT_SYM "__vdso_clock_gettime64" 184 | #define VDSO_CGT_VER "LINUX_2.6" 185 | 186 | #define SYSCALL_USE_SOCKETCALL 187 | -------------------------------------------------------------------------------- /app/src/main/cpp/SecureAPI/syscall/x86_64/syscall_arch.h: -------------------------------------------------------------------------------- 1 | #define __SYSCALL_LL_E(x) (x) 2 | #define __SYSCALL_LL_O(x) (x) 3 | 4 | static __inline long __syscall0(long n) 5 | { 6 | unsigned long ret; 7 | __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n) : "rcx", "r11", "memory"); 8 | return ret; 9 | } 10 | 11 | static __inline long __syscall1(long n, long a1) 12 | { 13 | unsigned long ret; 14 | __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1) : "rcx", "r11", "memory"); 15 | return ret; 16 | } 17 | 18 | static __inline long __syscall2(long n, long a1, long a2) 19 | { 20 | unsigned long ret; 21 | __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2) 22 | : "rcx", "r11", "memory"); 23 | return ret; 24 | } 25 | 26 | static __inline long __syscall3(long n, long a1, long a2, long a3) 27 | { 28 | unsigned long ret; 29 | __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2), 30 | "d"(a3) : "rcx", "r11", "memory"); 31 | return ret; 32 | } 33 | 34 | static __inline long __syscall4(long n, long a1, long a2, long a3, long a4) 35 | { 36 | unsigned long ret; 37 | register long r10 __asm__("r10") = a4; 38 | __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2), 39 | "d"(a3), "r"(r10): "rcx", "r11", "memory"); 40 | return ret; 41 | } 42 | 43 | static __inline long __syscall5(long n, long a1, long a2, long a3, long a4, long a5) 44 | { 45 | unsigned long ret; 46 | register long r10 __asm__("r10") = a4; 47 | register long r8 __asm__("r8") = a5; 48 | __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2), 49 | "d"(a3), "r"(r10), "r"(r8) : "rcx", "r11", "memory"); 50 | return ret; 51 | } 52 | 53 | static __inline long __syscall6(long n, long a1, long a2, long a3, long a4, long a5, long a6) 54 | { 55 | unsigned long ret; 56 | register long r10 __asm__("r10") = a4; 57 | register long r8 __asm__("r8") = a5; 58 | register long r9 __asm__("r9") = a6; 59 | __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2), 60 | "d"(a3), "r"(r10), "r"(r8), "r"(r9) : "rcx", "r11", "memory"); 61 | return ret; 62 | } 63 | 64 | #define VDSO_USEFUL 65 | #define VDSO_CGT_SYM "__vdso_clock_gettime" 66 | #define VDSO_CGT_VER "LINUX_2.6" 67 | #define VDSO_GETCPU_SYM "__vdso_getcpu" 68 | #define VDSO_GETCPU_VER "LINUX_2.6" 69 | 70 | #define IPC_64 0 -------------------------------------------------------------------------------- /app/src/main/cpp/Utils/ElfImg.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of LSPosed. 3 | * 4 | * LSPosed is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * LSPosed is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with LSPosed. If not, see . 16 | * 17 | * Copyright (C) 2019 Swift Gan 18 | * Copyright (C) 2021 LSPosed Contributors 19 | */ 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include "ElfImg.h" 28 | 29 | using namespace SandHook; 30 | 31 | template 32 | inline constexpr auto offsetOf(ElfW(Ehdr) *head, ElfW(Off) off) { 33 | return reinterpret_cast, T, T *>>( 34 | reinterpret_cast(head) + off); 35 | } 36 | 37 | ElfImg::ElfImg(std::string_view base_name) : elf(base_name) { 38 | if (!findModuleBase()) { 39 | base = nullptr; 40 | return; 41 | } 42 | 43 | //load elf 44 | int fd = open(elf.data(), O_RDONLY); 45 | if (fd < 0) { 46 | // LOGE("failed to open %s", elf.data()); 47 | return; 48 | } 49 | 50 | size = lseek(fd, 0, SEEK_END); 51 | if (size <= 0) { 52 | // LOGE("lseek() failed for %s", elf.data()); 53 | } 54 | 55 | header = reinterpret_cast(mmap(nullptr, size, PROT_READ, MAP_SHARED, fd, 0)); 56 | 57 | close(fd); 58 | 59 | section_header = offsetOf(header, header->e_shoff); 60 | 61 | auto shoff = reinterpret_cast(section_header); 62 | char *section_str = offsetOf(header, section_header[header->e_shstrndx].sh_offset); 63 | 64 | for (int i = 0; i < header->e_shnum; i++, shoff += header->e_shentsize) { 65 | auto *section_h = (ElfW(Shdr) *) shoff; 66 | char *sname = section_h->sh_name + section_str; 67 | auto entsize = section_h->sh_entsize; 68 | switch (section_h->sh_type) { 69 | case SHT_DYNSYM: { 70 | if (bias == -4396) { 71 | dynsym = section_h; 72 | dynsym_offset = section_h->sh_offset; 73 | dynsym_start = offsetOf(header, dynsym_offset); 74 | } 75 | break; 76 | } 77 | case SHT_SYMTAB: { 78 | if (strcmp(sname, ".symtab") == 0) { 79 | symtab = section_h; 80 | symtab_offset = section_h->sh_offset; 81 | symtab_size = section_h->sh_size; 82 | symtab_count = symtab_size / entsize; 83 | symtab_start = offsetOf(header, symtab_offset); 84 | } 85 | break; 86 | } 87 | case SHT_STRTAB: { 88 | if (bias == -4396) { 89 | strtab = section_h; 90 | symstr_offset = section_h->sh_offset; 91 | strtab_start = offsetOf(header, symstr_offset); 92 | } 93 | if (strcmp(sname, ".strtab") == 0) { 94 | symstr_offset_for_symtab = section_h->sh_offset; 95 | } 96 | break; 97 | } 98 | case SHT_PROGBITS: { 99 | if (strtab == nullptr || dynsym == nullptr) break; 100 | if (bias == -4396) { 101 | bias = (off_t) section_h->sh_addr - (off_t) section_h->sh_offset; 102 | } 103 | break; 104 | } 105 | case SHT_HASH: { 106 | auto *d_un = offsetOf(header, section_h->sh_offset); 107 | nbucket_ = d_un[0]; 108 | bucket_ = d_un + 2; 109 | chain_ = bucket_ + nbucket_; 110 | break; 111 | } 112 | case SHT_GNU_HASH: { 113 | auto *d_buf = reinterpret_cast(((size_t) header) + 114 | section_h->sh_offset); 115 | gnu_nbucket_ = d_buf[0]; 116 | gnu_symndx_ = d_buf[1]; 117 | gnu_bloom_size_ = d_buf[2]; 118 | gnu_shift2_ = d_buf[3]; 119 | gnu_bloom_filter_ = reinterpret_cast(d_buf + 4); 120 | gnu_bucket_ = reinterpret_cast(gnu_bloom_filter_ + 121 | gnu_bloom_size_); 122 | gnu_chain_ = gnu_bucket_ + gnu_nbucket_ - gnu_symndx_; 123 | break; 124 | } 125 | } 126 | } 127 | } 128 | 129 | ElfW(Addr) ElfImg::ElfLookup(std::string_view name, uint32_t hash) const { 130 | if (nbucket_ == 0) return 0; 131 | 132 | char *strings = (char *) strtab_start; 133 | 134 | for (auto n = bucket_[hash % nbucket_]; n != 0; n = chain_[n]) { 135 | auto *sym = dynsym_start + n; 136 | if (name == strings + sym->st_name) { 137 | return sym->st_value; 138 | } 139 | } 140 | return 0; 141 | } 142 | 143 | ElfW(Addr) ElfImg::GnuLookup(std::string_view name, uint32_t hash) const { 144 | static constexpr auto bloom_mask_bits = sizeof(ElfW(Addr)) * 8; 145 | 146 | if (gnu_nbucket_ == 0 || gnu_bloom_size_ == 0) return 0; 147 | 148 | auto bloom_word = gnu_bloom_filter_[(hash / bloom_mask_bits) % gnu_bloom_size_]; 149 | uintptr_t mask = 0 150 | | (uintptr_t) 1 << (hash % bloom_mask_bits) 151 | | (uintptr_t) 1 << ((hash >> gnu_shift2_) % bloom_mask_bits); 152 | if ((mask & bloom_word) == mask) { 153 | auto sym_index = gnu_bucket_[hash % gnu_nbucket_]; 154 | if (sym_index >= gnu_symndx_) { 155 | char *strings = (char *) strtab_start; 156 | do { 157 | auto *sym = dynsym_start + sym_index; 158 | if (((gnu_chain_[sym_index] ^ hash) >> 1) == 0 159 | && name == strings + sym->st_name) { 160 | return sym->st_value; 161 | } 162 | } while ((gnu_chain_[sym_index++] & 1) == 0); 163 | } 164 | } 165 | return 0; 166 | } 167 | 168 | ElfW(Addr) ElfImg::LinearLookup(std::string_view name) const { 169 | if (symtabs_.empty()) { 170 | symtabs_.reserve(symtab_count); 171 | if (symtab_start != nullptr && symstr_offset_for_symtab != 0) { 172 | for (ElfW(Off) i = 0; i < symtab_count; i++) { 173 | unsigned int st_type = ELF_ST_TYPE(symtab_start[i].st_info); 174 | const char *st_name = offsetOf(header, symstr_offset_for_symtab + 175 | symtab_start[i].st_name); 176 | if ((st_type == STT_FUNC || st_type == STT_OBJECT) && symtab_start[i].st_size) { 177 | symtabs_.emplace(st_name, &symtab_start[i]); 178 | } 179 | } 180 | } 181 | } 182 | if (auto i = symtabs_.find(name); i != symtabs_.end()) { 183 | return i->second->st_value; 184 | } else { 185 | return 0; 186 | } 187 | } 188 | 189 | 190 | ElfImg::~ElfImg() { 191 | //open elf file local 192 | if (buffer) { 193 | free(buffer); 194 | buffer = nullptr; 195 | } 196 | //use mmap 197 | if (header) { 198 | munmap(header, size); 199 | } 200 | } 201 | 202 | ElfW(Addr) 203 | ElfImg::getSymbOffset(std::string_view name, uint32_t gnu_hash, uint32_t elf_hash) const { 204 | if (auto offset = GnuLookup(name, gnu_hash); offset > 0) { 205 | // LOGD("found %s %p in %s in dynsym by gnuhash", name.data(), reinterpret_cast(offset), elf.data()); 206 | return offset; 207 | } else if (offset = ElfLookup(name, elf_hash); offset > 0) { 208 | // LOGD("found %s %p in %s in dynsym by elfhash", name.data(), reinterpret_cast(offset), elf.data()); 209 | return offset; 210 | } else if (offset = LinearLookup(name); offset > 0) { 211 | // LOGD("found %s %p in %s in symtab by linear lookup", name.data(), reinterpret_cast(offset), elf.data()); 212 | return offset; 213 | } else { 214 | return 0; 215 | } 216 | 217 | } 218 | 219 | bool ElfImg::findModuleBase() { 220 | dl_iterate_phdr([](struct dl_phdr_info *info, size_t size, void *data) -> int { 221 | auto *self = reinterpret_cast(data); 222 | if (strstr(info->dlpi_name, self->elf.data())) { 223 | self->elf = info->dlpi_name; 224 | self->base = reinterpret_cast(info->dlpi_addr); 225 | return 1; 226 | } 227 | return 0; 228 | }, this); 229 | return base != 0; 230 | } -------------------------------------------------------------------------------- /app/src/main/cpp/Utils/ElfImg.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of LSPosed. 3 | * 4 | * LSPosed is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * LSPosed is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with LSPosed. If not, see . 16 | * 17 | * Copyright (C) 2019 Swift Gan 18 | * Copyright (C) 2021 LSPosed Contributors 19 | */ 20 | #ifndef SANDHOOK_ELF_UTIL_H 21 | #define SANDHOOK_ELF_UTIL_H 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #define SHT_GNU_HASH 0x6ffffff6 31 | 32 | namespace SandHook { 33 | class ElfImg { 34 | public: 35 | 36 | ElfImg(std::string_view elf); 37 | 38 | constexpr ElfW(Addr) getSymbOffset(std::string_view name) const { 39 | return getSymbOffset(name, GnuHash(name), ElfHash(name)); 40 | } 41 | 42 | constexpr ElfW(Addr) getSymbAddress(std::string_view name) const { 43 | ElfW(Addr) offset = getSymbOffset(name); 44 | if (offset > 0 && base != nullptr) { 45 | return static_cast((uintptr_t) base + offset - bias); 46 | } else { 47 | return 0; 48 | } 49 | } 50 | 51 | template 52 | requires(std::is_pointer_v) 53 | constexpr T getSymbAddress(std::string_view name) const { 54 | return reinterpret_cast(getSymbAddress(name)); 55 | } 56 | 57 | bool isValid() const { 58 | return base != nullptr; 59 | } 60 | 61 | const std::string name() const { 62 | return elf; 63 | } 64 | 65 | ~ElfImg(); 66 | 67 | private: 68 | ElfW(Addr) getSymbOffset(std::string_view name, uint32_t gnu_hash, uint32_t elf_hash) const; 69 | 70 | ElfW(Addr) ElfLookup(std::string_view name, uint32_t hash) const; 71 | 72 | ElfW(Addr) GnuLookup(std::string_view name, uint32_t hash) const; 73 | 74 | ElfW(Addr) LinearLookup(std::string_view name) const; 75 | 76 | constexpr static uint32_t ElfHash(std::string_view name); 77 | 78 | constexpr static uint32_t GnuHash(std::string_view name); 79 | 80 | bool findModuleBase(); 81 | 82 | std::string elf; 83 | void *base = nullptr; 84 | char *buffer = nullptr; 85 | off_t size = 0; 86 | off_t bias = -4396; 87 | ElfW(Ehdr) *header = nullptr; 88 | ElfW(Shdr) *section_header = nullptr; 89 | ElfW(Shdr) *symtab = nullptr; 90 | ElfW(Shdr) *strtab = nullptr; 91 | ElfW(Shdr) *dynsym = nullptr; 92 | ElfW(Sym) *symtab_start = nullptr; 93 | ElfW(Sym) *dynsym_start = nullptr; 94 | ElfW(Sym) *strtab_start = nullptr; 95 | ElfW(Off) symtab_count = 0; 96 | ElfW(Off) symstr_offset = 0; 97 | ElfW(Off) symstr_offset_for_symtab = 0; 98 | ElfW(Off) symtab_offset = 0; 99 | ElfW(Off) dynsym_offset = 0; 100 | ElfW(Off) symtab_size = 0; 101 | 102 | uint32_t nbucket_{}; 103 | uint32_t *bucket_ = nullptr; 104 | uint32_t *chain_ = nullptr; 105 | 106 | uint32_t gnu_nbucket_{}; 107 | uint32_t gnu_symndx_{}; 108 | uint32_t gnu_bloom_size_; 109 | uint32_t gnu_shift2_; 110 | uintptr_t *gnu_bloom_filter_; 111 | uint32_t *gnu_bucket_; 112 | uint32_t *gnu_chain_; 113 | 114 | mutable std::unordered_map symtabs_; 115 | }; 116 | 117 | constexpr uint32_t ElfImg::ElfHash(std::string_view name) { 118 | uint32_t h = 0, g = 0; 119 | for (unsigned char p: name) { 120 | h = (h << 4) + p; 121 | g = h & 0xf0000000; 122 | h ^= g; 123 | h ^= g >> 24; 124 | } 125 | return h; 126 | } 127 | 128 | constexpr uint32_t ElfImg::GnuHash(std::string_view name) { 129 | uint32_t h = 5381; 130 | for (unsigned char p: name) { 131 | h += (h << 5) + p; 132 | } 133 | return h; 134 | } 135 | } 136 | 137 | #endif //SANDHOOK_ELF_UTIL_H -------------------------------------------------------------------------------- /app/src/main/cpp/Utils/Log.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | #ifdef DEBUG_BUILD 8 | #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "NativeGuard", __VA_ARGS__)) // Disable this on production 9 | #else 10 | #define LOGI(...) 11 | #endif 12 | -------------------------------------------------------------------------------- /app/src/main/cpp/Utils/obfuscate.h: -------------------------------------------------------------------------------- 1 | /* --------------------------------- ABOUT ------------------------------------- 2 | 3 | Original Author: Adam Yaxley 4 | Website: https://github.com/adamyaxley 5 | License: See end of file 6 | 7 | Obfuscate 8 | Guaranteed compile-time string literal obfuscation library for C++14 9 | 10 | Usage: 11 | Pass string literals into the AY_OBFUSCATE macro to obfuscate them at compile 12 | time. AY_OBFUSCATE returns a reference to an ay::obfuscated_data object with the 13 | following traits: 14 | - Guaranteed obfuscation of string 15 | The passed string is encrypted with a simple XOR cipher at compile-time to 16 | prevent it being viewable in the binary image 17 | - Global lifetime 18 | The actual instantiation of the ay::obfuscated_data takes place inside a 19 | lambda as a function level static 20 | - Implicitly convertible to a char* 21 | This means that you can pass it directly into functions that would normally 22 | take a char* or a const char* 23 | 24 | Example: 25 | const char* obfuscated_string = AY_OBFUSCATE("Hello World"); 26 | std::cout << obfuscated_string << std::endl; 27 | 28 | ----------------------------------------------------------------------------- */ 29 | 30 | #pragma once 31 | 32 | #include 33 | 34 | // Workaround for __LINE__ not being constexpr when /ZI (Edit and Continue) is enabled in Visual Studio 35 | // See: https://developercommunity.visualstudio.com/t/-line-cannot-be-used-as-an-argument-for-constexpr/195665 36 | #ifdef _MSC_VER 37 | #define AY_CAT(X,Y) AY_CAT2(X,Y) 38 | #define AY_CAT2(X,Y) X##Y 39 | #define AY_LINE int(AY_CAT(__LINE__,U)) 40 | #else 41 | #define AY_LINE __LINE__ 42 | #endif 43 | 44 | #ifndef AY_OBFUSCATE_DEFAULT_KEY 45 | // The default 64 bit key to obfuscate strings with. 46 | // This can be user specified by defining AY_OBFUSCATE_DEFAULT_KEY before 47 | // including obfuscate.h 48 | #define AY_OBFUSCATE_DEFAULT_KEY ay::generate_key(AY_LINE) 49 | #endif 50 | 51 | namespace ay { 52 | using size_type = unsigned long long; 53 | using key_type = unsigned long long; 54 | 55 | template 56 | struct remove_const_ref { 57 | using type = T; 58 | }; 59 | 60 | template 61 | struct remove_const_ref { 62 | using type = T; 63 | }; 64 | 65 | template 66 | struct remove_const_ref { 67 | using type = T; 68 | }; 69 | 70 | template 71 | struct remove_const_ref { 72 | using type = T; 73 | }; 74 | 75 | template 76 | using char_type = typename remove_const_ref::type; 77 | 78 | // Generate a pseudo-random key that spans all 8 bytes 79 | constexpr key_type generate_key(key_type seed) { 80 | // Use the MurmurHash3 64-bit finalizer to hash our seed 81 | key_type key = seed; 82 | key ^= (key >> 33); 83 | key *= 0xff51afd7ed558ccd; 84 | key ^= (key >> 33); 85 | key *= 0xc4ceb9fe1a85ec53; 86 | key ^= (key >> 33); 87 | 88 | // Make sure that a bit in each byte is set 89 | key |= 0x0101010101010101ull; 90 | 91 | return key; 92 | } 93 | 94 | // Obfuscates or deobfuscates data with key 95 | template 96 | constexpr void cipher(CHAR_TYPE *data, size_type size, key_type key) { 97 | // Obfuscate with a simple XOR cipher based on key 98 | for (size_type i = 0; i < size; i++) { 99 | data[i] ^= CHAR_TYPE((key >> ((i % 8) * 8)) & 0xFF); 100 | } 101 | } 102 | 103 | // Obfuscates a string at compile time 104 | template 105 | class obfuscator { 106 | public: 107 | // Obfuscates the string 'data' on construction 108 | constexpr explicit obfuscator(const CHAR_TYPE *data) { 109 | // Copy data 110 | for (size_type i = 0; i < N; i++) { 111 | m_data[i] = data[i]; 112 | } 113 | 114 | // On construction each of the characters in the string is 115 | // obfuscated with an XOR cipher based on key 116 | cipher(m_data, N, KEY); 117 | } 118 | 119 | constexpr const CHAR_TYPE *data() const { 120 | return &m_data[0]; 121 | } 122 | 123 | [[nodiscard]] constexpr size_type size() const { 124 | return N; 125 | } 126 | 127 | [[nodiscard]] constexpr key_type key() const { 128 | return KEY; 129 | } 130 | 131 | private: 132 | 133 | CHAR_TYPE m_data[N]{}; 134 | }; 135 | 136 | // Handles decryption and re-encryption of an encrypted string at runtime 137 | template 138 | class obfuscated_data { 139 | public: 140 | explicit obfuscated_data(const obfuscator &obfuscator) { 141 | // Copy obfuscated data 142 | for (size_type i = 0; i < N; i++) { 143 | m_data[i] = obfuscator.data()[i]; 144 | } 145 | } 146 | 147 | ~obfuscated_data() { 148 | // Zero m_data to remove it from memory 149 | for (size_type i = 0; i < N; i++) { 150 | m_data[i] = 0; 151 | } 152 | } 153 | 154 | operator std::string() { 155 | decrypt(); 156 | return m_data; 157 | } 158 | 159 | operator std::string_view() { 160 | decrypt(); 161 | return m_data; 162 | } 163 | 164 | // Returns a pointer to the plain text string, decrypting it if 165 | // necessary 166 | operator CHAR_TYPE *() { 167 | decrypt(); 168 | return m_data; 169 | } 170 | 171 | // Manually decrypt the string 172 | void decrypt() { 173 | if (m_encrypted) { 174 | cipher(m_data, N, KEY); 175 | m_encrypted = false; 176 | } 177 | } 178 | 179 | // Manually re-encrypt the string 180 | void encrypt() { 181 | if (!m_encrypted) { 182 | cipher(m_data, N, KEY); 183 | m_encrypted = true; 184 | } 185 | } 186 | 187 | // Returns true if this string is currently encrypted, false otherwise. 188 | [[nodiscard]] bool is_encrypted() const { 189 | return m_encrypted; 190 | } 191 | 192 | private: 193 | 194 | // Local storage for the string. Call is_encrypted() to check whether or 195 | // not the string is currently obfuscated. 196 | CHAR_TYPE m_data[N]; 197 | 198 | // Whether data is currently encrypted 199 | bool m_encrypted{true}; 200 | }; 201 | 202 | // This function exists purely to extract the number of elements 'N' in the 203 | // array 'data' 204 | template 205 | constexpr auto make_obfuscator(const CHAR_TYPE(&data)[N]) { 206 | return obfuscator(data); 207 | } 208 | } 209 | 210 | // Obfuscates the string 'data' at compile-time and returns a reference to a 211 | // ay::obfuscated_data object with global lifetime that has functions for 212 | // decrypting the string and is also implicitly convertable to a char* 213 | #define AY_OBFUSCATE(data) AY_OBFUSCATE_KEY(data, AY_OBFUSCATE_DEFAULT_KEY) 214 | 215 | // Obfuscates the string 'data' with 'key' at compile-time and returns a 216 | // reference to a ay::obfuscated_data object with global lifetime that has 217 | // functions for decrypting the string and is also implicitly convertable to a 218 | // char* 219 | #define AY_OBFUSCATE_KEY(data, key) \ 220 | []() -> ay::obfuscated_data>& { \ 221 | static_assert(sizeof(decltype(key)) == sizeof(ay::key_type), "key must be a 64 bit unsigned integer"); \ 222 | static_assert((key) >= (1ull << 56), "key must span all 8 bytes"); \ 223 | using char_type = ay::char_type; \ 224 | constexpr auto n = sizeof(data)/sizeof((data)[0]); \ 225 | constexpr auto obfuscator = ay::make_obfuscator(data); \ 226 | thread_local auto obfuscated_data = ay::obfuscated_data(obfuscator); \ 227 | return obfuscated_data; \ 228 | }() 229 | 230 | /* -------------------------------- LICENSE ------------------------------------ 231 | 232 | Public Domain (http://www.unlicense.org) 233 | 234 | This is free and unencumbered software released into the public domain. 235 | 236 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 237 | software, either in source code form or as a compiled binary, for any purpose, 238 | commercial or non-commercial, and by any means. 239 | 240 | In jurisdictions that recognize copyright laws, the author or authors of this 241 | software dedicate any and all copyright interest in the software to the public 242 | domain. We make this dedication for the benefit of the public at large and to 243 | the detriment of our heirs and successors. We intend this dedication to be an 244 | overt act of relinquishment in perpetuity of all present and future rights to 245 | this software under copyright law. 246 | 247 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 248 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 249 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE 250 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 251 | CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 252 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 253 | 254 | ----------------------------------------------------------------------------- */ -------------------------------------------------------------------------------- /app/src/main/cpp/constants.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Msii on 11/21/2024. 3 | // 4 | 5 | #ifndef ANDROID_NATIVE_GUARD_CONSTANTS_H 6 | #define ANDROID_NATIVE_GUARD_CONSTANTS_H 7 | 8 | #define _forceinline __attribute__((always_inline)) inline 9 | 10 | #ifdef __LP64__ 11 | #define x32_64(_32, _64) _64 12 | #else 13 | #define x32_64(_32, _64) _32 14 | #endif 15 | 16 | using Pointer = unsigned long; 17 | 18 | constexpr Pointer null = 0UL; 19 | 20 | #endif //ANDROID_NATIVE_GUARD_CONSTANTS_H 21 | -------------------------------------------------------------------------------- /app/src/main/cpp/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | #include "Utils/Log.h" 14 | 15 | #include "AntiDebug/AntiDebug.h" 16 | #include "FridaDetect/FridaDetect.h" 17 | #include "RiGisk/RiGisk.h" 18 | #include "RootDetect/RootDetect.h" 19 | #include "AntiDump/AntiDump.h" 20 | #include "AntiLibPatch/AntiLibPatch.h" 21 | 22 | JavaVM *g_VM; 23 | 24 | jclass mainActivityClass; 25 | jmethodID addLogMethod; 26 | void addLog(std::string log) { 27 | JNIEnv *env; 28 | g_VM->AttachCurrentThread(&env, nullptr); 29 | 30 | time_t now = time(nullptr); 31 | tm *ltm = localtime(&now); 32 | 33 | char date[20]; 34 | sprintf(date, "%02d:%02d:%02d", ltm->tm_hour, ltm->tm_min, ltm->tm_sec); 35 | 36 | log = "[" + std::string(date) + "] " + log; 37 | 38 | env->CallStaticVoidMethod(mainActivityClass, addLogMethod, env->NewStringUTF(log.c_str())); 39 | 40 | g_VM->DetachCurrentThread(); 41 | } 42 | 43 | // ==================== Callbacks ==================== // 44 | void onDebuggerDetected() { 45 | addLog("AntiDebug: Debugger detected."); 46 | } 47 | 48 | void onFridaDetected() { 49 | addLog("FridaDetect: Frida detected."); 50 | } 51 | 52 | void onDumpDetected() { 53 | addLog("AntiDump: An attempt to access/dump memory detected."); 54 | } 55 | 56 | void onLibTampered(const char *libPath, uint32_t old_checksum, uint32_t new_checksum) { 57 | char log[1024]; 58 | sprintf(log, "AntiLibPatch: %s has been tampered, 0x%08X -> 0x%08X", libPath, old_checksum, new_checksum); 59 | addLog(log); 60 | } 61 | 62 | // ==================== Main ==================== // 63 | std::vector services; 64 | std::vector threads; 65 | 66 | void AndroidNativeGuard() { 67 | addLog("Android Native Guard service started."); 68 | 69 | RootDetect rootDetect; 70 | if (rootDetect.execute()) { 71 | addLog("RootDetect: Root detected."); 72 | } 73 | 74 | RiGisk riGisk; 75 | if (riGisk.execute()) { 76 | addLog("RiGisk: Zygote injection detected."); 77 | } 78 | 79 | services.push_back(new AntiDebug(onDebuggerDetected)); 80 | services.push_back(new FridaDetect(onFridaDetected)); 81 | services.push_back(new AntiDump(onDumpDetected)); 82 | services.push_back(new AntiLibPatch(onLibTampered)); 83 | 84 | for (auto &service : services) { 85 | threads.emplace_back([&]() { 86 | while (true) { 87 | service->execute(); 88 | sleep(1); 89 | } 90 | }); 91 | } 92 | 93 | for (auto &thread : threads) { 94 | thread.detach(); 95 | } 96 | } 97 | 98 | JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { 99 | g_VM = vm; 100 | 101 | JNIEnv *env; 102 | vm->GetEnv((void **)&env, JNI_VERSION_1_6); 103 | 104 | jclass clazz = env->FindClass("id/kuro/androidnativeguard/MainActivity"); 105 | addLogMethod = env->GetStaticMethodID(clazz, "addLog", "(Ljava/lang/String;)V"); 106 | mainActivityClass = (jclass)env->NewGlobalRef(clazz); 107 | 108 | // execute security initializer in a background thread, 109 | // since AntiLibPatch constructor may take a significant time 110 | // main thread may become unresponsive 111 | std::thread(AndroidNativeGuard).detach(); 112 | return JNI_VERSION_1_6; 113 | } -------------------------------------------------------------------------------- /app/src/main/java/id/kuro/androidnativeguard/MainActivity.java: -------------------------------------------------------------------------------- 1 | package id.kuro.androidnativeguard; 2 | 3 | import androidx.appcompat.app.AppCompatActivity; 4 | 5 | import android.annotation.SuppressLint; 6 | import android.app.Activity; 7 | import android.os.Bundle; 8 | import android.os.Handler; 9 | import android.text.Html; 10 | import android.widget.TextView; 11 | 12 | public class MainActivity extends AppCompatActivity { 13 | @SuppressLint("StaticFieldLeak") 14 | static TextView tv_main; 15 | 16 | @Override 17 | protected void onCreate(Bundle savedInstanceState) { 18 | super.onCreate(savedInstanceState); 19 | setContentView(R.layout.activity_main); 20 | 21 | tv_main = findViewById(R.id.tv_main); 22 | System.loadLibrary("NativeGuard"); 23 | } 24 | 25 | public static void addLog(String log) { 26 | tv_main.append(Html.fromHtml(log + "
")); 27 | } 28 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/border_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 9 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /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/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v33/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aimardcr/AndroidNativeGuard/a3ee2be4bf5d183b022cf965f2964c85c72d2769/app/src/main/res/mipmap-hdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aimardcr/AndroidNativeGuard/a3ee2be4bf5d183b022cf965f2964c85c72d2769/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aimardcr/AndroidNativeGuard/a3ee2be4bf5d183b022cf965f2964c85c72d2769/app/src/main/res/mipmap-mdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aimardcr/AndroidNativeGuard/a3ee2be4bf5d183b022cf965f2964c85c72d2769/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aimardcr/AndroidNativeGuard/a3ee2be4bf5d183b022cf965f2964c85c72d2769/app/src/main/res/mipmap-xhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aimardcr/AndroidNativeGuard/a3ee2be4bf5d183b022cf965f2964c85c72d2769/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aimardcr/AndroidNativeGuard/a3ee2be4bf5d183b022cf965f2964c85c72d2769/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aimardcr/AndroidNativeGuard/a3ee2be4bf5d183b022cf965f2964c85c72d2769/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aimardcr/AndroidNativeGuard/a3ee2be4bf5d183b022cf965f2964c85c72d2769/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aimardcr/AndroidNativeGuard/a3ee2be4bf5d183b022cf965f2964c85c72d2769/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 | Android Native Guard 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/id/kuro/androidnativeguard/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package id.kuro.androidnativeguard; 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 '7.4.1' apply false 4 | id 'com.android.library' version '7.4.1' 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/aimardcr/AndroidNativeGuard/a3ee2be4bf5d183b022cf965f2964c85c72d2769/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Nov 21 18:49:51 IST 2024 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.11-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 | -------------------------------------------------------------------------------- /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 | rootProject.name = "Android Native Guard" 16 | include ':app' 17 | --------------------------------------------------------------------------------