이 영역을 누르면 첫 페이지로 이동
SH1R0_0의 기술블로그 블로그의 첫 페이지로 이동

SH1R0_0의 기술블로그

페이지 맨 위로 올라가기

SH1R0_0의 기술블로그

FridaLab

  • 2024.02.20 18:35
  • 📖 Study/Android

 

📌 Intro

이 문서는 Frida 활용 능력을 향상시키기 위해 FridaLab의 Challenge에 대한 Writeup입니다.

FridaLab은 총 8가지의 과제가 존재하며 각각의 과제를 수행한 내용을 본 문서에 상세히 기술하였습니다.

 

FridaLab.apk 실행 화면

 

🎯 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로 변경하기

uk.rossmarks.fridalab.MainActivity

MainActivity 클래스에 존재하는 onCreate 메소드를 확인하면 findviewById를 사용해서 check라는 ID를 가진 버튼을 찾고, 이 버튼에 ClickListener를 설정합니다. 클릭 이벤트가 발생하면 Listener 안에 정의된 onClick 메소드가 실행됩니다.

 

Challenge 01과 관련된 코드를 살펴보면 challenge_01.getChall01Int() == 1 을 만족하면 문제를 해결할 수 있습니다.

 

uk.rossmarks.fridalab.challenge_01

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() 실행하기

uk.rossmarks.fridalab.MainActivity

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를 반환하도록 만들기

uk.rossmarks.fridalab.MainActivity

 

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()에 보내기

uk.rossmarks.fridalab.MainActivity

 

 

 

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()에 보내기

uk.rossmarks.fridalab.MainActivity

 

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() 실행하기

uk.rossmarks.fridalab.MainActivity
uk.rossmarks.fridalab.challenge_06

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()로 확인하기

uk.rossmarks.fridalab.MainActivity
uk.rossmarks.fridalab.challenge_07

 

 

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'으로 변경하기

uk.rossmarks.fridalab.MainActivity

 

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

댓글

이 글 공유하기

  • 구독하기

    구독하기

  • 카카오톡

    카카오톡

  • 라인

    라인

  • 트위터

    트위터

  • Facebook

    Facebook

  • 카카오스토리

    카카오스토리

  • 밴드

    밴드

  • 네이버 블로그

    네이버 블로그

  • Pocket

    Pocket

  • Evernote

    Evernote

다른 글

  • 앱을 설치했을 때 아이콘이 보이지 않는 경우 (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
다른 글 더 둘러보기

정보

SH1R0_0의 기술블로그 블로그의 첫 페이지로 이동

SH1R0_0의 기술블로그

  • SH1R0_0의 기술블로그의 첫 페이지로 이동

검색

메뉴

  • 홈
  • 태그
  • 방명록

카테고리

  • 분류 전체보기 (33)
    • 📖 Study (11)
      • Crypto (0)
      • WebHacking (3)
      • Reversing (0)
      • Pwnable (1)
      • Develop & CS (1)
      • Android (4)
      • Etc (2)
    • 🚩 CTF Writeup (14)
      • SSTF 2023 (8)
      • osu!gaming CTF 2024 (2)
      • WxMCTF '24 (4)
      • KalmarCTF 2024 (0)
    • 🎮 Dreamhack Writeup (8)
      • Web (7)
      • Pwnable (1)

최근 글

인기 글

댓글

공지사항

  • 공지 - 박민혁 (SH1R0_0)

아카이브

태그

나의 외부 링크

  • 관리자
  • 글쓰기
  • 공부

정보

SHIR0_0의 SH1R0_0의 기술블로그

SH1R0_0의 기술블로그

SHIR0_0

블로그 구독하기

  • 구독하기
  • RSS 피드

방문자

  • 전체 방문자
  • 오늘
  • 어제

티스토리

  • 티스토리 홈
  • 이 블로그 관리하기
  • 글쓰기
Powered by Tistory / Kakao. Copyright © SHIR0_0.

티스토리툴바