[Dreamhack.io] rev-basic-8
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는 사용자 입력값을 가지고 있으며, 연산은 다음과 같이 진행된다.
- eax = eax * 0xFB(-5) // imul은 부호있는 숫자의 곱셈이여서 -5라고 생각함.
- eax = eax & FF // 위에서 한 곱셈에서 상위 바이트 싹 날리고 1바이트로 만듦.
- 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에 사용한 브루트포스에 대한 내용이다. 브루트 포스에 대해 살짝 설명하자면, 무차별 대입 공격 기법이다. 모든 탐색 영역을 하나하나 검증하기 때문에 최적 값을 찾을 수 있지만, 영역 및 조건에 따라 시간 복잡도가 크게 증가한다...