FridaLab
📌 Intro
이 문서는 Frida 활용 능력을 향상시키기 위해 FridaLab의 Challenge에 대한 Writeup입니다.
FridaLab은 총 8가지의 과제가 존재하며 각각의 과제를 수행한 내용을 본 문서에 상세히 기술하였습니다.
🎯 Goal
FridaLab에서 수행해야 하는 목표는 총 8가지 입니다.
1. 클래스 challenge_01의 변수 'chall01'을 1로 변경하기
2. chall02() 실행하기
3. chall03()이 true를 반환하도록 만들기
4. "frida"를 chall04()에 보내기
5. 항상 "frida"를 chall05()에 보내기
6. 올바른 값을 가지고 10초 후에 chall06() 실행하기
7. check07Pin()에 Bruteforce를 수행하고 chall07()로 확인하기
8. 'check' 버튼의 텍스트 값을 'Confirm'으로 변경하기
🛠️ 환경 구축
안드로이드는 애뮬레이터 (Nox 플레이어)를 사용하였습니다.
1) Frida 설치
pip install frida-tools
frida --version # frida 버전 확인
2) Frida-server 설치
nox_adb shell # 녹스 adb shell 실행(CMD)
getprop ro.product.cpu.abi # 안드로이드 비트 확인(adb shell)
- https://github.com/frida/frida/releases 로 접속 후 frida-server 최신버전 다운로드 후 압축해제
예시) https://github.com/frida/frida/releases/download/16.2.1/frida-server-16.2.1-android-x86.xz
3) 안드로이드로 frida-server 파일 옮기기
# cmd에서 입력
nox_adb push [frida-server 경로] /data/local/tmp/
4) frida-server 실행하기
nox_adb shell # 녹스 shell 접속
cd /data/local/tmp
mv frida-server-16.2.1-android-x86 frida-server
chmod 777 frida-server
frida-server & # frida-server를 백그라운드로 실행
5) 프로세스 확인
frida-ps -U 명령어를 통해 USB 장치에서 실행중인 프로세스들을 확인할 수 있습니다.
6) APK Decompiler
디컴파일러는 jadx-gui를 사용하였습니다.
🚩Exploit
Reference
- Frida HandBook : https://learnfrida.info/basic_usage/#an-overview-of-frida-api
풀이에 앞서, frida를 이용해서 script를 실행할 수 있는 python skeleton code를 참고했습니다.
실제로 풀이를 진행할때는 js로 작성한 코드를 frida로 실행했습니다.
Frida 기본 명령어
frida -U -f [패키지명] -l hooking.js
- -U : Frida를 USB로 연결된 장치에 연결하도록 지시합니다.
- -f [패키지명] : Frida에게 지정된 패키지명의 앱을 강제로 시작하도록 합니다.
- -l : 스크립트를 사용할 때 스크립트 경로를 지정합니다.
Python Skeleton Code
import frida, sys
def on_message(message, data):
print(message)
# Hooking 할 어플리케이션의 package 명
PACKAGE_NAME = "owasp.mstg.uncrackable1"
jscode = """
console.log("[+] Start Script");
Java.perform(function() {
console.log("[+] Hooking System.exit");
var exitClass = Java.use("java.lang.System");
exitClass.exit.implementation = function() {
console.log("[+] System.exit called");
}
});
"""
process = frida.get_usb_device(1).attach(PACKAGE_NAME)
script = process.create_script(jscode)
script.on('message', on_message)
print('[+] Running Hook')
script.load()
sys.stdin.read()
📖 FridaLab 1) 클래스 challenge_01의 변수 'chall01'을 1로 변경하기
MainActivity 클래스에 존재하는 onCreate 메소드를 확인하면 findviewById를 사용해서 check라는 ID를 가진 버튼을 찾고, 이 버튼에 ClickListener를 설정합니다. 클릭 이벤트가 발생하면 Listener 안에 정의된 onClick 메소드가 실행됩니다.
Challenge 01과 관련된 코드를 살펴보면 challenge_01.getChall01Int() == 1 을 만족하면 문제를 해결할 수 있습니다.
challenge_01 클래스를 확인하면 chall01 변수가 static int로 정의되어 있습니다.
이 값을 1로 만들기 위해서 아래와 같은 코드를 작성할 수 있습니다.
console.log("[+] Start Script");
Java.perform(function() { // 현재 스레드가 가상 머신에 연결되어 있는지 확인하고 함수를 호출
var challenge_01 = Java.use("uk.rossmarks.fridalab.challenge_01"); // challenge_01 클래스 객체를 반환
challenge_01.chall01.value = 1; // challenge_01 클래스의 chall01 인스턴스의 값을 1로 변경
console.log("[+] chall01 Complete !");
});
📖 FridaLab 2) chall02() 실행하기
MainActivity에 chall02() 함수가 정의되어 있습니다.
static으로 함수를 선언하면 함수가 메모리에 올라갈 때 정적 함수를 자동으로 생성해주기 때문에 Java.use() 함수로 메모리에 있는 정적 함수를 가져올 수 있지만, static으로 선언하지 않으면 정적 함수가 자동으로 생성되지 않기 때문에, 이 함수를 실행하려면 이 함수를 가지고 있는 인스턴스를 직접 찾아서 함수를 실행시켜줘야 합니다.
@minmoong
따라서 다음과 같이 chall02() 함수를 가지고 있는 MainActivity의 인스턴스를 찾고, 해당 함수를 실행시킬 수 있습니다.
console.log("[+] Start Script");
Java.perform(function (){
Java.choose("uk.rossmarks.fridalab.MainActivity", { // 찾고자 하는 인스턴스
onMatch : function(instance) { // 인스턴스를 찾았을 경우 해당 인스턴스를 인자로 받음
instance.chall02();
},
onComplete: function() { // 인스턴스 찾기가 완료되었을 경우
console.log("[+] chall02 Complete !");
}
});
})
📖 FridaLab 3) chall03()이 true를 반환하도록 만들기
MainActivity에 정의된 chall03() 함수는 기본적으로 false를 반환합니다.
이 반환값을 true로 만들기 위해서는 메소드의 구현 내용을 재작성 해야합니다.
console.log("[+] Start Script");
Java.perform(function() {
var MainActivity = Java.use("uk.rossmarks.fridalab.MainActivity");
// MainActivity내 chall03 메소드의 구현 내용을 implementation을 이용하여 재작성
MainActivity.chall03.implementation = function() {
return true;
}
console.log("[+] chall03 Complete !");
})
📖 FridaLab 4) "frida"를 chall04()에 보내기
console.log("[+] Start Script");
Java.perform(function (){
Java.choose("uk.rossmarks.fridalab.MainActivity", {
onMatch : function(instance) {
instance.chall04("frida");
},
onComplete: function() {
console.log("[+] chall04 Complete !");
}
});
})
📖 FridaLab 5) 항상 "frida"를 chall05()에 보내기
console.log("[+] Start Script");
Java.perform(function (){
var MainActivity = Java.use("uk.rossmarks.fridalab.MainActivity");
MainActivity.chall05.implementation = function(str) {
var str = "frida"
this.chall05(str)
}
console.log("[+] chall05 Complete !");
})
📖 FridaLab 6) 올바른 값을 가지고 10초 후에 chall06() 실행하기
console.log("[+] Start Script");
Java.perform(function() {
var challenge_06 = Java.use("uk.rossmarks.fridalab.challenge_06")
setTimeout(() => {
Java.choose("uk.rossmarks.fridalab.MainActivity",{
onMatch: function(instance){
instance.chall06(challenge_06.chall06.value);
},
onComplete: function(){
console.log("[+] chall06 Complete !");
}
})
}, 11000)
})
📖 FridaLab 7) check07Pin()에 Bruteforce를 수행하고 chall07()로 확인하기
console.log("[+] Start Script");
Java.perform(function() {
var challenge_07 = Java.use("uk.rossmarks.fridalab.challenge_07")
for (let i = 1000; i < 10000; i++) {
if (challenge_07.check07Pin(String(i))) {
Java.choose("uk.rossmarks.fridalab.MainActivity", {
onMatch: function(instance) {
instance.chall07(String(i))
},
onComplete: function() {
console.log("[+] chall07 Complete !");
}
})
}
}
})
📖 FridaLab 8) 'check' 버튼의 텍스트 값을 'Confirm'으로 변경하기
console.log("[+] Start Script");
Java.perform(function (){
var Button = Java.use("android.widget.Button");
Java.choose("uk.rossmarks.fridalab.MainActivity", {
onMatch: function(instance) {
var check = instance.findViewById(0x7f07002f);
var check_button = Java.cast(check, Button);
var str = Java.use('java.lang.String')
check_button.setText(str.$new('Confirm'))
},
onComplete: function() {
console.log("[+] chall08 Complete !");
}
})
})
'📖 Study > Android' 카테고리의 다른 글
앱을 설치했을 때 아이콘이 보이지 않는 경우 (feat. intent-filter) (0) | 2024.04.03 |
---|---|
Backtrace (with Frida) (0) | 2024.03.21 |
APK 리패키징 (Android 11 이상) (0) | 2024.03.21 |
댓글
이 글 공유하기
다른 글
-
앱을 설치했을 때 아이콘이 보이지 않는 경우 (feat. intent-filter)
앱을 설치했을 때 아이콘이 보이지 않는 경우 (feat. intent-filter)
2024.04.03 -
Backtrace (with Frida)
Backtrace (with Frida)
2024.03.21 -
APK 리패키징 (Android 11 이상)
APK 리패키징 (Android 11 이상)
2024.03.21