퍼블 딴 문제
스크래치 문제인데 나름 재밌었다.
더러운 코드들이 보인다.
실행해보면 플래그를 입력하라 하고
zz 플래그가 틀리면 화낸다.
일단 분석을 위해 모든 변수, 리스트, 함수이름을 바꿔준다.
먼저 기본 변수 및 리스트 초기화를 해주는데, var26이 0임을 계속 생각하면 좋다. (상수 역할)
the_ball object 에 flag를 list2에 입력받고 check 신호를 보낸다.
이후 배경 오브젝트 에서 check 신호를 받는다.
list2 값들을 list1에 넣고 check2 신호를 보낸다.
분석하기 귀찮으니 동적분석
check2 신호를 받는 core object 코드를 살짝 떼놓고 실행해본다.
list1 과 list2를 화면에 띄우고 abcd1234를 입력해보면
그냥 통상적인 encode 임을 알 수 있다.
다시 check2 를 보면 CCC - AAA - FFF 를 반복한 후 flag list와 값을 비교한다.
따라서 CCC AAA FFF 함수만 분석하면 된다.
var20 과 var21 각각 4번 루프를 돌면서 256을 곱하면서 list1(encode된 input) 을 넣어준다.
256 곱하는게 << 8 과 같고, 이는 곧 big endian 으로 flag를 4바이트 읽는 것이다.
즉 func_CCC 는 flag 앞 8 글자를 4바이트씩 var20 과 var21 에 big endian 으로 읽어 저장하는 것이다.
이후 list1 앞 8글자를 삭제한다.
func_AAA:
먼저 func_DDD를 보자.
복잡해보이는 연산이지만 var26은 0이므로 0 - (0 - (0 * var2 + 1) ) , 그냥 1이다.
아래 연산은 var8 * (1 + 1) , var8 *= 2 해주는 코드이다.
param1 번 만큼 2배해주는 것이므로 func_DDD(param1) 는 return pow(2, param1) 이다.
즉 2**0, 2**1, 2**2, 2**(4+1) = 32, var8은 32가 된다.
이제 32번 반복하는 내용을 분석하자.
func_GGG:
func_EEE:
func_DDD(1) 로 2를 var8에 저장한다. 이후 var3 % 2, var3 /= 2 하는 것을 보면 2진수로 변환하는 작업임을 알 수 있다.
즉 func_DDD(x) : return bin(x)[2:] 이다.
다시 func_GGG 로 돌아와서
두 값을 이진수로 변환하고
길이가 긴 값을 기준으로 변수를 설정하고,
길이가 부족한 놈에게 0으로 padding 해준다.
이후 2진수로 변환한 각 값들을 더해주는데, carry 를 버리니 xor 연산이 된다.
func_BBB에 xor 한 값을 넘겨주는데, 맥락상 2진수를 다시 10진수로 변환하는 int(x, 2) 역할일 것이다.
대충 보면 그렇다.
다시 check2 로 돌아와서 정연산을 따라 구현해본다.
사실 위 알고리즘은 여러 리버싱 문제에 나오는 유명한 tea 암호화 알고리즘이다.
위 암호화는 xor만 하므로 상수값(key,
)만 안다면 최종 값을 토대로 원문을 복호화할 수 있다.
Flag : amateursCTF{screw_scratch_llvm_we_code_by_hand_1a89c87b}
'CTF Writeup' 카테고리의 다른 글
2023 SSTF - Dusty Code (0) | 2023.08.21 |
---|---|
2023 SSTF - Libreria (0) | 2023.08.21 |
zer0ptsCTF 2023 - decompile_me Writeup (0) | 2023.07.19 |
zer0ptsCTF 2023 - mimikyu Writeup (0) | 2023.07.19 |
zer0ptsCTF 2023 - fvm Writeup (1) | 2023.07.18 |