상세 컨텐츠

본문 제목

루팅 탐지 우회

CTF

by ser-ser 2025. 4. 19. 13:47

본문

루팅 탐지 우회란

안드로이드 앱이 디바이스의 루팅 여부를 감지하여 동작을 제한하거나 종료하는 기능을 무력화하는 기술입니다. 이는 프리다(Frida)와 같은 동적 분석 도구를 사용하여 앱의 루팅 탐지 로직을 수정하거나 후외하는 과정을 포함합니다, 이번 포스팅에서는 UnCrackable-Level1.apk 앱의 루팅 탐지 기능을 우회하여 앱 종료를 방지하는 방법을 알아보겠습니다.


준비과정

  • 구글에서 "Crackmes/Android/Level_01/UnCrackable-Level1.apk"를 검색하여 깃허브 사이트에 접속합니다.


  • 해당 사이트에서 UnCrackable-Level1.apk 파일을 다운로드 합니다.
  • 녹스 에뮬레이터를 실행하고, CMD 창에서 nox_adb install[apk경로]를 입력하여 APK를 설치합니다.


  • 앱을 실행하면 "This is unacceptable. the app is now going to exit"라는 경고창과 함께 종료됩니다. 이는 루팅 팀지 로직이 동작한 결과입니다.

문제 설명

  • UnCrackable-Level1.apk 앱은 루팅 탐지를 수행하며, 루팅이 감지되면 "Root detected!" 경고와 함께 종료됩니다.
    이를 루팅 탐지 로직을 우회하여 앱이 종료되지 않도록 해야 합니다.

소스코드 분석 (onCreate)

루팅 탐지 로직을 분석하기 위해 UnCrackable-Level1.apk를 jadx-gui로 열어 내부 코드를 살펴보겠습니다.



  • 앱 실행 시 출력된 메시지 "Root detected!"를 검색하여 관련 코드를 찾습니다.
  • MainActivity 클래스의 onCreate 메서드에서 해당 로직을 확인합니다
    protected void onCreate(Bundle bundle) {
        if (c.a() || c.b() || c.c()) {
            a("Root detected!");
        }
    • c.a(), c.b(), c.c()
      • 루팅 탐지 메서드들로, 하나라도 true를 반환하면 루팅이 감지됩니다.
    • a("Root detected!")
      • 루팅 감지 시 경고창을 띄우는 메서드를 호출합니다.

소스코드 분석(a())

  • on Create의 a("Root detected!")의 a 메서드 부분을 더블클릭하여 소스코드를 확인합니다.
    private void a(String str) {
        AlertDialog create = new AlertDialog.Builder(this).create();
        create.setTitle(str);
        create.setMessage("This is unacceptable. The app is now going to exit.");
        create.setButton(-3, "OK", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                System.exit(0);
            }
        });
    }


    • AlertDialog
      • "Root detected!" 제목과ㅏ "This is unacceptable..."메시지를 표시합니다.
    • setButton
      • "OK"버튼 클릭 시 System.exit(0)가 호출하여 앱을 종료합니다.
    • 목표
      • "OK" 버튼 클릭 시 System.exit(0)가 호출되지 않도록 수정합니다.

프리다 자바스크립트 작성

루팅 탐지로 인한 앱 종료를 방지하기 위해 츠리다 스크립트를 작성하겠습니다. 두 가지 접근법을 시도한 과정을 설명합니다.

  • 첫 번째 소스코드

    setImmediate(function() {
        Java.perform(function() {
            var exit_pass = Java.use("android.content.DialogInterface.OnClickListener");
            exit_pass.onClick.implementation = function(arg, arg2) {
                console.log("[*] pass");
            };
        });
    });
    • Java.use("android.content.DialogInterface.OnClickListener")
      • OnClickListener 인터페이스를 후킹하여 "OK" 버튼의 클릭 동작을 수정하려 했습니다.
    • onClik.implementation
      • onClick 메서드를 재정의하여 System.exit(0) 대신 "[*] pass"를 출력하도록 했습니다
    • 문제점
      • jaca.lang.ClassNotFoundException 오류가 발생했습니다. 이는 OnClickListener가 인터페이스이며, 대상 앱에서 익명 클래스로 구현된 특정 인스턴스를 직접 후킹할 수 없기 때문입니다.

  • 두 번째 소스코드
    setImmediate(function() {
        Java.perform(function() {
            var exit_pass = Java.use("java.lang.System");
            exit_pass.exit.implementation = function(arg) {
                console.log("[*] pass");
            };
        });
    });

    • Java.use("java.lang.System")
      • System 클래스를 불러옵니다.
    • exit.implementation
      • System.exit()메서드를 후킹하여 원래 동작(앱 종료)을 무력화 합니다.
    • function(arg){console.log("[*] pass")}
      • exit() 호출 시 앱을 종료하는 대신 "[*] pass"를 출력합니다.

실행

  • 스크립트 저장 및 실행
    • 두 번째 코드를 UnCreackable_system_exit.js로 저장합니다.
    • CMD에서 frida -U -l UnCreackable_system_exit.js Uncrackable1를 입력하여 프리다 스크립트를 실행합니다.
    • 앱을 실행하면 루팅 탐지 경고창이 나타나고, "OK" 버튼을 클릭해도 앱이 종료되지 않습니다.
    • 콘솔에 "[*] pass"가 출력되어 System.exit()가 성공적으로 우회된 것을 확인할 수 있습니다.

문제 해결 과정에서의 주의점

  • 클래스 후킹 대상 선정
    • 첫 번째 시도에서 OnClickListener 인터페이스를 후킹하려 했으나, 익명 클래스의 동적 특성으로 인해 실패했습니다. 대신 System.exit()과 같은 명확한 메서드를 후킹하는 것이 효과적입니다.
  • 루팅 탐지 우회 전략
    • 루팅 탐지(c.a(), c.b(), c.c()) 자체를 수정할 수도 있지만, 이번 경우에는 결과적으로 호출되는 System.exit()를 무력홯여 간단히 해결했습니다.

이번 포스팅에서는 UnCrakable-Level1.apk의 루팅 탐지 기능을 프리다를 사용해 우회하는 방법을 배웠습니다. 첫 번째 시도에서 onClickListener 후킹이 실패했으나, System.exit()를 후킹하여 앱 종료를 방지하는 두 번째 접근법으로 문제를 해결했습니다.

'CTF' 카테고리의 다른 글

로그인 우회  (0) 2025.04.22
암호 복호화  (0) 2025.04.20
FridaLab_08  (0) 2025.04.18
FridaLab_07  (1) 2025.04.17
FridaLab_06  (1) 2025.04.17

관련글 더보기