먼저 문제파일을 열어보면 다음과 같이 실행파일과 redme.txt가 주어집니다.
readme.txt를 열어보면
다음과 같이 문제에 대한 간략한 설명이 써있습니다.
이 프로그램에 들어갈 이름을 찾아야 하는데, 시리얼 값이 다음과 같을때의 이름을 알아내야 한다는것으로 보입니다.
우선 프로그램을 exeinfope로 열어보면
32비트 기반에 비주얼 c++로 작성된 프로그램이고, 별다른 패킹은 되어있지 않습니다.
이제 프로그램을 한번 실행 시켜보겠습니다.
실행시키면 이름을 입력받습니다.
아무 이름이나 입력하면
다음과 같이 시리얼값을 입력받습니다.
여기에 아까전에 제공된 시리얼값을 입력하는것일겁니다.
하지만 시리얼값을 입력해보면 프로그램이 바로 종료되므로
제대로 분석하기 위해서 IDA를 사용할것입니다.
IDA를 통해서 열어보면 간략하게 다음과 같은 구조를 가지고 있습니다.
먼저 main함수가 시작하는 부분을 보면 프로시저를 시작하는 부분다음에
아까전에 프로그램이 시작할때 처음 나왔던 문자열인 Input Name: 이라는 문자열을
스택에 푸쉬하고 sub_4011B9 라는 함수를 호출합니다.
이 함수가 어떤 함수인지 확인해보면
다음과 같은 어셈블리가 나오는데 여기서는 sub_401427 이라는 함수가 호출되는것이 보입니다.
이 함수도 확인해보면
간략화된 구조만 봐도 굉장히 복잡해 보이는 함수입니다.
어떤 작업을 하는 함수인지 확인해보기 위해서 하나하나 살펴보다가 발견한 함수가 있습니다.
_write_string 이라는 함수가 쓰인것을 알수 있습니다.
이 함수를 찾아보면 다음과 같은 함수가 있다는것을 알수 있습니다.
이 함수는 윈도우창에 텍스트를 출력시키는 함수입니다.
이러한 정보를 바탕으로 생각해보면
sub_4011B9 라는 함수는 printf 함수기능을 하는 함수를 직접 만든것이라고 추측해볼수 있습니다.
이 작업이 끝난 뒤에는 %s라는 포맷 스트링과 변수의 주소를 푸쉬한뒤에 scanf함수를 호출하므로
이름을 입력받는 작업을 한다는것을 알수 있습니다.
이 다음부터는 연산이 살짝 복잡해지므로 decompiler의 도움을 살짝 받아볼것입니다.
24line 까지 분석을 했으므로 그 다음부터 분석해보면 될것입니다.
입력한 이름은 변수 v7에 저장됩니다. 그리고나서 v7의 길이만큼 반복문을 돌린다는것을
알수 있습니다. 반복문을 돌리는 로직은 i = 0 부터 1씩 더하고, v3 = 0을 v7의 길이와 비교하면서
v3가 v7의 길이와 같지 않을때 반복문을 돌린다는 것을 알수 있습니다.
그리고 반복문 안에서는 i 가 3보다 크거나 같다면 i를 0으로 초기화 시킨뒤
sprintf함수를 활용해서 Buffer에 있는 문자열과 변수들을 활용한 계산결과를
포맷스트링을 통해서 조합한뒤 Buffer에 저장한다는것을 알수 있습니다.
그리고 마지막 부분에서 Input Serial이란 문자열이 나온뒤 입력받은 시리얼값과
v7과 이름과 다른 변수를 이용해서 연산을 한 최종값인
Buffer를 비교해서 서로 같을때 printf함수의 역할을 하는 함수인 sub_4011B9 함수를 이용해서
aCorrect를 출력시키고 서로 다르면 aWrong을 출력시킵니다.
이 두개의 변수에는
다음과 같이 Correct ! 와 Wrong 이라는 문자열이 있으므로
서로 같아야 맞는 값이란것을 알수 있습니다.
복잡한 연산을 거친후의 값이 시리얼값과 같아야 하는데, 일일이 손으로 연산하는것은
시간이 너무 오래 걸리고 틀릴수도 있으므로
xor연산은 같은값으로 다시 연산하면 처음값으로 돌아온다는 특성을 이용해서
역연산 코드를 짤것입니다.
이름을 이용해서 시리얼값을 만드는 과정을 잘보면
이름 1자리를 이용해서 시리얼값 2자리를 만들기 때문에, 역연산을 할때는
시리얼 2자리를 이용해서 이름의 1자리를 만들어야 합니다.
시리얼의 자릿수는 16자리이므로 이 특성을 이용한다고 치면 이름은 8자리일것입니다.
이것들을 이용해서 코드를 짜보면 다음과 같습니다.
#include <stdio.h>
main(){
char serial[8] = {0x5B,0x13,0x49,0x77,0x13,0x5E,0x7D,0x13};
int i, v3=0;
char v6[4] = {16,32,48};
for(i=0;v3<8;++i){
if(i >= 3)
i = 0;
printf("%c",serial[v3++] ^ v6[i]);
}
printf("\n");
}
이것을 실행해보면 다음과 같이 성공적으로 이름이 나오는것을 알수 있습니다.
이렇게해서 얻은 이름으로 동적분석을 해보면서 이 이름이 맞는지 확인해봐야 합니다.
이 이름을 써서 분석을 해보면 검사루틴을 성공적으로 통과하고
Currect ! 라는 문자열이 성공적으로 출력되는것을 확인할수 있습니다.
그러므로 올바른 이름은 K3yg3nm3 입니다.
'워게임 > Reversing.kr' 카테고리의 다른 글
[Reversing.kr] ImagePrc 풀이 (0) | 2022.07.02 |
---|---|
[Reversing.kr] Replace 풀이 (0) | 2022.06.30 |
[Reversing.kr] Music Player 풀이 (0) | 2022.06.29 |
[Reversing.kr] Easy Unpack 풀이 (0) | 2022.06.29 |
[Reversing.kr] Easy Crack 풀이 (0) | 2022.06.29 |