Write-up/dreamhack.io

[Dreamhack.io] rev-basic-8

새달아 2022. 8. 31. 06:02

dreamhack.io의 Wargame rev-basic-8 문제이다.

https://dreamhack.io/wargame/challenges/22/

 

rev-basic-8

Reversing Basic Challenge #8 이 문제는 사용자에게 문자열 입력을 받아 정해진 방법으로 입력값을 검증하여 correct 또는 wrong을 출력하는 프로그램이 주어집니다. 해당 바이너리를 분석하여 correct를 출

dreamhack.io

 

#문제분석

이전 문제들과 별반 차이없다. 입력값 검증 함수를 찾아보자!

 

#문제풀이

[main]

메인함수는 문자열 검색을 이용하여 찾았으며, 프로그램을 돌렸을 때 입력값을 받아오는 부분에서 걸리기도 한다. 아무튼... 우리가 눈 여겨봐야할 함수는 <chall8.sub_7FF6DF291000> 함수로, 아마 저 함수가 입력값을 검사하는 부분이지 않을까 싶다. 해당 함수는 rcx(사용자 입력값이 들어있음)를 인자로 가지고 간다.

 

[chall8.sub_7FF6DF291000]

크게 어려워 보이지 않으니 천천히 보자.

...
movsxd rax, dword ptr ss:[rsp]
cmp rax, 15
jae chall8.7FF6DF291055
...

해당 부분은 스택확장 및 [rsp] = 0 이후에 점프하는 곳이다. rax에 0을 넘겨주고 0x15와 비교를 하여 jae 분기가 나오는데, [rsp]가 0x15와 같거나 커지면 해당 함수가 끝나게 된다. 해당 함수 구조를 살펴본 결과 [rsp]는 반복문의 횟수, 인덱스라고 생각이 든다.

 

...
imul eax, eax, FB
and eax, FF
movsxd rcx, dword ptr ss:[rsp]
lea rdx, qword ptr ds:[7FF6DF293000]
movzx ecx, byte ptr ds:[rdx+rcx]
cmp eax, ecx
je chall8.7FF6DF291053
...

여기서 eax는 사용자 입력값을 가지고 있으며, 연산은 다음과 같이 진행된다.

  1. eax = eax * 0xFB(-5) // imul은 부호있는 숫자의 곱셈이여서 -5라고 생각함.
  2. eax = eax & FF // 위에서 한 곱셈에서 상위 바이트 싹 날리고 1바이트로 만듦.
  3. eax == [7FF6DF293000]에 있는 값들

[7FF6DF293000]에는 어떤 값이 있는지 확인만 하면 역연산으로 풀 수 있을 것 같다...!

덤프로 따라가면 다음과 같이 값들이 채워져 있다. 이제 exploit 코드를 작성해보자.

#include <stdio.h>

int main()
{
	int key[21] = {172, 243, 12, 37, 163, 16, 183, 37, 22, 198, 183, 188, 7, 37, 2, 213, 198, 17, 7, 197, 0};
	
	int i, j;
	
	for(i = 0; i < 21; i++)
	{
		for(j = 0; j < 256; j++)
		{
			if(((j * 251) & 255) == key[i])
			{
				printf("%c", j);
				break;
			}
		}
	}
    printf("\n");
	return 0;
}

코드를 짤 때 중요한 것은... type을 맞춰줘야 한다는 것... 이거 때문에 시간 좀 날렸다ㅠ 기본적인건데... 아무튼 모두 10진수로 바꿔서 코드를 작성했더니 잘 됐다. 해당 코드를 실행시키면...

Did_y0u_brute_force?

쨘! 이렇게 쉽게 flag를 얻을 수 있다!

 

이번 flag는 exploit code에 사용한 브루트포스에 대한 내용이다. 브루트 포스에 대해 살짝 설명하자면, 무차별 대입 공격 기법이다. 모든 탐색 영역을 하나하나 검증하기 때문에 최적 값을 찾을 수 있지만, 영역 및 조건에 따라 시간 복잡도가 크게 증가한다...