본문 바로가기
Write-up/dreamhack.io

[Dreamhack.io] rev-basic-5

by 새달아 2022. 2. 21.

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