Root Detection هي آلية أمان تحمي تطبيقات Android من التشغيل على الأجهزة التي تمتلك صلاحيات المستخدم الفائق. تقوم التطبيقات المصرفية والمدفوعات والشركات بحظر أو تقييد الوظائف على الأجهزة المجذرة، لأن الوصول الجذري يزيل قيود بيئة Android المعزولة ويفتح إمكانية اعتراض حركة المرور وقراءة ذاكرة العمليات وتزوير البيانات. وفقًا OWASP Mobile Top 10 (2024)، فإن غياب Root Detection يندرج ضمن الفئة M8 (Security Decisions via Untrusted Inputs). Root Detection يعتمد على مزيج من الفحوصات الثابتة لنظام الملفات والتحليل الديناميكي لسلوك وقت التشغيل.
الملخص
Root Detection هي آلية برمجية تكشف وجود الوصول الجذري على جهاز Android. يوفر الوصول الجذري تحكمًا كاملاً في نظام التشغيل، مما يسمح للتطبيقات والبرامج النصية بتنفيذ أوامر بمعرف UID 0. على الجهاز المجذر، يُفقد عزل التطبيقات (Android Sandbox)، مما يجعل من الممكن اعتراض إدخال لوحة المفاتيح، وقراءة قواعد بيانات SQLite للتطبيقات الأخرى، وحقن الكود في العمليات، واستبدال شهادات SSL في المخزن الموثوق.
بالنسبة للتطبيقات المالية وتطبيقات الشركات، يشكل التشغيل على جهاز مجذر خطرًا غير مقبول: يحصل المخترق على الوصول إلى الرموز المميزة ومفاتيح الجلسة والبيانات الشخصية. تطلب الجهات التنظيمية، بما في ذلك PCI Security Standards Council، من تطبيقات الدفع اكتشاف الوصول الجذري والاستجابة له. واستجابة لذلك، يدمج مطورو Android Root Detection كجزء من استراتيجية حماية استباقية.
يوجد نهجان للكشف: ثابت، يحلل نظام الملفات والحزم المثبتة، وديناميكي، يقوم بفحوصات في وقت التشغيل. يعتبر النهج المشترك الأكثر موثوقية، لأنه يغطي نواقل التجاوز المختلفة. وفقًا لدراسة أجرتها NowSecure (2025)، فإن 76% من التطبيقات المصرفية في أفضل 100 على Google Play تحتوي على شكل من أشكال Root Detection.
يتم تنفيذ الطرق الثابتة عند بدء تشغيل التطبيق وتفحص علامات الوصول الجذري التي تتركها أدوات التجذير في نظام الملفات. لا تتطلب هذه الطرق تنفيذ أوامر مميزة وتعمل ضمن سياق تطبيق عادي.
المؤشر الرئيسي للوصول الجذري هو وجود الملف التنفيذي su في المسارات القياسية: /system/bin/su، /system/xbin/su، /sbin/su، /su/bin/su. يتحقق التطبيق من وجود الملف عبر File.exists() أو تنفيذ أصلي لـ access() من libc. بالإضافة إلى ذلك، يمكن محاولة تنفيذ su --version أو su -c id والتحقق من رمز الخروج.
التطبيقات النموذجية لإدارة الوصول الجذري: 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، فهذا يشير إلى برنامج ثابت مخصص، غالبًا مع وصول جذري. بالإضافة إلى ذلك، يتم فحص ro.build.tags و ro.debuggable و ro.secure عبر قراءة /system/build.prop.
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) {
// package not found
}
}
return false;
}
}
يتم تنفيذ الطرق الديناميكية أثناء تشغيل التطبيق وتحلل بيئة التنفيذ. على عكس الطرق الثابتة، يمكنها اكتشاف التجذير المخفي عبر Magisk Hide أو Zygisk، لأنها تتحقق من سلوك النظام وليس فقط بنية الملفات.
مع الوصول الجذري، يتم تحميل بعض أقسام النظام بالعلم rw (قراءة-كتابة) بدلاً من ro (قراءة فقط). يقرأ التطبيق /proc/mounts ويتحقق من أن /system محمل كـ ro. إذا كان /system محملاً كـ rw، فهذا يشير إلى نظام معدل. بالإضافة إلى ذلك، يتم التحقق من وجود تحميل /su عبر Magisk.
يقوم الوضع الآمن في Android بتعطيل تطبيقات الطرف الثالث، بما في ذلك مديري الجذر. يمكن لتنفيذ صحيح لـ Root Detection التحقق مما إذا كان الجهاز يعمل في الوضع الآمن. إذا اكتشف التطبيق أن مديري الجذر غير مرئيين ولكن الثنائي su موجود، فهذا مؤشر على Magisk Hide.
محاولة تنفيذ su -c id عبر ProcessBuilder أو Runtime.exec هي اختبار مباشر للوصول الجذري. ومع ذلك، يمكن لـ Magisk اعتراض هذه الاستدعاء. النهج الأكثر موثوقية هو التحقق عبر الكود الأصلي: فتح /proc/1/limits أو /proc/self/maps وتحليل UID للعمليات الجارية. إذا تمكن التطبيق من الحصول على UID 0 أو قراءة ملفات يمكن الوصول إليها فقط من قبل الجذر، فإن الجهاز مخترق.
public boolean checkRootDynamically() {
// Build flags check
String buildTags = Build.TAGS;
if (buildTags != null && buildTags.contains("test-keys")) {
return true;
}
// Checking /system mount
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) {
// error reading mounts
}
return false;
}
يمكن تجاوز Root Detection المنفذ بلغة Java بسهولة عبر وحدات Xposed أو Frida، التي تعترض طرق Java وتستبدل القيم المعادة. التنفيذ الأصلي بلغة C++ عبر JNI أكثر مقاومة بشكل ملحوظ: أدوات التحليل الديناميكي التي تعمل على مستوى Java لا ترى استدعاءات libc الأصلية مثل stat و access و popen و dlopen.
#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، مما يجعله غير مرئي لأدوات التجاوز التي تعمل على مستوى Dalvik/ART. للحماية الإضافية، يوصى بتخزين الثوابت (قائمة المسارات) ليس في قسم للقراءة فقط، بل حسابها من خلال دوال عكسية بسيطة. استدعاء stat من libc يصل مباشرة إلى نواة Linux، متجاوزًا أغلفة Java، ولا يمكن اعتراضه عبر Xposed.
يحتاج مطورو الحماية إلى فهم طرق التجاوز الحالية لبناء نظام كشف قوي. كل طريقة تجاوز تتطلب إجراءً مضادًا على المستوى المناسب.
Magisk هي أداة التجذير الأكثر شيوعًا على Android 9–14. يخفي Magisk Hide وجود su من /proc ويزور نتائج فحص المسارات. يعمل Magisk على مستوى النواة ويعترض stat() و access() قبل أن تراها التطبيق. الإجراء المضاد: التحقق من وجود Magisk نفسه عبر وجود /sbin/.magisk أو التحقق عبر قراءة maps الخاصة بالتطبيق — يحقن Magisk مكتبته في كل عملية.
Frida هي أداة أدوات ديناميكية يمكنها اعتراض الدوال الأصلية عبر Ptrace أو Dobby. تستبدل Frida القيمة المعادة لأي فحص، مزيّنة نتيجة stat إلى ENOENT. الإجراء المضاد: التحقق من سلامة الدوال الأصلية عبر حساب مجموع اختباري للتعليمات في الذاكرة واكتشاف Frida عبر تحليل /proc/self/maps للبحث عن وجود frida-agent.so أو frida-helper.
يمكن إزالة Root Detection المنفذ بلغة Java في 2–3 دقائق: يتم فك ضغط APK عبر apktool، ويتم تغيير القيمة المعادة للطريقة إلى false في كود smali، ويتم إعادة بناء APK وتوقيعه. الإجراء المضاد: نقل المنطق الحرج إلى الكود الأصلي والتحقق من التوقيع الرقمي للتطبيق في وقت التشغيل عبر واجهة برمجة تطبيقات Signature أو مقارنة تجزئة APK بمرجع على الخادم.
يُبنى Root Detection الفعال على هندسة متعددة الطبقات. لا توفر أي طريقة بمفردها حماية كافية. مزيج من الفحوصات الثابتة والديناميكية والكود الأصلي والتحقق من جانب الخادم يعطي أقصى مقاومة.
لا تعتمد فقط على الفحص من جانب العميل. أرسل نتائج Root Detection إلى الخادم مع رمز جلسة لمرة واحدة. يتخذ الخادم قرار حظر أو تقييد الوظائف. يمنع هذا الهجمات على مستوى واجهة برمجة التطبيقات، حيث يمكن تعديل تطبيق العميل بينما يبقى الخادم طرفًا موثوقًا.
يجب تشويش كود Root Detection. إذا رأى المهاجم تسلسلاً واضحًا لفحوصات مسارات su في jadx، فسيستغرق التجاوز دقائق. استخدم ProGuard أو DexGuard لتشويش تدفق التحكم وتشفير السلاسل. التشويش يزيد وقت تحليل كود الحماية من دقائق إلى ساعات.
يجب تحديث قائمة المسارات والحزم والمؤشرات التي يتم فحصها مع كل إصدار من التطبيق. تظهر أدوات تجذير وتجاوز جديدة شهريًا. قائمة ثابتة لم تتغير لمدة عام لن تكتشف الطرق الحديثة. يوصى بتحميل التوقيعات الحالية من الخادم عند بدء تشغيل التطبيق قبل تنفيذ الفحوصات.
الأسئلة الشائعة
يحمي Root Detection من تشغيل التطبيق على جهاز حيث تكون بيئة Android المعزولة معطلة. على الجهاز المجذر، يمكن لأي تطبيق قراءة بيانات التطبيقات الأخرى. التطبيقات المصرفية وتطبيقات الدفع ملزمة بحظر التشغيل على الأجهزة المجذرة وفقًا لمتطلبات PCI DSS وتوصيات OWASP Mobile Security.
يستخدم Magisk Hide آلية تحميل مساحة الاسم (mount namespace). لكل عملية في قائمة الاستثناءات، ينشئ Magisk مساحة اسم معزولة حيث يكون الثنائي su غير مرئي. استدعاءات النظام stat و access و open في هذه المساحة لا ترى ملفات Magisk. يمكن اكتشاف Magisk عبر التحقق من وجود /proc/self/maps والبحث عن تفريغات magisk.
نعم، إذا كان التطبيق لا يتحقق من سلامة كوده. عبر Frida، يمكن اعتراض طريقة التحقق في Java وإجبارها على إرجاع false. الإجراء المضاد هو تنفيذ أصلي للمنطق الحرج بلغة C++ والتحقق من السلامة عبر تجزئة ملف DEX. بدون تشويش، يمكن تجاوز أي Root Detection بلغة Java في 5–10 دقائق.
SafetyNet (قديم) و Play Integrity API هما فحوصات من جانب الخادم من Google تؤكد سلامة الجهاز. تشمل فحص محمل الإقلاع وتوقيع النظام وحالة الجذر. Play Integrity API هو البديل الموصى به لـ SafetyNet، ويوفر ثلاثة مستويات: BASIC و DEVICE و STRONG. يكمل Root Detection من جانب العميل التحقق من جانب الخادم.
قم بتثبيت التطبيق على جهاز مجذر حقيقي (مثل Pixel مع Magisk). تحقق مما إذا كان الحظر يعمل. ثم حاول إخفاء الجذر عبر Magisk Hide لتطبيقك وأعد تشغيل الاختبار. للفحص المتعمق، استخدم Frida لاعتراض الطرق المستهدفة وتأكد من أن الحماية الأصلية لا يمكن تجاوزها.
الخلاصة
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.
اقرأ أيضًا