워게임/CTFlearn

[CTFlearn] Is it the Flag? (JAVA) - 프로그래밍 / Python

SecurityMan 2023. 4. 7. 11:00

 

CTFlearn의 여든 다섯번째 문제

 

이번엔 Hard 난이도의 프로그래밍 문제이다.

 

갈수록 어려운 문제가 나와서 이젠 못풀수도 있겠다 싶다.

 

반응형

 

문제 설명을 읽어보면 

 

플래그는 6글자의 alphanumeric characters 라고 한다.

 

alphanumeric 은 a ~ z, 0 ~ 9 까지의 문자열을 모두 합한걸 의미한다.

 

public class IsItTheFlag {

public static boolean isFlag(String str) {
	return str.hashCode() == 1471587914 && str.toLowerCase().hashCode() == 1472541258;
}

public static void main(String[] args) {

String flag = "------";

if (isFlag(flag))
	System.out.println("You found it!");
else
	System.out.println("Try again :(");

	}
}

 

이게 문제에서 주어지는 코드이다.

 

입력값은 6글자의 string 이고

 

이 string 에 대해 hashCode() 를 실행한 결과가

 

1471587914 이면서, 

 

string 을 소문자로 바꿨을때 hashCode() 를 실행한 결과가 1472541258 라면

 

True 가 리턴된다.

 

java 로 풀어보려했는데

 

익숙치가 않아서 그냥 python 을 이용해서 풀어보기로 했다.

 

 

구글에 hashCode() 함수에 대해 검색해봤더니

 

계산하는 수식이 나왔다.

 

위 수식은 길이가 n인 입력값에 대해 계산하는 수식이다.

 

수식을 알았다면 Python에서 충분히 구현이 가능하다.

 

그리고 수식을 통해서 중요한 정보를 얻을 수 있는데

 

입력값이 지금 6글자이니 

 

수식의 맨 앞이 s[0] * 31 ^ 5 가 될 것이다.

 

이 뜻은 입력값의 맨 첫번째 글자가 결과값에 가장 큰 숫자를 차지한다는 것이다.

 

그래서 맨 앞 두글자 정도를 모든 경우에 수에 대해서 계산해보면

 

대략적으로 어떤 글자가 앞에 오는지 알 수 있을 것이다.

 

string = '0123456789abcdefghijkmlnopqrstuvwxyz'

for i in range(len(string)):
    for j in range(len(string)):
        test = string[i] + string[j] + '0000'
        hashcode = (ord(test[0]) * pow(31,5)) + (ord(test[1]) * pow(31,4)) + (ord(test[2]) * pow(31,3)) + (ord(test[3]) * pow(31,2)) + (ord(test[4]) * 31) + ord(test[5])
        print(hashcode, test)

 

처음 Python 코드는 이렇게 짰다.

 

수식을 그냥 그대로 가져다 쓰고

 

맨 앞 두글자는 모든 경우의 수를, 

 

뒤에 네글자는 0000으로 넣어서 hashcode를 계산했다.

 

 

계산을 해보니 맨 앞글자가 숫자 0일때

 

문제에서 요구하는 147 로 시작하는 값이 나왔다.

 

두번째 글자도 g 부터 l 정도의 범위만 계산해봐도 될듯했다.

 

string = '0123456789abcdefghijkmlnopqrstuvwxyz'
second = 'ghijkl'

for i in range(len(second)):
    for j in range(len(string)):
        for l in range(len(string)):
            for m in range(len(string)):
                for n in range(len(string)):
                    test = '0' + second[i] + string[j] + string[l] + string[m] + string[n]
                    hashcode = (ord(test[0]) * pow(31,5)) + (ord(test[1]) * pow(31,4)) + (ord(test[2]) * pow(31,3)) + (ord(test[3]) * pow(31,2)) + (ord(test[4]) * 31) + ord(test[5])
                    if hashcode == 1472541258:
                        print('found', hashcode, test)

 

알아낸 정보를 기반으로 조금 수정했다.

 

첫번째 글자는 0 으로 고정하고

 

두번째 글자는 g 부터 l 까지만 계산하게끔 했다.

 

나머지는 전체를 다 계산했다.

 

이렇게 하면 경우의 수가 확 줄어든다.

 

 

코드를 실행시키면

 

문제에서 요구하는 값을 찾을 수 있다.

 

하지만 여기서 끝이 아니다.

 

이 값은 .toLowerCase 했을때 계산한 값이다.

 

이제 이중 어떤게 대문자인지 알아내야한다.

 

second = '**'
third = '**'
fourth = '**'
fifth = '**'
sixth = '**'


for i in range(len(second)):
    for j in range(len(third)):
        for k in range(len(fourth)):
            for l in range(len(fifth)):
                for m in range(len(sixth)):
                    test = '0' + second[i] + third[j] + fourth[k] + fifth[l] + sixth[m]
                    hashcode = (ord(test[0]) * pow(31,5)) + (ord(test[1]) * pow(31,4)) + (ord(test[2]) * pow(31,3)) + (ord(test[3]) * pow(31,2)) + (ord(test[4]) * 31) + ord(test[5])
                    if hashcode == 1471587914:
                        print('found', hashcode, test)

 

대문자인지 알아내는 코드는 위와 같다.

 

각 글자마다 소문자하나, 대문자 하나씩 그냥 모든 경우의 수를 넣어봤다.

 

 

잠깐 기다리면 플래그값을 찾을 수 있다.

반응형