이번에 풀 문제는 Easy Keygen이라는 문제이다.
문제를 클릭하여 압축 파일을 받으면 압축 파일 안에는 ReadMe.txt와 문제 바이너리 파일이 함께 있다.
ReadMe.txt를 읽어보면 시리얼이 5B134977135E7D13 인 이름을 찾으라는 말이 나와있다. 이 이름이 이 문제의 flag 임을 알 수 있다.
그리고 문제 바이너리는 .exe 파일임을 확인하고 실행시켜보면 이름을 입력하라고 나오고 이름을 입력하면 시리얼을 입력하라고 나오는데 시리얼은 뭔지 모르므로 아무 값이나 입력하면 틀렸다고 나오고 프로그램은 종료된다.
해당 바이너리를 OllyDbg로 열고 앞선 문제풀이에서 했듯이 이 프로그램에 속한 문자열을 살펴보면 다음과 같다.
위의 문자열들을 보고 프로그램이 어떤 방식으로 돌아갈 것인지 상상해보면 다음과 같다.
우선 프로그램은 이름에 따라 다른 시리얼을 생성하는 것 같다.
프로그램은 이름을 입력 받은 후에 그 이름에 알맞은 시리얼을 생성한다.
그리고 우리가 입력하는 시리얼을 받아서 프로그램이 생성한 시리얼과 비교한다.
비교 결과, 같으면 Correct! 라는 문자열을, 다르면 Wrong 이라는 문자열을 출력한 후 종료된다.
따라서 우리는 우선, Name을 기반으로 시리얼을 만드는 방법을 알아낸 후에 그 방법을 거꾸로 적용하여 시리얼이 5B134977135E7D13인 이름을 찾아야 한다. Name을 기반으로 시리얼을 만드는 부분은 우선 우리가 Name을 입력한 후에 있을 것이므로 이름을 입력하는 부분으로 가서 살펴보기로한다. 그 부분은 다음과 같다.
이름을 입력하라는 글자를 화면에 띄운 뒤, scanf로 우리의 입력을 받아들이는 모습이다. 이 뒤에 우리가 입력한 문자열을 이용해서 시리얼을 만드는 곳이 있다. 그 부분은 다음과 같다.
위의 어셈블리를 디버깅하며 해석해보면 다음과 같은 일을 한다.
1. 입력한 Name의 길이를 구한다.
2. Name의 길이만큼 루프를 돈다.
3. 루프를 돌때마다 0x10, 0x20, 0x30 과 차례대로 번갈아가며 Name의 문자들과 하나씩 xor한다.
4. xor한 결과들을 저장한다. 그 것이 시리얼이다.
따라서 우리는 위의 방법을 거꾸로 진행하면 문제를 풀 수 있다.
xor은 다시 xor하면 원래 값이 나오므로, 주어진 시리얼 5B134977135E7D13 을 두 글자를 한 16진수 숫자로 생각하여 0x10, 0x20, 0x30과 차례대로 번갈아가며 xor 해주면 그 결과가 이번 문제의 답이다.
필자는 이를 스크립트를 이용해 해결했으며, 이 문제에 사용된 스크립트는 다음과 같다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #-*- coding: utf-8 -*- __author__ = 'mojo' Name = "" Serial = "5B134977135E7D13" key = [0x10, 0x20, 0x30] j=0 for i in range(len(Serial)/2) : if(j==len(key)): j = 0 serial_piece = Serial[2*i:2*(i+1)] tmp_name = int(serial_piece,16)^key[j] Name += chr(tmp_name) j+=1 print Name | cs |
그 결과 나오는 이름이 Flag 다.
'WriteUp' 카테고리의 다른 글
| Crackit2.exe Writeup (0) | 2016.02.01 |
|---|---|
| Crackit2.exe Writeup (0) | 2016.01.15 |
| Crackit2.exe Writeup (0) | 2016.01.14 |