본문으로 바로가기

안드로이드·갤럭시·AOS 애플리케이션 취약점진단/모의해킹 무료 강의 학식(hagsig)

 

가. 취약점 정의

- 안드로이드는 사용자가 최상위 권한(root)을 획득할 수 없도록 되어있으나, 루팅(rooting)을 통해 최상위 권한을 획득할 수 있다.

- 루팅된 디바이스에서 앱이 동작할 경우 보안을 우회하는 등의 행위가 가능해서 개인정보 유출 등의 침해사고가 발생할 수 있다.

- 루팅된 디바이스에서 앱이 동작하면 강제종료 되게끔 보안조치를 하여야 한다.

- 허술하게 루팅 탐지 로직을 구현할 경우 *런타임 조작*smali 파일*달빅 바이트 코드 변조등의 방법으로  쉽게 우회할 수 있다.

*런타임 조작 : 앱 실행 중에 동작을 조작하여 정상적인 결과가 아닌 공격자가 원하는 결과가 되도록 하는 것

*smali 파일 : An assembler/disassembler for Android’s dex format의 약자로 DEX 바이너리를 사람이 읽을 수 있도록 표현한 언어

*달빅 바이트 코드 : 안드로이드 런타임에서 구동되는 Java 바이트 코드로 smali 파일에 기입되어 있음

- 상용 솔루션을 쓰지 않는 이상 완벽한 대응방법은 없겠지만 보안조치를 복합적으로 적용하면 루팅 탐지 우회를 매우 어렵게 하여 레벨이 낮은 해커들의 공격에는 충분히 대응할 수 있다.

 

나. 취약점 대응방안(조치방법)

1. 루팅 탐지 기능 추가

- 루팅된 환경에서 디바이스가 동작중인지 확인할 수 있는 방법 중 대표적인 방법은 아래와 같다.

- 아래의 방법 중 하나만 사용하는게 아니라 복합적으로 사용하여 루팅 탐지 우회 시 최대한 어렵게 하여야한다.

- 함수/변수명은 그대로 가져다 쓰는게 아닌 최대한 추측이 불가능한 문구로 변경하여 사용하는 것이 좋다.

 

1.1. 루팅된 환경에서만 사용할 수 있는 명령어의 실행결과를 통한 루팅 탐지 방법

- su, which 등과 같은 루팅된 환경에서만 사용가능한 명령어를 실행하고 그 결과값으로 루팅 여부를 판단한다.

private boolean checkSuExists() {
    Process process = null;
    try {
        process = Runtime.getRuntime().exec(new String[] {"/system /xbin/which", "su"});
        BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
        String line = in.readLine();
        process.destroy();
        return line != null;
    } catch (Exception e) {
        if (process != null) {
            process.destroy();
        }
        return false;
    }
}

 

1.2. Test Key 존재 확인을 통한 루팅 탐지 방법

- 루팅이 되지 않은 정상적인 환경에서는 release-key를 찾을 수 있게되고 루팅된 환경에서는 test-key를 찾을 수 있다.

private boolean detectTestKeys() {
    String buildTags = android.os.Build.TAGS;
    return buildTags != null && buildTags.contains("test-keys");
}

 

1.3. Google OTA 인증서

- 루팅된 환경에서는 *Google OTA(Over-The-Air) 인증서가 존재하지 않으므로, 파일 존재여부를 통해 루팅 여부를 확인할 수 있다.

*OTA : 새로운 펌웨어, 설정, 암호화 키를 휴대전화와 같은 장치에 무선으로 배포하기 위한 방식을 말하며, 비휘발성 메모리에 탑재되어 있다.

public static boolean checkOTACerts() {
    String OTAPath = "/etc/security/otacerts.zip";
    File f = new File(OTAPath);
    boolean fileExists = f.exists();
    if (fileExists) {
        return true;
    }
    else {
        return false;
    }
}

 

1.4. 루팅된 환경에서만 존재하는 바이너리(파일) 존재여부를 통한 루팅 탐지 방법

- 루팅 환경에서 사용하는 *바이너리가 존재하는지 확인하여 루팅 여부를 확인할 수 있다.

*루팅 환경에 존재하는 바이너리 : busybox, su, magisk, superuser.apk 등

private String[] binaryPaths = {
        "/data/local/",
        "/data/local/bin/",
        "/data/local/xbin/",
        "/sbin/",
        "/su/bin/",
        "/system/bin/",
        "/system/bin/.ext/",
        "/system/bin/failsafe/",
        "/system/sd/xbin/",
        "/system/usr/we-need-root/",
        "/system/xbin/",
        "/system/app/",
        "/cache",
        "/data",
        "/dev"
};

private boolean checkForBusyBoxBinary() {
   return checkForBinary("busybox");
}

private boolean checkForSuBinary() {
    return checkForBinary("su");
}

private boolean checkForMagiskBinary() {
   return checkForBinary("magisk");
}

private boolean checkSuperuserApkBinary() {
   return checkForBinary("Superuser.apk");
}

private boolean checkForBinary(String filename) {
    for (String path : binaryPaths) {
        File f = new File(path, filename);
        boolean fileExists = f.exists();
        if (fileExists) {
            return true;
        }
    }
    return false;
}

 

1.5. 루팅 시 설치되는 패키지의 존재 유무를 통한 루팅 탐지 방법

- 루팅 시 설치되는 패키지가 존재하는지 확인하여 루팅 여부를 판단할 수 있다.

static final String[] knownRootAppsPackages = {
    "com.noshufou.android.su",
    "com.noshufou.android.su.elite",
    "eu.chainfire.supersu",
    "com.koushikdutta.superuser",
    "com.thirdparty.superuser",
    "com.yellowes.su",
    "com.topjohnwu.magisk",
    "com.kingroot.kinguser",
    "com.kingo.root",
    "com.smedialink.oneclickroot",
    "com.zhiqupk.root.global",
    "com.alephzain.framaroot"
};

public static boolean checkRootFilesAndPackages(Context context) {
    boolean result = false;
    for(String string1: knownRootAppsPackages) {
        if(isPackageInstalled(string1, context)) {
            result = true;
            break;
        }
    }
    return result;
}

private static boolean isPackageInstalled(String packagename, Context context){
    PackageManager pm = context.getPackageManager();
    try {
        pm.getPackageInfo(packagename, PackageManager.GET_ACTIVITIES);
        return true;
    } catch (NameNotFoundException e) {
        return false;
    }
}

 

1.6. 루팅 시 설치되는 앱의 존재 유무를 통한 루팅 탐지 방법

- 루팅 시 설치되는 앱이 존재하는지 확인하여 루팅 여부를 판단할 수 있다.

public static final String[] knownDangerousAppsPackages = {
    "com.koushikdutta.rommanager",
    "com.koushikdutta.rommanager.license",
    "com.dimonvideo.luckypatcher",
    "com.chelpus.lackypatch",
    "com.ramdroid.appquarantine",
    "com.ramdroid.appquarantinepro",
    "com.android.vending.billing.InAppBillingService.COIN",
    "com.android.vending.billing.InAppBillingService.LUCK",
    "com.chelpus.luckypatcher",
    "com.blackmartalpha",
    "org.blackmart.market",
    "com.allinone.free",
    "com.repodroid.app",
    "org.creeplays.hack",
    "com.baseappfull.fwd",
    "com.zmapp",
    "com.dv.marketmod.installer",
    "org.mobilism.android",
    "com.android.wp.net.log",
    "com.android.camera.update",
    "cc.madkite.freedom",
    "com.solohsu.android.edxp.manager",
    "org.meowcat.edxposed.manager",
    "com.xmodgame",
    "com.cih.game_cih",
    "com.charles.lpoqasert",
    "catch_.me_.if_.you_.can_"
};

public boolean detectPotentiallyDangerousApps(String[] additionalDangerousApps) {
    ArrayList packages = new ArrayList<>();
    packages.addAll(Arrays.asList(Const.knownDangerousAppsPackages));
    if (additionalDangerousApps!=null && additionalDangerousApps.length>0){
        packages.addAll(Arrays.asList(additionalDangerousApps));
    }
    return isAnyPackageFromListInstalled(packages);
}

 

1.7. Rooting Cloaking 앱 설치 유무로 루팅 탐지 방법

- 타 앱에서 루팅여부를 판단할 수 없도록 루팅 상태를 숨길수 있는 은폐 앱(Cloaking App)들이 설치되어 있는 경우가 있다.

- 이럴경우 역으로 Cloaking App이 설치되어 있는지 확인하여 루팅 여부를 판단할 수 있다.

public static final String[] knownRootCloakingPackages = {
    "com.devadvance.rootcloak",
    "com.devadvance.rootcloakplus",
    "de.robv.android.xposed.installer",
    "com.saurik.substrate",
    "com.zachspong.temprootremovejb",
    "com.amphoras.hidemyroot",
    "com.amphoras.hidemyrootadfree",
    "com.formyhm.hiderootPremium",
    "com.formyhm.hideroot"
};

public boolean detectRootCloakingApps(String[] additionalRootCloakingApps){
    ArrayList packages = new ArrayList<>  (Arrays.asList(Const.knownRootCloakingPackages));
    if (additionalRootCloakingApps!=null && additionalRootCloakingApps.length>0){
        packages.addAll(Arrays.asList(additionalRootCloakingApps));
    }
    return isAnyPackageFromListInstalled(packages);
}

private boolean isAnyPackageFromListInstalled(List packages){
    boolean result = false;
    PackageManager pm = mContext.getPackageManager();
    for (String packageName : packages) {
        try {
            pm.getPackageInfo(packageName, 0);
            QLog.e(packageName + " ROOT management app detected!");
            result = true;
        } catch (PackageManager.NameNotFoundException e) {
            // Exception thrown, package is not installed into the system  }
    }
    return result;
}

 

1.8. 특정 디렉터리의 쓰기권한을 통한 루팅 탐지 방법

- 안드로이드 운영체제는 특정 디렉터리에 쓰기 권한이 제한되어 있다.

- 루팅된 환경에서는 이런 디렉터리에도 쓰기 권한으로 접근이 가능하므로 이를 통해 루팅 여부를 확인할 수 있다.

public static final String[] pathsThatShouldNotBeWrtiable = {
    "/",
    "/data",
    "/system",
    "/system/bin",
    "/system/sbin",
    "/system/xbin",
    "/vendor/bin",
    "/sys",
    "/sbin",
    "/etc",
    "/proc",
    "/dev"
}

public static boolean checkForRWPaths() {
    boolean result = false;
    String[] lines = mountReader();
    for (String line : lines) {
        String[] args = line.split(" ");
        if (args.length < 4){
            continue;
        }
        String mountPoint = args[1];
        String mountOptions = args[3];
        for(String pathToCheck: Constants.pathsThatShouldNotBeWrtiable) {
            if (mountPoint.equalsIgnoreCase(pathToCheck)) {
                for (String option : mountOptions.split(",")){
                    if (option.equalsIgnoreCase("rw")){
                        result = true;
                        break;
                    }
                }
            }
        }
    }
    return result;
}

 

1.9. build.prop 설정값 확인을 통한 루팅 탐지 방법

- Android 기기의 build.prop 파일에는 운영 기기 전체에 적용되는 시스템 속성과 빌드 정보가 포함되어 있다.

- 정상적인 환경에서의 속성과 루팅된 환경에서의 *속성의 값이 다르므로 이를통해 루팅 여부를 확인할 수 있다.

*ro.debuggable = 1 이면 루팅된 환경이라 판단

*ro.secure = 0 이면 루팅된 환경이라 판단

private String[] propsReader() {
    try {
        InputStream inputstream =  Runtime.getRuntime().exec("getprop").getInputStream();
        if (inputstream == null) return null;
        String propVal = new Scanner(inputstream).useDelimiter("\\A").next();
        return propVal.split("\n");
    } catch (IOException | NoSuchElementException e) {
        QLog.e(e);
        return null;
    }
}

public boolean checkForDangerousProps() {
    final Map dangerousProps = new HashMap<>();
    dangerousProps.put("ro.debuggable", "1");
    dangerousProps.put("ro.secure", "0");
    boolean result = false;
    String[] lines = propsReader();
    if (lines == null){
        return false;
    }
    for (String line : lines) {
        for (String key : dangerousProps.keySet()) {
            if (line.contains(key)) {
                String badValue = dangerousProps.get(key);
                badValue = "[" + badValue + "]";
                if (line.contains(badValue)) {
                    QLog.v(key + " = " + badValue + " detected!");
                    result = true;
                }
            }
        }
    }
    return result;
}

 

2. 소스코드 난독화 적용

- 안드로이드 앱은 APK파일 디컴파일을 통해 누구든지 소스코드를 확인할 수 있다. 소스코드가 평문으로 저장되어 있으면 스말리 코드를 분석하는데 많은 도움이 되므로 *프로가드(Proguard)와 같은 소스코드 난독화 프로그램을 이용하여 소스코드를 쉽게 분석할 수 없도록 한다.

*프로가드 : 안드로이드 스튜디오에서 기본적으로 제공하는 소스코드 난독화 도구

 

3. 무결성 검증 기능 적용

- 앱의 Signing 키를 검증하는 등의 방식을 사용하여 무결성 검증 기능을 추가한다.

- 변조된 코드로 동작하는 리패키징 앱 실행 시 강제종료되도록 하여야 하며, 웹 통신으로 키를 검증하는 방식은 중간자공격에 의해 우회될 수 있으므로 주의하여야 한다.

 

4. 안티 디버깅 기능 적용

- 무결성 검증 기능을 디버깅 툴을 이용해 우회할 수 없도록 안티디버깅 기능을 적용한다.

https://seo-security.tistory.com/19

 

[Android] 안티 디버깅(Anti-Debugging) 코드

안티 디버깅(Anti-Debugging) 앱 안티 디버깅은 특정 모바일 앱의 디버깅을 감지하고 방지하기 위한 기술 및 메커니즘의 사용을 의미합니다. 앱을 디버깅하면 실행 중 동작을 분석하고 이해할 수 있

seo-security.tistory.com

 

다. 취약점 실습

1. 분석 대상 앱 설치

- 실습을 위해 인시큐어뱅크 애플리케이션을 설치한다.

※ 인시큐어뱅크 앱이 설치되어있지 않은 사람은 아래의 글을 참고하여 앱을 설치하길 바란다.

2023.04.10 - [Mobile App 취약점 진단/AOS App 진단] - 인시큐어뱅크 앱 설치 및 실행 방법 정리(InsecureBankv2)

 

인시큐어뱅크 앱 설치 및 실행 방법 정리(InsecureBankv2)

1. 인시큐어뱅크 앱 이란? - 모바일 뱅킹 취약점 진단을 위한 테스트 용도로 제작된 애플리케이션이다. - 안드로이드 앱 취약점 진단을 실습할 수 있는 환경을 제공한다. - 2019년 이후로 업데이트

hagsig.tistory.com

 

2. 진단 대상 앱 apk 파일 추출

- 아래의 링크를 참고하여 인시큐어뱅크 앱으로부터 apk 파일을 추출한다.

안드로이드 앱(app)으로부터 apk 파일 추출 방법 정리

 

안드로이드 앱(app)으로부터 apk 파일 추출 방법 정리

1. apk 파일이란? - 안드로이드(Android) OS에 애플리케이션(Application, App)을 설치할 수 있는 파일이다. - 윈도우 OS의 설치파일(exe, msi)같은거라 생각하면 쉽다. 2. apk 파일을 추출해야하는 이유 - 취약

hagsig.tistory.com

 

3. APK파일 디컴파일 

- 아래의 게시글을 참고하여 추출한 APK파일을 디컴파일 한다.

[AOS App 취약점 진단 · 모의해킹] - 안드로이드 APK 파일 디컴파일/리패키징 방법

 

안드로이드 APK 파일 디컴파일/리패키징 방법

1. 디컴파일/리패키징 이란? 1.1. 컴파일(compile) - 소스코드(source code)에서 기계가 인식할 수 있는 바이너리(binary) 파일로 변환하는 과정을 말한다. - 안드로이드는 컴파일 이후 패키징(packaging)과 코

hagsig.tistory.com

 

4. extractNativeLibs 속성 확인

- 리패키징 홈 디렉토리에 존재하는 AndroidManifest.xml 파일을 메모장으로 열어 extractNativeLibs 속성이 false로 설정되어 있는지 확인한다.

- extractNativeLibs 속성이 false로 설정되어 있을경우, 앱 변조 후 리패키징시 오류가 발생하므로 true로 변경하여야 한다

#extractNativeLibs 예시
<application 
	android:extractNativeLibs="false">
</application>Copy

 

5. 루팅 탐지 포인트 탐지

- 본인이 변조하고자 하는 기능을 정한뒤 소스코드를 분석하여 스말리 코드의 어느 부분을 변조하면 되는지 탐색하는 과정이다.

 

※ 만약 본인이 무결성 검증 기능이 존재하는지 확인만 하고 싶은 거라면 아래의 모든 과정을 생략하고 APK파일을 리패키징한 다음 설치 및 실행하여 정상 동작하는지만 확인하면 된다.

 

- 본글에서는 인시큐어뱅크 앱 로그인 후 메인화면에 출력되는 Text 문구를 변조하여 볼 것이다.

#인시큐어뱅크 기본 계정정보(default ID/PW)
username : dinesh
password : Dinesh@123$

username : jack
password : Jack@123$Copy

 

6. 코드 분석

- 아래의 링크에 접속하여 jadx-gui-x.x.x-with-jre-win.zip 파일을 다운로드한 뒤, 압축을 해제한다.

https://github.com/skylot/jadx/releases/tag/v1.4.7

 

Release 1.4.7 · skylot/jadx

Features [core] Inline lambdas by instance field (#1800) [plugins] Allow to load classes using input stream or byte array in jadx-input plugin (#1457) Bug Fixes [core] Restore missing type param...

github.com

 

- jadx-gui-x.x.x.exe를 실행한 뒤 위에서 추출한 인시큐어뱅크 apk파일을 로드한 다음, "Rooted Device!!"을 검색한다.

 

- 소스코드를 분석하니 boolean 타입의 isrooted 변수 값이 true/false에 따라 루팅탐지 여부를 판단하는 것으로 확인된다.

*조건1 : /system/app/Superuser.apk 파일 존재 여부

*조건2 : su 명령어 사용가능 여부

 

- 아래의 *경로에 진입하뒤 PostLogin.smali 파일을 메모장으로 연다.

*경로 : InsecureBankv2\smali\com\android\insecurebankv2\PostLogin.smali

 

- 메서드 명 "showRootStatus()"을 검색하여 소스코드 분석을 통해 알아낸 변조 포인트를 찾아낸다.

 

- smile 코드를 분석한 내용은 아래와 같다.

422   .method showRootStatus()V	← 메소드 명과 리턴타입을 명시함.
423       .locals 3	← 메소드 내부에서 사용되는 레지스터 갯수를 명시함.
424   
425       .prologue	← 메소드 내부에의 코드 시작을 알림.
426       const/4 v1, 0x1	← v1에 1(true)값을 저장.
427   
428       .line 86	← 소스코드의 86번 라인인 것을 명시함.
429       const-string v2, "/system/app/Superuser.apk"	← "/system/app/Superuser.apk" 문자열을 v2에 저장
430   
431       invoke-direct {p0, v2}, Lcom/android/insecurebankv2/PostLogin;->doesSuperuserApkExist(Ljava/lang/String;)Z	← PostLogin에서 doesSuperuserApkExist 함수를 v2 인자로 호출.
432   
433       move-result v2	← 호출한 함수의 리턴값을 v2에 저장.
434   
435       if-nez v2, :cond_0	← v2의 값이 0과 다르면 cond_0 지점으로 이동.
436   
437       .line 87	← 소스코드의 87번 라인인 것을 명시함.
438       invoke-direct {p0}, Lcom/android/insecurebankv2/PostLogin;->doesSUexist()Z	← PostLogin에서 doesSUexist 함수를 호출.
439   
440       move-result v2	← 호출한 함수의 리턴값을 v2에 저장.
441   
442       if-eqz v2, :cond_1	← v2의 값이 0과 같으면 cond_1 지점으로 이동.
443   
444       :cond_0	← goto의 도착지점 cond_0를 명시함.
445       move v0, v1	← v1의 값을 v0으로 이동.
446   
447       .line 88	← 소스코드의 88번 라인인 것을 명시함.
448       .local v0, "isrooted":Z	← isrooted를 v0으로 명명.
449       :goto_0	← goto의 도착지점 goto_0를 명시함.
450       if-ne v0, v1, :cond_2	← v0과 v1의 값이 다르다면 cond_2 지점으로 이동.
451   
452       .line 90	← 소스코드의 90번 라인인 것을 명시함.
453       iget-object v1, p0, Lcom/android/insecurebankv2/PostLogin;->root_status:Landroid/widget/TextView;	← PostLogin에서 p0의 인스턴스필드 TextView를 v1으로 가져온다.
454   
455       const-string v2, "Rooted Device!!"	← v2에 "Rooted Device!!"를 저장한다.
456   
457       invoke-virtual {v1, v2}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V	← TextView에서 setText 함수를 v2 인자로 호출. 화면에 "Rooted Device!!" 문자열이 표시된다.
458   
459       .line 96	← 소스코드의 96번 라인인 것을 명시함.
460       :goto_1	← goto의 도착지점 goto_1을 명시함.
461       return-void	← 메소드의 결과값을 리턴하며 메소드를 종료함.
462   
463       .line 87	← 소스코드의 87번 라인인 것을 명시함.
464       .end local v0    # "isrooted":Z	← isrooted 인스턴스 v0을 해제함.
465       :cond_1	← goto의 도착지점 cond_1을 명시함.
466       const/4 v0, 0x0	← v0에 0(false)를 저장함.
467   
468       goto :goto_0	← goto_0 지점으로 이동함.
469   
470       .line 94	← 소스코드의 94번 라인인 것을 명시함.
471       .restart local v0    # "isrooted":Z	← isrooted 인스턴스 v0을 재할당함.
472       :cond_2	← goto의 도착지점 cond_2를 명시함.
473       iget-object v1, p0, Lcom/android/insecurebankv2/PostLogin;->root_status:Landroid/widget/TextView;	← PostLogin에서 p0의 인스턴스필드 TextView를 v1으로 가져온다.
474   
475       const-string v2, "Device not Rooted!!"	← v2에 "Device not Rooted!!"를 저장한다.
476   
477       invoke-virtual {v1, v2}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V	← TextView에서 setText 함수를 v2 인자로 호출. 화면에 "Device not Rooted!!" 문자열이 표시된다.
478   
479       goto :goto_1	← goto_1 지점으로 이동함.
480   .end method		← 메소드의 끝을 명시함.

 

 

- 코드를 분석한 결과 첫 번째 분기점의 분기조건과 조건에 따른 이동지점을 루팅이 탐지되지 않았을 때 실행되는 지점으로 변조한다면 루팅탐지 우회를 할 수 있을 것 같다.

- 아래와 같이 코드를 변경하여 루팅탐지가 될 경우 제일 마지막 부분으로 보내 루팅탐지 기능을 우회하도록 변조한다.

- v1에 기본적으로 1(true)이 저장되어 있고 v2에는 루팅된 환경에서 실행시켰으므로 1(true)이 저장되어 있을 것이다.

- 둘이 동일한 값을 가졌으므로, 동일한 값을 가졌을때 cond_2로 이동하라고 아래와 같이 수정한다.

 

- 아래의 게시글을 참고하여 변조한 파일을 리패키징/인증서를 씌운다.

[AOS App 취약점 진단 · 모의해킹] - 안드로이드 APK 파일 디컴파일/리패키징 방법

 

안드로이드 APK 파일 디컴파일/리패키징 방법

1. 디컴파일/리패키징 이란? 1.1. 컴파일(compile) - 소스코드(source code)에서 기계가 인식할 수 있는 바이너리(binary) 파일로 변환하는 과정을 말한다. - 안드로이드는 컴파일 이후 패키징(packaging)과 코

hagsig.tistory.com

 

- 변조한 APK파일을 디바이스에 *설치한다.

*Nox일 경우 드래그 앤 드롭으로 간편하게 설치할 수 있고, 물리적 디바이스일 경우 adb install 명령어를 통해 설치할 수 있다.

 

- 변조한 APK파일을 실행하면 이전과는 다르게 본인이 변조한 문구가 출력되는 것을 확인할 수 있다.

 

- 프리다를 통한 런타임 조작으로 루팅탐지를 우회하고 싶다면 아래의 글을 참고하길 바란다.

 

 

라. 참고 URL

https://philosopher-chan.tistory.com/355

 

root detection in android device

Root Detection in Android device 의 번역본입니다. Root Access is the process of allowing users smartphones, tablets and other devices running the Android mobile operating system to attain privileged control (known as root access). 루트 어세스

philosopher-chan.tistory.com

 

https://saltlee.tistory.com/155

 

[Android] 루팅 탐지 기법 / 루팅 탐지 우회 기법

[루팅 탐지 기법] 다양한 루팅 탐지 기법 있는데 거의 다 적용된 앱이 있어서 분석쓰 1) detectRootManagementApps : 루팅 관련 앱 탐지하는것 같다 2) detectPotentiallyDangerousApps : 루팅에서만 설치되는 Dangerou

saltlee.tistory.com

 

https://www.appknox.com/blog/root-detection-techniques

 

Is Your Android Rooted? Detect With These 6 Proven Ways

Here are the most commonly used root detection methods that developers use to prevent attackers from bypassing their app validation measures.

www.appknox.com

 

https://stackoverflow.com/questions/44235138/root-check-for-android-device

 

Root check for Android device

This is an old question and asked answered by many but here I go again.. I want to check whether the device is rooted or not. I don't want my application to be installed on rooted devices. Now I went

stackoverflow.com