안녕하세요! 저번시간에는 Nox&Frida 설치 에 대하여 포스팅 했습니다. 이번시간엔 FridaLab 문제 1~8번까지 풀이를 진행해보려고 합니다! 우선 FridaLab 이란 Frida툴을 연습할수 있도록 만든 APK입니다! FridaLab어플의 소스코드를 분석하여 저희가 원하는 동작을 하도록 유도하는 것이 이번 포스팅의 목표입니다!
※만약 Nox&Frida 설치가 안되셨다면 밑에 링크를 통하여 설치를 진행하고 오셔야 합니다!
[Mobile Hacking] Nox & Frida 설치방법 (환경세팅)
안녕하세요! 이번 포스팅에서는 모바일 앱해킹에서 가장 중요하게 사용되는 Frida 설치 방법에 대하여 알려드리겠습니다. Frida 란? > 모바일 애플리케이션 및 기타 프로그램에서 사용되는 동적
jamesbexter.tistory.com
Nox&Frida 설치가 완료되셨다면 시작전 준비물을 두가지입니다.
- FridaLab(분석할 어플)
- Jadx(디컴파일러)
1. FridaLab
저희가 분석할 어플인 FridaLab은 밑에 링크에서 다운로드 받으실 수 있습니다. 다운로드 받으신 후 nox 앱플레이어에 드래그 앤 드롭 하시면 nox에 설치하실수 있습니다! 즉 로컬컴퓨터에 하나 Nox에뮬레이터에 하나 , 총 두군데에 FridaLab이 설치되어있어야 합니다!
https://rossmarks.uk/blog/fridalab
2. Jadx
Jadx란 디컴파일러 도구입니다. 디컴파일러란 저희가 코틀린이나 자바로 어플을 만들었다면 역으로 짰던 코드를 다시 뜯어볼수 있게만드는 행위입니다. 우선 Jadx로 FridaLab이라는 어플이 어떻게 이루어졌는지 뜯어보고 그 소스코드를 활용하여 Frida를 통해 저희가 원하는 동작을 유도할 것입니다!
Jadx는 아래 링크를 통하여 다운로드 받으실 수 있습니다.
https://github.com/skylot/jadx/releases
↓ 아래처럼 zip파일을 받은후 압축을 풀어주세요!
<본격적인 문제풀이 돌입!>
문제풀이를 위해서 cmd 창에서 다음 명령어를 차례대로 작성하여 frida-server를 실행합니다. 이 frida-server를 통해 저희가 실행을 유도할 스크립트 구문을 frida를통해 nox로 넣어줄수가 있습니다. 이렇게 frida-server를 실행시킨후 , 스크립트를 삽입해줄 또 다른 프롬프트창을 켜주시면 준비가 완료됩니다.
>> nox_adb shell (nox 에뮬레이터에 명령어창으로 접근합니다)
>> su (지금부터 관리자 권한으로 명령어를 실행합니다)
>> cd data/local/tmp (지정된 경로로 이동합니다)
>> ./frida-server & (tmp 폴더에 있는 frida-server 라는 파일을 실행합니다)
※만약 실행하는데 '파일이 아닌 디렉토리'라는 에러가 뜨면 frida-server를 nox에 설치하실때 파일이 아닌 frida-server 라는 폴더안에 frida-server 라는 '파일'이 존재하는 거니깐 폴더안에서 파일을 tmp 폴더로 빼주시고 빈 frida-server 폴더는 삭제해주세요.
이제 Jadx를 실행후 저희가 다운받았던 FridaLab.apk 파일을 열어주세요. 디컴파일링 된 FridaLab 어플의 코드를 확인하실 수 있습니다.
1. FridaLab challenge_01
(1.1) 첫번째 문제는 'challege_01이라는 이름의 클래스의 chall01이라는 변수의 값을 1로 바꿔라' 입니다.
이를 위해서 Jadx에서 challenge_01이라는 클래스를 확인해봅시다.
(1.2) 보니깐 challenge_01클래스에는 static 변수로 chall01 이라는 이름의 변수가 선언이 되어있습니다. 이 선언된 변수의 값을 1로 만들어주면 클리어 됩니다.
(1.3) 이를 위해서 VisualStudio Code 를 통해 js 파일을 생성후 스크립트 코드를 짜줍니다.
//후킹코드 작성
setImmediate(function () {
//challenge 1
Java.perform(function () { //후킹코드는 기본적으로 perform()함수안에 실행할 함수다
let challenge_01 = Java.use('uk.rossmarks.fridalab.challenge_01');
challenge_01.chall01.value = 1;
console.log("Challenge 1 clear!");
});
});
↓ 이런식으로 해줍니다.
setImmediate() => frida는 에뮬레이터의 속도가 느려질경우 frida 연결을 강제종료하는 특성이 있기 때문에 이를 방지하기 위하여 선언하여 줍니다.
Java.perform() => 'APK에 써있는 클래스나 static 변수등 필요한 부분들을 메모리에 올린후' 안에 써진 스크립트 코드를 실행합니다. 이를 안써줄 경우 class 가 메모리에 올려지기도전에 Java.use를 통하여 패키지에서 클래스를 불러오게 되면 메모리에 올라가기 전이니 클래스를 불러오는데 실패하게 됩니다.
Java.use() => uk.rossmarks.fridalab라는 패키지에서 challenge_01이라는 클래스를 메모리에서 가져온후 'challenge_01'라는 객체에 넣어줍니다. 이를통해 저희는 challenge_01 클래스에 접근할 수 있게됩니다.
challenge_01.chall01.value =1 => challenge_01이라는 클래스에서 chall01이라는 변수의 값을 1로 지정합니다.
(1.4) Dos창에서 작성된 스크립트를 frida 를 통해 삽입한 후 FridaLab을 실행시키는 명령어를 작성해줍니다. 이후 " Challenge 1 clear! " 라는 메시지가 출력이 된다면 성공한겁니다! 만약 안뜨신다면 위에 frida서버를 관리자권한으로 실행시키지 않았거나 , 경로에 한글이 포함되었거나 , 스크립트 코드가 틀렸거나 , 명령어가 틀렸거나 중에 하나일 가능성이 높습니다.
>> frida -U FridaLab -l "스크립트 파일의 경로"
(FridaLab 이라는 프로그램을 실행시킬때 "스크립트 파일의 경로" 에 있는 파일을 로드한다)
Check 버튼을 클릭! | 1번 문제 클리어 확인 |
![]() |
![]() |
이번 문제에서 배워가야 할 점은 다음과 같습니다
1. "선언된 변수의 값을 바꿔서 실행하는 법"
2. FridaLab challenge_02
(2.1) 두번째 문제는 chall02() 라는 함수를 실행시키면 되는것 같습니다.
(2.2) chall02() 라는 함수가 무엇인지 Jadx로 확인해봅시다. 보니깐 MainActivity 클래스에 void로 선언되어있는 chall02() 함수를 실행시켜야 하는것 같습니다. 위에 문제와 다른점은 이번엔 static 이 아니라 기본 void 함수로 선언이 되어있습니다. 그래서 이번엔 조금 다르게 접근해야합니다.
(2.3) 문제 해결을 위해 스크립트 코드를 짜줍니다.
setImmediate(function () { // 자바가 느려져서 꺼지는걸 방지.
//challenge 1
Java.perform(function () { //후킹코드는 기본적으로 perform()함수안에 실행할 함수다
Java.choose('uk.rossmarks.fridalab.MainActivity', { // 일단 MainActivity클래스의 인스턴스를 찾아서 instance함수안에 넣어준다
onMatch: function (instance) { //넣어준 instance를 인자로 함수를 실행!
instance.chall02(); //instance에서 참조된 chall02() 라는 함수를 실행한다.
},
onComplete: function () { // 인스턴스찾기가 완료되었을 경우 동작
console.log('challenge 2 clear! haha!'); // challenge2가 클리어 되었다는 메세지를 콘솔창에 출력!
}
});
});
});
Java.choose => uk.rossmarks.fridalab.MainActivity 에 해당하는 클래스의 인스턴스를 찾습니다.
(보통 Java.choose 는 선언된 함수나 변수를 '사용'할때 , Java.use는 선언된 함수나 변수의 값을 '바꾸고 싶을때' 사용하는 것 같습니다)
onMatch => 해당하는 인스턴스를 발견하면 안에 코드를 실행합니다.
onComplete => onMatch 안에 코드가 완료되면 안에 코드를 실행합니다.
※ 참고로 어플을 실행할 시 class 이름과 선언된 static 변수는 실행과 동시에 바로 메모리에 올라가기 때문에(인스턴스가 만들어 지기 때문에) Java.use로 바로 접근이 가능합니다. 하지만 static이 아니라 그냥 void 로 선언된 함수나 변수는 객체에 클래스를 저장한 후 인스턴스화를 거쳐서 접근해야만 합니다. 이 내용이 이해가 안되시면 '기본변수와 Static변수는 무슨차이일까?' 에 대하여 구글에 쳐서 알아두시는게 좋습니다. 즉! 인스턴스를 쓰는상황과 아닌상황 을 구별하실줄 알아야합니다!! 인스턴스가 무엇인지 모르신다면 개발을 안해보셨거나 class에 대하여 정확히 모르는 상태이시니 아래 제 게시물을 참조해주세요!
https://jamesbexter.tistory.com/entry/클래스-객체-인스턴트-확실히-알고-넘어가자-feat붕어빵
클래스 - 객체 - 인스턴트 : 확실히 알고 넘어가자! (feat.붕어빵)
안녕하세요! 오늘은 모바일 앱해킹을 하다가 문득 객체와 인스턴스의 차이점이 궁금해져서 찾아본 내용을 정리해서 전달해 드릴까 합니다! 그 내용은 바로 클래스(Class) , 객체(Object) , 인스턴
jamesbexter.tistory.com
(2.4) 스크립트 코드를 실행해줍니다.
(2.5) 2번째 문제가 클리어 됐습니다!
이번 문제에서 배워가야 할 점은 다음과 같습니다.
1. "작성된 코드의 함수를 frida 로 실행시키는 방법"
2. "static 변수와 기본 변수의 차이"
3. "클래스& 객체 & 인스턴스의 관계"
4. Java.use와 Java.choose 의 용도차이
3. FridaLab challenge_03
(3.1) 세번째 문제는 chall03()함수가 true를 반환하도록 하는것이 목표인것 같습니다.
(2.2) Jadx 로 확인하니 chall03함수는 false를 return 하는 함수입니다. 이 함수를 재작성 해줘야 합니다.
(3.3) 스크립트 코드를 작성합니다. chall03이 true를 반환하도록 합니다.
// 여기에 후킹코드 작성
setImmediate(function () { // 자바가 느려져서 꺼지는걸 방지.
Java.perform(function () { //후킹코드는 기본적으로 perform()함수안에 실행할 함수다
let challenge03 = Java.use('uk.rossmarks.fridalab.MainActivity');
challenge03.chall03.implementation = function () {
return true;
};
console.log('challenge03 very easy!!!');
});
});
challenge03.chall03.implemetation => MainActivity클래스에 있는 chall03 함수의 implementation(내용)을 재구성한다.
※ 여기서 이렇게 재작성해버리면 "기존에 있는 함수가 먼저 실행된 후 재작성된 함수가 실행되기 때문에 클리어 하는거냐" 라고 의문을 가질수 있는데 , 이렇게 실행하면 재작성된 코드만 실행됩니다! 기존의 함수는 실행이 되지않습니다! 기존의 함수를 실행시키고 싶으시면 this.chall05(); 라는 코드를 사용하시면 됩니다. 이 내용은 5번문제에서 다루게 될 것입니다.
(3.4) 작성된 스크립트를 삽입하여 실행합니다.
(3.5) 세번째 문제가 해결되었습니다!!
이번 문제에서 배워가야 할 점은 다음과 같습니다
1. 작성된 함수를 변경하여 사용할 수 있는가.
4. FridaLab challenge_04
(4.1) 4번째 문제는 chall04() 함수에 frida라는 문자열을 보내라고 되어있습니다. 당장엔 무슨 소리인지 모르겠으니 chall04() 함수가 어떻게 이루어진 함수인지 확인해봐야 할 것 같습니다.
(4.2) 아 보아하니 chall04의 입력값으로 frida가 들어오면 클리어 되는 방식인것 같습니다.
(4.3) 이를 위하여 스크립트 코드를 짜줍니다.
// 여기에 후킹코드 작성
setImmediate(function () { // frida가 느려져서 꺼지는걸 방지.
Java.perform(function () { //후킹코드는 기본적으로 perform()함수안에 실행할 함수다
Java.choose('uk.rossmarks.fridalab.MainActivity', {
onMatch: function (instance) {
instance.chall04("frida");
},
onComplete: function () {
console.log('clear challenge4 !!');
}
});
});
});
instance.chall04("frida"); => chall04라는 함수를 frida라는 파라미터를 넣어 실행한다.
(4.4) 작성된 스크립트 코드를 실행합니다.
(4.5) 5번 문제가 해결되었습니다!!
이번 문제에서 배워가야 할 점은 다음과 같습니다.
1. 원하는 파라미터 값을 집어넣어서 함수를 실행시킬수 있는가?
5. FridaLab challenge_05
(5.1) 5번 문제는 chall05() 함수를 항상 frida라는 파라미터값을 넣어서 실행시키게 만드는건가 봅니다.
(5.2) frida를 넣어서 실행시켜야 초록불이 뜨게 만들었나 봅니다. 근데 이러면 4번문제와 같지않을까 하던중...
아..역시 Check버튼을 클릭하면 chall05("notfrida!") 라는 함수가 실행되도록 만들어놓았습니다.. 즉 저희가 4번처럼 "frida"를 넣어서 실행시킨후 체크 버튼을 누르면 "notfrida"로 다시 실행되어 초록불이 안뜰겁니다...
(5.3) chall05() 함수에 "notfrida" 가 들어와도 다시 frida로 고친후 실행시키도록 만들어줍니다.
// 여기에 후킹코드 작성
setImmediate(function () { // frida가 느려져서 꺼지는걸 방지.
Java.perform(function () { //후킹코드는 기본적으로 perform()함수안에 실행할 함수다
let ch5 = Java.use('uk.rossmarks.fridalab.MainActivity');
ch5.chall05.implementation = function (str) {
str = "frida";
this.chall05(str);
};
console.log("clear challgenge5!! ");
});
});
this.chall05(str) => 원래의 chall05함수를 str문자열을 넣어실행합니다. 이때의 chall05()함수는 재작성된 함수가 아닌 원래 작성되었던 함수입니다!
(5.4) 스크립트 코드를 실행하여줍니다.
(5.5) 5번문제가 해결되었습니다!
이번 문제에서 배워가야할 점은 다음과 같습니다.
1. 기존 파라미터값을 원하는 파라미터값으로 바꿔서 실행할 수 있는가?
2. this를 통하여 기존의 함수를 실행할 수 있다.
6. FridaLab challenge_06
(6.1) Chall06()함수를 10초뒤에 올바른 값과 함께 실행하라 입니다... 무슨말인지 잘 모르겠으니 chall06함수가 어찌 작성되어있는지 한번 확인해봐야 합니다..
(6.2.1) 음.. 우선 challenge_06의 클래스파일은 이런식으로 이루어져 있습니다...한번 분석해보죠
[challenge_06 클래스]
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;
}
}
}
- chall06, timeStart 라는 변수가 static으로 선언되어있다..
- startTime을 통해 프로그램이 시작된후 시간이 timeStart변수에 저장이 되나보다..
- confirmChall06(int i) 라는 함수를 통해 ' i의 값과 chall06의 값이 같고' 어플이 시작된지 10초가 넘었으면 true를 반환하는것 같다.
-addChall06(int i) 라는 함수를통해 (i값 + chall06 의 값)을 chall06에 저장한다. 또한 9000이 chall06의 값이 9000을 넘을경우 i의 값으로 chall06의 값을 초기화 한다.
솔직히 이것만 봐선 무슨 문제인지 잘 모르겠습니다. MainActivity 클래스에 chall06() 함수가 있는지 확인해봅시다.
(6.2.2) 코드를 한번 분석해보겠습니다.
[MainActivity 클래스 중 chall06() 관련 부분]
challenge_06.startTime();
challenge_06.addChall06(new Random().nextInt(50) + 1);
new Timer().scheduleAtFixedRate(new TimerTask() { // from class: uk.rossmarks.fridalab.MainActivity.2
@Override // java.util.TimerTask, java.lang.Runnable
public void run() {
int nextInt = new Random().nextInt(50) + 1;
challenge_06.addChall06(nextInt);
Integer.toString(nextInt);
}
}, 0L, 1000L);
- addChall06의 파라미터값으로 정수 1~50 사이의 랜덤값을 넣어준다.
- TimerTask() 함수를 통해 10초에 한번씩 run() 함수안에 있는 코드를 실행시켜줍니다.
(여기서 run 함수는 새로운 쓰레드를 생성하여 독립적으로 시행됩니다. 이게 무슨말이냐면 10초 이후에 코드가 실행되면 다른 동작에 영향을 미칠수 있지만 run 함수안에 있으면 독립적으로 시행되기 때문에 다른 동작에 영향을 미치지 않게됩니다. )
=> 즉 10초에 한번씩 chall06의 값이 바뀌고 있음을 뜻합니다. 이 바뀌는 값을 캐치해주어야 하는것 같습니다.
이후 chall06의 값을 아래사진의 함수의 파라미터값(int i) 로 넣어서 true를 반환시켜야 하는것이 문제의 목적같습니다.
(6.3) 이를 위해 스크립트 코드를 작성하여 줍니다.
setImmediate(function () {
Java.perform(function () { //클래스들을 메모리에 로드해주어야 함. 안그러면 스크립트로 클래스를 못씀
/*challenge5번문제 코드가 써있는데 생략*/
});
});
setTimeout(function () {
//challenge 6
let challenge_06 = Java.use('uk.rossmarks.fridalab.challenge_06');
Java.choose('uk.rossmarks.fridalab.MainActivity', {
onMatch: function (instance) {
let chall06 = challenge_06.chall06.value;
instance.chall06(chall06);
},
onComplete: function () { }
});
console.log("clear challenge_06!!");
}, 10000);
Java.perform => 우선 필요한 class를 메모리에 올려줘야 하기 때문에 실행합니다.
setTimeout => 10초 뒤에 실행시키기 위하여 설정해줍니다. (ms초 단위이기 때문에 10000 작성)
challenge_06.chall.value => 현재 랜덤하게 설정된 값을 바뀌기 전에 chall06에 저장합니다.
instance.chall06(chall06) => 저장한 chall06변수를 파라미터로 chall06()함수를 실행합니다.
(6.4) 작성한 스크립트를 실행합니다. 이후 10초를 기다리면 클리어 메세지가 뜨게됩니다!
(6.5) 6번문제가 해결되었습니다!
이번 문제를 통해 배워갈 점은 다음과 같습니다
1. Java.use 와 Java.choose를 병행하며 사용해보기
2. 원하는 시간에 맞춰서 코드를 실행할 수 있다.
3. run() 을 통해 스크립트 코드를 다른 동작과 독립적으로 실행할 수 있다.
7. FridaLab challenge_07
(7.1) 보아하니 브루트포스(무작위대입)를 통해 check07의 핀번호를 알아낸 후 chall07()함수를 실행하는 것 같습니다.
(7.2.1) 일단 challenge_07 의 클래스는 이렇게 구성되어 있습니다.. 한번 분석해 봅시다!
package uk.rossmarks.fridalab;
/* loaded from: classes.dex */
public class challenge_07 {
static String chall07;
public static void setChall07() {
chall07 = BuildConfig.FLAVOR + (((int) (Math.random() * 9000.0d)) + 1000);
}
public static boolean check07Pin(String str) {
return str.equals(chall07);
}
}
-static 변수로 chall07 선언
-setChall07()함수를 통해 만들어지는 chall07값은 1000~9999사이인것같다.
일단 저희가 구해야할 Pin번호는 1000~9999 사이에 있다는 것을 알 수 있습니다.
(7.2.2) 보아하니 onCreate로 어플이 시작된 후 setChall07() 함수를 통해 Pin번호가 발급되는것 같습니다.
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.activity_main);
/* 이 사이엔 다른 문제 관련 코드여서 생략!*/
challenge_07.setChall07();
}
↓ 이후 Pin번호를 chall07함수에 파라미터값으로 넣고 실행시키면 되는것 같습니다!
(7.3) 브루트포스를 하기 위하여 스크립트 코드르 짜주었습니다.
// 여기에 후킹코드 작성
setImmediate(function () { // frida가 느려져서 꺼지는걸 방지.
Java.perform(function () { //후킹코드는 기본적으로 perform()함수안에 실행할 함수다
let challenge_07 = Java.use('uk.rossmarks.fridalab.challenge_07');
let chall07 = challenge_07.chall07.value;
let i = 1000;
let pin = null;
do {
if (chall07 == i) {
console.log(`PIN PASS : ${i}`);
pin = i;
break;
} else {
i = i + 1;
}
} while (i <= 9999);
if (pin != null) {
Java.choose('uk.rossmarks.fridalab.MainActivity', {
onMatch: function (instance) {
instance.chall07(String(pin));
},
onComplete: function () {
console.log("clear challenge_07");
}
});
} else {
console.log("PIN not found."); // PIN을 찾지 못한 경우
}
});
});
let chall07=challenge_07.chall07.value => Pin번호를 담아둘 변수입니다. Pin번호는 static변수로 선언되어 있기 때문에 이렇게 바로 인스턴스화 없이 가져올 수 있다는 점을 다시한번 명시해드립니다!!
while 문 => 1000부터 9999까지 대입해보면서 chall07과 일치하면 그 값을 pin 변수에 저장 후 break를 통해 빠져나옵니다.
instance.chall07(String(pin))=> chall07() 함수는 static 함수가 아니기 때문에 인스턴스화 하여 실행합니다. 또한 chall07(String str) 형태이기 때문에 Int형인 Pin변수를 문자열로 변환하여 실행해야 합니다.
(7.4) 작성한 스크립트를 실행합니다. 핀번호를 출력후 클리어 된 것을 확인하실수 있습니다!
(7.5) 7번문제가 해결되었습니다!!
이번 문제에서 배워갈 점은 다음과 같습니다.
1. frida를 통한 브루트포스 공격 구현
2. 함수사용시 파라미터값의 타입 맞춰주기
3. 다시한번 강조되는 static과 기존함수의 용도 차이
8. FridaLab challenge_08
(8.1) 마지막 문제입니다! check 버튼의 'check'값을 'Confrim' 으로 바꿔야 하는것 같네요!
(8.2.1) Jadx로 확인해본 결과 체크버튼의 text값을 Confirm으로 바꾸면 되는것 같습니다. 이를 위해선 R.id.check의 id값에 접근할 필요가 있습니다.
(8.2.2) Cntrl + 마우스 를 갖다대면 저렇게 보라색 표시로 해당 내용이 선언된 부분으로 접근할 수 있습니다.
(8.2.3) 접근해보면 이렇게 'R' 이라는 클래스로 이동되는데 , view값들의 id 주소들이 모두 적혀있습니다. 여기서 check의 id주소값인 0x7f07002f를 복사해줍니다.
(8.3) 위에 내용을 활용하여 스크립트를 작성해보겠습니다.
// 여기에 후킹코드 작성
setImmediate(function () { // frida가 느려져서 꺼지는걸 방지.
Java.perform(function () { //후킹코드는 기본적으로 perform()함수안에 실행할 함수다
Java.choose('uk.rossmarks.fridalab.MainActivity', {
onMatch: function (instance) {
Java.scheduleOnMainThread(function () {
let btnclass = Java.use('android.widget.Button');
let view = instance.findViewById(0x7f07002f); //view타입으로 저장
let checkbtn = Java.cast(view, btnclass); //view 타입을 button타입으로 변환
let string = Java.use('java.lang.String'); //JavaString 타입의 빈문자열 생성
checkbtn.setText(string.$new('Confirm'));//settext로 문자열 삽입
});
},
onComplete: function () {
console.log("clear challenge8!!");
}
});
});
});
Java.scheduleOnMainThread => 앱개발을 해보셨으면 아시겠지만 연산을 위한 동작은 메인쓰레드에서 돌아가야 하고 UI를 위한 동작은 UI쓰레드 에서 동작해야 합니다. Check버튼이란 UI의 텍스트값을 바꾸는 행위는 UI동작이므로 Main이 아닌 UI 쓰레드에서 동작하기 위해 써주어야 합니다.
btnclass => check 버튼의 접근후 setText() 함수를 사용하기 위하여 빈 button클래스를 선언해줍니다.
view => findViewById를 통해 위에서 복사한 check버튼의 주소값을 통해 check버튼의 view를 가져옵니다. 여기서 오해하시면 안되는게 view 타입을 가져온거지 아직 view 타입이 버튼 타입이라고는 선언 안해주었습니다. view는 textview,button,edittext 등 어떤것이든 될 수 있는 상태라고 생각하시면 됩니다.
Java.cast(view,btnclass) => view변수에 저장된 view의 타입을 button타입으로 지정해주는 순간입니다. 이를 통해 button클래스의 함수인 setText()를 사용하여 button의 텍스트값을 변경할 수 있게됩니다. (그냥 view 상태일땐 setText가 사용이 안됩니다.)
checkbtn.setText(string.$new('Confirm')) => 체크버튼의 텍스트값을 Confirm 으로 바꿔줍니다. 전 여기서 되게 의아했던게 그냥 "Confirm" 을 삽입하면 되지 왜 굳이 string.$new('Confirm') 라는 번거로운 변환을 사용하지 라고 생각했습니다. 하지만 저렇게 사용해야 하는 이유는 setText안에 들어가는 문자열은 Java String 타입으로써 저희가 흔히 아는 기본 String 이랑은 다른 타입이기 때문에 그렇다고 합니다.
저는 ...코틀린 개발을 하면서 setText사용할때 그냥 setText("안녕하세요") 이런식으로 사용을 했는데 자바로 개발을 했으면 저런식으로 String 변환을 다 해주어야 했던거였습니다!...문제를 풀면서 코틀린이 얼마나 편한 언어인지 다시금 깨닫게 되었습니다 하하...
(8.4) 작성해준 스크립트 코드를 실행합니다!
(8.5) 8번째 문제까지 해결되었습니다!!
이번 문제에서 배워가야 할 점
1. UI(View) 요소에 접근하여 원하는대로 바꿀수 있다.
2. UI요소에 접근할땐 UI쓰레드에서 동작하게끔 조심해야한다
3.Java String 타입과 기본 문자열 타입은 다른 개념이다.
긴 글 읽어주셔서 감사합니다!
'모바일 앱해킹(Android) > Frida Lab' 카테고리의 다른 글
[Mobile Hacking] Nox & Frida 설치방법 (환경세팅) (0) | 2024.10.19 |
---|