seKUrity_Study : Andriod

[andriod 실습] frida lab 5번, 6번

Sapphire. 2023. 4. 29. 19:01

5. Always send "frida" to chall05()

항상 frida 라는 문자열을 chall05에 보내야 하는 것으로 보이며, "항상" 이라는 말이 들어가 있는거 보면 한번만 보내는 것이 아닌 check 버튼을 누를 때마다 frida 라는 문자열을 보내야 하는것으로 파악된다.

 

먼저 chall05 메소드를 확인해 보면,

 

    public void chall05(String str) {
        if (str.equals("frida")) {
            this.completeArr[4] = 1;
        } else {
            this.completeArr[4] = 0;
        }
    }

위 4번과 같이 문자열을 보내는 방식은 동일하지만 else 로 한번더 확인을 해주면서 전송이 계속 되지 않으면 다시 0 값을 반환한다.

여기서 this.chall05() api를 사용하여서 기존의 chall05가 하는 루틴을 그대로 따라가게 되면서 저기에 frida 문자열을 넣어 줘야 한다.

즉, 원래 정상적으로 루틴을 타면서 chall05가 실행될때마다 frida 라는 문자열이 전달되도록 해야한다는 것이다.

기존의 것을 사용하니깐 Java.use를 사용한다.

 

먼저 코드를 작성하기 전에 자바 메소드 오버로딩 개념을 이해해야 한다. (필자도 자바를 배우면서 하는 중이라 이 개념을 몰라서 해매었다.)

 

메소드 오버로딩이란?

메소드 오버로딩이란 같은 이름의 메소드를 중복하여 정의하는 것을 의미합니다.

자바에서는 원래 한 클래스 내의 같은 이름의 메소드를 둘 이상 가질 수  없습니다.

 

하지만 매개변수의 개수나 타입을 다르게 하면, 하나의 이름으로 메소드를 작성할 수 있습니다.

즉, 메소드 오버로딩은 서로 다른 시그니처를 갖는 여러 메소드를 같은 이름으로 정의하는 것이라고 할 수 있습니다.

 

예를 들면 A라는 클래스 내에 B라는 이름을 가진 메서드 3개가 아래와 같이 존재하자고 가정하자

 

1 : B(String str)

2 : B(String str, int num)

3 : B(int num1, int num2)

 

이름이 같은 3개의 메서드들을 각각 호출하기 위해서 매개변수로 구분하여 호출이 가능하다.

 

 

이를 이용하여서 5번을 풀기 위해 코드를 작성하자면,

chall_05.chall05().overload("")를 이용해서 chall05라는 메소드가 매개변수 정보가 다른 이름의 메소드가 존재한다고 가정하여 풀어보겠다. this 키워드를 이용해서 메소드 자신을 호출할때 frida 문자열을 인자에 전달하도록 로직을 재작성 한다.

setImmediate(function() {
  Java.perform(function() {
    var chall_05 = Java.use("uk.rossmarks.fridalab.MainActivity");
    chall_05.chall05.overload("java.lang.String").implementation = function(arg) {
        this.chall05("frida");
        console.log("\n5번 전달 성공");
    }
  })
})

인자 값이 받는것이 있으니 arg를 이용해서 값을 전달 해 주었다.

 

성공


6. Run chall06() after 10 seconds with correct value

올바른 값으로 10초 후에 chall06()의 메서드를 실행해야 하는것으로 보인다.

즉, 라이브 변수를 조작해야 한다는 뜻이다.

 

먼저 mainactivity의 chall06() 을 확인해 보자

    public void chall06(int i) {
        if (challenge_06.confirmChall06(i)) {
            this.completeArr[5] = 1;
        }
    }

chall06 메서드에 임의의 정수형 값을 주고 if문 내의 challenge_06 클래스 내의 confirmChall06(i)의 인자값과 동일해지면 해결되는 문제로 파악된다.

 

confirmChall06을 더블클릭해 해당 메소드로 이동하여 확인 할 수 있다.

package uk.rossmarks.fridalab;

/* loaded from: classes.dex */
public class challenge_06 {
    static int chall06;
    static long timeStart;

    public static void startTime() {
        timeStart = System.currentTimeMillis();
    }

    public static boolean confirmChall06(int i) {
        return i == chall06 && System.currentTimeMillis() > timeStart + 10000;
    }

    public static void addChall06(int i) {
        chall06 += i;
        if (chall06 > 9000) {
            chall06 = i;
        }
    }
}

코드를 확인해 보니 

 

i == chal06 && System.currentTimeMillis() > timeStart + 10000;

 

i 값과 chall06 값이 같으면서 메서드가 시작된 지 starttime이 10초가 지나면 참값을 반환한다

 

해결하기 위해서 setTimeout()을 이용할 것이다.

 

setTimeout(function, delay)
delay 값에 전달되는 시간만큼 지연된 후 function 콜백 함수를 호출한다.

 

delay에 시간을 10초 주어서 해당 시간이 지난 후에 fuction에 작성한 로직이 실행 될수 있도록 할것임

 

그다음 challenge_06 클래스의 confirmChall06 메서드를 항상 true 로 반환되도록 만든 수 MainActivity 인스턴스로 chall06을 호출하면 문제 해결.

 

chall06을 호출 할때는, int형 인자값을 받기 때문에 아무 숫자나 넣으면 해결된다!

 

setTimeout(function(){ 
	console.log("\n 10 seconds later...");
	setImmediate(function(){
		Java.perform(function(){
			let challenge_main;
			Java.choose("uk.rossmarks.fridalab.MainActivity", {
				onMatch: function(instance) {
					challenge_main = instance;
					const chall_06 = Java.use("uk.rossmarks.fridalab.challenge_06");
					chall_06.confirmChall06.implementation = function () {
						console.log("\n6번 문제 해결");
						return true;
					}
					challenge_main.chall06(1);
				},
				onComplete: function() {}
			});
		})
	})
}, 10000);