FridaLab apk Files
풀이참조
FridaLab.apk
Check 버튼 클릭 시, 챌린지 클리어 : 초록색, 미해결 챌린지 : 빨간색
Challenge 01
EN :
Change class challenge_01's variable 'chall01' to: 1KOR :
클래스 challenge_01의 변수 'challenge01'을 1로 변경해라.
우선 문제들을 풀기 위해선 해당 apk파일 (FridaLab.apk) 을 디컴파일할 필요가 있다. 챌린지 클리어를 위해 디컴파일 툴인 jdax 툴을 이용하여 디컴파일을 수행하였다.
Windows Choco Install : choco install jadx
먼저 이번 챌린지는 challenge01 에 대한 문제이므로, 해당 객체를 찾아보았다.
challenge_01 문제의 의도는 apk 파일 내부 클래스 변수에 대한 값 변조가 가능하냐 묻는 문제이다. 챌린지 해결을 위해서 해야할 일은 challenge_01 이라는 클래스 내부에 존재하는 chall01 의 값을 1로 변경해주는 것이다.
챌린지 해결을 위해 python 으로 해당 변수를 조작하는 코드를 짜서 실행하였다.
# Frida 함수 사용을 위한 프리다 선언
import frida
# Java.use 를 통해 해당 어플리케이션 내부 클래스를 변수로 가져오기
## Java.use(classname) 은 특정 클래스를 로드하는 명령
jscode ="""
Java.perform(function() {
var challenge_01 = Java.use('uk.rossmarks.fridalab.challenge_01');
// chall01값 1로 선언
challenge_01.chall01.value = 1;
});
"""
# 프로세스 변수로 frida usb device (연결된 디바이스) 실행
process = frida.get_usb_device().attach('FridaLab')
script = process.create_script(jscode)
script.load()
challenge_01.py
해당 코드 실행 이후, 기기의 CHECK 버튼 클릭시 1번 문제가 초록색으로 바뀌는 것을 확인할 수 있다.
Challenge 02
EN :
Run chall02()KOR :
chall02() 실행해라.
문제 그대로 chall02() 함수를 실행시키면 풀리는 챌린지다. 그럼 FridaLab
에서 chall02() 가 뜻하고 있는 것이 무엇인가 확인해보자.
안드로이드 UI 구성을 위해 가장 기본이 되는 요소는 바로 Activity 라는 것 이다. 이 요소는 안드로이드 어플리케이션을 화면 UI 로 표시하기 위해선 최소 1개 이상을 가져야 하고, 사용자가 원하는 특정 어플리케이션 실행 시 지정된 Activity 를 실행해 사용자에게 UI를 표시해준다. 그 중에서 현재 FridaLab.apk 에 존재하는 chall02() 가 위치한 MainActivity 는 어플리케이션 실행 시 최초로 보여지는 Activity 다. (안드로이드 스튜디오에서 생성되는 템플릿 코드로 어플리케이션 실행 시 최초 실행하도록 기본 지정됨)
다시 문제로 돌아가 chall02() 를 살펴보자. 우선 해당 클래스 변수는 MainActivity 에 위치하여 선언되어 있으나, 다른 내부 어디에서도 호출되지 않고 있다.
추가적으로 1번과는 다르게 해당 함수는 static-인스턴스를 사용하지 않음 -함수가 아니라서 바로 불러서 사용할 수 없다. (use() 함수) 그렇기에 1번에서 사용했던 use() 함수가 아닌 Choose() 함수를 이용해 인스턴스를 호출해야 한다.
# frida 함수 사용을 위한 프리다 선언
import frida
# Java.choose 를 통해 해당 어플리케이션 내부 instance 호출
## Java.choose(classname) 는 메소드가 정적이지 않을 경우, 이용
jscode = """
Java.perform(function() {
var main;
// Java.choose 함수를 이용한 인스턴스 호출
Java.choose('uk.rossmarks.fridalab.MainActivity', {
onMatch: function(instance) {
main = instance;
},
onComplete: function() {}
});
main.chall02();
});
"""
# 프로세스 변수로 frida usb device (연결된 디바이스) 실행
process =frida.get_usb_device().attach('FridaLab')
script = process.create_script(jscode)
script.load()
Challenge_02.py
해당 코드 실행 이후, 기기의 CHECK 버튼 클릭시 2번 문제가 초록색으로 바뀌는 것을 확인할 수 있다.
Challenge 03
EN :
Make chall03() return trueKOR :
chall03() 를 true 로 반환해라.
이번 챌린지의 경우, chall03() 의 반환값을 true로 변환하면 되는 문제이다. 그렇기에 challenge_01 문제와 비슷하게 해당 값에 대한 변경이나 선언만 해주면 풀릴 것이라 예상하였다.
challenge_03 에 해당하는 chall03 은 MainActivity 내부에 선언되어있고, 본래 false 로 선언한다. 해당 값을 변경시켜주기 위해선 overload 라는 것을 진행해야 하는대, 해석 그대로 중복정의를 true 라는 값으로 해주는 것이라 생각했다.
# frida 함수 사용을 위한 프리다 선언
import frida
# Java.choose 를 통해 해당 어플리케이션 내부 instance 호출
## Java.choose(classname) 는 메소드가 정적이지 않을 경우, 이용
jscode = """
Java.perform(function() {
var main;
// Java.choose 함수를 이용한 인스턴스 호출
Java.choose('uk.rossmarks.fridalab.MainActivity', {
onMatch: function(instance) {
main = instance;
},
onComplete: function() {}
});
// overload 함수를 이용한 chall03 반환 값 변경
main.chall03.overload().implementation = function() {
return true;
};
});
"""
# 프로세스 변수로 frida usb device (연결된 디바이스) 실행
## input() 으로 버튼을 누르기 전까지 해당 함수 유효 유보
process = frida.get_usb_device().attach('FridaLab')
script = proces.create_script(jscode)
script.load()
input()
Challenge_03.py
해당 코드 실행하고 기기의 CHECK 버튼 클릭시 3번 문제가 초록색으로 바뀌는 것을 확인할 수 있다. 이때 초록색으로 변경이 완료되면 후킹코드 실행창에서 exit 눌러 종료시켜주자.
Challenge 04
EN :
Send "frida" to chall04()KOR :
chall04() 로 "frida" 를 보내라.
2번 문제와 마찬가지로 main.chall04() 를 호출 한 뒤, 인자로 "frida" 를 입력하면 된다 생각하였고, 이전 코드에서 main.chall04("frida") 를 입력해 해당 챌린지를 풀어내었다. chall04 를 확인하면 이전 3번과 마찬가지로 MainActivity 내부에 존재하며, if문으로만 이루어져 있기 때문에 문자열을 입력하는 것으로 풀이하면 된다.
# frida 함수 사용을 위한 프리다 선언
import frida
# Java.choose 를 통해 해당 어플리케이션 내부 instance 호출
## Java.choose(classname) 는 메소드가 정적이지 않을 경우, 이용
jscode = """
Java.perform(function() {
var main;
// Java.choose 함수를 이용한 인스턴스 호출
Java.choose('uk.rossmarks.fridalab.MainActivity', {
onMatch: function(instance) {
main = instance;
},
onComplete: function() {}
});
// chall04() 문자열로 "frida" 입력
main.chall04("frida")
});
"""
# 프로세스 변수로 frida usb device (연결된 디바이스) 실행
## input() 으로 버튼을 누르기 전까지 해당 함수 유효 유보
process = frida.get_usb_device().attach('FridaLab')
script = proces.create_script(jscode)
script.load()
input()
challenge_04.py
해당 코드 실행하고 기기의 CHECK 버튼 클릭시 4번 문제가 초록색으로 바뀌는 것을 확인할 수 있다. 이 챌린지도 초록색으로 변경이 완료되면 후킹코드 실행창에서 exit 눌러 종료시켜주자.
Challenge 05
EN :
Allways send "frida" to chall05()KOR :
chall05() 로 지속적으로 "frida" 를 보내라.
chall05() 의 인자가 항상 frida가 되어야한다. chall04 에선 한번만 입력해주면 되어야 하기 때문에 일반적으로 선언만 해주었지만 MainActivity 내 선언된 chall05() 를 확인하게 되면 실행할 때 마다 확인하는 것을 볼 수 있다. 그렇기 때문에 항상 chall05("frida") 를 호출되게 해야한다.
# frida 함수 사용을 위한 프리다 선언
import frida
# Java.choose 를 통해 해당 어플리케이션 내부 instance 호출
## Java.choose(classname) 는 메소드가 정적이지 않을 경우, 이용
jscode = """
Java.perform(function() {
var main;
// Java.choose 함수를 이용한 인스턴스 호출
Java.choose('uk.rossmarks.fridalab.MainActivity', {
onMatch: function(instance) {
main = instance;
},
onComplete: function() {}
});
// overload 함수를 이용한 string 문자열 -> chall05로 오버로드 후
// 메소드 내부 chall05("frida") 호출
main.chall05.overload('java.lang.String').implementation = function (arg0) {
this.chall05.overload('java.lang.String').call(this.'frida');
return ;
};
});
"""
# 프로세스 변수로 frida usb device (연결된 디바이스) 실행
## input() 으로 버튼을 누르기 전까지 해당 함수 유효 유보
process = frida.get_usb_device().attach('FridaLab')
script = proces.create_script(jscode)
script.load()
input()
challenge_05.py
해당 코드 실행하고 기기의 CHECK 버튼 클릭시 5번 문제가 초록색으로 바뀌는 것을 확인할 수 있다. 이 챌린지도 초록색으로 변경이 완료되면 후킹코드 실행창에서 exit 눌러 종료시켜주자.
Challenge 06
EN :
Run chall06() after 10 seconds with correct valueKOR :
10초 후 올바른 값으로 chall06() 실행해라
챌린지에 대한 설명을 보기 전에 우선 해당하는 코드를 보자.
우선 chall06() 을 MainActivity 에서 int형 인자를 challenge_06.confirmChall 에 전달하여 confirmChall06(i) 의 결과가 True 일 경우, 해결된다.
때문에 해당 문제 해결을 위해 따로 선언되어있는 challenge_06 을 확인해보면 confirmChall06 메소드는 인자를 받아 현재 시간이 timeStart+10000 보다 클 경우 인자와 chall06 의 값이 동일해야한다.
MainActivity 의 OnCreate() 함수는 challenge_06.startTime() 을 구하게 되고, Timer() 을 새로 설정, 1초가 지날 때마가 무작위(랜덤)로 나온 수를 chall06 에 더해주게 된다. (addChall06) 그렇기에 이번 챌린지를 풀기 위해서 chall06 값을 알아야한다.
# frida 함수 사용을 위한 프리다 선언
import frida
# Java.choose 를 통해 해당 어플리케이션 내부 instance 호출
## Java.choose(classname) 는 메소드가 정적이지 않을 경우, 이용
jscode = """
Java.perform(function() {
// 해당 객체 가져오기
var challenge_06 = Java.use('uk.rossmarks.fridalab.challenge_06')
// overload 함수를 이용한 해당 값 출력하기
challenge_06.addChall06.overload('int').implementation = function (arg0) {
console.log(this.chall06.value);
challenge_06.addChall06.overload('int').call(this, arg0);
return ;
};
});
"""
# 프로세스 변수로 frida usb device (연결된 디바이스) 실행
## input() 으로 버튼을 누르기 전까지 해당 함수 유효 유보
process = frida.get_usb_device().attach('FridaLab')
script = process.create_script(jscode)
script.load()
input()
Challenge_06-data.py
Challenge_05 와 마찬가지로 chall06 값을 증가시키는 addChall06 메소드를 오버라이드 시킨 다음, 본 함수를 호출하며 chall06 값을 출력하도록 짠 코드이다. 때문에 해당 코드를 실행시키고 난 이후, 앱을 종료하고 키게 되면 1초마다 숫자가 출력하게 된다.
해당 값에 대한 확인이 끝났으니 10초뒤에 chall06() 의 인자로 전달하면 된다. 원래대로 하면 10초 이후를 계산해야 하나, 간단한 풀이를 위해 addChall06 이 호출될 때마다 현재 chall06 값을 전달하는 코드로 작성하게 되었다.
# frida 함수 사용을 위한 프리다 선언
import frida
# Java.choose 를 통해 해당 어플리케이션 내부 instance 호출
## Java.choose(classname) 는 메소드가 정적이지 않을 경우, 이용
jscode = """
java.perform(function() {
var main;
Java.choose('uk.rossmarks.fridalab.MainActivity', {
onMatch: function(instance) {
main = instance;
},
onComplete: function() {}
});
// 해당 객체 가져오기
var challenge_06 = Java.use('uk.rossarks.fridalab.challenge_06')
challenge_06.addChall06.overload('int').implementation = function (arg0) {
// overload 함수를 이용한 해당 값 출력하기
console.log(this.chall06.value);
challenge_06.addChall06.overload('int').call(this, arg0);
// chall06 값 전달
main.chall06(this.chall06.value)
return ;
};
});
"""
# 프로세스 변수로 frida usb device (연결된 디바이스) 실행
## input() 으로 버튼을 누르기 전까지 해당 함수 유효 유보
process = frida.get_usb_device().attach('FridaLab')
script = process.create_script(jscode)
script.load()
input()
Challenge_06.py
스크립트 실행 이후 10초가 지난 뒤에 CHECK 버튼을 클릭하면 챌린지가 클리어 된다.
Challenge 07
EN :
Bruteforce check07Pin() then confirm with chall07()KOR :
check07Pin()에 무작위대입을 하고 난 다음, chall07() 로 확인해라
이전 챌린지들과 다르게 해당 문제는 chall07() 에 대한 값이 아닌 check07pin() 을 무작위대입을 해야한다.
setChall07() 을 통해 랜덤으로 1,000 부터 9,999 까지 수를 chall07 에 저장한다. 그렇기에 check07Pin() 으로 chall07 과 인자를 비교해볼 수 있다.
# frida 함수 사용을 위한 프리다 선언
import frida
# Java.choose 를 통해 해당 어플리케이션 내부 instance 호출
## Java.choose(classname) 는 메소드가 정적이지 않을 경우, 이용
jscode = """
// // Java.choose 함수를 이용한 인스턴스 호출
Java.perform(function(){
var main;
Java.choose('uk.rossmarks.fridalab.MainActivity', {
onMatch: function(instance) {
main = instance;
},
onComplete: function() {}
});
// challenge_07 인스턴스 사용, check07Pin 인자로 return 값 True 로
var challenge_07 = Java.use('uk.rossmarks.fridalab.challenge_07')
for (var i = 1000 ; i < 10000 ; i++ ) {
if (challenge_07.check07Pin(i.toString())){
main.chall07(i.toString())
break;
}
}
});
"""
# 프로세스 변수로 frida usb device (연결된 디바이스) 실행
## input() 으로 버튼을 누르기 전까지 해당 함수 유효 유보
process = frida.get_usb_device().attach('FridaLab')
script = process.create_script(jscode)
script.load()
input()
Challenge_07.py
반복문인 for 문을 이용해 1,000 부터 9,999 까지 반복 생성 후, check07Pin 의 인자로 넘겨 return 이 True가 되어 main chall07 을 호출하는 형태로 해당 챌린지 클리어가 가능하다.
Challenge 08
EN :
Change 'check' button's text value to 'Confirm'KOR :
'check' 버튼의 텍스트 값을 'Confrim' 으로 바꿔라
생각 외로 간단한 문제인데, 이 챌린지의 해결을 위해선 안드로이드 UI 함수를 찾아봐야한다.
안드로이드 UI 함수는 Main UI Thread 에서 동작하게 되며, 이 스레드는 안드로이드 시스템 내에서 어플리케이션 프로세스를 실행해주는 역할을 하게 된다. 이는 안드로이드 시스템 내 생성된 Main UI thread 는 화명 구성에 관한 역할을 담당하게 되고 버튼이나 체크박스, 텍스트 뷰 등 UI도구 키트 구성요서를 생성이나 조작하였을 경우 상호작용의 동작을 하게 된다.
때문에 Main Thread 혹은 UI Thread 라고도 하게 된다.
개념참고
해당 챌린지 해결을 위해선 id 를 통해 view 를 불러와서, button 으로 캐스팅 한 뒤, setText 로 버튼의 텍스트를 수정할 수 있다.
# frida 함수 사용을 위한 프리다 선언
import frida
# Java.choose 를 통해 해당 어플리케이션 내부 instance 호출
## Java.choose(classname) 는 메소드가 정적이지 않을 경우, 이용
jscode = """
// Java.choose 함수를 이용한 인스턴스 호출
Java.perform(function(){
var main;
Java.choose('uk.rossmarks.fridalab.MainActivity', {
onMatch: function(instance) {
main = instance;
},
onComplete: function() {}
});
// 'check' 에 해당하는 id, 버튼 (객체), 체크박스, 체크 버튼 불러온 후 변경
var id = main.findViewById(2131165231);
var button = Java.use('android.widget.Button');
var checkButton = Java.cast(id, button);
var string = Java.use('java.lang.String');
checkButton.setText(string.$new('Confirm'));
});
"""
# 프로세스 변수로 frida usb device (연결된 디바이스) 실행
## input() 으로 버튼을 누르기 전까지 해당 함수 유효 유보
process = frida.get_usb_device().attach('FridaLab')
script = process.create_script(jscode)
script.load()
input()
Challenge_08.py
$new 는 java 에서 new 와 같이 생성자를 부르게 된다.
FridaLab_Challenge-Oneque
# frida 함수 사용을 위한 프리다 선언
import frida
# Java.choose 를 통해 해당 어플리케이션 내부 instance 호출
## Java.choose(classname) 는 메소드가 정적이지 않을 경우, 이용
jscode = """
Java.perform (function() {
// Challenge_01
var challenge_01 = Java.use('uk.rossmarks.fridalab.challenge_01');
challenge_01.chall01.value = 1;
// Challenge_02
var main;
Java.choose('uk.rossmarks.fridalab.MainActivity', {
onMatch: function(instance) {
main = instance;
},
onComplete: function() {}
});
main.chall02();
// Challenge_03
main.chall03.overload().implementation = function() {
return true;
};
// Challenge_04
main.chall04("frida");
// Challenge_05
main.chall05.overload('java.lang.String').implementation = function (arg0) {
this.chall05.overload('java.lang.String').call(this,'frida');
return ;
};
// Challenge_06
var challenge_06 = Java.use('uk.rossmarks.fridalab.challenge_06')
challenge_06.addChall06.overload('int').implementation = function (arg0) {
console.log(this.chall06.value);
challenge_06.addChall06.overload('int').call(this,arg0);
main.chall06(this.chall06.value)
return ;
};
// Challenge_07
var challenge_07 = Java.use('uk.rossmarks.fridalab.challenge_07')
for (var i = 1000; i < 10000; i++) {
if (challenge_07.check07Pin(i.toString())) {
main.chall07(i.toString());
break;
}
}
// Challenge_08
var id = main.findViewById(2131165231);
var button = Java.use('android.widget.Button');
var checkButton = Java.cast(id, button);
var string = Java.use('java.lang.String');
checkButton.setText(string.$new('Confirm'));
});
"""
# 프로세스 변수로 frida usb device (연결된 디바이스) 실행
## input() 으로 버튼을 누르기 전까지 해당 함수 유효 유보
process = frida.get_usb_device().attach('FridaLab')
script = process.create_script(jscode)
script.load()
input()
'Tools > Frida' 카테고리의 다른 글
Frida SSL Pinning (0) | 2023.08.24 |
---|---|
Frida - Application Dump (0) | 2023.08.22 |
Frida-iOS-DUMP IPA (0) | 2023.08.22 |
Frida BASIC (0) | 2023.08.22 |
Frida ERROR - SyntaxError: unexpected character (0) | 2022.08.25 |