Mobile

[Mobile] Uncrackable_Level1

오스_ 2025. 6. 9. 14:31
반응형

 

💡Introduction

OWASP Mobile Application Security Testing Guide(MASTG) 저장소는 모바일 앱 리버스 엔지니어링 및 보안 테스트 실습을 위한 훈련용 크랙미 앱들이 저장되어 있다.

 

Level_01은 가장 기초적인 리버싱 연습용 APK로, 초보자들이 Android 앱 구조, 클래스 디컴파일, 후킹, 암호 해독 등의 기본기를 익히도록 설계 되어 있다.

※ 필자는 Frida 사용법을 익히기 위해 해당 실습을 진행하였음

 

owasp-mastg/Crackmes/Android/Level_01 at master · OWASP/owasp-mastg

The Mobile Application Security Testing Guide (MASTG) is a comprehensive manual for mobile app security testing and reverse engineering. It describes the technical processes for verifying the contr...

github.com


📌Step-By-Step

Step1) 분석 대상 APK를 단말기에 설치해 실행한 결과, 앱 실행 직후 Root detected! 라는 다이얼로그가 출력되고, 확인 버튼(OK) 클릭 시 앱이 강제 종료됐다

 

Step2) Jadx를 이용하여 디컴파일한 결과, 아래와 같은 코드에서 Root 탐지 조건이 확인했다

root 검색
sg.vantagepoint.uncrackable1.MainActivity 클래스

 

 

Step3) if (c.a() || c.b() || c.c()) 조건 에서 세 가지 중 하나라도 true를 반환하면 루팅으로 간주되는 것으로 추측된다. 일단 c.a() 메서드 코드를 확인하기 위해 더블클릭하여 코드로 접근해줬다.

sg.vantagepoint.a.c 클래스

 

 

Step4) a 메서드가 false를 반환하도록 후킹 코드를 작성해줬다

※ 왜 a메서드만 후킹했는지에 대한 내용은 아래 쪽 Reference & Notes 부분의 내용을 확인바람

//level_1.js
Java.perform(function() {
    //1 Hook rooting!
    var hookClass = Java.use('sg.vantagepoint.a.c');
    hookClass.a.implementation = function(str) {
        console.log('[+] Hooked hookClass!');

        return false;
    };
});
// frida 실행 방법
frida -U -f owasp.mstg.uncrackable1 -l level_1.js

 

 

Step5) 루팅 우회가 성공적으로 되는 것을 확인하였으며, 이후 입력창에 값을 입력했을 때 잘못된 입력이면 "Nope" 다이얼로그가 출력되는 것을 확인했다.

 

Step6) Jadx로 조건을 확인해본 결과, a.a(obj) 내부에서 입력 문자열을 특정 값과 비교하고 있었다.

sg.vantagepoint.uncrackable1.MainActivity 클래스
sg.vantagepoint.uncrackable1.a 클래스

 

 

Step7) sg.vantagepoint.a.a.a() 메서드를 확인해보니 AES 복호화 메서드를 확인할 수 있었다. 복호화 메서드를 토대로 실제 패스워드의 값을 알아냈다.

//level_1.js
Java.perform(function() {
    //1 Hook rooting!
    var hookClass = Java.use('sg.vantagepoint.a.c');
    hookClass.a.implementation = function(str) {
        console.log('[+] Hooked hookClass!');

        return false;
    };

    //2 Find Flag!
    const TargetClass = Java.use("sg.vantagepoint.uncrackable1.a");

    TargetClass.a.implementation = function (inputStr) {
        console.log("[+] sg.vantagepoint.uncrackable1.a.a() 호출됨");
        console.log("    입력값:", inputStr);

        const result = this.a(inputStr);

        const keyHex = "8d127684cbc37c17616d806cf50473cc";
        const cipherB64 = "5UJiFctbmgbDoLXmpL12mkno8HT4Lv8dlat8FxR2GOc=";

        const keyBytes = Java.use("sg.vantagepoint.uncrackable1.a").b(keyHex); // hex → byte[]
        const Base64 = Java.use("android.util.Base64");
        const cipherBytes = Base64.decode(cipherB64, 0);

        const AESUtil = Java.use("sg.vantagepoint.a.a");
        const decryptedBytes = AESUtil.a(keyBytes, cipherBytes);

        const decryptedString = Java.use("java.lang.String").$new(decryptedBytes);
        console.log("    복호화 결과:", decryptedString);

        return result; // 원래 결과 반환
    };
});
// frida 실행 방법
frida -U -f owasp.mstg.uncrackable1 -l level_1.js

🚩Flag Revealed

I want to believe


💡 Reference & Notes

Step3에서 코드상으로만 보면 c.a(), c.b(), c.c() 세 가지 조건 중 하나라도 true를 반환하면 루팅된 것으로 간주되어 앱이 종료됩니다. 그런데 왜 a() 메서드만 후킹했냐면.. 사실 운이 좋았습니다

 

처음에는 세 개 중 하나만 먼저 후킹해서 시도해보자고 생각했고, 그 대상이 a() 메서드였습니다. 그런데 예상 외로 그것만 후킹했는데도 루팅 우회가 성공했죠.

 

이걸 보고 "아 지금 환경에서는 a()만 true를 반환하고 있고 b()와 c()는 false 겠구나"라고 추측할 수 있었어요.

 

보다 정확하게 확인하기 위해 Frida를 이용해서 실행 중인 클래스와 메서드를 추적하고, 각 메서드가 어떤 값을 반환하는지 출력하는 코드를 작성해봤습니다. 

 

그 결과 실제로 c.a() 메서드만 호출되어 true를 반환하고 있었고, b()와 c()는 실행되지 않았다는 것을 확인할 수 있었습니다.

 

우린 이걸 동적 분석이라고 할 수 있겠네요 처음 부터 동적 분석으로 확인해봤으면 더 간단했겠지만 정적 분석의 눈을 밝히고 싶어서 해당 포스트에서는 정적 분석 위주로 진행했습니다ㅎㅎ

 

긴 글 읽어주셔서 감사합니다. 궁금한점이 있으면 언제든 댓글 부탁드립니다 그럼 이만.. 총총총..

반응형