Mobile

[Mobile] Uncrackable_Level2

오스_ 2025. 6. 10. 09:53
반응형

💡Introduction

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

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

 

owasp-mastg/Crackmes/Android/Level_02/UnCrackable-Level2.apk 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) 앱 실행시 Level1 단계에서와 같게 "Root detected!"라는 다이얼로그가 출력되지만 앱이 바로 종료되었다.

 

 

Step2) Jadx로 분석 시 아래와 같은 코드에서 Root 탐지 조건을 확인했다. Level1 단계에서도 b.a()메서드만 반환됐었는데 해당 Level에서도 마찬가지였다. 그래서 a() 메서드만 후킹하는 코드를 작성하였다.

sg.vantagepoint.uncrackable2.MainActivity
sg.vantagepoint.a.b

//level_2.js
Java.perform(function() {
    //1 Hook rooting!
    var bClass = Java.use('sg.vantagepoint.a.b');
    bClass.a.implementation = function(str) {
        console.log('[+] Hooked hookClass!');
        return false;
    };
});

 

 

Step3) 루팅은 우회가 됐지만 여기서 Flag 값을 찾아야 한다. Success!를 띄우는 조건을 확인하기 위해 this.m.a()를 더블 클릭하여 자세히 들어가 봤다

sg.vantagepoint.uncrackable2.MainActivity

Step4) Level1 단계에서와 같이 직관적으로 뭐가 보이지는 않았지만, 여기서 native 코드가 존재하는 것을 확인했다.

sg.vantagepoint.uncrackable2.CodeCheck

 

 Codecheck 클래스 안에는 native bar(byte[]) 메서드가 존재하고 있는데, native 키워드는 Java 안에 구현이 없고, C/C++ .so 파일에 구현되어 있다. 즉, 해당 메서드는 Java 안에서는 몸체가 없고, 외부 네이티브 라이브러리에서 연결되는 것이다.

 

Java에서 native 메서드를 쓸려면 반드시 .so 파일을 로드 해야 하는데 그걸 해주는게 해당 코드에서 바로 아래 부분과 같다.

("foo" 라고 쓰지만, 실제로는 접두어 lib와 접미어 .so가 자동으로 붙어서 → libfoo.so로 되는 것 해당 파일은 IDA로 분석 가능)

static {
    System.loadLibrary("foo"); // libfoo.so 로드
}

 

Step5) apk 파일을 zip파일로 변경하여 압축을 풀면 lib폴더 안에 libfoo.so 파일이 존재할 것이다. IDA로 분석을 진행하면 함수 부분에 bar라고 검색 해보니 함수가 검색되는 것을 확인하였고 v7 버퍼에 "Thanks for all the fish"라는 문자열을 저장하는 코드를 발견했다. 즉 해당 문자열을 입력하면 Success! 반응이 나올 것이다.


🚩Flag Revealed

Thanks for all the fish


💡 Reference & Notes

해당 문제에 중점이라 말할 수 있는 native 코드에 대해서 좀 더 자세히 작성해봤습니다.

 

Android 앱에서 native 코드는 일반적으로 Java/Kotlin이 아닌 C 또는 C++로 작성된 코드를 말합니다.

이는 JNI(Java Native Interface)를 통해 앱과 연결되며, .so 파일 형태로 컴파일되어서 APK에 포함됩니다.

 

❓왜 Native 코드를 사용할까요

목적 설명
성능 연산이 많거나 속도가 중요한 연산을 C/C++로 작성 (e.g 게임, 미디어 처리)
보안 중요 로직을 역공학하기 어렵도록 native로 숨김 (e.g 라이선스 검증, 암호화)
코드 재사용 기존의 C/C++ 라이브러리를 활용

 

 

🖇️어떻게 연결되는가

Java에서 native 함수를 다음과 같이 선언합니다

public class MyClass {
	static {
    	System.loadLibrary("mylib"); //libmylib.so 로드
    }
    
    public native int checkSomething(byte[] input); // 선언
}

 

이 메서드의 실제 구현은 libmylib.so 안에 다음처럼 존재합니다

JNIEXPORT jint JNICALL
Java_com_example_MyClass_checkSomething(JNIEnv *env, jobject thiz, jbyteArray input) {
    return 1;
}
반응형