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)
대문자인지 알아내는 코드는 위와 같다.
각 글자마다 소문자하나, 대문자 하나씩 그냥 모든 경우의 수를 넣어봤다.
잠깐 기다리면 플래그값을 찾을 수 있다.
'워게임 > CTFlearn' 카테고리의 다른 글
[CTFlearn] Music To My Ears - 포렌식 / faad (62) | 2023.04.15 |
---|---|
[CTFlearn] Python Reversal - 프로그래밍 (56) | 2023.04.12 |
[CTFlearn] HailCaesar! - 포렌식 / ASCII Cipher (66) | 2023.04.02 |
[CTFlearn] Weird Android Calculator - 프로그래밍 / JADX / Python (52) | 2023.03.30 |
[CTFlearn] CoppeRSA Lattice - 암호학 / RsaCtfTool (64) | 2023.03.28 |