[Mobile] Uncrackable_Level1
💡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 탐지 조건이 확인했다
Step3) if (c.a() || c.b() || c.c()) 조건 에서 세 가지 중 하나라도 true를 반환하면 루팅으로 간주되는 것으로 추측된다. 일단 c.a() 메서드 코드를 확인하기 위해 더블클릭하여 코드로 접근해줬다.
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) 내부에서 입력 문자열을 특정 값과 비교하고 있었다.
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
💡 Reference & Notes
Step3에서 코드상으로만 보면 c.a(), c.b(), c.c() 세 가지 조건 중 하나라도 true를 반환하면 루팅된 것으로 간주되어 앱이 종료됩니다. 그런데 왜 a() 메서드만 후킹했냐면.. 사실 운이 좋았습니다
처음에는 세 개 중 하나만 먼저 후킹해서 시도해보자고 생각했고, 그 대상이 a() 메서드였습니다. 그런데 예상 외로 그것만 후킹했는데도 루팅 우회가 성공했죠.
이걸 보고 "아 지금 환경에서는 a()만 true를 반환하고 있고 b()와 c()는 false 겠구나"라고 추측할 수 있었어요.
보다 정확하게 확인하기 위해 Frida를 이용해서 실행 중인 클래스와 메서드를 추적하고, 각 메서드가 어떤 값을 반환하는지 출력하는 코드를 작성해봤습니다.
그 결과 실제로 c.a() 메서드만 호출되어 true를 반환하고 있었고, b()와 c()는 실행되지 않았다는 것을 확인할 수 있었습니다.
우린 이걸 동적 분석이라고 할 수 있겠네요 처음 부터 동적 분석으로 확인해봤으면 더 간단했겠지만 정적 분석의 눈을 밝히고 싶어서 해당 포스트에서는 정적 분석 위주로 진행했습니다ㅎㅎ
긴 글 읽어주셔서 감사합니다. 궁금한점이 있으면 언제든 댓글 부탁드립니다 그럼 이만.. 총총총..