react-native-device-defense 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +236 -0
- package/android/build.gradle +90 -0
- package/android/proguard-rules.pro +28 -0
- package/android/src/main/AndroidManifest.xml +4 -0
- package/android/src/main/cpp/CMakeLists.txt +45 -0
- package/android/src/main/cpp/device-security.cpp +314 -0
- package/android/src/main/java/vn/osp/security/DebugDetection.kt +131 -0
- package/android/src/main/java/vn/osp/security/DeviceSecurityModule.kt +277 -0
- package/android/src/main/java/vn/osp/security/DeviceSecurityPackage.kt +58 -0
- package/android/src/main/java/vn/osp/security/EmulatorDetection.kt +204 -0
- package/android/src/main/java/vn/osp/security/HookDetection.kt +270 -0
- package/android/src/main/java/vn/osp/security/NativeSecurityCheck.kt +66 -0
- package/android/src/main/java/vn/osp/security/RootDetection.kt +349 -0
- package/lib/commonjs/NativeDeviceSecurity.js +9 -0
- package/lib/commonjs/NativeDeviceSecurity.js.map +1 -0
- package/lib/commonjs/api.js +213 -0
- package/lib/commonjs/api.js.map +1 -0
- package/lib/commonjs/components/SecurityBlockedScreen.js +177 -0
- package/lib/commonjs/components/SecurityBlockedScreen.js.map +1 -0
- package/lib/commonjs/components/index.js +13 -0
- package/lib/commonjs/components/index.js.map +1 -0
- package/lib/commonjs/hooks/index.js +13 -0
- package/lib/commonjs/hooks/index.js.map +1 -0
- package/lib/commonjs/hooks/useDeviceSecurity.js +81 -0
- package/lib/commonjs/hooks/useDeviceSecurity.js.map +1 -0
- package/lib/commonjs/index.js +48 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/types.js +2 -0
- package/lib/commonjs/types.js.map +1 -0
- package/lib/module/NativeDeviceSecurity.js +3 -0
- package/lib/module/NativeDeviceSecurity.js.map +1 -0
- package/lib/module/api.js +206 -0
- package/lib/module/api.js.map +1 -0
- package/lib/module/components/SecurityBlockedScreen.js +169 -0
- package/lib/module/components/SecurityBlockedScreen.js.map +1 -0
- package/lib/module/components/index.js +2 -0
- package/lib/module/components/index.js.map +1 -0
- package/lib/module/hooks/index.js +2 -0
- package/lib/module/hooks/index.js.map +1 -0
- package/lib/module/hooks/useDeviceSecurity.js +73 -0
- package/lib/module/hooks/useDeviceSecurity.js.map +1 -0
- package/lib/module/index.js +21 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/types.js +2 -0
- package/lib/module/types.js.map +1 -0
- package/lib/typescript/NativeDeviceSecurity.d.ts +16 -0
- package/lib/typescript/NativeDeviceSecurity.d.ts.map +1 -0
- package/lib/typescript/api.d.ts +55 -0
- package/lib/typescript/api.d.ts.map +1 -0
- package/lib/typescript/components/SecurityBlockedScreen.d.ts +23 -0
- package/lib/typescript/components/SecurityBlockedScreen.d.ts.map +1 -0
- package/lib/typescript/components/index.d.ts +2 -0
- package/lib/typescript/components/index.d.ts.map +1 -0
- package/lib/typescript/hooks/index.d.ts +3 -0
- package/lib/typescript/hooks/index.d.ts.map +1 -0
- package/lib/typescript/hooks/useDeviceSecurity.d.ts +7 -0
- package/lib/typescript/hooks/useDeviceSecurity.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +12 -0
- package/lib/typescript/index.d.ts.map +1 -0
- package/lib/typescript/types.d.ts +81 -0
- package/lib/typescript/types.d.ts.map +1 -0
- package/package.json +72 -0
- package/react-native-device-security.podspec +18 -0
- package/src/NativeDeviceSecurity.ts +33 -0
- package/src/api.ts +225 -0
- package/src/components/SecurityBlockedScreen.tsx +204 -0
- package/src/components/index.ts +1 -0
- package/src/hooks/index.ts +5 -0
- package/src/hooks/useDeviceSecurity.ts +91 -0
- package/src/index.ts +27 -0
- package/src/types.ts +95 -0
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
#include <jni.h>
|
|
2
|
+
#include <string>
|
|
3
|
+
#include <vector>
|
|
4
|
+
#include <fstream>
|
|
5
|
+
#include <dirent.h>
|
|
6
|
+
#include <sys/stat.h>
|
|
7
|
+
#include <unistd.h>
|
|
8
|
+
#include <android/log.h>
|
|
9
|
+
#include <stdexcept>
|
|
10
|
+
|
|
11
|
+
#define LOG_TAG "DeviceSecurityNative"
|
|
12
|
+
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
|
|
13
|
+
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Check if a file exists
|
|
17
|
+
*/
|
|
18
|
+
static bool fileExists(const std::string& path) {
|
|
19
|
+
struct stat buffer;
|
|
20
|
+
return (stat(path.c_str(), &buffer) == 0);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Check if a file is executable
|
|
25
|
+
*/
|
|
26
|
+
static bool isExecutable(const std::string& path) {
|
|
27
|
+
struct stat buffer;
|
|
28
|
+
if (stat(path.c_str(), &buffer) != 0) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
return (buffer.st_mode & S_IXUSR) != 0;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Check if a directory exists
|
|
36
|
+
*/
|
|
37
|
+
static bool directoryExists(const std::string& path) {
|
|
38
|
+
struct stat buffer;
|
|
39
|
+
return (stat(path.c_str(), &buffer) == 0) && S_ISDIR(buffer.st_mode);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Check for su binary in various locations
|
|
44
|
+
*/
|
|
45
|
+
static bool checkSuBinary() {
|
|
46
|
+
const std::vector<std::string> suPaths = {
|
|
47
|
+
"/system/bin/su",
|
|
48
|
+
"/system/xbin/su",
|
|
49
|
+
"/sbin/su",
|
|
50
|
+
"/data/local/xbin/su",
|
|
51
|
+
"/data/local/bin/su",
|
|
52
|
+
"/system/sd/xbin/su",
|
|
53
|
+
"/system/bin/failsafe/su",
|
|
54
|
+
"/data/local/su",
|
|
55
|
+
"/su/bin/su",
|
|
56
|
+
"/magisk/.core/bin/su",
|
|
57
|
+
"/system/usr/we-need-root/su"
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
for (const auto& path : suPaths) {
|
|
61
|
+
if (fileExists(path) && isExecutable(path)) {
|
|
62
|
+
LOGD("Found su binary at: %s", path.c_str());
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Check for dangerous binaries
|
|
72
|
+
*/
|
|
73
|
+
static bool checkDangerousBinaries() {
|
|
74
|
+
const std::vector<std::string> binaries = {
|
|
75
|
+
"/system/xbin/busybox",
|
|
76
|
+
"/system/bin/busybox",
|
|
77
|
+
"/sbin/busybox",
|
|
78
|
+
"/data/local/xbin/busybox",
|
|
79
|
+
"/data/local/bin/busybox",
|
|
80
|
+
"/system/app/Superuser.apk",
|
|
81
|
+
"/sbin/.magisk",
|
|
82
|
+
"/system/xbin/magisk",
|
|
83
|
+
"/system/bin/magisk"
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
for (const auto& binary : binaries) {
|
|
87
|
+
if (fileExists(binary)) {
|
|
88
|
+
LOGD("Found dangerous binary: %s", binary.c_str());
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Check for root-related directories
|
|
98
|
+
*/
|
|
99
|
+
static bool checkRootDirectories() {
|
|
100
|
+
const std::vector<std::string> directories = {
|
|
101
|
+
"/data/local/xbin",
|
|
102
|
+
"/data/local/bin",
|
|
103
|
+
"/su",
|
|
104
|
+
"/system/app/SuperSU",
|
|
105
|
+
"/system/app/Superuser",
|
|
106
|
+
"/data/data/com.noshufou.android.su",
|
|
107
|
+
"/data/data/com.thirdparty.superuser",
|
|
108
|
+
"/data/data/eu.chainfire.supersu",
|
|
109
|
+
"/data/data/com.topjohnwu.magisk",
|
|
110
|
+
"/cache/magisk.log",
|
|
111
|
+
"/dev/com.topjohnwu.magisk",
|
|
112
|
+
"/system/app/MagiskManager",
|
|
113
|
+
"/data/adb/magisk",
|
|
114
|
+
"/data/adb/modules"
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
for (const auto& dir : directories) {
|
|
118
|
+
if (directoryExists(dir)) {
|
|
119
|
+
LOGD("Found root directory: %s", dir.c_str());
|
|
120
|
+
return true;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Check system properties for root indicators
|
|
129
|
+
*/
|
|
130
|
+
static bool checkSystemProperties() {
|
|
131
|
+
const std::vector<std::string> propFiles = {
|
|
132
|
+
"/default.prop",
|
|
133
|
+
"/system/build.prop",
|
|
134
|
+
"/vendor/build.prop",
|
|
135
|
+
"/product/build.prop"
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
for (const auto& propFile : propFiles) {
|
|
139
|
+
if (!fileExists(propFile)) continue;
|
|
140
|
+
|
|
141
|
+
std::ifstream file(propFile);
|
|
142
|
+
std::string line;
|
|
143
|
+
|
|
144
|
+
while (std::getline(file, line)) {
|
|
145
|
+
if (line.find("ro.debuggable=1") != std::string::npos) {
|
|
146
|
+
LOGD("Found ro.debuggable=1 in %s", propFile.c_str());
|
|
147
|
+
return true;
|
|
148
|
+
}
|
|
149
|
+
if (line.find("ro.secure=0") != std::string::npos) {
|
|
150
|
+
LOGD("Found ro.secure=0 in %s", propFile.c_str());
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
153
|
+
if (line.find("service.adb.root=1") != std::string::npos) {
|
|
154
|
+
LOGD("Found service.adb.root=1 in %s", propFile.c_str());
|
|
155
|
+
return true;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Check mount points for RW system
|
|
165
|
+
*/
|
|
166
|
+
static bool checkMountPoints() {
|
|
167
|
+
std::ifstream mounts("/proc/mounts");
|
|
168
|
+
std::string line;
|
|
169
|
+
|
|
170
|
+
const std::vector<std::string> systemMounts = {
|
|
171
|
+
"/system",
|
|
172
|
+
"/vendor",
|
|
173
|
+
"/product",
|
|
174
|
+
"/system_ext"
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
while (std::getline(mounts, line)) {
|
|
178
|
+
// Check if any system mount is mounted RW
|
|
179
|
+
for (const auto& mount : systemMounts) {
|
|
180
|
+
if (line.find(mount) != std::string::npos) {
|
|
181
|
+
if (line.find("rw,") != std::string::npos ||
|
|
182
|
+
line.find(" rw ") != std::string::npos) {
|
|
183
|
+
LOGD("Found RW mount: %s", line.c_str());
|
|
184
|
+
return true;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return false;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Check for tracer PID (debugger detection)
|
|
195
|
+
*/
|
|
196
|
+
static bool checkTracerPid() {
|
|
197
|
+
std::ifstream statusFile("/proc/self/status");
|
|
198
|
+
std::string line;
|
|
199
|
+
|
|
200
|
+
while (std::getline(statusFile, line)) {
|
|
201
|
+
if (line.find("TracerPid:") == 0) {
|
|
202
|
+
try {
|
|
203
|
+
size_t pos = line.find_last_not_of(" \t\n\r");
|
|
204
|
+
if (pos != std::string::npos && pos > 10) {
|
|
205
|
+
std::string value = line.substr(10, pos - 9);
|
|
206
|
+
int tracerPid = std::stoi(value);
|
|
207
|
+
if (tracerPid > 0) {
|
|
208
|
+
LOGD("Tracer PID detected: %d", tracerPid);
|
|
209
|
+
return true;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
} catch (const std::exception& e) {
|
|
213
|
+
// Parse error, ignore
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return false;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Check for Frida in /proc/self/maps
|
|
223
|
+
*/
|
|
224
|
+
static bool checkFridaInMaps() {
|
|
225
|
+
std::ifstream mapsFile("/proc/self/maps");
|
|
226
|
+
std::string line;
|
|
227
|
+
|
|
228
|
+
while (std::getline(mapsFile, line)) {
|
|
229
|
+
if (line.find("frida") != std::string::npos ||
|
|
230
|
+
line.find("frida-agent") != std::string::npos ||
|
|
231
|
+
line.find("libfrida") != std::string::npos) {
|
|
232
|
+
LOGD("Found Frida in maps: %s", line.c_str());
|
|
233
|
+
return true;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
return false;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Main root detection function
|
|
242
|
+
*/
|
|
243
|
+
static bool performRootDetection() {
|
|
244
|
+
// Check for su binary
|
|
245
|
+
if (checkSuBinary()) {
|
|
246
|
+
return true;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Check for dangerous binaries
|
|
250
|
+
if (checkDangerousBinaries()) {
|
|
251
|
+
return true;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Check for root directories
|
|
255
|
+
if (checkRootDirectories()) {
|
|
256
|
+
return true;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// Check system properties
|
|
260
|
+
if (checkSystemProperties()) {
|
|
261
|
+
return true;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Check mount points
|
|
265
|
+
if (checkMountPoints()) {
|
|
266
|
+
return true;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
return false;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
extern "C" JNIEXPORT jboolean JNICALL
|
|
273
|
+
Java_vn_osp_security_NativeSecurityCheck_isRooted(JNIEnv* env, jobject /* this */) {
|
|
274
|
+
return performRootDetection() ? JNI_TRUE : JNI_FALSE;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
extern "C" JNIEXPORT jboolean JNICALL
|
|
278
|
+
Java_vn_osp_security_NativeSecurityCheck_hasDangerousBinaries(JNIEnv* env, jobject /* this */) {
|
|
279
|
+
return checkDangerousBinaries() ? JNI_TRUE : JNI_FALSE;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
extern "C" JNIEXPORT jboolean JNICALL
|
|
283
|
+
Java_vn_osp_security_NativeSecurityCheck_hasSuspiciousSystemProperties(JNIEnv* env, jobject /* this */) {
|
|
284
|
+
return checkSystemProperties() ? JNI_TRUE : JNI_FALSE;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
extern "C" JNIEXPORT jboolean JNICALL
|
|
288
|
+
Java_vn_osp_security_NativeSecurityCheck_hasHookFramework(JNIEnv* env, jobject /* this */) {
|
|
289
|
+
return checkFridaInMaps() ? JNI_TRUE : JNI_FALSE;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
extern "C" JNIEXPORT jboolean JNICALL
|
|
293
|
+
Java_vn_osp_security_NativeSecurityCheck_isDebuggerAttached(JNIEnv* env, jobject /* this */) {
|
|
294
|
+
return checkTracerPid() ? JNI_TRUE : JNI_FALSE;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
extern "C" JNIEXPORT jstring JNICALL
|
|
298
|
+
Java_vn_osp_security_NativeSecurityCheck_getSecurityStatus(JNIEnv* env, jobject /* this */) {
|
|
299
|
+
bool isRooted = performRootDetection();
|
|
300
|
+
bool hasDangerousBins = checkDangerousBinaries();
|
|
301
|
+
bool hasSuspiciousProps = checkSystemProperties();
|
|
302
|
+
bool hasHook = checkFridaInMaps();
|
|
303
|
+
bool hasDebugger = checkTracerPid();
|
|
304
|
+
|
|
305
|
+
std::string json = "{";
|
|
306
|
+
json += "\"isRooted\":" + std::string(isRooted ? "true" : "false") + ",";
|
|
307
|
+
json += "\"hasDangerousBins\":" + std::string(hasDangerousBins ? "true" : "false") + ",";
|
|
308
|
+
json += "\"hasSuspiciousProps\":" + std::string(hasSuspiciousProps ? "true" : "false") + ",";
|
|
309
|
+
json += "\"hasHookFramework\":" + std::string(hasHook ? "true" : "false") + ",";
|
|
310
|
+
json += "\"isDebuggerAttached\":" + std::string(hasDebugger ? "true" : "false");
|
|
311
|
+
json += "}";
|
|
312
|
+
|
|
313
|
+
return env->NewStringUTF(json.c_str());
|
|
314
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
package vn.osp.security
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.os.Debug
|
|
5
|
+
import java.io.BufferedReader
|
|
6
|
+
import java.io.File
|
|
7
|
+
import java.io.InputStreamReader
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Detection for debuggers and debugging tools
|
|
11
|
+
*/
|
|
12
|
+
class DebugDetection(private val context: Context) {
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Check if app is debuggable
|
|
16
|
+
*/
|
|
17
|
+
fun isDebuggable(): Boolean {
|
|
18
|
+
// Check application flags
|
|
19
|
+
val appInfo = context.applicationInfo
|
|
20
|
+
if ((appInfo.flags and android.content.pm.ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
|
|
21
|
+
return true
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Check if debugger is connected
|
|
25
|
+
if (Debug.isDebuggerConnected()) {
|
|
26
|
+
return true
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Check if debugger is waiting
|
|
30
|
+
if (Debug.waitingForDebugger()) {
|
|
31
|
+
return true
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Check for tracer PID
|
|
35
|
+
if (checkTracerPid()) {
|
|
36
|
+
return true
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return false
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Check for tracer PID in /proc/self/status
|
|
44
|
+
* Tracer PID > 0 indicates a debugger is attached
|
|
45
|
+
*/
|
|
46
|
+
private fun checkTracerPid(): Boolean {
|
|
47
|
+
try {
|
|
48
|
+
val statusFile = File("/proc/self/status")
|
|
49
|
+
if (!statusFile.exists()) {
|
|
50
|
+
return false
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
val bufferedReader = BufferedReader(InputStreamReader(statusFile.inputStream()))
|
|
54
|
+
bufferedReader.use { reader ->
|
|
55
|
+
var line: String?
|
|
56
|
+
while (reader.readLine().also { line = it } != null) {
|
|
57
|
+
if (line?.startsWith("TracerPid:") == true) {
|
|
58
|
+
val tracerPid = line.substringAfter(":").trim()
|
|
59
|
+
val pid = tracerPid.toIntOrNull()
|
|
60
|
+
// TracerPid > 0 means a debugger is attached
|
|
61
|
+
return pid != null && pid > 0
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
} catch (e: Exception) {
|
|
66
|
+
// Ignore errors
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return false
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Check for debugging tools installed
|
|
74
|
+
*/
|
|
75
|
+
fun hasDebuggingTools(): Boolean {
|
|
76
|
+
val debugPackages = listOf(
|
|
77
|
+
"com.android.spare_parts", // Android spare parts
|
|
78
|
+
"com.android.development", // Development settings
|
|
79
|
+
"com.android.customlocale2", // Custom locale
|
|
80
|
+
"com.android.emulator.gps", // Emulator GPS
|
|
81
|
+
"com.saurik.substrate", // Substrate (cydia alternative)
|
|
82
|
+
"com.n0n3m4.gpsroot", // GPS root
|
|
83
|
+
"com.zachspong.temprootremovejb", // Temp root remove
|
|
84
|
+
"com.ramdroid.appquarantine", // App quarantine
|
|
85
|
+
"com.devadvance.rootcloak", // Root cloak
|
|
86
|
+
"com.devadvance.rootcloakplus", // Root cloak plus
|
|
87
|
+
"de.robv.android.xposed.installer", // Xposed
|
|
88
|
+
"com.saurik.substrate", // Substrate
|
|
89
|
+
"com.pyler.panel", // Xposed module
|
|
90
|
+
"com.elpuerco.touches", // Touches indicator
|
|
91
|
+
"com.manic.networkhandup", // Network handup
|
|
92
|
+
"com.automate1234 automate", // Automate
|
|
93
|
+
"com.faendir.leo.louise", // Louise
|
|
94
|
+
"com.faendir.leo.louise.free", // Louise free
|
|
95
|
+
"com.faendir.leo.louise.paid", // Louise paid
|
|
96
|
+
"com.faendir.leo.louise.unlock", // Louise unlock
|
|
97
|
+
"com.faendir.leo.louise.unlock.all" // Louise unlock all
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
return debugPackages.any { isPackageInstalled(it) }
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Check if ADB debugging is enabled
|
|
105
|
+
*/
|
|
106
|
+
fun isAdbEnabled(): Boolean {
|
|
107
|
+
// Check global settings for ADB
|
|
108
|
+
return try {
|
|
109
|
+
val settings = android.provider.Settings.Global.getInt(
|
|
110
|
+
context.contentResolver,
|
|
111
|
+
android.provider.Settings.Global.ADB_ENABLED,
|
|
112
|
+
0
|
|
113
|
+
)
|
|
114
|
+
settings == 1
|
|
115
|
+
} catch (e: Exception) {
|
|
116
|
+
false
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Check if package is installed
|
|
122
|
+
*/
|
|
123
|
+
private fun isPackageInstalled(packageName: String): Boolean {
|
|
124
|
+
return try {
|
|
125
|
+
context.packageManager.getPackageInfo(packageName, 0)
|
|
126
|
+
true
|
|
127
|
+
} catch (e: Exception) {
|
|
128
|
+
false
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|