ABOUT ME

Today
Yesterday
Total
  • [Frida] FridaLab 1~8 풀이
    Learning/Android 2023. 12. 16. 23:04

    프리다랩을 풀어보았고 최대한 다른 풀이를 보지 않고 풀었다. 8번은 도저히 모르겠어서 풀이를 참고했다...

     


    1번

    challenge_01 클래스의 변수인 chall01의 값을 1로 바꿔야 한다.

     

    해당 문제의 코드부분이다. 내부에서 선언된 변수를 바로 return 해주는 것을 볼 수 있다.

    setImmediate(function() {
    	Java.perform(function() {
    		console.log("[*] Script start"); 
    		
    		let challenge_01 = Java.use("uk.rossmarks.fridalab.challenge_01");
    		challenge_01["getChall01Int"].implementation = function () {
    			challenge_01.chall01.value=1;
    			let result = this["getChall01Int"]();
    			console.log(`challenge_01.getChall01Int result=${result}`);
    			return result;
    		};	
    		
    		console.log("[*] Script finish");
    	});
    });

    Java.use를 사용해 challenge_01 클래스를 불러왔고, implementation을 이용해 getChall01Int 메서드를 수정해서 문제를 풀었다. 

    1번 끝!


    2번

    스크롤을 살짝만 올려보면 문제를 볼 수 있다.

    chall02()를 실행하면 되는 정말 간단한 문제이다.

    chall02()는 메인액티비티 내에 정의되어 있다.

     

    액티비티가 실행될 때 맨 처음 실행되는 로직인 onCreate를 살펴보면 그 어디에도 chall02 메서드를 호출하는 곳이 없다.

    우리가 직접 실행시켜줘야한다.

     

    setImmediate(function() {
    	Java.perform(function() {
    		console.log("[*] Script start"); 
    		
    		Java.choose("uk.rossmarks.fridalab.MainActivity", {
    			onMatch: function(instance) {
    				console.log("Run chall02()");
    				instance.chall02();
    			},
    		});
    		
    		
    		console.log("[*] Script finish");
    	});
    });

    Java.choose를 사용해 문제를 풀었다.

     

    Java.choose()와 Java.use의 용도 차이가 있다.

    간단히 정리하면 static으로 돼있는 메서드는 메모리에 올라오므로 Java.use()를 사용하고,

    그렇지 않으면 힙에서 인스턴스화 된 객체를 찾는 Java.choose()를 이용한다.

     

     

    실행시킬 때 나는 TypeError 에러는 왜 뜨는지 찾지를 못했다...

    그래도 2번 끝!


    3번

    3번은 chall03()의 반환값을 true로 만들어야한다.

    chall03은 2번 문제와 마찬가지로 메인 액티비티에 정의되어 있다.

     

    setImmediate(function() {
    	Java.perform(function() {
    		console.log("[*] Script start"); 
    		
    		Java.choose("uk.rossmarks.fridalab.MainActivity", {
    			onMatch: function(instance) {
    				instance.chall03.implementation = function() {
    					return true;
    				}
    			},
    		});
    		
    		console.log("[*] Script finish");
    	});
    });

    풀이는 2번 문제와 다를 바가 없다!

     

     

     

    3번도 끝!

     


    4번

    4번은 chall04()의 인자로 "frida"를 보내줘야 한다.

    chall04는 메인액티비티에 있고 그렇다면 코드는 달라질 부분이 크게 없다

     

    setImmediate(function() {
    	Java.perform(function() {
    		console.log("[*] Script start"); 
    		
    		Java.choose("uk.rossmarks.fridalab.MainActivity", {
    			onMatch: function(instance) {
    				console.log("call chall04(\"frida\")");
    				instance.chall04("frida");
    			}
    		});
    		
    		console.log("[*] Script finish");
    	});
    });

     

    4번도 끝!


    5번

    5번문제는 chall05() 메서드의 인자로 "frida"를 항상 보내주어야 한다.

     

    메인 액티비티의 onCreate 부분을 보면 check 버튼이 클릭될 때마다 chall05 메서드의 인자로 "notfrida!"를 넘겨주는 것을 볼 수 있다.

     

    chall05 메서드는 인자가 frida가 넘어와야 문제가 풀린다.

     

    setImmediate(function() {
    	Java.perform(function() {
    		console.log("[*] Script start"); 
    		
    		Java.choose("uk.rossmarks.fridalab.MainActivity", {
    			onMatch: function(instance) {
    				console.log("send frida to chall05");
    				setInterval(() => instance.chall05("frida"), 0);
    			}
    		});
    			
    		console.log("[*] Script finish");
    	});
    });

    setInterval 함수를 이용해 0ms마다 chall05("frida")를 호출하도록 했다.

    근데 적으면서 생각해보니까 오버로딩과 implementation을 이용해서 함수 자체를 바꿔버려도 됐을 것 같다.

     

    아암튼 5번해결

     


    6번

    6번 문제는 chall06 메서드를 10초 후에 알맞은 값을 인자로 넘기며 호출해야한다.

     

    challenge_06 클래스는 위 사진이다.

     

     

    1. startTime 메서드에서 실행된 시간을 timeStart라는 변수에 저장한다.

    2. addChall06 메서드에서 chall06의 값이 항상 바뀐다.

    3. confirmChall06 메서드에서 메서드가 실행된 시간과 timeStart의 차이가 10000ms(10초) 넘게  차이나는지 확인한다.

    4. 3번 과정에서 1초마다 바뀌는 chall06과 인자로 넘어온 값을 비교한다

     

    메인액티비티를 봐보자!

    onCreate 내부

    1. onCreate에서 challenge_06.startTime()을 실행시킨다.

    2. 1초마다 addChall06 메서드의 인자로 랜덤값이 들어간다.

     

    정석적인 풀이는 실행 후 10초가 지난 시점에 해당하는 i의 값을 알맞게 넘겨주는 것임이 틀림없다

    요점은 10초후 실행과 알맞은 i의 값이다.

     

     

    검증 로직을 다시 봐보자.

    chall06변수는 뭐 후킹해서 값을 바로 가져오면되고,

    timeStart와 현재 시간을 비교하기 때문에 timeStart의 값만 바꿔준다면 바로 실행해도 10초후에 실행시킨 것처럼 할 수 있다.

     

    이를 바탕으로 코드를 짜보자!

     

    setImmediate(function() {
    	Java.perform(function() {
    		
    		console.log("[*] Script start"); 	
    		var challenge06 = Java.use("uk.rossmarks.fridalab.challenge_06");
    		
    		Java.choose("uk.rossmarks.fridalab.MainActivity", {
    			onMatch: function(instance) {		
    				challenge06.addChall06.implementation = function (i) {
    					challenge06.timeStart.value = -10000;
    					this.addChall06(i);
    				};
    
    				console.log("call chall06");
    				instance.chall06(Number(challenge06.chall06.value));
    			},
    			onComplete: function(instance) {
    			}
    		});	
    		
    		console.log("[*] Script finish");
    	});
    });

     

    우선 Java.choose를 사용해 메인 액티비티를 불러온다

    그 후 addChall06.implementation을 사용해 timeStart 변수의 값을 -10000으로 만들어준다.

    세팅을 마쳤다면 instance.chall06(Number(challenge06.chall06.value))을 바로 실행시켜준다.

    그렇게 된다면 chall06의 변수는 우리가 후킹했기 때문에 i==chall06이 통과되고,

    timeStart도 -10000으로 바꿨기 때문에 currentTimeMillis()는 timeStart + 10000 보다 무조건 클 수밖에 없다.

     

    프리다를 할수록 잔머리만 늘어가는 것 같다.

    6번도 끝!


    7번

    7번은 check07Pin()에 대한 알맞은 값을 브루트포싱 해야한다.

    출제자의 의도는 브루트포싱이지만,,,,, 난 값을 후킹해서 바로 넣어줬다.

     

    6번 문제의 의도는 setTimeout 함수를 이용해서 10초 뒤에 함수를 실행시키는 것이었지만 얼렁뚱땅 풀었으니 뭐....

     

     

    challenge_07 클래스다

    setChall07 메서드에서 chall07에 대한 값을 세팅해준다. 세팅값은 랜덤 숫자 4자리이다

    그리고 검증은 check07Pin 메서드에서 진행한다.

     

    메인 액티비티에서는 check07Pin의 반환값에 따라서 정답인지 아닌지 판단한다.

    그냥 후킹 걸어서 return true를 하도록 할수도 있겠지만,,, 너무 간단하니 다른 방법을 사용했다

    setImmediate(function() {
    	Java.perform(function() {
    		
    		console.log("[*] Script start"); 	
    		
    		let challenge_07 = Java.use("uk.rossmarks.fridalab.challenge_07");
    
    		challenge_07["setChall07"].implementation = function () {
    			console.log(`challenge_07.setChall07 is called`);
    			this["setChall07"]();
    			Java.choose("uk.rossmarks.fridalab.MainActivity", {
    				onMatch: function(instance) {
    					instance.chall07(String(challenge_07.chall07.value));
    				},
    				onComplete: function(instance) {
    				}
    			});
    		};
    		
    		console.log("[*] Script finish");
    	});
    });

     

    setChall07.implementation을 이용해 setChall07을 실행시키며 메인액티비티의 chall07 메서드를 바로 호출했다.

     

    7번도 끝!

     


    8번

    8번 문제는 우리가 매번 누르던 CHECK 버튼의 텍스트 내용을 Confirm으로 바꿔야한다.

     

    메인액티비티에서 findViewById로 CHECK 버튼의 인스턴스를 가져와 텍스트 값이 Confirm과 같은지 확인한다.

     

    check 버튼에 대한 id는 0x7f07002f이다

     

    setImmediate(function() {
    	Java.perform(function() {
    		
    		console.log("[*] Script start"); 	
    
    		Java.choose("uk.rossmarks.fridalab.MainActivity", {
    			onMatch: function(instance) {
    				var Button = Java.use('android.widget.Button');
    				var checkid = instance.findViewById(0x7f07002f);
    				var check = Java.cast(checkid, Button);
    				var string = Java.use('java.lang.String');
    				check.setText(string.$new("Confirm"));
    			},
    			onComplete: function(instance) {
    			}
    		});
    		console.log("[*] Script finish");
    	});
    });

    우선 자바의 버튼 클래스를 가져온다

    그리고 findViewById를 이용해 check 버튼에 대한 인스턴스를 가져와 버튼 클래스로 캐스팅 한다

    마지막으로 자바의 문자열 클래스에서 문자열을 만들어서 넣어준다.

     

    8번도 끝났다!


    프리다를 해보고 싶었지만 어렵겠지 하는 막연한 불안감에 시작을 못하고 있었다.

    같은 동아리를 하는 누나의 기초 강의를 듣고 프리다를 시작할 수 있게 되었으며 프리다랩까지 풀게 되었다!!

    생각보다 너무 재밌어서 계속 틈틈이 공부해볼 생각이다.

     

    좀만 빨리 알았더라면 우리은행 모의해킹 대회에서 더 좋은 결과를 받을 수 있지 않았을까하는... 조금의 아쉬움이 있다.

    'Learning > Android' 카테고리의 다른 글

    댓글

Hi