exeinfope로 확인해보면 델파이로 작성된 32비트 실행파일이고 별다른 패킹은 안되어있습니다.
프로그램을 실행시켜보면
이렇게 구성되어있는데 문제에서 제시하는대로 알파벳 1글자와 시리얼키를 입력해보면
문자를 더 입력해야한다는 문자열이 출력됩니다.
이 문자열이 안뜨려면 이름을 3글자 이상 입력해야하는것을 봐서는 패치가 필요해보입니다.
이 문자열은 이름 길이검사루틴에서 쓰일것이기 때문에
IDA를 통해서 이 문자열이 쓰이는 곳을 찾을수 있다면 검사루틴을 찾을수 있습니다.
이 함수에서 문자열이 쓰이는것을 봐선 이 함수가 검사루틴일것이므로 한번 함수로 들어가보면
다음과 같은 구조를 하고있는 검사루틴을 볼수있습니다.
이 분기가 바로 이름의 길이를 검사하는 분기문인데
분석해보면 입력받은 이름의 길이를 얻은뒤 그 값과 3을 비교해서
3보다 작으면 더 입력하라는 문자열을 출력하므로
동적분석을 위해서 이 부분을 1로 패치해줘야 합니다.
이 부분을 1로 패치해주면 이름 길이검사를 넘길수 있습니다.
계속해서 분석해보면 시리얼값을 검사하는 부분은 다음과 같습니다.
동적분석을해보면
처음 GetText 함수를 사용할때는 시리얼값을 ebp-10에 저장하고 eax에 복사해서 eax를 스택에 푸쉬합니다.
그리고 ebp-18에는 이름을 저장합니다.
그리고나서 사용자정의 함수에 이름값과 빈 스택을 푸쉬한뒤 호출합니다.
사용자정의 함수에서 연산을 거친뒤 ebp-14의 값을 확인해보면
시리얼값의 형식과같은 값이 들어가있습니다.
그리고나서 아까전에 스택에 푸쉬했던 입력했던 시리얼값과 생성된 시리얼값을 비교한뒤
분기를 나누는것을 봤을때 아까전의 사용자정의함수가
이름값에 따라서 시리얼키를 생성하는 함수로 보입니다.
그러므로 이 함수에서 시리얼값이 생성되는 로직을 분석해봐야합니다.
동적분석을 해보면 다음과 같은 연산과정을 거치고나서 esi값을 확인해보면
아까전에 이름값 A를 넣었을때 최종적으로 나왔던 시리얼키의 앞부분값이
esi값의 앞에 4자리와 동일하다는것을 기반으로
이 연산루틴이 시리얼값을 생성하는 첫번째 루틴이라는것을 알수있습니다.
그러므로 이 시리얼값에대한 올바른 이름을 알아내기 위해서는
이 연산루틴에 숫자부터 모든 알파벳을 전부다 넣어보는 브루트포싱이 필요하고
그렇게해서 원래 시리얼값의 앞부분과 동일한 이름값이 바로 정답일것입니다.
#include <stdio.h>
main(){
int esi, tmp=0;
for(esi=0x30; esi <= 0x7A; esi++){
int edx = 0;
tmp = esi;
if((esi >= 0x3A && esi <= 0x40) || (esi >= 0x5B && esi <= 0x60))
continue;
esi += edx;
esi *= 0x772;
edx = esi;
edx *= esi;
esi += edx;
esi *= 0x474;
esi += esi;
edx = esi;
printf("%c : %X\n",tmp,edx);
esi = tmp;
}
}
연산루틴을 기반으로 짜본 브루트포스 코드입니다.
이 코드를 실행시키면
다음과 같이 각각의 이름으로 나오는 시리얼값이 출력되는데
여기서 잘 찾아보면
이름이 F 일 경우에 원래 시리얼값과 동일하다는것을 알수 있습니다.
그러므로 올바른 이름은 F 가 될것입니다.
한번 입력해보면
성공 메세지가 나오므로 이름이 F가 확실해집니다.
이제 F를 md5한값을 찾아야하는데 md5 암호화사이트에서 암호화를 해보면
800618943025315F869E4E1F09471012 라는 값이 나오므로 이 값이 정답입니다.
'워게임 > CodeEngn' 카테고리의 다른 글
[CodeEngn] Malware Analysis L02 (0) | 2022.10.06 |
---|---|
[CodeEngn] Malware Analysis L01 (0) | 2022.10.06 |
[CodeEngn] Basic RCE L16 (0) | 2022.07.08 |
[CodeEngn] Basic RCE L15 (0) | 2022.07.06 |
[CodeEngn] Basic RCE L14 (0) | 2022.07.06 |