├── .gitignore
├── .idea
├── .gitignore
├── compiler.xml
├── gradle.xml
├── jarRepositories.xml
├── misc.xml
└── vcs.xml
├── DetectFrida.iml
├── LICENSE
├── README.md
├── app
├── .gitignore
├── app.iml
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── darvin
│ │ └── security
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── c
│ │ ├── CMakeLists.txt
│ │ ├── arch
│ │ │ ├── arm64-v8a
│ │ │ │ └── syscall_arch.h
│ │ │ ├── armeabi-v7a
│ │ │ │ └── syscall_arch.h
│ │ │ ├── x86
│ │ │ │ └── syscall_arch.h
│ │ │ └── x86_64
│ │ │ │ └── syscall_arch.h
│ │ ├── mylibc.h
│ │ ├── native-lib.c
│ │ └── syscalls.h
│ ├── java
│ │ └── com
│ │ │ └── darvin
│ │ │ └── security
│ │ │ └── MainActivity.java
│ └── res
│ │ ├── drawable-v24
│ │ └── ic_launcher_foreground.xml
│ │ ├── drawable
│ │ └── ic_launcher_background.xml
│ │ ├── layout
│ │ └── activity_main.xml
│ │ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ └── values
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── darvin
│ └── security
│ └── ExampleUnitTest.java
├── build.gradle
├── detectfridalib
├── .gitignore
├── build.gradle
├── consumer-rules.pro
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── example
│ │ └── detectfridalib
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ └── AndroidManifest.xml
│ └── test
│ └── java
│ └── com
│ └── example
│ └── detectfridalib
│ └── ExampleUnitTest.java
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── obfuscated-app-release.apk
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/caches
5 | /.idea/libraries
6 | /.idea/modules.xml
7 | /.idea/workspace.xml
8 | /.idea/navEditor.xml
9 | /.idea/assetWizardSettings.xml
10 | .DS_Store
11 | /build
12 | /captures
13 | .externalNativeBuild
14 | *.cxx
15 | app/.cxx/*
16 |
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/.idea/jarRepositories.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/DetectFrida.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Darvin
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # DetectFrida
2 | This project has 3 ways to detect frida hooking
3 | 1. Detect through named pipes used by Frida
4 | 2. Detect through frida specific named thread
5 | 3. Compare text section in memory with text section in disk for both libc and native library
6 |
7 | More details can be found in my blog -> [DetectFrida](https://darvincitech.wordpress.com/2019/12/23/detect-frida-for-android)
8 |
9 | Also this project has 3 mechanisms to harden the native code
10 | 1. Replace certain libc calls with syscalls
11 | 2. Replace string,memory related operation with custom implementation
12 | 3. Apply O-LLVM native obfuscation
13 |
14 | More details can be found in my blog -> [Hardening Native Code](https://darvincitech.wordpress.com/2020/01/07/security-hardening-of-android-native-code)
15 |
16 | arm64, armv7a, x86_64 architectures are supported in this project. The hardened APK is provided for interested reverse engineers to analyze.
17 |
18 | ## Updates
19 | - Re-aligned functions
20 | - Fix scanning of executable sections only if it is readable to avoid crashes when app is targetting API 29
21 | - Stripped comment section in native library to prevent APKId detecting O-LLVM obfuscator is used
22 | - Updated Target API to 30
23 | - Updated Obfuscator-LLVM to [OLLVM-TLL](https://github.com/yazhiwang/ollvm-tll)
24 | - Fixed false positives found in Android 10 and Android 11. Now the memdisk compare checks the PLT and TEXT sections of libc and native library in a proper way
25 | - Memdisk comparison approach is frida agnostic, hence [frida specific signature changes](https://github.com/feicong/strong-frida) does not bypass this detection mechanism.
26 |
27 | ## Note
28 | Henceforth, Please don't raise issue asking for OLLVM binary for Windows. PRs welcome.
29 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/app.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | generateDebugSources
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 30
5 | buildToolsVersion "30.0.3"
6 | defaultConfig {
7 | applicationId "com.darvin.security"
8 | minSdkVersion 19
9 | targetSdkVersion 30
10 | versionCode 2
11 | versionName "1.1"
12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
13 | ndk {
14 | abiFilters 'arm64-v8a', 'armeabi-v7a', 'x86_64'
15 | }
16 | }
17 | buildTypes {
18 | release {
19 | minifyEnabled false
20 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
21 | }
22 | }
23 | externalNativeBuild {
24 | cmake {
25 | path "src/main/c/CMakeLists.txt"
26 | version "3.10.2"
27 | }
28 | }
29 | }
30 |
31 | dependencies {
32 | implementation fileTree(dir: 'libs', include: ['*.jar'])
33 | implementation 'androidx.appcompat:appcompat:1.2.0'
34 | implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
35 | testImplementation 'junit:junit:4.13.1'
36 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
37 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
38 | }
39 |
--------------------------------------------------------------------------------
/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
22 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/darvin/security/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.darvin.security;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumented test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
23 |
24 | assertEquals("com.darvin.security", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/c/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # For more information about using CMake with Android Studio, read the
2 | # documentation: https://d.android.com/studio/projects/add-native-code.html
3 |
4 | # Sets the minimum version of CMake required to build the native library.
5 |
6 | cmake_minimum_required(VERSION 3.4.1)
7 |
8 | set(can_use_assembler TRUE)
9 | enable_language(ASM)
10 |
11 | #Start - Comment this block for generating non-obfuscated builds
12 | set(OLLVM_PATH ${CMAKE_HOME_DIRECTORY}/../../../../../o-llvm-binary/ollvm-tll/build/bin_Darwin)
13 | set(OLLVM_C_COMPILER ${OLLVM_PATH}/clang)
14 | set(OLLVM_CXX_COMPILER ${OLLVM_PATH}/clang++)
15 |
16 | set(OLLVM_C_FLAGS "-mllvm -sub -mllvm -bcf -mllvm -fla")
17 |
18 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OLLVM_C_FLAGS}")
19 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OLLVM_C_FLAGS}")
20 | set(CMAKE_C_COMPILER ${OLLVM_C_COMPILER})
21 | set(CMAKE_CXX_COMPILER ${OLLVM_CXX_COMPILER})
22 | #End - Comment this block for generating non-obfuscated builds
23 |
24 | #Set flags to detect arm32 bit or arm64 bit for switching between elf structures
25 | if(${ANDROID_ABI} STREQUAL "armeabi-v7a" OR ${ANDROID_ABI} STREQUAL "x86")
26 | add_definitions("-D_32_BIT")
27 | elseif(${ANDROID_ABI} STREQUAL "arm64-v8a" OR ${ANDROID_ABI} STREQUAL "x86_64")
28 | add_definitions("-D_64_BIT")
29 | endif()
30 |
31 |
32 | add_library( # Sets the name of the library.
33 | native-lib
34 |
35 | # Sets the library as a shared library.
36 | SHARED
37 |
38 | # Provides a relative path to your source file(s).
39 | native-lib.c)
40 |
41 | target_include_directories(native-lib PRIVATE arch/${ANDROID_ABI})
42 |
43 | # Searches for a specified prebuilt library and stores the path as a
44 | # variable. Because CMake includes system libraries in the search path by
45 | # default, you only need to specify the name of the public NDK library
46 | # you want to add. CMake verifies that the library exists before
47 | # completing its build.
48 |
49 | find_library( # Sets the name of the path variable.
50 | log-lib
51 |
52 | # Specifies the name of the NDK library that
53 | # you want CMake to locate.
54 | log )
55 |
56 | # Specifies libraries CMake should link to your target library. You
57 | # can link multiple libraries, such as libraries you define in this
58 | # build script, prebuilt third-party libraries, or system libraries.
59 |
60 | target_link_libraries( # Specifies the target library.
61 | native-lib
62 |
63 | # Links the target library to the log library
64 | # included in the NDK.
65 | ${log-lib} )
66 |
67 | add_custom_command( TARGET native-lib
68 | POST_BUILD
69 | COMMAND "${ANDROID_TOOLCHAIN_PREFIX}strip" -R .comment -g -S -d --strip-unneeded ${CMAKE_HOME_DIRECTORY}/../../../build/intermediates/cmake/${CMAKE_BUILD_TYPE}/obj/${ANDROID_ABI}/libnative-lib.so
70 | COMMENT "Stripped native library")
71 |
--------------------------------------------------------------------------------
/app/src/main/c/arch/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/c/arch/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/c/arch/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/c/arch/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/c/mylibc.h:
--------------------------------------------------------------------------------
1 | #ifndef DETECTFRIDA_MYLIBC_H
2 | #define DETECTFRIDA_MYLIBC_H
3 | /*
4 | * These functions are copied from glibc, android libc, apple libc open source code.
5 | * This is to avoid easy bypass through libc functions
6 | */
7 |
8 | __attribute__((always_inline))
9 | static inline size_t
10 | my_strlcpy(char *dst, const char *src, size_t siz)
11 | {
12 | char *d = dst;
13 | const char *s = src;
14 | size_t n = siz;
15 | /* Copy as many bytes as will fit */
16 | if (n != 0) {
17 | while (--n != 0) {
18 | if ((*d++ = *s++) == '\0')
19 | break;
20 | }
21 | }
22 | /* Not enough room in dst, add NUL and traverse rest of src */
23 | if (n == 0) {
24 | if (siz != 0)
25 | *d = '\0'; /* NUL-terminate dst */
26 | while (*s++)
27 | ;
28 | }
29 | return(s - src - 1); /* count does not include NUL */
30 | }
31 |
32 | __attribute__((always_inline))
33 | static inline
34 | size_t my_strlen(const char *s)
35 | {
36 | size_t len = 0;
37 | while(*s++) len++;
38 | return len;
39 | }
40 |
41 | __attribute__((always_inline))
42 | static inline int
43 | my_strncmp(const char *s1, const char *s2, size_t n)
44 | {
45 | if (n == 0)
46 | return (0);
47 | do {
48 | if (*s1 != *s2++)
49 | return (*(unsigned char *)s1 - *(unsigned char *)--s2);
50 | if (*s1++ == 0)
51 | break;
52 | } while (--n != 0);
53 | return (0);
54 | }
55 |
56 | __attribute__((always_inline))
57 | static inline char *
58 | my_strstr(const char *s, const char *find)
59 | {
60 | char c, sc;
61 | size_t len;
62 |
63 | if ((c = *find++) != '\0') {
64 | len = my_strlen(find);
65 | do {
66 | do {
67 | if ((sc = *s++) == '\0')
68 | return (NULL);
69 | } while (sc != c);
70 | } while (my_strncmp(s, find, len) != 0);
71 | s--;
72 | }
73 | return ((char *)s);
74 | }
75 |
76 | __attribute__((always_inline))
77 | static inline
78 | void* my_memset(void* dst, int c, size_t n)
79 | {
80 | char* q = (char*)dst;
81 | char* end = q + n;
82 | for (;;) {
83 | if (q >= end) break; *q++ = (char) c;
84 | if (q >= end) break; *q++ = (char) c;
85 | if (q >= end) break; *q++ = (char) c;
86 | if (q >= end) break; *q++ = (char) c;
87 | }
88 | return dst;
89 | }
90 |
91 | __attribute__((always_inline))
92 | static inline int
93 | my_strcmp(const char *s1, const char *s2)
94 | {
95 | while (*s1 == *s2++)
96 | if (*s1++ == 0)
97 | return (0);
98 | return (*(unsigned char *)s1 - *(unsigned char *)--s2);
99 | }
100 |
101 | __attribute__((always_inline))
102 | static inline int my_atoi(const char *s)
103 | {
104 | int n=0, neg=0;
105 | while (isspace(*s)) s++;
106 | switch (*s) {
107 | case '-': neg=1;
108 | case '+': s++;
109 | }
110 | /* Compute n as a negative number to avoid overflow on INT_MIN */
111 | while (isdigit(*s))
112 | n = 10*n - (*s++ - '0');
113 | return neg ? n : -n;
114 | }
115 |
116 |
117 | #endif //DETECTFRIDA_MYLIBC_H
118 |
--------------------------------------------------------------------------------
/app/src/main/c/native-lib.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 |
14 | #include
15 | #include
16 | #include
17 | #include
18 |
19 | #include "syscall_arch.h"
20 | #include "syscalls.h"
21 | #include "mylibc.h"
22 |
23 | #define MAX_LINE 512
24 | #define MAX_LENGTH 256
25 | static const char *APPNAME = "DetectFrida";
26 | static const char *FRIDA_THREAD_GUM_JS_LOOP = "gum-js-loop";
27 | static const char *FRIDA_THREAD_GMAIN = "gmain";
28 | static const char *FRIDA_NAMEDPIPE_LINJECTOR = "linjector";
29 | static const char *PROC_MAPS = "/proc/self/maps";
30 | static const char *PROC_STATUS = "/proc/self/task/%s/status";
31 | static const char *PROC_FD = "/proc/self/fd";
32 | static const char *PROC_TASK = "/proc/self/task";
33 | #define LIBC "libc.so"
34 |
35 | //Structure to hold the details of executable section of library
36 | typedef struct stExecSection {
37 | int execSectionCount;
38 | unsigned long offset[2];
39 | unsigned long memsize[2];
40 | unsigned long checksum[2];
41 | unsigned long startAddrinMem;
42 | } execSection;
43 |
44 |
45 | #define NUM_LIBS 2
46 |
47 | //Include more libs as per your need, but beware of the performance bottleneck especially
48 | //when the size of the libraries are > few MBs
49 | static const char *libstocheck[NUM_LIBS] = {"libnative-lib.so", LIBC};
50 | static execSection *elfSectionArr[NUM_LIBS] = {NULL};
51 |
52 |
53 | #ifdef _32_BIT
54 | typedef Elf32_Ehdr Elf_Ehdr;
55 | typedef Elf32_Shdr Elf_Shdr;
56 | #elif _64_BIT
57 | typedef Elf64_Ehdr Elf_Ehdr;
58 | typedef Elf64_Shdr Elf_Shdr;
59 | #endif
60 |
61 | static inline void parse_proc_maps_to_fetch_path(char **filepaths);
62 |
63 | static inline bool fetch_checksum_of_library(const char *filePath, execSection **pTextSection);
64 |
65 | static inline void detect_frida_loop(void *pargs);
66 |
67 | static inline bool
68 | scan_executable_segments(char *map, execSection *pTextSection, const char *libraryName);
69 |
70 | static inline ssize_t read_one_line(int fd, char *buf, unsigned int max_len);
71 |
72 | static inline unsigned long checksum(void *buffer, size_t len);
73 |
74 | static inline void detect_frida_threads();
75 |
76 | static inline void detect_frida_namedpipe();
77 |
78 | static inline void detect_frida_memdiskcompare();
79 |
80 | //Upon loading the library, this function annotated as constructor starts executing
81 | __attribute__((constructor))
82 | void detectfrida() {
83 |
84 | char *filePaths[NUM_LIBS];
85 |
86 | parse_proc_maps_to_fetch_path(filePaths);
87 | __android_log_print(ANDROID_LOG_VERBOSE, APPNAME, "Libc[%x][%x][%x][%x][%x][%x]", __NR_openat,
88 | __NR_lseek, __NR_read, __NR_close, __NR_readlinkat, __NR_nanosleep);
89 | for (int i = 0; i < NUM_LIBS; i++) {
90 | fetch_checksum_of_library(filePaths[i], &elfSectionArr[i]);
91 | if (filePaths[i] != NULL)
92 | free(filePaths[i]);
93 | }
94 | pthread_t t;
95 | pthread_create(&t, NULL, (void *) detect_frida_loop, NULL);
96 |
97 | }
98 |
99 | __attribute__((always_inline))
100 | static inline void parse_proc_maps_to_fetch_path(char **filepaths) {
101 | int fd = 0;
102 | char map[MAX_LINE];
103 | int counter = 0;
104 | if ((fd = my_openat(AT_FDCWD, PROC_MAPS, O_RDONLY | O_CLOEXEC, 0)) != 0) {
105 |
106 | while ((read_one_line(fd, map, MAX_LINE)) > 0) {
107 | for (int i = 0; i < NUM_LIBS; i++) {
108 | if (my_strstr(map, libstocheck[i]) != NULL) {
109 | char tmp[MAX_LENGTH] = "";
110 | char path[MAX_LENGTH] = "";
111 | char buf[5] = "";
112 | sscanf(map, "%s %s %s %s %s %s", tmp, buf, tmp, tmp, tmp, path);
113 | if (buf[2] == 'x') {
114 | size_t size = my_strlen(path) + 1;
115 | filepaths[i] = malloc(size);
116 | my_strlcpy(filepaths[i], path, size);
117 | counter++;
118 | }
119 | }
120 | }
121 | if (counter == NUM_LIBS)
122 | break;
123 | }
124 | my_close(fd);
125 | }
126 | }
127 |
128 | __attribute__((always_inline))
129 | static inline bool fetch_checksum_of_library(const char *filePath, execSection **pTextSection) {
130 |
131 | Elf_Ehdr ehdr;
132 | Elf_Shdr sectHdr;
133 | int fd;
134 | int execSectionCount = 0;
135 | fd = my_openat(AT_FDCWD, filePath, O_RDONLY | O_CLOEXEC, 0);
136 | if (fd < 0) {
137 | return NULL;
138 | }
139 |
140 | my_read(fd, &ehdr, sizeof(Elf_Ehdr));
141 | my_lseek(fd, (off_t) ehdr.e_shoff, SEEK_SET);
142 |
143 | unsigned long memsize[2] = {0};
144 | unsigned long offset[2] = {0};
145 |
146 |
147 | for (int i = 0; i < ehdr.e_shnum; i++) {
148 | my_memset(§Hdr, 0, sizeof(Elf_Shdr));
149 | my_read(fd, §Hdr, sizeof(Elf_Shdr));
150 |
151 | // __android_log_print(ANDROID_LOG_VERBOSE, APPNAME, "SectionHeader[%d][%ld]", sectHdr.sh_name, sectHdr.sh_flags);
152 |
153 | //Typically PLT and Text Sections are executable sections which are protected
154 | if (sectHdr.sh_flags & SHF_EXECINSTR) {
155 | // __android_log_print(ANDROID_LOG_VERBOSE, APPNAME, "SectionHeader[%d][%ld]", sectHdr.sh_name, sectHdr.sh_flags);
156 |
157 | offset[execSectionCount] = sectHdr.sh_offset;
158 | memsize[execSectionCount] = sectHdr.sh_size;
159 | execSectionCount++;
160 | if (execSectionCount == 2) {
161 | break;
162 | }
163 | }
164 | }
165 | if (execSectionCount == 0) {
166 | __android_log_print(ANDROID_LOG_WARN, APPNAME, "No executable section found. Suspicious");
167 | my_close(fd);
168 | return false;
169 | }
170 | //This memory is not released as the checksum is checked in a thread
171 | *pTextSection = malloc(sizeof(execSection));
172 |
173 | (*pTextSection)->execSectionCount = execSectionCount;
174 | (*pTextSection)->startAddrinMem = 0;
175 | for (int i = 0; i < execSectionCount; i++) {
176 | my_lseek(fd, offset[i], SEEK_SET);
177 | uint8_t *buffer = malloc(memsize[i] * sizeof(uint8_t));
178 | my_read(fd, buffer, memsize[i]);
179 | (*pTextSection)->offset[i] = offset[i];
180 | (*pTextSection)->memsize[i] = memsize[i];
181 | (*pTextSection)->checksum[i] = checksum(buffer, memsize[i]);
182 | free(buffer);
183 | // __android_log_print(ANDROID_LOG_WARN, APPNAME, "ExecSection:[%d][%ld][%ld][%ld]", i,
184 | // offset[i],
185 | // memsize[i], (*pTextSection)->checksum[i]);
186 | }
187 |
188 | my_close(fd);
189 | return true;
190 | }
191 |
192 |
193 | void detect_frida_loop(void *pargs) {
194 |
195 | struct timespec timereq;
196 | timereq.tv_sec = 5; //Changing to 5 seconds from 1 second
197 | timereq.tv_nsec = 0;
198 |
199 | while (1) {
200 |
201 | detect_frida_threads();
202 | detect_frida_namedpipe();
203 | detect_frida_memdiskcompare();
204 |
205 |
206 | my_nanosleep(&timereq, NULL);
207 |
208 | }
209 | }
210 |
211 | __attribute__((always_inline))
212 | static inline bool
213 | scan_executable_segments(char *map, execSection *pElfSectArr, const char *libraryName) {
214 | unsigned long start, end;
215 | char buf[MAX_LINE] = "";
216 | char path[MAX_LENGTH] = "";
217 | char tmp[100] = "";
218 |
219 | sscanf(map, "%lx-%lx %s %s %s %s %s", &start, &end, buf, tmp, tmp, tmp, path);
220 | //__android_log_print(ANDROID_LOG_VERBOSE, APPNAME, "Map [%s]", map);
221 |
222 | if (buf[2] == 'x') {
223 | if (buf[0] == 'r') {
224 | uint8_t *buffer = NULL;
225 |
226 | buffer = (uint8_t *) start;
227 | for (int i = 0; i < pElfSectArr->execSectionCount; i++) {
228 | if (start + pElfSectArr->offset[i] + pElfSectArr->memsize[i] > end) {
229 | if (pElfSectArr->startAddrinMem != 0) {
230 | buffer = (uint8_t *) pElfSectArr->startAddrinMem;
231 | pElfSectArr->startAddrinMem = 0;
232 | break;
233 | }
234 | }
235 | }
236 | for (int i = 0; i < pElfSectArr->execSectionCount; i++) {
237 | unsigned long output = checksum(buffer + pElfSectArr->offset[i],
238 | pElfSectArr->memsize[i]);
239 | // __android_log_print(ANDROID_LOG_VERBOSE, APPNAME, "Checksum:[%ld][%ld]", output,
240 | // pElfSectArr->checksum[i]);
241 |
242 | if (output != pElfSectArr->checksum[i]) {
243 | __android_log_print(ANDROID_LOG_VERBOSE, APPNAME,
244 | "Executable Section Manipulated, "
245 | "maybe due to Frida or other hooking framework."
246 | "Act Now!!!");
247 | }
248 | }
249 |
250 | } else {
251 |
252 | char ch[10] = "", ch1[10] = "";
253 | __system_property_get("ro.build.version.release", ch);
254 | __system_property_get("ro.system.build.version.release", ch1);
255 | int version = my_atoi(ch);
256 | int version1 = my_atoi(ch1);
257 | if (version < 10 || version1 < 10) {
258 | __android_log_print(ANDROID_LOG_VERBOSE, APPNAME, "Suspicious to get XOM in "
259 | "version < Android10");
260 | } else {
261 | if (0 == my_strncmp(libraryName, LIBC, my_strlen(LIBC))) {
262 | //If it is not readable, then most likely it is not manipulated by Frida
263 | __android_log_print(ANDROID_LOG_VERBOSE, APPNAME, "LIBC Executable Section"
264 | " not readable! ");
265 |
266 | } else {
267 | __android_log_print(ANDROID_LOG_VERBOSE, APPNAME, "Suspicious to get XOM "
268 | "for non-system library on "
269 | "Android 10 and above");
270 | }
271 | }
272 | }
273 | return true;
274 | } else {
275 | if (buf[0] == 'r') {
276 | pElfSectArr->startAddrinMem = start;
277 | }
278 | }
279 | return false;
280 | }
281 |
282 | __attribute__((always_inline))
283 | static inline ssize_t read_one_line(int fd, char *buf, unsigned int max_len) {
284 | char b;
285 | ssize_t ret;
286 | ssize_t bytes_read = 0;
287 |
288 | my_memset(buf, 0, max_len);
289 |
290 | do {
291 | ret = my_read(fd, &b, 1);
292 |
293 | if (ret != 1) {
294 | if (bytes_read == 0) {
295 | // error or EOF
296 | return -1;
297 | } else {
298 | return bytes_read;
299 | }
300 | }
301 |
302 | if (b == '\n') {
303 | return bytes_read;
304 | }
305 |
306 | *(buf++) = b;
307 | bytes_read += 1;
308 |
309 | } while (bytes_read < max_len - 1);
310 |
311 | return bytes_read;
312 | }
313 |
314 | __attribute__((always_inline))
315 | static inline unsigned long checksum(void *buffer, size_t len) {
316 | unsigned long seed = 0;
317 | uint8_t *buf = (uint8_t *) buffer;
318 | size_t i;
319 | for (i = 0; i < len; ++i)
320 | seed += (unsigned long) (*buf++);
321 | return seed;
322 | }
323 |
324 | __attribute__((always_inline))
325 | static inline void detect_frida_threads() {
326 |
327 | DIR *dir = opendir(PROC_TASK);
328 |
329 | if (dir != NULL) {
330 | struct dirent *entry = NULL;
331 | while ((entry = readdir(dir)) != NULL) {
332 | char filePath[MAX_LENGTH] = "";
333 |
334 | if (0 == my_strcmp(entry->d_name, ".") || 0 == my_strcmp(entry->d_name, "..")) {
335 | continue;
336 | }
337 | snprintf(filePath, sizeof(filePath), PROC_STATUS, entry->d_name);
338 |
339 | int fd = my_openat(AT_FDCWD, filePath, O_RDONLY | O_CLOEXEC, 0);
340 | if (fd != 0) {
341 | char buf[MAX_LENGTH] = "";
342 | read_one_line(fd, buf, MAX_LENGTH);
343 | if (my_strstr(buf, FRIDA_THREAD_GUM_JS_LOOP) ||
344 | my_strstr(buf, FRIDA_THREAD_GMAIN)) {
345 | //Kill the thread. This freezes the app. Check if it is an anticpated behaviour
346 | //int tid = my_atoi(entry->d_name);
347 | //int ret = my_tgkill(getpid(), tid, SIGSTOP);
348 | __android_log_print(ANDROID_LOG_WARN, APPNAME,
349 | "Frida specific thread found. Act now!!!");
350 | }
351 | my_close(fd);
352 | }
353 |
354 | }
355 | closedir(dir);
356 |
357 | }
358 |
359 | }
360 |
361 | __attribute__((always_inline))
362 | static inline void detect_frida_namedpipe() {
363 |
364 | DIR *dir = opendir(PROC_FD);
365 | if (dir != NULL) {
366 | struct dirent *entry = NULL;
367 | while ((entry = readdir(dir)) != NULL) {
368 | struct stat filestat;
369 | char buf[MAX_LENGTH] = "";
370 | char filePath[MAX_LENGTH] = "";
371 | snprintf(filePath, sizeof(filePath), "/proc/self/fd/%s", entry->d_name);
372 |
373 | lstat(filePath, &filestat);
374 |
375 | if ((filestat.st_mode & S_IFMT) == S_IFLNK) {
376 | //TODO: Another way is to check if filepath belongs to a path not related to system or the app
377 | my_readlinkat(AT_FDCWD, filePath, buf, MAX_LENGTH);
378 | if (NULL != my_strstr(buf, FRIDA_NAMEDPIPE_LINJECTOR)) {
379 | __android_log_print(ANDROID_LOG_WARN, APPNAME,
380 | "Frida specific named pipe found. Act now!!!");
381 | }
382 | }
383 |
384 | }
385 | }
386 | closedir(dir);
387 | }
388 |
389 | __attribute__((always_inline))
390 | static inline void detect_frida_memdiskcompare() {
391 | int fd = 0;
392 | char map[MAX_LINE];
393 |
394 | if ((fd = my_openat(AT_FDCWD, PROC_MAPS, O_RDONLY | O_CLOEXEC, 0)) != 0) {
395 |
396 | while ((read_one_line(fd, map, MAX_LINE)) > 0) {
397 | for (int i = 0; i < NUM_LIBS; i++) {
398 | if (my_strstr(map, libstocheck[i]) != NULL) {
399 | if (true == scan_executable_segments(map, elfSectionArr[i], libstocheck[i])) {
400 | break;
401 | }
402 | }
403 | }
404 | }
405 | } else {
406 | __android_log_print(ANDROID_LOG_WARN, APPNAME,
407 | "Error opening /proc/self/maps. That's usually a bad sign.");
408 |
409 | }
410 | my_close(fd);
411 |
412 | }
413 |
414 |
--------------------------------------------------------------------------------
/app/src/main/c/syscalls.h:
--------------------------------------------------------------------------------
1 | #ifndef DETECTFRIDA_SYSCALLS_H
2 | #define DETECTFRIDA_SYSCALLS_H
3 | /*
4 | * System calls such as file operations, sleep are converted to syscalls to avoid easy bypass
5 | * through readymade scripts hooking onto libc calls.
6 | */
7 | __attribute__((always_inline))
8 | static inline int my_openat(int __dir_fd, const void* __path, int __flags, int __mode ){
9 | return (int)__syscall4(__NR_openat, __dir_fd, (long)__path, __flags, __mode);
10 | }
11 |
12 | __attribute__((always_inline))
13 | static inline ssize_t my_read(int __fd, void* __buf, size_t __count){
14 | return __syscall3(__NR_read, __fd, (long)__buf, (long)__count);
15 | }
16 |
17 | __attribute__((always_inline))
18 | static inline off_t my_lseek(int __fd, off_t __offset, int __whence){
19 | return __syscall3(__NR_lseek, __fd, __offset, __whence);
20 | }
21 |
22 | __attribute__((always_inline))
23 | static inline int my_close(int __fd){
24 | return (int)__syscall1(__NR_close, __fd);
25 | }
26 |
27 | __attribute__((always_inline))
28 | static inline int my_nanosleep(const struct timespec* __request, struct timespec* __remainder){
29 | return (int)__syscall2(__NR_nanosleep, (long)__request, (long)__remainder);
30 | }
31 |
32 | __attribute__((always_inline))
33 | static inline ssize_t my_readlinkat(int __dir_fd, const char* __path, char* __buf, size_t __buf_size){
34 | return __syscall4(__NR_readlinkat, __dir_fd, (long)__path, (long)__buf,(long)__buf_size);
35 | }
36 |
37 | //Not Used
38 | __attribute__((always_inline))
39 | static inline int my_tgkill(int __tgid, int __tid, int __signal){
40 | return (int)__syscall3(__NR_tgkill, __tgid, __tid, __signal);
41 | }
42 |
43 | //Not Used
44 | __attribute__((always_inline))
45 | static inline void my_exit(int __status){
46 | __syscall1(__NR_exit, __status);
47 | }
48 |
49 | #endif //DETECTFRIDA_SYSCALLS_H
--------------------------------------------------------------------------------
/app/src/main/java/com/darvin/security/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.darvin.security;
2 |
3 | import androidx.appcompat.app.AppCompatActivity;
4 | import android.os.Bundle;
5 |
6 | public class MainActivity extends AppCompatActivity {
7 |
8 | // Used to load the 'native-lib' library on application startup.
9 | static {
10 | System.loadLibrary("native-lib");
11 | }
12 |
13 | @Override
14 | protected void onCreate(Bundle savedInstanceState) {
15 | super.onCreate(savedInstanceState);
16 | setContentView(R.layout.activity_main);
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/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 |
18 |
19 |
--------------------------------------------------------------------------------
/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-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kumar-rahul/detectfridalib/d909118a75f1b574f0619cc4fd69344f01e23d6c/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kumar-rahul/detectfridalib/d909118a75f1b574f0619cc4fd69344f01e23d6c/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kumar-rahul/detectfridalib/d909118a75f1b574f0619cc4fd69344f01e23d6c/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kumar-rahul/detectfridalib/d909118a75f1b574f0619cc4fd69344f01e23d6c/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kumar-rahul/detectfridalib/d909118a75f1b574f0619cc4fd69344f01e23d6c/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kumar-rahul/detectfridalib/d909118a75f1b574f0619cc4fd69344f01e23d6c/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kumar-rahul/detectfridalib/d909118a75f1b574f0619cc4fd69344f01e23d6c/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kumar-rahul/detectfridalib/d909118a75f1b574f0619cc4fd69344f01e23d6c/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kumar-rahul/detectfridalib/d909118a75f1b574f0619cc4fd69344f01e23d6c/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kumar-rahul/detectfridalib/d909118a75f1b574f0619cc4fd69344f01e23d6c/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #008577
4 | #00574B
5 | #D81B60
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | DetectFrida
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/test/java/com/darvin/security/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.darvin.security;
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 |
3 | buildscript {
4 | repositories {
5 | google()
6 | mavenCentral()
7 | jcenter()
8 |
9 | }
10 | dependencies {
11 | classpath 'com.android.tools.build:gradle:3.5.0'
12 |
13 | // NOTE: Do not place your application dependencies here; they belong
14 | // in the individual module build.gradle files
15 | }
16 | }
17 |
18 | allprojects {
19 | repositories {
20 | google()
21 | mavenCentral()
22 | jcenter()
23 | }
24 | }
25 |
26 | task clean(type: Delete) {
27 | delete rootProject.buildDir
28 | }
29 |
--------------------------------------------------------------------------------
/detectfridalib/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/detectfridalib/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.library'
3 | }
4 |
5 | android {
6 | compileSdkVersion 30
7 | buildToolsVersion "30.0.3"
8 |
9 | defaultConfig {
10 | minSdkVersion 16
11 | targetSdkVersion 30
12 | versionCode 1
13 | versionName "1.0"
14 |
15 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
16 | consumerProguardFiles "consumer-rules.pro"
17 | }
18 |
19 | buildTypes {
20 | release {
21 | minifyEnabled false
22 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
23 | }
24 | }
25 | compileOptions {
26 | sourceCompatibility JavaVersion.VERSION_1_8
27 | targetCompatibility JavaVersion.VERSION_1_8
28 | }
29 | }
30 |
31 | dependencies {
32 |
33 | implementation 'com.android.support:appcompat-v7:28.0.0'
34 | testImplementation 'junit:junit:4.+'
35 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
36 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
37 | }
--------------------------------------------------------------------------------
/detectfridalib/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kumar-rahul/detectfridalib/d909118a75f1b574f0619cc4fd69344f01e23d6c/detectfridalib/consumer-rules.pro
--------------------------------------------------------------------------------
/detectfridalib/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
--------------------------------------------------------------------------------
/detectfridalib/src/androidTest/java/com/example/detectfridalib/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.example.detectfridalib;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumented test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
23 | assertEquals("com.example.detectfridalib.test", appContext.getPackageName());
24 | }
25 | }
--------------------------------------------------------------------------------
/detectfridalib/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
--------------------------------------------------------------------------------
/detectfridalib/src/test/java/com/example/detectfridalib/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.example.detectfridalib;
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 | }
--------------------------------------------------------------------------------
/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=-Xmx1536m
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 |
15 |
16 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kumar-rahul/detectfridalib/d909118a75f1b574f0619cc4fd69344f01e23d6c/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Tue Nov 12 22:58:47 SGT 2019
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/obfuscated-app-release.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kumar-rahul/detectfridalib/d909118a75f1b574f0619cc4fd69344f01e23d6c/obfuscated-app-release.apk
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':detectfridalib'
2 | include ':app'
3 | rootProject.name='DetectFrida'
4 |
--------------------------------------------------------------------------------