CTF/리버싱

[angstromCTF] Taking Off - 리버싱 / IDA

SecurityMan 2022. 3. 15. 12:00

반응형


Taking Off 세번째 리버싱 문제이다. 

 

이 문제부터는 조금씩 머리를 써야한다.

 

물론 그렇게 어렵진 않다. 



taking_off 라는 바이너리 파일이 하나 주어진다. 역시나 확장자는 없고
elf 라는 파일형태로 리눅스에서 실행가능한 프로그램이다.
(리눅스에서 쓰는 exe파일 같은거라 생각하면된다.)
리눅스에서 해당 바이너리 파일을 실행해보면

맨 마지막 줄에
Make sure you have the correct amount of command line arguments
라고하면서 argument 의 갯수를 맞춰보라고 한다.

지난번 revving_up 문제에서는 argument가 "banana" 하나였다.

(참고 : https://hackingstudypad.tistory.com/33 )

이번문제에서는 몇개인지 확인해보자.
 
해당 프로그램을 IDA 라는 디스어셈블러로 열어본다.


열어보면 알수없는 복잡한 코드들이 마구 보이는데
 
쫄거없다. 하나씩 살펴보면 아주 쉽다.
 
if(argc == 5)
가장 먼저 살펴볼 부분은 네번째 줄이다.
 
argc 에 5라는 값이 들어가 있는지 조건문으로 확인을 한다.
 
여기있는 argc가 바로 argumnet의 갯수를 의미한다.
 
예를들어 지난번 revving_up 을 생각해보자.
 
플래그를  얻기 위해 ./revving_up banana 라고 입력했다.
 
그러면 argument는 이렇게 전달된다.
argv[0] = revving_up
argv[1] = banana

0번째에는 항상 실행경로가 들어가고 띄어쓰기로 구분해서 1번째에 banana가 들어가게 된다.

 

그리고 argc는 위의 갯수니 2가 출력될 것이다.

 

좀더 심화해서 ./hello.exe I am security man 이라고 입력했다고 치자

argv[0] = hello.exe
argv[1] = I
argv[2] = am
argv[3] = security
argv[4] = man

그럼 이렇게 각각 구분이 되고 argc 는 총 갯수인 5가 될것이다.

 

이문제의 argc도 5이니 인자를 실행경로 제외하고 4개를 줘야한다.

 

이제 어떤 값을 줘야하지 알아보자.

 

7,8,9번째 줄을 보면 된다.

string_to_int(argv[1], &v4);
string_to_int(argv[2], &v5);
string_to_int(argv[3], &v6);
사용자의 입력값(string)을 정수형(int)로 변환시켜서 각각 변수에 담고있다.
 
argv[1] 은 v4에, argv[2] 은 v5에, argv[3] 은 v6에 각각 담고있다.
 
그럼 첫번째, 두번째, 세번째 인자는 각각 v4, v5 ,v6에 맞는 값을 넣어주면 되는것이다.
 
100 * v5 + 10 * v4 + v6 != 932
12번째줄을 보면 이렇게 써있다.
 
100 * v5 + 100 * v4 + v6 의 값이 932와 같지 않은지 비교한다.
 
그럼 저 연산의 값이 932가 되게 하면 되는것이다.
 
따라서 v4, v5, v6에는 각각 3, 9, 2 가 들어가게 된다.

 

strcmp(argv[4], "chicken")

argc가 5이므로 아직 argument가 하나 남았다

 

마지막 argument는 13번째 줄에서 찾을 수 있다.

 

strcmp는 string compare로 문자열을 비교하는 함수이다.

 

argv[4]가 chicken 인지 비교하고 있다.

 

따라서 마지막 인자는 chicken으로 주면 된다.



지금까지 정보를 종합해서 입력해본다.
 
./taking_off 3 9 2 chicken

 

이렇게 입력하면 된다.
 
Well, you found the argumentm but what's the password?
이제 끝일줄 알았는데 한번 더 물어본다..
 
실컷 argument 다 찾아놨더니 비밀번호를 알아오라고 한다.
 
비밀번호는 맨 밑에있는 if문을 보면 된다.
if( ((unsigne __int8)s[i] ^ 0x2A ) != desired[i])

이 부분이다.

 

s 라는 배열은 사용자가 입력한 password 정보를 담고 있다.

 

예를들어 hello 라고 입력했다면 ['h', 'e', 'l', 'l', 'o'] 이런식으로 한글자씩 쪼개서 s 라는 배열에 들어가게 된다.

 

그리고 그 배열은 앞에서부터 차례로 0x2A 라는 값과 XOR 하게된다.

 

^ 기호는 논리연산에서 XOR 이라는 의미이다. (두 비교대상이 같으면 0, 다르면 1을 리턴한다.)

 

각각 XOR 된 값을 desired 라는 배열에 들어있는 값과 비교하고있다.

 

IDA에서 desired 라는 부분을 더블클릭하면 해당 배열의 내용을 볼 수 있다.


 
desired 배열은 위와 같은 값이 순서대로 들어가 있다. 뒤에있는 h는 16진수라는 뜻이다.
 
desired배열 내에 어떤 값이 들어있는지 알았으니 저 값들을 2A와 XOR 해주면 된다.
 
이런거할때 CyberChef 라는 사이트를 자주 이용한다. 아주 편하다.
 
해당 값들을 XOR 해주면
 
please give flag 라는 문자가 나오게 된다. 이게 바로 우리가 찾던 비밀번호이다.

 
다시한번 ./taking_off 3 9 2 chicken 을 입력해주고,
 
비밀번호를 물어볼때 please give flag 라고 입력해주면
 
플래그를 획득할 수 있다.
반응형