CTF/리버싱

[HouseplantCTF] Fragile - 리버싱 / Java

SecurityMan 2022. 6. 6. 11:00

 

이번 대회의 리버싱 문제 중 가장 쉬웠던 문제이다.

 

처음엔 뭐 이렇게 쉽나 생각했는데

 

약간 함정이었던게 이 문제를 베이스로 해서 뒤로 갈 수록 더욱더 괴상한 문제들이 나왔었다.

 

철저한 빌드업이었던것..

 

반응형

 

 

문제파일로는 fragile.java 파일이 주어진다.

 

import java.util.*;

public class fragile
{
    public static void main(String args[]) {
        Scanner scanner = new Scanner(System.in);
        System.out.print("Enter flag: ");
        String userInput = scanner.next();
        String input = userInput.substring("rtcp{".length(),userInput.length()-1);
        if (check(input)) {
            System.out.println("Access granted.");
        } else {
            System.out.println("Access denied!");
        }
    }
    
    public static boolean check(String input){
        boolean h = false;
        String flag = "h1_th3r3_1ts_m3";
        String theflag = "";
        if(input.length() != flag.length()){
            return false;
        }
        for(int i = 0; i < flag.length(); i++){
            theflag += (char)((int)(flag.charAt(i)) + (int)(input.charAt(i)));
        }
        return theflag.equals("ÐdØә§å’ÍaèÒÁ¡—");
    }
}

 

fragile.java 파일의 내용을 위와 같다.

 

대충 코드 흐름을 살펴보면

 

사용자에게 입력을 가장 먼저 받고, 입력받은 값을 정제해서 input 변수에 저장한다.

 

그리고 나서 check 함수를 통해서 입력값을 검증하는데

 

여기엔 flag 변수와 theflag 변수가 있다.

 

flag 변수에는 h1_th3r3_1ts_m3 라는 string이 저장되어 있고

 

theflag 에는 아무런 값도 저장되어 있지 않은데

 

아래쪽 for 문을 보면 사용자의 입력인 input 변수에 저장된 값과 flag 변수에 저장된 값을 각각 더해

 

theflag 변수에 결과를 담아주고 있고,

 

마지막으로 theflag 변수가 ÐdØә§å’ÍaèÒÁ¡— 와 똑같은지 비교하고 결과를 return 해준다.

 

 

(가독성을 위한 깔끔한 코드)

 

이런 문제는 사실 간단한데

 

역으로 계산해주면 금방 풀린다.

 

theflag = flag + input 였으니

 

input = theflag - flag 라고 보면 된다.

 

ÐdØә§å’ÍaèÒÁ¡— 에서 h1_th3r3_1ts_m3 를 뺀 값이 우리가 맞춰야할 input 값이 되는것이다.

 

 

java 파일은 eclipse를 이용해서 컴파일 해볼 수 있다.

 

이렇게 코드가 주어지면 컴파일 해보면서 푸는게 가장 편하다.

 

조만간 eclipse 설치 방법에 관한 내용도 포스팅을 해봐야겠다.

 

 

이클립스를 이용해 새로운 자바 프로젝트를 하나 만들어 주고

 

 

새로만든 프로젝트 아래에 패키지를 하나 만들어서 거기 fragile.java 파일을 넣어주면 된다.

 

 

코드를 이렇게 실행시켜보면

 

Enter flag: 라는 문자열이 나오고 사용자 입력을 받는다.

 

1을 입력해봤더니 역시나 Access denied! 가 나온다.

 

이제 소스코드를 수정해보자.

 

package test;
import java.util.*;

public class fragile
{
    public static void main(String args[]) {
        Scanner scanner = new Scanner(System.in);
        System.out.print("Enter flag: ");
        String input = scanner.next();

        if (check(input)) {
            System.out.println("Access granted.");
        } else {
            System.out.println("Access denied!");
        }
    }
    
    public static boolean check(String input){
        boolean h = false;
        String flag = "h1_th3r3_1ts_m3";
        String theflag = "ÐdØә§å’ÍaèÒÁ¡—";
        String hiddenflag = "";

        for(int i = 0; i < flag.length(); i++){
            hiddenflag += (char)((int)(theflag.charAt(i)) - (int)(flag.charAt(i)));
        }
        System.out.println(hiddenflag);
        return true;
    }
}

 

필요없는 코드는 과감하게 지워버렸다.

 

지워버린 부분은 입력을 체크하는 부분, 그리고 입력값에서 플래그 포멧인 rtct{ 를 잘라내는(정제하는) 부분이다.

 

핵심은 check 함수인데

 

check 함수 안에 hiddenflag 라는 변수를 새로 하나 만들어서 저장했고,

 

theflag 에는 ÐdØә§å’ÍaèÒÁ¡— 를 저장해줬다.

 

그리고나서 theflag - flag 한 값을 hiddenflag 에 저장해준 뒤 출력시켜줬다.

 

 

그리고나서 컴파일하면

 

아까처럼 Enter flag: 라는 문자가 나오면서 사용자 입력을 받는데

 

아무거나 입력하면

 

아래쪽으 숨겨져있던 플래그가 출력되는걸 볼 수 있다.

반응형