Skip to content
Open
110 changes: 110 additions & 0 deletions app/src/main/cpp/detector/debug_detector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,113 @@ MultiLayerResult DebugDetector::detectPtrace() {
result.syscallResult = false; // Can't check ptrace via syscall reliably
return result;
}

// Anti-timing attack detection
// Detects debugger breakpoints by measuring initialization elapsed time.
// If a debugger inserts breakpoints during security initialization,
// execution will take abnormally long (>= 2 seconds).
// The caller should capture time_t at the start of initialization, then
// call this method to check if too much time has elapsed.
bool DebugDetector::checkInitTimingAttack(time_t initStartTime) {
time_t currentTime;
time(&currentTime);

time_t elapsed = currentTime - initStartTime;

if (elapsed >= 2) {
LOGD("🚨 Anti-timing attack: init took %ld seconds (>= 2s threshold), "
"debugger breakpoints suspected!", (long)elapsed);
return true; // Timing attack detected
}

LOGD("Anti-timing: init completed in %ld seconds (normal)", (long)elapsed);
return false; // Normal execution time
}

// ===================== Suspicious Tool Path Detection =====================
// Iterates over suspicious tool path array, using access() to check file existence

// Suspicious tool path entries with descriptions
struct ToolPathEntry {
const char* path;
const char* description;
};

static const ToolPathEntry SUSPICIOUS_TOOL_PATHS[] = {
{"/data/local/tmp/android_server", "IDA debugger (32-bit)"},
{"/data/local/tmp/android_server64", "IDA debugger (64-bit)"},
{"/data/local/tmp/gdbserver", "GDB debugger"},
{"/data/local/tmp/inject", "Injection tool"},
{"/data/local/tmp/libhello.so", "Frida gadget"},
{"/sdcard/xxxx/", "Unpacker (FART etc.)"},
{"/sdcard/ooxx/", "Unpacker"},
{"/sdcard/fart/", "FART unpacker"},
{"/sdcard/Download/dexDump/", "DEX dump tool"},
{"/sdcard/Download/top.niunaijun.blackdexa32_logcat.txt", "BlackDex log (32-bit)"},
{"/sdcard/Download/top.niunaijun.blackdexa64_logcat.txt", "BlackDex log (64-bit)"},
{"/data/data/top.niunaijun.blackdexa32", "BlackDex app (32-bit)"},
{"/data/data/top.niunaijun.blackdexa64", "BlackDex app (64-bit)"},
};
static const int SUSPICIOUS_TOOL_PATHS_COUNT = sizeof(SUSPICIOUS_TOOL_PATHS) / sizeof(SUSPICIOUS_TOOL_PATHS[0]);

bool DebugDetector::checkSuspiciousToolPathsNative() {
for (int i = 0; i < SUSPICIOUS_TOOL_PATHS_COUNT; i++) {
if (access(SUSPICIOUS_TOOL_PATHS[i].path, F_OK) == 0) {
LOGD("Suspicious tool path found (native): %s [%s]",
SUSPICIOUS_TOOL_PATHS[i].path, SUSPICIOUS_TOOL_PATHS[i].description);
return true;
}
}
return false;
}

bool DebugDetector::checkSuspiciousToolPathsSyscall() {
for (int i = 0; i < SUSPICIOUS_TOOL_PATHS_COUNT; i++) {
if (syscall_file_exists(SUSPICIOUS_TOOL_PATHS[i].path)) {
LOGD("Suspicious tool path found (syscall): %s [%s]",
SUSPICIOUS_TOOL_PATHS[i].path, SUSPICIOUS_TOOL_PATHS[i].description);
return true;
}
}
return false;
}

std::string DebugDetector::getDetectedSuspiciousToolPaths() {
std::string result = "[";
bool first = true;

for (int i = 0; i < SUSPICIOUS_TOOL_PATHS_COUNT; i++) {
bool nativeExists = (access(SUSPICIOUS_TOOL_PATHS[i].path, F_OK) == 0);
bool syscallExists = syscall_file_exists(SUSPICIOUS_TOOL_PATHS[i].path);

if (nativeExists || syscallExists) {
if (!first) result += ",";
first = false;

result += "{\"path\":\"";
result += SUSPICIOUS_TOOL_PATHS[i].path;
result += "\",\"desc\":\"";
result += SUSPICIOUS_TOOL_PATHS[i].description;
result += "\",\"native\":";
result += nativeExists ? "true" : "false";
result += ",\"syscall\":";
result += syscallExists ? "true" : "false";
result += "}";

LOGD("Detected suspicious tool: %s [%s] (native:%d, syscall:%d)",
SUSPICIOUS_TOOL_PATHS[i].path, SUSPICIOUS_TOOL_PATHS[i].description,
nativeExists, syscallExists);
}
}

result += "]";
return result;
}

MultiLayerResult DebugDetector::detectSuspiciousToolPaths() {
MultiLayerResult result;
result.javaResult = false; // Not checked at Java layer
result.nativeResult = checkSuspiciousToolPathsNative();
result.syscallResult = checkSuspiciousToolPathsSyscall();
return result;
}
16 changes: 16 additions & 0 deletions app/src/main/cpp/detector/debug_detector.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include <string>
#include <vector>
#include <ctime>

struct MultiLayerResult;

Expand All @@ -22,6 +23,21 @@ class DebugDetector {

// Get TracerPid value
static int getTracerPid();

// Anti-timing attack detection
// Measures initialization elapsed time, if >= 2s, debugger breakpoints detected
// @param initStartTime The time_t value captured at init start
// @return true if timing attack detected (init took >= 2 seconds)
static bool checkInitTimingAttack(time_t initStartTime);

// Suspicious tool path detection
// Detects debuggers, injection tools, Frida gadgets, unpackers, etc.
static bool checkSuspiciousToolPathsNative();
static bool checkSuspiciousToolPathsSyscall();
static std::string getDetectedSuspiciousToolPaths();

// Combined detection for suspicious tool paths
static MultiLayerResult detectSuspiciousToolPaths();
};

#endif // LAUNCH_DEBUG_DETECTOR_H
38 changes: 32 additions & 6 deletions app/src/main/cpp/detector/emulator_detector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,29 +14,55 @@ const std::vector<std::string>& EmulatorDetector::getEmulatorFiles() {
"/dev/qemu_pipe",
"/dev/qemu_trace",
"/dev/goldfish_pipe",
"/system/lib/libc_malloc_debug_qemu.so",
"/sys/devices/virtual/misc/qemu_pipe",
"/sys/class/misc/qemu_pipe",
"/sys/qemu_trace",
"/system/lib/libc_malloc_debug_qemu.so",
"/system/lib/libc_malloc_debug_qemu.so-arm",
"/system/bin/qemu-props",
"/system/framework/libqemu_wl.txt",
"/data/downloads/qemu_list.txt",
"/init.goldfish.rc",
"/init.ranchu.rc",
// Android Emulator
"/system/lib/egl/libEGL_emulation.so",
// Genymotion
"/dev/socket/genyd",
"/dev/socket/baseband_genyd",
// Nox
// VirtualBox
"/sys/module/vboxsf",
"/ueventd.vbox86.rc",
"/fstab.vbox86",
// Nox (夜神模拟器)
"/data/data/com.bignox.app.store.hd",
"/system/bin/nox",
"/system/bin/nox-prop",
"/system/bin/nox-vbox-sf",
"/system/lib/libnox.so",
"/system/lib/libnb.so",
"/fstab.nox",
// LDPlayer
// LDPlayer (雷电模拟器)
"/system/bin/ldinit",
"/system/bin/ldmountsf",
"/fstab.andy",
// MEmu
// MEmu (逍遥模拟器)
"/data/data/com.microvirt.guide",
"/system/bin/microvirt",
"/fstab.vbox86",
// Droid4X (海马玩模拟器)
"/system/droid4x",
"/system/bin/droid4x-vbox-sf",
// TiantianVM (天天模拟器)
"/system/lib/egl/libEGL_tiantianVM.so",
"/system/bin/ttVM-vbox-sf",
// BlueStacks
"/data/data/com.bluestacks.settings"
"/data/data/com.bluestacks.settings",
"/dev/com.bluestacks.superuser.daemon",
"/boot/bstmods/vboxsf.ko",
// AndroVM
"/system/bin/androVM-vbox-sf",
// Yiwan (逸玩模拟器)
"/system/bin/yiwan-prop",
"/system/bin/yiwan-sf"
};
return files;
}
Expand Down
Loading