Root Detection — механизам заштите Android апликација од покретања на уређајима са привилегијама суперкорисника. Банкарске, платне и корпоративне апликације блокирају или ograničavaju функционалност на рутованим уређајима, јер роот приступ уклања ограничења Android пешчаника и отвара могућност пресретања саобраћаја, читања меморије процеса и замене података. Према OWASP Mobile Top 10 (2024), недостатак Root Detection спада у категорију M8 (Security Decisions via Untrusted Inputs). Root Detection се заснива на комбинацији статичких провера фајл система и динамичке анализе понашања у runtime-у.
Главно
Root Detection — програмски механизам који утврђује присуство роот приступа на Android уређају. Роот приступ пружа потпуну контролу над оперативним системом, омогућавајући апликацијама и скриптама да извршавају команде са UID 0. На рутованом уређају губи се изолација апликација (Android Sandbox), што омогућава пресретање уноса са тастатуре, читање SQLite база података других апликација, убризгавање кода у процесе и замену SSL сертификата у поверљивом складишту.
За финансијске и корпоративне апликације рад на рутованом уређају представља неприхватљив ризик: нападач добија приступ токенима, сесијским кључевима и личним подацима. Регулатори, укључујући PCI Security Standards Council, захтевају од платних апликација откривање и реакцију на роот приступ. Као одговор на то, Android програмери уграђују Root Detection као део стратегије проактивне заштите.
Постоје два приступа откривању: статички, који анализира фајл систем и инсталиране пакете, и динамички, који врши провере у runtime-у. Комбиновани приступ се сматра најпоузданијим, јер покрива различите векторе заобилажења. Према истраживању 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) {
// paket nije pronađen
}
}
return false;
}
}
Динамичке методе се извршавају током рада апликације и анализирају окружење извршавања. За разлику од статичких, могу открити рутовање сакривено кроз Magisk Hide или Zygisk, јер проверавају понашање система, а не само структуру фајлова.
При роот приступу, неке системске партиције се монтирају са rw (read-write) заставицом уместо ro (read-only). Апликација чита /proc/mounts и проверава да ли је /system монтиран као ro. Ако је /system монтиран као rw — то је знак модификованог система. Додатно се проверава присуство монтирања /su кроз Magisk.
Android Safe Mode искључује апликације трећих страна, укључујући роот менаџере. Исправна имплементација Root Detection-а може проверити да ли уређај ради у безбедном режиму. Ако апликација открије да роот менаџери нису видљиви, али su бинарни фајл постоји — то је знак Magisk Hide-а.
Покушај извршавања su -c id кроз ProcessBuilder или Runtime.exec — директан тест роот приступа. Међутим, Magisk може пресрести овај позив. Поузданија опција — провера кроз нативни код: отварање /proc/1/limits или /proc/self/maps и анализа UID-а покренутих процеса. Ако апликација може добити UID 0 или читати фајлове доступне само роот-у — уређај је компромитован.
public boolean checkRootDynamically() {
// Provera flagova kompilacije
String buildTags = Build.TAGS;
if (buildTags != null && buildTags.contains("test-keys")) {
return true;
}
// Provera montiranja /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) {
// greška pri čitanju mount-a
}
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 API, што је чини невидљивом за алате за заобилажење који раде на Dalvik/ART нивоу. За додатну заштиту препоручује се чување константи (листа путања) не у read-only секцији, већ њихово израчунавање кроз једноставне реверзибилне функције. 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. Противмера: провера интегритета нативних функција кроз израчунавање checksum-а инструкција у меморији и откривање Frida-е кроз анализу /proc/self/maps на присуство frida-agent.so или frida-helper.
Root Detection имплементиран у Java-и се уклања за 2–3 минута: APK се распакује кроз apktool, у smali коду се мења повратна вредност метода на false, APK се поново саставља и потписује. Противмера: премештање критичне логике у нативни код и провера дигиталног потписа апликације у runtime-у кроз Signature API или поређење хеша APK-а са еталоном на серверу.
Ефикасан Root Detection се заснива на вишеслојној архитектури. Ниједна метода појединачно не обезбеђује довољан ниво заштите. Комбинација статичких и динамичких провера, нативног кода и серверске верификације даје максималну отпорност.
Не ослањајте се само на client-side проверу. Шаљите на сервер резултате Root Detection-а заједно са једнократним токеном сесије. Сервер доноси одлуку о блокирању или ограничавању функционалности. Ово спречава нападе на API нивоу, где клијентска апликација може бити модификована, а сервер остаје поверљива страна.
Код Root Detection-а мора бити обфускован. Ако нападач види у jadx-у јасну секвенцу провера su путања — заобилажење ће трајати минуте. Користите 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-а које потврђују интегритет уређаја. Оне укључују проверу bootloader-а, системског потписа и роот статуса. Play Integrity API — препоручена замена за SafetyNet, која даје три нивоа: BASIC, DEVICE и STRONG. Root Detection на клијенту допуњује серверску атестацију.
Инсталирајте апликацију на стварни рутовани уређај (нпр. Pixel са Magisk-ом). Проверите да ли се блокирање активира. Затим покушајте сакрити роот кроз Magisk Hide за вашу апликацију и поновите тест. За детаљну проверу користите Frida за пресретање циљних метода и уверите се да нативна заштита не подлеже заобилажењу.
Закључци
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође