Root Detection در برنامه‌های موبایل — ماهیت، روش‌های تشخیص و اصل کار

نویسنده: IT Sectr منتشر شده: 2026-04-03 زمان مطالعه: 9 دقیقه

Root Detection — مکانیزم محافظت از برنامه‌های Android در برابر اجرا روی دستگاه‌هایی با امتیازات superuser. برنامه‌های بانکی، پرداخت و شرکتی عملکرد را روی دستگاه‌های روت شده مسدود یا محدود می‌کنند، زیرا دسترسی root محدودیت‌های sandbox Android را برمی‌دارد و امکان رهگیری ترافیک، خواندن حافظه فرآیندها و جعل داده‌ها را فراهم می‌کند. بر اساس OWASP Mobile Top 10 (2024)، نبود Root Detection متعلق به دسته M8 (Security Decisions via Untrusted Inputs) است. Root Detection بر ترکیبی از بررسی‌های ایستای فایل‌سیستم و تحلیل پویای رفتار runtime ساخته شده است.

مهمترین نکات

  • Root Detection — بررسی دستگاه Android برای وجود دسترسی root به منظور محافظت از برنامه در برابر اجرا در محیط به خطر افتاده
  • روش‌های ایستا فایل‌سیستم را برای وجود باینری‌های su، برنامه‌های Superuser و تغییرات در پارتیشن‌های سیستم بررسی می‌کنند
  • روش‌های پویا runtime را تحلیل می‌کنند: بررسی Build.TAGS، تلاش برای باز کردن /proc/self/maps با فرآیندهای ممتاز
  • پیاده‌سازی بومی به زبان C/C++ از طریق JNI مقاومت در برابر دور زدن از طریق Xposed و Frida در سطح Java را تضمین می‌کند
  • امنیت Root Detection برای جلوگیری از جعل نتایج بررسی نیاز به obfuscation مداوم و تأیید سمت سرور دارد

Root Detection چیست؟

Root Detection — مکانیزم نرم‌افزاری که وجود دسترسی root را در دستگاه Android تعیین می‌کند. دسترسی root کنترل کامل بر سیستم عامل را فراهم می‌کند و به برنامه‌ها و اسکریپت‌ها اجازه می‌دهد دستورات را با UID 0 اجرا کنند. در دستگاه روت شده، ایزولاسیون برنامه‌ها (Android Sandbox) از بین می‌رود که رهگیری ورودی صفحه کلید، خواندن پایگاه‌های داده SQLite سایر برنامه‌ها، تزریق کد به فرآیندها و جعل گواهی‌های SSL در فروشگاه معتمد را ممکن می‌سازد.

برای برنامه‌های مالی و شرکتی، کار روی دستگاه روت شده یک ریسک غیرقابل قبول است: مهاجم به توکن‌ها، کلیدهای جلسه و داده‌های شخصی دسترسی پیدا می‌کند. نهادهای نظارتی، از جمله PCI Security Standards Council، از برنامه‌های پرداخت می‌خواهند دسترسی root را شناسایی و به آن واکنش نشان دهند. در پاسخ به این، توسعه‌دهندگان Android Root Detection را به عنوان بخشی از استراتژی حفاظت proactive پیاده‌سازی می‌کنند.

دو رویکرد برای تشخیص وجود دارد: ایستا، که فایل‌سیستم و بسته‌های نصب شده را تحلیل می‌کند، و پویا، که بررسی‌ها را در runtime انجام می‌دهد. رویکرد ترکیبی قابل اعتمادترین محسوب می‌شود، زیرا بردارهای مختلف دور زدن را پوشش می‌دهد. بر اساس تحقیق NowSecure (2025)، 76٪ از برنامه‌های بانکی در 100 برنامه برتر Google Play حاوی نوعی Root Detection هستند.

روش‌های ایستای تشخیص root

روش‌های ایستا هنگام راه‌اندازی برنامه اجرا می‌شوند و نشانه‌های دسترسی root را که ابزارهای روت در فایل‌سیستم بر جای می‌گذارند، بررسی می‌کنند. این روش‌ها نیازی به اجرای دستورات ممتاز ندارند و در بافت یک برنامه معمولی کار می‌کنند.

بررسی وجود باینری su

نشانه اصلی دسترسی root — وجود فایل اجرایی su در مسیرهای استاندارد: /system/bin/su، /system/xbin/su، /sbin/su، /su/bin/su. برنامه وجود فایل را از طریق File.exists() یا پیاده‌سازی بومی access() از libc بررسی می‌کند. علاوه بر این، می‌توان su --version یا su -c id را اجرا کرده و کد خروج را بررسی کرد.

جستجوی مدیرهای root

برنامه‌های معمول برای مدیریت دسترسی root: Superuser، SuperSU، Magisk Manager، KingRoot. وجود آنها از طریق PackageManager.getPackageInfo() یا خواندن دایرکتوری /data/app/ بررسی می‌شود. بسته‌های قابل بررسی: com.topjohnwu.magisk، eu.chainfire.supersu، com.noshufou.android.su، com.thirdparty.superuser، com.koushikdutta.superuser، com.zacharee1.systemuituner.

بررسی ویژگی‌های سیستم

Android اطلاعات مربوط به وضعیت سیستم را در ویژگی‌های سیستمی ذخیره می‌کند که از طریق System.getProperty و Build.TAGS قابل دسترسی هستند. اگر مقدار Build.TAGS حاوی test-keys باشد نه release-keys — این نشان‌دهنده سیستم‌عامل سفارشی است که اغلب با دسترسی root همراه است. علاوه بر این، ro.build.tags، ro.debuggable و ro.secure از طریق خواندن /system/build.prop بررسی می‌شوند.

java
public class RootDetectionChecker {
    private static final String[] SU_PATHS = {
        "/system/bin/su",
        "/system/xbin/su",
        "/sbin/su",
        "/su/bin/su",
        "/system/sd/xbin/su"
    };

    public boolean checkRootByFiles() {
        for (String path : SU_PATHS) {
            if (new File(path).exists()) {
                return true;
            }
        }
        return false;
    }

    public boolean checkRootByPackages(Context ctx) {
        String[] packages = {
            "com.topjohnwu.magisk",
            "eu.chainfire.supersu",
            "com.noshufou.android.su",
            "com.koushikdutta.superuser"
        };
        for (String pkg : packages) {
            try {
                ctx.getPackageManager().getPackageInfo(pkg, 0);
                return true;
            } catch (PackageManager.NameNotFoundException e) {
                // پکیج پیدا نشد
            }
        }
        return false;
    }
}

روش‌های پویای بررسی

روش‌های پویا در طول اجرای برنامه انجام می‌شوند و محیط اجرا را تحلیل می‌کنند. برخلاف روش‌های ایستا، می‌توانند روت مخفی شده از طریق Magisk Hide یا Zygisk را تشخیص دهند، زیرا رفتار سیستم را بررسی می‌کنند، نه فقط ساختار فایل را.

بررسی نقاط mount

هنگام دسترسی root، برخی پارتیشن‌های سیستم با پرچم rw (read-write) به جای ro (read-only) mount می‌شوند. برنامه /proc/mounts را می‌خواند و بررسی می‌کند که /system به صورت ro mount شده است. اگر /system به صورت rw mount شده باشد — این نشانه یک سیستم تغییر یافته است. علاوه بر این، وجود mount /su از طریق Magisk بررسی می‌شود.

تست حالت امن

Android Safe Mode برنامه‌های شخص ثالث، از جمله مدیرهای root را غیرفعال می‌کند. پیاده‌سازی صحیح Root Detection می‌تواند بررسی کند که آیا دستگاه در حالت امن کار می‌کند. اگر برنامه تشخیص دهد که مدیرهای root قابل مشاهده نیستند، اما باینری su وجود دارد — این نشانه Magisk Hide است.

بررسی اجرای دستورات

تلاش برای اجرای su -c id از طریق ProcessBuilder یا Runtime.exec — یک تست مستقیم دسترسی root است. با این حال، Magisk می‌تواند این فراخوانی را رهگیری کند. گزینه قابل اعتمادتر — بررسی از طریق کد بومی: باز کردن /proc/1/limits یا /proc/self/maps و تحلیل UID فرآیندهای در حال اجرا. اگر برنامه بتواند UID 0 را به دست آورد یا فایل‌های قابل دسترسی فقط برای root را بخواند — دستگاه به خطر افتاده است.

java
public boolean checkRootDynamically() {
    // بررسی فلاگ‌های ساخت
    String buildTags = Build.TAGS;
    if (buildTags != null && buildTags.contains("test-keys")) {
        return true;
    }

    // بررسی مونت /system
    try {
        BufferedReader reader = new BufferedReader(
            new InputStreamReader(new FileInputStream("/proc/mounts"))
        );
        String line;
        while ((line = reader.readLine()) != null) {
            if (line.contains("/system")
                && line.contains("rw")) {
                reader.close();
                return true;
            }
        }
        reader.close();
    } catch (IOException e) {
        // خطا در خواندن مونت
    }

    return false;
}

پیاده‌سازی بومی Root Detection در C++

Root Detection پیاده‌سازی شده در Java به راحتی از طریق ماژول‌های Xposed یا Frida که متدهای Java را رهگیری کرده و مقادیر بازگشتی را جعل می‌کنند، دور زده می‌شود. پیاده‌سازی بومی در C++ از طریق JNI به طور قابل توجهی مقاوم‌تر است: ابزارهای تحلیل پویا که در سطح Java کار می‌کنند، فراخوانی‌های بومی libc مانند stat، access، popen و dlopen را نمی‌بینند.

cpp
#include <unistd.h>
#include <sys/stat.h>
#include <cstring>
#include <vector>

extern "C"
JNIEXPORT jboolean JNICALL
Java_com_example_checker_RootCheck_nativeCheck(
    JNIEnv* env, jobject instance) {

    std::vector<const char*> paths = {
        "/system/bin/su",
        "/system/xbin/su",
        "/sbin/su",
        "/data/local/su"
    };

    struct stat st;
    for (const char* path : paths) {
        if (stat(path, &st) == 0) {
            return JNI_TRUE;
        }
    }
    return JNI_FALSE;
}

بررسی بومی از Java API استفاده نمی‌کند، که آن را برای ابزارهای دور زدن که در سطح Dalvik/ART کار می‌کنند، نامرئی می‌کند. برای محافظت بیشتر، توصیه می‌شود ثابت‌ها (لیست مسیرها) را نه در بخش read-only، بلکه با محاسبه آنها از طریق توابع ساده برگشت‌پذیر ذخیره کنید. فراخوانی stat از libc مستقیماً به هسته Linux مراجعه می‌کند و wrapperهای Java را دور می‌زند و نمی‌توان آن را از طریق Xposed رهگیری کرد.

روش‌های دور زدن Root Detection

توسعه‌دهندگان حفاظت باید روش‌های موجود دور زدن را درک کنند تا یک سیستم تشخیص مقاوم بسازند. هر روش دور زدن نیاز به اقدام متقابل در سطح مربوطه دارد.

دور زدن از طریق Magisk Hide و Zygisk

Magisk — محبوب‌ترین ابزار روت در Android 9–14. Magisk Hide وجود su را از /proc پنهان می‌کند و نتایج بررسی مسیرها را جعل می‌کند. Magisk در سطح هسته کار می‌کند و stat() و access() را قبل از دیده شدن توسط برنامه رهگیری می‌کند. اقدام متقابل: بررسی وجود خود Magisk از طریق وجود /sbin/.magisk یا بررسی از طریق خواندن maps خود برنامه — Magisk کتابخانه خود را در هر فرآیند جاسازی می‌کند.

دور زدن از طریق Frida

Frida — ابزار instrumentation پویا که می‌تواند توابع بومی را از طریق Ptrace یا Dobby رهگیری کند. Frida مقدار بازگشتی هر بررسی را جایگزین کرده و نتیجه stat را با ENOENT جعل می‌کند. اقدام متقابل: بررسی یکپارچگی توابع بومی از طریق محاسبه checksum دستورالعمل‌ها در حافظه و تشخیص Frida از طریق تحلیل /proc/self/maps برای وجود frida-agent.so یا frida-helper.

دور زدن از طریق وصله APK

Root Detection پیاده‌سازی شده در Java در 2–3 دقیقه حذف می‌شود: APK با apktool باز می‌شود، در کد smali مقدار بازگشتی متد به false تغییر می‌یابد، APK دوباره ساخته و امضا می‌شود. اقدام متقابل: انتقال منطق بحرانی به کد بومی و بررسی امضای دیجیتال برنامه در runtime از طریق Signature API یا مقایسه hash APK با الگو روی سرور.

توصیه‌هایی برای محافظت قابل اعتماد

Root Detection مؤثر بر معماری چندلایه ساخته شده است. هیچ روشی به تنهایی سطح حفاظت کافی را فراهم نمی‌کند. ترکیب بررسی‌های ایستا و پویا، کد بومی و تأیید سمت سرور حداکثر مقاومت را می‌دهد.

تأیید سمت سرور

فقط به بررسی سمت کلient اعتماد نکنید. نتایج Root Detection را همراه با یک token یک‌بار مصرف جلسه به سرور ارسال کنید. سرور درباره مسدودسازی یا محدود کردن عملکرد تصمیم می‌گیرد. این کار از حملات در سطح API جلوگیری می‌کند، جایی که برنامه کلient ممکن است تغییر یافته باشد، اما سرور طرف معتمد باقی می‌ماند.

Obfuscation کد بررسی

کد Root Detection باید obfuscated شود. اگر مهاجم در jadx توالی واضحی از بررسی مسیرهای su ببیند — دور زدن دقیقه‌ها طول می‌کشد. از ProGuard یا DexGuard برای پیچیده کردن جریان کنترل و رمزگذاری رشته‌ها استفاده کنید. Obfuscation زمان تحلیل کد حفاظت را از چند دقیقه به چند ساعت افزایش می‌دهد.

به‌روزرسانی منظم امضاها

لیست مسیرها، بسته‌ها و شاخص‌های قابل بررسی باید با هر نسخه از برنامه به‌روز شود. ابزارهای جدید روت و دور زدن ماهانه ظاهر می‌شوند. یک لیست ایستا که یک سال تغییر نکرده است، روش‌های مدرن را تشخیص نمی‌دهد. توصیه می‌شود امضاهای به‌روز را از سرور هنگام راه‌اندازی برنامه قبل از انجام بررسی‌ها بارگیری کنید.

سوالات متداول

چرا برنامه‌ها به Root Detection نیاز دارند؟

Root Detection از اجرای برنامه روی دستگاهی که sandbox Android در آن غیرفعال است محافظت می‌کند. در دستگاه روت شده، هر برنامه‌ای می‌تواند داده‌های سایر برنامه‌ها را بخواند. برنامه‌های بانکی و پرداخت موظفند کار روی دستگاه‌های روت شده را طبق الزامات PCI DSS و توصیه‌های OWASP Mobile Security مسدود کنند.

Magisk Hide چگونه کار می‌کند؟

Magisk Hide از مکانیزم mount namespace استفاده می‌کند. برای هر فرآیند مشخص شده در لیست استثناها، Magisk یک namespace ایزوله ایجاد می‌کند که در آن باینری su نامرئی است. فراخوانی‌های سیستمی stat، access و open در این namespace فایل‌های Magisk را نمی‌بینند. Magisk را می‌توان از طریق بررسی وجود /proc/self/maps و جستجوی dump magisk تشخیص داد.

آیا می‌توان Root Detection را بدون روت دور زد؟

بله، اگر برنامه یکپارچگی کد خود را بررسی نکند. از طریق Frida می‌توان متد Java بررسی را رهگیری کرده و به اجبار false返回 کرد. اقدام متقابل — پیاده‌سازی بومی منطق بحرانی در C++ و بررسی یکپارچگی از طریق hash فایل DEX. بدون obfuscation هر Root Detection در Java در 5–10 دقیقه دور زده می‌شود.

Safety net و attestation چیست؟

SafetyNet (منسوخ) و Play Integrity API — بررسی‌های سمت سرور Google هستند که یکپارچگی دستگاه را تأیید می‌کنند. آنها شامل بررسی bootloader، امضای سیستم و وضعیت root هستند. Play Integrity API — جایگزین توصیه شده SafetyNet که سه سطح ارائه می‌دهد: BASIC، DEVICE و STRONG. Root Detection سمت کلient، attestation سرور را تکمیل می‌کند.

چگونه Root Detection را در برنامه خود بررسی کنیم؟

برنامه را روی یک دستگاه واقعی روت شده (مثلاً Pixel با Magisk) نصب کنید. بررسی کنید که آیا مسدودسازی فعال می‌شود. سپس سعی کنید root را از طریق Magisk Hide برای برنامه خود پنهان کرده و تست را تکرار کنید. برای بررسی عمیق از Frida برای رهگیری متدهای هدف استفاده کنید و مطمئن شوید که حفاظت بومی قابل دور زدن نیست.

خلاصه

  • Root Detection — یک جزء امنیتی اجباری برای برنامه‌های بانکی، پرداخت و شرکتی Android که بر ترکیبی از بررسی‌های ایستا و پویا کار می‌کند
  • روش‌های ایستا شامل جستجوی باینری su در مسیرهای استاندارد، بررسی مدیرهای root نصب شده و تحلیل ویژگی‌های سیستم Build.TAGS
  • روش‌های پویا mount شدن /system در حالت rw را تحلیل می‌کنند، یکپارچگی /proc/mounts را بررسی می‌کنند و تست‌های اجرای دستورات ممتاز را انجام می‌دهند
  • پیاده‌سازی بومی در C++ از طریق JNI بررسی‌ها را برای Xposed و Frida که در سطح Java کار می‌کنند نامرئی می‌کند و نیاز به دور زدن از طریق Dobby یا Ptrace دارد
  • Magisk Hide — ابزار اصلی دور زدن Root Detection از طریق mount namespaces که از طریق تحلیل /proc/self/maps برای کتابخانه‌های magisk تشخیص داده می‌شود
  • معماری توصیه شده: بررسی‌های بومی + obfuscation کد + تأیید سمت سرور نتایج + به‌روزرسانی منظم امضاها
  • Play Integrity API از Google، Root Detection سمت کلient را با تأیید سمت سرور دستگاه تکمیل می‌کند و حفاظت جامع را فراهم می‌کند

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید