Android 루팅 탐지

지프치프·2024년 9월 27일
0

Android

목록 보기
86/89
post-thumbnail

“Android 로봇은 Google에서 제작하여 공유한 저작물을 복제하거나 수정한 것으로 Creative Commons 3.0 저작자 표시 라이선스의 약관에 따라 사용되었습니다.”


루팅(Rooting)이란?

루팅(root + ing)이란 UNIX 계열 운영체제에서 최고 관리자 권한인 root 권한을 취득하는 것을 의미합니다.

일반적으로 루팅이라 함은 Android 환경에서 이루어지는 행위를 일컫는 용어입니다.

Android는 다른 리눅스와 달리 기본적으로 root 접근을 막고 있으며

이는 소비자(사용자)에게 예상치 못한 시스템 파일 손상을 방지하고 안정적인 사용자 경험을 제공하기 위함입니다.

따라서 대부분의 루팅 방법은 단말기 제조사에서 적합한 방법으로 제공하는 방법이 아니며

대부분의 루팅은 보안 취약점을 공격하여 부트로더 언락을 통해 권한을 취득하는 방식입니다.

루팅은 제조사에서 권장하는 방법이 아니기 때문에 루팅으로 인해 발생하는 피해는 제조사에서 보증하지 않습니다.

루팅 탐지

루팅은 여러가지 방법으로 탐지가 가능합니다.

자세한 설명은 아래 코드와 주석을 통해 설명하겠습니다.

    private fun isRooted(): Boolean {
        try {
            // test-keys 태그가 있는지 확인
            val buildTags = Build.TAGS
            if (buildTags != null && buildTags.contains("test-keys")) {
                return true
            }

            // Superuser.apk 파일이 있는지 확인
            // Superuser.apk는 루팅된 디바이스를 제어할 수 있도록 개발된 오픈소스 앱으로
            // 해당 앱이 설치되었다는 것은 루팅된 단말기로 판단할 수 있습니다.
            val file = File("/system/app/Superuser.apk")
            if (file.exists()) {
                return true
            }

            // su, busybox 바이너리가 해당 경로에 있는지 확인
            // 아래 바이너리들은 부트로더 언락을 위해 필요한 바이너리들로
            // 부트로더 언락이 되었다는 것은 루팅이 된 것으로 판단할 수 있습니다.
            val paths = arrayOf(
                "/system/bin/",
                "/system/xbin/",
                "/sbin/",
                "/system/sd/xbin/",
                "/system/bin/failsafe/",
                "/system/bin/.ext/",
                "/system/usr/we-need-root/",
                "/data/local/xbin/",
                "/data/local/bin/",
                "/data/local/"
            )
            for (path in paths) {
                if (File(path + "su").exists() || File(path + "busybox").exists()) {
                    return true
                }
            }

            // su 명령이 실행 가능한지 확인
            // su 명령은 리눅스에서 계정을 전환하여 명령을 내릴 수 있는 명령어로
            // root 권한으로써 명령을 내릴 수 있기 때문에
            // su 명령이 실행된다면 루팅된 단말기로 판단합니다.
            var process: Process? = null
            try {
                process = Runtime.getRuntime().exec("su")
                return true
            } catch (e: Exception) {
            } finally {
                if (process != null) {
                    try {
                        process.destroy()
                    } catch (e: Exception) {
                    }
                }
            }
        } catch (e: Exception) {
        }
        return false
    }

위 4가지 방법 중 하나라도 해당된다면 루팅된 단말기로 판단이 가능합니다.

실행 결과

루팅된 단말기

정상 단말기

개인적으로 공부했던 것을 바탕으로 작성하다보니
잘못된 정보가 있을수도 있습니다.
인지하게 되면 추후 수정하겠습니다.
피드백은 언제나 환영합니다.
읽어주셔서 감사합니다.

profile
지프처럼 거침없는 개발을 하고싶은 개발자

0개의 댓글