dreamhack.io의 Wargame rev-basic-5 문제이다.
https://dreamhack.io/wargame/challenges/19/?page=6
rev-basic-5
Reversing Basic Challenge #5 이 문제는 사용자에게 문자열 입력을 받아 정해진 방법으로 입력값을 검증하여 correct 또는 wrong을 출력하는 프로그램이 주어집니다. 해당 바이너리를 분석하여 correct를 출
dreamhack.io
#문제분석
문제는 다음과 같이 나와있다.
입력값을 검증하는 함수를 찾아보자.
#문제풀이
위 영역은 문자열참조를 사용하여 찾은 메인함수 영역이다.
해당 부분에 중단점을 설정하고 디버깅을 했을 때 이 부분에서 문자열 입력이 요구되니까 메인함수가 맞을 것이다.
문자열을 받아온 이후, 바로 문자열 검증 함수로 넘어가게 된다.
<chall5.sub_7FF7850B1220>함수를 자세히 살펴보자.
여기서 알 수 있는 것들...
- 0x18만큼 반복하는 반복문이구나.
- <chall5.00007FF7850B1024>영역이 문자열을 검증하는구나.
해당 부분을 자세히 뜯어보자.
movsxd rax, dword ptr ss:[rsp] // 인덱스 [rsp]를 rax에 전달.
mov rcx, qword ptr ss:[rsp+20] // 입력값을 rcx에 전달. (메인함수에서 입력값을 [rsp+20]에 담음.)
movzx eax, byte ptr ds:[rcx+rax] // 사용자가 입력한 문자열의 해당 인덱스에 있는 문자를 eax(n)에 전달.
mov ecx, dword ptr ss:[rsp] // ecx를 인덱스로 초기화.
inc ecx // ecx를 1만큼 증가.
movsxd rcx, ecx // ecx를 rcx로 확장. (왜 확장을 해주는 걸까??)
mov rdx, qword ptr ss:[rsp+20] // 입력값을 rdx에 전달.
movzx ecx, byte ptr ds:[rdx+rcx] // 사용자가 입력한 문자열의 해당 인덱스에 있는 문자를 ecx(n+1)에 전달.
add eax, ecx // eax와 ecx를 더해 eax에 저장. (n번째 문자 + (n+1)번째 문자)
movsxd rcx, dword ptr ss:[rsp] // rcx를 인덱스로 초기화.
lea rdx, qword ptr ds:[7FF7850B3000] // 비교 문자열이 있는 주소를 rdx에 전달.
movzx ecx, byte ptr ds:[rdx+rcx] // 비교 문자열의 해당 인덱스에 있는 문자를 ecx에 전달.
cmp eax, ecx // eax와 ecx를 비교.
je chall5.7FF850B105B // 같으면 검증통과.
파란색으로 강조한 부분이 핵심.
- 사용자가 입력한 문자열의 문자들 중 n번째 문자와 n+1번째 문자에 대해 합 연산을 해준다.
- 이후 0x7FF7850B3000 주소에 있는 문자들과 비교를 한다.
해당 비교 문자열이 있는 주소를 덤프로 따라가면...
이렇게 Hex값과 아스키값이 나온다!
그런데... 문자열을 모두 모르는 상태에서 이 암호를 풀기에는 경우의 수가 너무 많다...!
왜냐하면...
랜덤한 문자 2개로 0xAD를 만든다고 생각해보면,
(A, L) (B, K) (C, J) 등의 수많은 순서쌍이 나오고, 해당 문자의 위치까지 달라질 수 있기 때문에...
그래서,
무조건 문자 하나는 알아야 한다!
조건에서 반복문은 0x18만큼 반복하는데, 해당 덤프의 0x18번째에는 0x00(NULL)이 기입되어 있다.
즉, 우리가 입력해야 할 마지막 문자는 널문자이고, 해당 덤프의 0x17번째는 입력값과 같다는 것!
n번째 입력값 + (n+1)번째 입력값 = n번째 덤프값
이므로...
0x17번째 입력값 + 0x18번째 입력값 = 0x17번째 덤프값
그러므로... 0x17번째 입력값은 0x4C
위의 내용을 역계산 해주면...
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
int i;
char dump[24] = {0xAD, 0xD8, 0xCB, 0xCB, 0x9D, 0x97, 0xCB, 0xC4, 0x92, 0xA1, 0xD2, 0xD7, 0xD2, 0xD6, 0xA8, 0xA5, 0xDC, 0xC7, 0xAD, 0xA3, 0xA1, 0x98, 0x4C};
char flag[24];
flag[22] = dump[22];
for(i = 22; i > 0; i--)
{
flag[i-1] = dump[i-1] - flag[i];
}
printf("%s", flag);
return 0;
}
All_l1fe_3nds_w1th_NULL
쨘! flag 획득 성공!
'Write-up > dreamhack.io' 카테고리의 다른 글
[Dreamhack.io] easy-crackme2 (0) | 2022.08.24 |
---|---|
[Dreamhack.io] easy-crackme1 (0) | 2022.08.16 |
[Dreamhack.io] rev-basic-4 (0) | 2022.01.17 |
[Dreamhack.io] rev-basic-3 (0) | 2022.01.17 |
[Dreamhack.io] rev-basic-2 (0) | 2022.01.11 |