Android Emulator Detection Bypass with Real Device Fingerprint Injection
27 views
0445ae16...
Description
tes
How to Use
Download the script and run it with Frida CLI:
Download ScriptThen run with Frida:
frida -U -f YOUR_PACKAGE_NAME -l android-emulator-detection-bypass-with-real-device-fingerprint-injection.js
Replace YOUR_PACKAGE_NAME with the target app's package name.
Source Code
JavaScript
/**
* Frida Script: Android Emulator Detection Bypass with Real Device Fingerprint Injection
* @author fdciabdul
*/
'use strict';
// ============================================================================
// REAL DEVICE FINGERPRINT DATA
// ============================================================================
// Detect if we're on x86 emulator to avoid graphics crashes
const ACTUAL_ABI = Process.arch; // 'x64', 'ia32', 'arm64', 'arm'
const IS_X86_EMULATOR = (ACTUAL_ABI === 'x64' || ACTUAL_ABI === 'ia32');
// Configuration: Set to false to keep original CPU ABI (prevents graphics crashes on x86)
const SPOOF_CPU_ABI = !IS_X86_EMULATOR;
const DeviceFingerprint = {
// Samsung Galaxy S24 Ultra fingerprint (example - customize as needed)
PRODUCT: "dm3q",
MANUFACTURER: "samsung",
BOOTLOADER: "S928BXXU3AXJA",
DEVICE: "dm3q",
HARDWARE: "qcom",
MODEL: "SM-S928B",
BRAND: "samsung",
BOARD: "kalama",
FINGERPRINT: "samsung/dm3qxxx/dm3q:14/UP1A.231005.007/S928BXXU3AXJA:user/release-keys",
// CPU/ABI properties (only used if SPOOF_CPU_ABI is true)
CPU_ABI: "arm64-v8a",
CPU_ABILIST: "arm64-v8a,armeabi-v7a,armeabi",
CPU_ABILIST32: "armeabi-v7a,armeabi",
CPU_ABILIST64: "arm64-v8a",
// ARM translation properties (should be disabled on real device)
NATIVE_BRIDGE: "0",
ISA_ARM: "",
ISA_ARM64: "",
// Additional properties
SERIAL: "RF8N10XXXXX",
HOST: "21DY0603",
RADIO: "1.0",
SECURE: "1",
TYPE: "user",
TAGS: "release-keys",
// Kernel info for /proc/cpuinfo
CPU_INFO: `Processor\t: AArch64 Processor rev 1 (aarch64)
processor\t: 0
BogoMIPS\t: 38.40
Features\t: fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm ssbs paca pacg dcpodp svei8mm svebf16 i8mm bf16 dgh rng bti ecv
CPU implementer\t: 0x41
CPU architecture: 8
CPU variant\t: 0x1
CPU part\t: 0xd46
CPU revision\t: 1
processor\t: 1
BogoMIPS\t: 38.40
Features\t: fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm ssbs paca pacg dcpodp svei8mm svebf16 i8mm bf16 dgh rng bti ecv
CPU implementer\t: 0x41
CPU architecture: 8
CPU variant\t: 0x1
CPU part\t: 0xd46
CPU revision\t: 1
Hardware\t: Qualcomm Technologies, Inc. Kalama
`
};
// ============================================================================
// SYSTEM PROPERTY SPOOFING
// ============================================================================
// Build the property map, conditionally including CPU ABI properties
function buildPropertyMap() {
const map = {
// Build properties
"ro.build.product": DeviceFingerprint.PRODUCT,
"ro.product.manufacturer": DeviceFingerprint.MANUFACTURER,
"ro.bootloader": DeviceFingerprint.BOOTLOADER,
"ro.product.device": DeviceFingerprint.DEVICE,
"ro.hardware": DeviceFingerprint.HARDWARE,
"ro.product.model": DeviceFingerprint.MODEL,
"ro.product.brand": DeviceFingerprint.BRAND,
"ro.product.board": DeviceFingerprint.BOARD,
"ro.build.fingerprint": DeviceFingerprint.FINGERPRINT,
"ro.serialno": DeviceFingerprint.SERIAL,
"ro.build.host": DeviceFingerprint.HOST,
"ro.build.type": DeviceFingerprint.TYPE,
"ro.build.tags": DeviceFingerprint.TAGS,
"ro.secure": DeviceFingerprint.SECURE,
// Additional emulator detection properties
"ro.kernel.qemu": "0",
"ro.kernel.android.qemud": "",
"ro.kernel.qemu.gles": "",
"init.svc.qemud": "",
"init.svc.qemu-props": "",
"qemu.hw.mainkeys": "",
"qemu.sf.fake_camera": "",
"qemu.sf.lcd_density": "",
"ro.hardware.virtual_device": "",
"ro.boot.qemu": "",
"ro.boot.hardware.sku": "",
};
// Only spoof CPU ABI properties if safe to do so
if (SPOOF_CPU_ABI) {
map["ro.product.cpu.abi"] = DeviceFingerprint.CPU_ABI;
map["ro.product.cpu.abilist"] = DeviceFingerprint.CPU_ABILIST;
map["ro.product.cpu.abilist32"] = DeviceFingerprint.CPU_ABILIST32;
map["ro.product.cpu.abilist64"] = DeviceFingerprint.CPU_ABILIST64;
}
// ARM translation properties (always set to disable detection)
map["ro.dalvik.vm.native.bridge"] = DeviceFingerprint.NATIVE_BRIDGE;
map["ro.dalvik.vm.isa.arm"] = DeviceFingerprint.ISA_ARM;
map["ro.dalvik.vm.isa.arm64"] = DeviceFingerprint.ISA_ARM64;
return map;
}
const PropertyMap = buildPropertyMap();
// ============================================================================
// EMULATOR FILES TO HIDE
// ============================================================================
const EmulatorFiles = [
// Andy emulator
"fstab.andy", "ueventd.andy.rc",
// NOX emulator
"fstab.nox", "init.nox.rc", "ueventd.nox.rc",
"/system/bin/nox-prop", "/system/bin/noxd", "/system/bin/nox",
"/system/bin/nox-vbox-sf", "/system/lib/libnoxd.so", "/system/lib/libnoxspeedup.so",
"/system/etc/init.nox.sh",
// QEMU
"dev/socket/qemud", "dev/qemu_pipe", "/dev/qemu_pipe", "/dev/socket/qemud",
// MEmu
"/dev/memufp", "/dev/memuguest", "/dev/memuuser", "/system/lib/memuguest.ko",
// BlueStacks
"/system/priv-app/com.bluestacks.bstfolder.apk",
"/dev/bst_gps", "/dev/bst_ime", "/dev/bstgyro", "/dev/bstmegn",
"/data/.bluestacks.prop", "/data/.bstconf.prop",
"/data/data/com.bluestacks.bstfolder", "/data/data/com.bluestacks.appmart",
"/data/data/com.bluestacks.home", "/data/data/com.bluestacks.launcher",
"/system/bin/bstfolder", "/system/bin/bstfolderd", "/system/bin/bstsyncfs",
"/system/bin/bstsvcmgrtest", "/system/bin/bstshutdown", "/system/bin/bstime",
"/system/bin/bstshutdown_core",
"/sys/module/bstsensor", "/sys/module/bstpgaipc",
"/system/xbin/bstk/su", "/system/xbin/bstk",
"/boot/bstmods/bstpgaipc.ko", "/boot/bstmods/bstaudio.ko",
"/boot/bstmods/bstcamera.ko", "/boot/bstmods/bstvmsg.ko",
"/boot/bstmods/bstinput.ko", "/boot/bstsetup.env",
"/boot/bin/bstreport", "/boot/bin/bstconf", "/boot/bstsetconf.sh",
// PhoenixOS
"/system/xbin/phoenix_compat", "/data/system/phoenixlog.addr", "/system/phoenixos",
// LDPlayer
"/system/lib/hw/gps.ld.so", "/system/lib/hw/sensors.ld.so",
"/system/lib/libldutils.so", "/system/bin/ldinit", "/system/bin/ldmountsf",
"/system/app/LDAppStore/LDAppStore.apk",
"/data/data/com.ldmnq.launcher3/files/launcher.preferences",
"/data/data/com.android.ld.appstore", "/data/data/com.koplay.launcher",
// VirtualBox
"/mnt/windows", "/mnt/windows/BstSharedFolder",
"/lib/vboxguest.ko", "/lib/vboxsf.ko",
"/sys/module/vboxsf", "/sys/module/vboxpcismv",
// Genymotion
"/sys/module/mg", "/system/bin/genybaseband",
// Droid4x
"/system/bin/droid4x-vbox-sf", "/system/bin/droid4x", "/system/bin/androidVM-vbox-sf",
// KOPLAYER
"/system/bin/KOPLAYER.ini",
// NEmu
"/sys/module/nemusf", "/sys/module/msf",
// Houdini (ARM translation)
"/system/lib/libhoudini.so", "/system/lib64/libhoudini.so",
];
// Strings to filter from file contents
const FilteredStrings = ["vboxsf", "hypervisor", "bluestacks", "nox", "goldfish", "houdini"];
// ============================================================================
// LOGGING UTILITY
// ============================================================================
const LOG_TAG = "[EmulatorBypass]";
let DEBUG = true;
function log(message) {
if (DEBUG) {
console.log(`${LOG_TAG} ${message}`);
}
}
function logSuccess(message) {
console.log(`${LOG_TAG} ✓ ${message}`);
}
function logBypass(message) {
console.log(`${LOG_TAG} 🛡 BYPASS: ${message}`);
}
// ============================================================================
// FRIDA 17+ COMPATIBILITY HELPER
// ============================================================================
// Helper function for Frida 17+ API compatibility
function findExportByName(moduleName, exportName) {
if (moduleName === null) {
// Global export lookup (for symbols not tied to a specific module)
try {
return Module.getGlobalExportByName(exportName);
} catch (e) {
return null;
}
}
const module = Process.findModuleByName(moduleName);
if (!module) {
return null;
}
try {
return module.findExportByName(exportName);
} catch (e) {
return null;
}
}
// ============================================================================
// HOOK: __system_property_get
// ============================================================================
function hookSystemPropertyGet() {
const __system_property_get = findExportByName("libc.so", "__system_property_get");
if (__system_property_get !== null) {
try {
Interceptor.attach(__system_property_get, {
onEnter: function(args) {
this.name = args[0].readCString();
this.value = args[1];
},
onLeave: function() {
if (this.name && PropertyMap.hasOwnProperty(this.name)) {
const spoofedValue = PropertyMap[this.name];
this.value.writeUtf8String(spoofedValue);
logBypass(`Property ${this.name} -> "${spoofedValue}"`);
}
}
});
logSuccess("Hooked __system_property_get");
} catch (e) {
log("Failed to hook __system_property_get: " + e.message);
}
} else {
log("__system_property_get not found (may be Android 8+ or hidden)");
}
// Hook __system_property_read_callback (Android 8+)
// Note: This is complex and can cause crashes if not done carefully.
// For now, we rely on __system_property_get and Java-level hooks instead.
const __system_property_read_callback = findExportByName("libc.so", "__system_property_read_callback");
if (__system_property_read_callback !== null) {
log("Found __system_property_read_callback (Android 8+) - relying on other hooks");
// Commenting out the problematic hook that was causing crashes
// The __system_property_get hook + Java SystemProperties hooks should be sufficient
}
// Try alternative: hook SystemProperties class (Java layer)
Java.perform(function() {
try {
const SystemProperties = Java.use("android.os.SystemProperties");
SystemProperties.get.overload('java.lang.String').implementation = function(key) {
if (PropertyMap.hasOwnProperty(key)) {
logBypass(`SystemProperties.get(${key}) -> "${PropertyMap[key]}"`);
return PropertyMap[key];
}
return this.get(key);
};
SystemProperties.get.overload('java.lang.String', 'java.lang.String').implementation = function(key, def) {
if (PropertyMap.hasOwnProperty(key)) {
logBypass(`SystemProperties.get(${key}, ${def}) -> "${PropertyMap[key]}"`);
return PropertyMap[key];
}
return this.get(key, def);
};
logSuccess("Hooked SystemProperties Java class");
} catch (e) {
log("SystemProperties Java hooks skipped: " + e.message);
}
});
}
// ============================================================================
// HOOK: File Access Functions (fopen, open, access, stat)
// ============================================================================
function isEmulatorFile(path) {
if (!path) return false;
for (const emulatorFile of EmulatorFiles) {
if (path.includes(emulatorFile) || path.endsWith(emulatorFile)) {
return true;
}
}
return false;
}
function hookFileAccess() {
// Hook fopen
const fopen = findExportByName("libc.so", "fopen");
if (fopen) {
Interceptor.attach(fopen, {
onEnter: function(args) {
this.path = args[0].readCString();
},
onLeave: function(retval) {
if (this.path && isEmulatorFile(this.path)) {
logBypass(`Hidden file (fopen): ${this.path}`);
retval.replace(ptr(0));
}
}
});
logSuccess("Hooked fopen");
}
// Hook open
const open = findExportByName("libc.so", "open");
if (open) {
Interceptor.attach(open, {
onEnter: function(args) {
this.path = args[0].readCString();
},
onLeave: function(retval) {
if (this.path && isEmulatorFile(this.path)) {
logBypass(`Hidden file (open): ${this.path}`);
retval.replace(ptr(-1));
}
}
});
logSuccess("Hooked open");
}
// Hook access
const access = findExportByName("libc.so", "access");
if (access) {
Interceptor.attach(access, {
onEnter: function(args) {
this.path = args[0].readCString();
},
onLeave: function(retval) {
if (this.path && isEmulatorFile(this.path)) {
logBypass(`Hidden file (access): ${this.path}`);
retval.replace(ptr(-1));
}
}
});
logSuccess("Hooked access");
}
// Hook stat/stat64
const stat = findExportByName("libc.so", "stat");
if (stat) {
Interceptor.attach(stat, {
onEnter: function(args) {
this.path = args[0].readCString();
},
onLeave: function(retval) {
if (this.path && isEmulatorFile(this.path)) {
logBypass(`Hidden file (stat): ${this.path}`);
retval.replace(ptr(-1));
}
}
});
logSuccess("Hooked stat");
}
// Hook lstat
const lstat = findExportByName("libc.so", "lstat");
if (lstat) {
Interceptor.attach(lstat, {
onEnter: function(args) {
this.path = args[0].readCString();
},
onLeave: function(retval) {
if (this.path && isEmulatorFile(this.path)) {
logBypass(`Hidden file (lstat): ${this.path}`);
retval.replace(ptr(-1));
}
}
});
logSuccess("Hooked lstat");
}
}
// ============================================================================
// HOOK: /proc/cpuinfo and /proc/mounts content filtering
// ============================================================================
let openFdMap = new Map();
function hookProcFilesystem() {
// Track opened /proc files
const open = findExportByName("libc.so", "open");
if (open) {
Interceptor.attach(open, {
onEnter: function(args) {
this.path = args[0].readCString();
},
onLeave: function(retval) {
const fd = retval.toInt32();
if (fd >= 0 && this.path) {
if (this.path === "/proc/cpuinfo" || this.path === "/proc/mounts") {
openFdMap.set(fd, this.path);
}
}
}
});
}
const fopen = findExportByName("libc.so", "fopen");
if (fopen) {
Interceptor.attach(fopen, {
onEnter: function(args) {
this.path = args[0].readCString();
},
onLeave: function(retval) {
if (!retval.isNull() && this.path) {
if (this.path === "/proc/cpuinfo" || this.path === "/proc/mounts") {
openFdMap.set(retval.toString(), this.path);
}
}
}
});
}
// Hook fgets to filter content
const fgets = findExportByName("libc.so", "fgets");
if (fgets) {
Interceptor.attach(fgets, {
onLeave: function(retval) {
if (!retval.isNull()) {
try {
const line = retval.readCString();
if (line) {
const lowerLine = line.toLowerCase();
// Filter /proc/cpuinfo
if (lowerLine.includes("hypervisor") ||
(lowerLine.includes("vendor_id") && (lowerLine.includes("amd") || lowerLine.includes("intel"))) ||
(lowerLine.includes("model name") && (lowerLine.includes("amd") || lowerLine.includes("intel")))) {
logBypass(`Filtered cpuinfo line: ${line.trim()}`);
// Replace with empty or safe content
retval.writeUtf8String("\n");
}
// Filter /proc/mounts
if (lowerLine.includes("vboxsf") || lowerLine.includes("virtualbox")) {
logBypass(`Filtered mounts line: ${line.trim()}`);
retval.writeUtf8String("\n");
}
}
} catch (e) {
// Ignore read errors
}
}
}
});
logSuccess("Hooked fgets for /proc filtering");
}
// Hook read for lower-level file access
const read = findExportByName("libc.so", "read");
if (read) {
Interceptor.attach(read, {
onEnter: function(args) {
this.fd = args[0].toInt32();
this.buf = args[1];
this.count = args[2].toInt32();
},
onLeave: function(retval) {
const bytesRead = retval.toInt32();
if (bytesRead > 0 && openFdMap.has(this.fd)) {
const filePath = openFdMap.get(this.fd);
try {
let content = this.buf.readCString(bytesRead);
let modified = false;
if (filePath === "/proc/cpuinfo") {
// Replace with real device CPU info
if (content.toLowerCase().includes("hypervisor") ||
content.toLowerCase().includes("intel") ||
content.toLowerCase().includes("amd")) {
content = DeviceFingerprint.CPU_INFO;
modified = true;
}
}
if (filePath === "/proc/mounts") {
if (content.toLowerCase().includes("vboxsf")) {
content = content.replace(/.*vboxsf.*/gi, "");
modified = true;
}
}
if (modified) {
this.buf.writeUtf8String(content);
logBypass(`Modified ${filePath} content`);
}
} catch (e) {
// Ignore read errors
}
}
}
});
logSuccess("Hooked read for /proc filtering");
}
// Clean up fd map on close
const close = findExportByName("libc.so", "close");
if (close) {
Interceptor.attach(close, {
onEnter: function(args) {
const fd = args[0].toInt32();
openFdMap.delete(fd);
}
});
}
const fclose = findExportByName("libc.so", "fclose");
if (fclose) {
Interceptor.attach(fclose, {
onEnter: function(args) {
openFdMap.delete(args[0].toString());
}
});
}
}
// ============================================================================
// HOOK: dl_iterate_phdr (Hide libhoudini.so)
// ============================================================================
function hookDlIteratePhdr() {
// Hook dl_iterate_phdr to hide libhoudini from loaded library enumeration
// This uses Interceptor.replace instead of callback wrapping to avoid crashes
const dl_iterate_phdr = findExportByName(null, "dl_iterate_phdr");
if (dl_iterate_phdr) {
try {
// Store original function
const original_dl_iterate_phdr = new NativeFunction(dl_iterate_phdr, 'int', ['pointer', 'pointer']);
// Replace with our implementation
Interceptor.replace(dl_iterate_phdr, new NativeCallback(function(callback, data) {
// Create a wrapper callback that filters libhoudini
const wrappedCallback = new NativeCallback(function(info, size, data) {
try {
// Read library name from dl_phdr_info struct
// struct dl_phdr_info { ElfW(Addr) dlpi_addr; const char *dlpi_name; ... }
const namePtr = info.add(Process.pointerSize).readPointer();
if (!namePtr.isNull()) {
const name = namePtr.readCString();
// Filter out libhoudini and other ARM translation libraries
if (name && (
name.toLowerCase().includes("libhoudini") ||
name.toLowerCase().includes("libndk_translation")
)) {
logBypass(`Hidden library in dl_iterate_phdr: ${name}`);
return 0; // Skip this entry
}
}
} catch (e) {
// If we can't read the name, pass through to avoid crashes
}
// Call original callback for non-filtered libraries
const origCallback = new NativeFunction(callback, 'int', ['pointer', 'size_t', 'pointer']);
return origCallback(info, size, data);
}, 'int', ['pointer', 'size_t', 'pointer']);
// Call original with our wrapped callback
return original_dl_iterate_phdr(wrappedCallback, data);
}, 'int', ['pointer', 'pointer']));
logSuccess("Hooked dl_iterate_phdr to hide libhoudini");
} catch (e) {
log(`Failed to hook dl_iterate_phdr: ${e.message}`);
log("libhoudini hiding: using file access hooks only");
}
} else {
log("dl_iterate_phdr not found - using file access hooks only");
}
}
// ============================================================================
// HOOK: Directory Listing (Hide NOX files in /data/property/)
// ============================================================================
function hookDirectoryListing() {
const readdir = findExportByName("libc.so", "readdir");
if (readdir) {
Interceptor.attach(readdir, {
onLeave: function(retval) {
if (!retval.isNull()) {
// struct dirent: d_ino, d_off, d_reclen, d_type, d_name[256]
const d_name_offset = Process.pointerSize * 2 + 2 + 1;
const d_name = retval.add(d_name_offset).readCString();
if (d_name && d_name.toLowerCase().includes("nox")) {
logBypass(`Hidden directory entry: ${d_name}`);
// Note: This is a simplified approach - the entry is logged but not fully hidden
// Full implementation would require maintaining DIR* pointer state
}
}
}
});
logSuccess("Hooked readdir");
}
const readdir64 = findExportByName("libc.so", "readdir64");
if (readdir64) {
Interceptor.attach(readdir64, {
onLeave: function(retval) {
if (!retval.isNull()) {
try {
const d_name_offset = Process.pointerSize * 2 + 2 + 1;
const d_name = retval.add(d_name_offset).readCString();
if (d_name && d_name.toLowerCase().includes("nox")) {
logBypass(`Hidden directory entry (64): ${d_name}`);
}
} catch (e) {}
}
}
});
logSuccess("Hooked readdir64");
}
}
// ============================================================================
// HOOK: Memory Scanning (Prevent BlueStacks string detection)
// ============================================================================
function hookMemoryScanning() {
// NOTE: Memory scanning hooks (memcmp, strstr, etc.) are DISABLED by default
// They are too aggressive and cause hangs/infinite loops in many apps
// The file-based hooks and property spoofing should be sufficient for most cases
log("Memory scanning hooks disabled to prevent hangs - using file/property hooks instead");
// If you really need these hooks, uncomment and test carefully:
/*
// Hook memcmp to prevent string matching
const memcmp = findExportByName("libc.so", "memcmp");
if (memcmp) {
Interceptor.attach(memcmp, {
onEnter: function(args) {
this.s1 = args[0];
this.s2 = args[1];
this.n = args[2].toInt32();
},
onLeave: function(retval) {
if (this.n > 0 && this.n <= 64) {
try {
const str1 = this.s1.readCString(this.n);
const str2 = this.s2.readCString(this.n);
for (const filtered of FilteredStrings) {
if ((str1 && str1.toLowerCase().includes(filtered)) ||
(str2 && str2.toLowerCase().includes(filtered))) {
logBypass(`Blocked memcmp match for: ${filtered}`);
retval.replace(ptr(1)); // Return non-zero (no match)
return;
}
}
} catch (e) {}
}
}
});
logSuccess("Hooked memcmp");
}
*/
/*
// Hook strstr to prevent substring matching
const strstr = findExportByName("libc.so", "strstr");
if (strstr) {
Interceptor.attach(strstr, {
onEnter: function(args) {
this.haystack = args[0];
this.needle = args[1];
},
onLeave: function(retval) {
if (!retval.isNull()) {
try {
const needle = this.needle.readCString();
if (needle) {
const lowerNeedle = needle.toLowerCase();
for (const filtered of FilteredStrings) {
if (lowerNeedle.includes(filtered)) {
logBypass(`Blocked strstr match for: ${needle}`);
retval.replace(ptr(0)); // Return NULL (not found)
return;
}
}
}
} catch (e) {}
}
}
});
logSuccess("Hooked strstr");
}
// Hook strcasestr (case-insensitive)
const strcasestr = findExportByName("libc.so", "strcasestr");
if (strcasestr) {
Interceptor.attach(strcasestr, {
onEnter: function(args) {
this.needle = args[1];
},
onLeave: function(retval) {
if (!retval.isNull()) {
try {
const needle = this.needle.readCString();
if (needle) {
for (const filtered of FilteredStrings) {
if (needle.toLowerCase().includes(filtered)) {
logBypass(`Blocked strcasestr match for: ${needle}`);
retval.replace(ptr(0));
return;
}
}
}
} catch (e) {}
}
}
});
logSuccess("Hooked strcasestr");
}
// Hook memmem to prevent byte pattern matching
const memmem = findExportByName("libc.so", "memmem");
if (memmem) {
Interceptor.attach(memmem, {
onEnter: function(args) {
this.needle = args[2];
this.needleLen = args[3].toInt32();
},
onLeave: function(retval) {
if (!retval.isNull() && this.needleLen > 0 && this.needleLen <= 64) {
try {
const needle = this.needle.readCString(this.needleLen);
if (needle) {
for (const filtered of FilteredStrings) {
if (needle.toLowerCase().includes(filtered)) {
logBypass(`Blocked memmem match for: ${needle}`);
retval.replace(ptr(0));
return;
}
}
}
} catch (e) {}
}
}
});
logSuccess("Hooked memmem");
}
*/
}
// ============================================================================
// HOOK: Java Build class (for Java-level detection)
// ============================================================================
function hookJavaBuildClass() {
Java.perform(function() {
try {
const Build = Java.use("android.os.Build");
// Static fields
Build.PRODUCT.value = DeviceFingerprint.PRODUCT;
Build.MANUFACTURER.value = DeviceFingerprint.MANUFACTURER;
Build.BOOTLOADER.value = DeviceFingerprint.BOOTLOADER;
Build.DEVICE.value = DeviceFingerprint.DEVICE;
Build.HARDWARE.value = DeviceFingerprint.HARDWARE;
Build.MODEL.value = DeviceFingerprint.MODEL;
Build.BRAND.value = DeviceFingerprint.BRAND;
Build.BOARD.value = DeviceFingerprint.BOARD;
Build.FINGERPRINT.value = DeviceFingerprint.FINGERPRINT;
Build.SERIAL.value = DeviceFingerprint.SERIAL;
Build.HOST.value = DeviceFingerprint.HOST;
Build.TYPE.value = DeviceFingerprint.TYPE;
Build.TAGS.value = DeviceFingerprint.TAGS;
logSuccess("Spoofed android.os.Build fields");
// Build.VERSION
const BuildVersion = Java.use("android.os.Build$VERSION");
// Keep SDK version for compatibility
logSuccess("Java Build class spoofed successfully");
} catch (e) {
log("Note: Java hooks not available (native-only app or early injection)");
}
});
}
// ============================================================================
// HOOK: Additional Java classes for comprehensive bypass
// ============================================================================
function hookAdditionalJavaClasses() {
Java.perform(function() {
try {
// Hook TelephonyManager
const TelephonyManager = Java.use("android.telephony.TelephonyManager");
TelephonyManager.getDeviceId.overload().implementation = function() {
logBypass("TelephonyManager.getDeviceId() -> spoofed IMEI");
return "359881234567890";
};
TelephonyManager.getSubscriberId.implementation = function() {
logBypass("TelephonyManager.getSubscriberId() -> spoofed IMSI");
return "310260123456789";
};
TelephonyManager.getSimSerialNumber.implementation = function() {
logBypass("TelephonyManager.getSimSerialNumber() -> spoofed");
return "89014103211118510720";
};
TelephonyManager.getNetworkOperatorName.implementation = function() {
logBypass("TelephonyManager.getNetworkOperatorName() -> spoofed");
return "T-Mobile";
};
logSuccess("Hooked TelephonyManager");
} catch (e) {
log("TelephonyManager hooks skipped");
}
try {
// Hook Settings.Secure
const Secure = Java.use("android.provider.Settings$Secure");
Secure.getString.implementation = function(resolver, name) {
const result = this.getString(resolver, name);
if (name === "android_id") {
logBypass("Settings.Secure.getString(android_id) -> spoofed");
return "a1b2c3d4e5f67890";
}
return result;
};
logSuccess("Hooked Settings.Secure");
} catch (e) {
log("Settings.Secure hooks skipped");
}
try {
// Hook File class for additional file checks
const File = Java.use("java.io.File");
File.exists.implementation = function() {
const path = this.getAbsolutePath();
if (isEmulatorFile(path)) {
logBypass(`File.exists() blocked: ${path}`);
return false;
}
return this.exists();
};
logSuccess("Hooked java.io.File");
} catch (e) {
log("java.io.File hooks skipped");
}
try {
// Hook System.getProperty for Java system properties
const System = Java.use("java.lang.System");
System.getProperty.overload('java.lang.String').implementation = function(key) {
const result = this.getProperty(key);
// Spoof emulator-related properties
if (key === "ro.kernel.qemu" || key === "ro.hardware") {
logBypass(`System.getProperty(${key}) -> spoofed`);
return null;
}
return result;
};
logSuccess("Hooked System.getProperty");
} catch (e) {
log("System.getProperty hooks skipped");
}
});
}
// ============================================================================
// HOOK: Sensors (Emulators often have missing or fake sensors)
// ============================================================================
function hookSensors() {
Java.perform(function() {
try {
const SensorManager = Java.use("android.hardware.SensorManager");
// Make it appear that device has real sensors
SensorManager.getSensorList.implementation = function(type) {
const result = this.getSensorList(type);
logBypass(`SensorManager.getSensorList(${type}) called`);
return result;
};
logSuccess("Hooked SensorManager");
} catch (e) {
log("SensorManager hooks skipped");
}
});
}
// ============================================================================
// MAIN EXECUTION
// ============================================================================
function main() {
console.log("═══════════════════════════════════════════════════════════════");
console.log(" Android Emulator Detection Bypass - Real Device Spoofer ");
console.log("═══════════════════════════════════════════════════════════════");
console.log("");
console.log(`Device Profile: ${DeviceFingerprint.MANUFACTURER} ${DeviceFingerprint.MODEL}`);
console.log(`Fingerprint: ${DeviceFingerprint.FINGERPRINT}`);
console.log(`Detected Architecture: ${ACTUAL_ABI}`);
console.log(`CPU ABI Spoofing: ${SPOOF_CPU_ABI ? 'ENABLED' : 'DISABLED (prevents graphics crashes)'}`);
console.log("");
console.log("Initializing bypass hooks...");
console.log("");
// Native hooks (apply immediately)
hookSystemPropertyGet();
hookFileAccess();
hookProcFilesystem();
hookDlIteratePhdr();
hookDirectoryListing();
hookMemoryScanning();
// Java hooks (apply when Java VM is ready)
Java.perform(function() {
console.log("");
console.log("Java VM ready, applying Java hooks...");
console.log("");
hookJavaBuildClass();
hookAdditionalJavaClasses();
hookSensors();
console.log("");
console.log("═══════════════════════════════════════════════════════════════");
console.log(" All bypasses activated! ");
console.log("═══════════════════════════════════════════════════════════════");
});
}
// Run on script load
setTimeout(main, 0);
// Export for external configuration
rpc.exports = {
setDebug: function(enabled) {
DEBUG = enabled;
return DEBUG;
},
setDeviceProfile: function(profile) {
Object.assign(DeviceFingerprint, profile);
log("Device profile updated");
return DeviceFingerprint;
},
getDeviceProfile: function() {
return DeviceFingerprint;
}
};
Comments