dreamhack.io의 Wargame rev-basic-1 문제이다.
https://dreamhack.io/wargame/challenges/15/?page=2
rev-basic-1
Reversing Basic Challenge #1 이 문제는 사용자에게 문자열 입력을 받아 정해진 방법으로 입력값을 검증하여 correct 또는 wrong을 출력하는 프로그램이 주어집니다. 해당 바이너리를 분석하여 correct를 출
dreamhack.io
#문제분석
문제 정보는 다음과 같이 나와있다.
문자열을 입력받아 어떤 검증 함수를 거친 뒤 correct 또는 wrong으로 넘어가는구나.
그러면 입력 값을 비교하는 함수를 찾으면 풀 수 있겠지?
#문제풀이
파일을 x64dbg로 열면 Entry Point에서 시작된다.
이제 메인 함수 영역을 찾아야 하는데, 나는 문자열 참조를 사용해 찾았다.
상단의 문자열 참조를 통해 문자열 구역으로 오게 된다면 "Input : "이나 "Wrong"과 같은 영역으로 갈 수 있는 주소가 있다.
실제로 파일을 실행시켰을 때 이러한 문자열이 나오니까 이 부분이 메인함수라고 생각!
그리하여 메인 함수 영역으로 가본다면...
위 부분이 문자열을 검증하는 부분인데, 빨간색 네모 안의 3번째 줄을 보면 je(같을 경우 점프)라고 나와있다.
test eax, eax 에서 eax가 0이면 ZF가 1로 나오게 되고, eax가 그 외라면 ZF가 0으로 나온다.
ZF는 연산결과가 0이면 참(1)이 되기 때문에 eax가 0이면 ZF가 1이됨.
Correct로 가기 위해서는 점프하면 안되기에, eax가 0이 아닌 숫자가 되어야 한다.
call <chall1. sub_7FF7AE521000> 함수에서 eax값을 반환해주는 것 같으니 이 부분을 보면 key값을 알 수 있을 것!
메인함수를 간단히 코드화 한다면 다음과 같다.
#include <stdio.h>
int sub_7FF7AE521000(char string[]); // 문자열 검사 함수
{
}
int main()
{
int flag;
char string[256];
printf("Input : ");
scanf("%s", string);
flag = sub_7FF7AE521000(string);
if(flag == 0)
printf("Correct!");
else
printf("Wrong!");
return 0;
}
얼핏 보기에도 길다.
그런데 잘 보면 규칙이 보인다...!
이부분이 계속적으로 반복되는 것!
이것을 천천히 해석해보자면...
mov qword ptr ss : [rsp+8], rcx // 받아온 문자열 rcx를 [rsp+8]에 저장
mov eax, 1 // eax를 1로 초기화
imul rax, rax, 0 // rax는 여기서 rcx(문자열)의 index로 사용
mov rcx, qword ptr ss : [rsp+8]
movzx eax, byte ptr ds : [rcx+rax] // eax에 [rcx+0]즉, 문자열의 첫번째 문자를 저장
cmp eax, 43 // 첫번째 문자가 'C'가 맞는가?
je chall1.7FF7AE521023 // 같으면 chall1.7FF7AE521023로 점프
xor eax, eax // 아니면 eax에 대해 xor연산 진행
jmp chall1.7FF7AE52128E // 이후 chall1.7FF7AE52128E로 점프
이 다음 부분도 보자면...
mov eax, 1 // eax를 1로 초기화
imul rax, rax, 1
mov rcx, qword ptr ss : [rsp+8]
movzx eax, byte ptr ds : [rcx+rax] // eax에 [rcx+1]즉, 문자열의 두번째 문자를 저장
cmp eax, 6F // 두번째 문자가 'o'가 맞는가?
je chall1.7FF7AE521041 // 같으면 chall1.7FF7AE521041로 점프
xor eax, eax // 아니면 eax에 대해 xor연산 진행
jmp chall1.7FF7AE52128E // 이후 chall1.7FF7AE52128E로 점프
이렇게 계속 반복되는 것이다!
그렇다면 chall1.7FF7AE52128E는 어떤 부분일까?
그냥 바로 함수가 끝나버린다...
다시말해 xor연산을 한 값을 가진 eax가 반환된다는 것이다.
정상적으로 모든 연산을 통과했다면 eax가 마지막에 1로 초기화되어서 반환되고 "Correct!"가 출력될 것인데...
하나라도 잘못 입력하면 eax에 0이 반환된다는 것!
즉, cmp eax, (아스키코드)만 잘 봐준다면 쉽게 풀 수 있다!
이 전체를 다시 코드화 시킨다면...
#include <stdio.h>
int sub_7FF7AE521000(char string[])
{
if(string[0] != 'C')
return -1;
if(string[1] != 'o')
return -1;
if(string[2] != 'm')
return -1;
if(string[3] != 'p')
return -1;
if(string[4] != 'a')
return -1;
if(string[5] != 'r')
return -1;
if(string[6] != '3')
return -1;
if(string[7] != '_')
return -1;
if(string[8] != 't')
return -1;
if(string[9] != 'h')
return -1;
if(string[10] != 'e')
return -1;
if(string[11] != '_')
return -1;
if(string[12] != 'c')
return -1;
if(string[13] != 'h')
return -1;
if(string[14] != '4')
return -1;
if(string[15] != 'r')
return -1;
if(string[16] != 'a')
return -1;
if(string[17] != 'c')
return -1;
if(string[18] != 't')
return -1;
if(string[19] != '3')
return -1;
if(string[20] != 'r')
return -1;
return 0;
}
int main()
{
int flag;
char string[256];
printf("Input : ");
scanf("%s", string);
flag = sub_7FF7AE521000(string);
if(flag == 0)
printf("Correct!");
else
printf("Wrong!");
return 0;
}
조잡하지만 이렇게 표현할 수 있다.
간단히 string.h를 이용해 표현 할 수도 있다!
아무튼 key값을 입력하게 된다면 성공!
Compar3_the_ch4ract3r
쨘! 이렇게 key값을 성공적으로 찾을 수 있다.
'Write-up > dreamhack.io' 카테고리의 다른 글
[Dreamhack.io] rev-basic-8 (0) | 2022.08.31 |
---|---|
[Dreamhack.io] Inject ME!!! (1) | 2022.08.30 |
[Dreamhack.io] rev-basic-0 (0) | 2022.08.30 |
[Dreamhack.io] easy-crackme2 (0) | 2022.08.24 |
[Dreamhack.io] easy-crackme1 (0) | 2022.08.16 |