rev-basic-5

A_dawn·2024년 8월 15일
0

Reversing

목록 보기
1/1
post-thumbnail

Reversing Basic Challenge #5

문제 주소:https://dreamhack.io/wargame/challenges/19

Dreamhack의 2단계 난이도의 리버싱 문제이다.

문제


문제는 다음과 같다.

이 문제는 사용자에게 문자열 입력을 받아 정해진 방법으로 입력값을 검증하여 correct 또는 wrong을 출력하는 프로그램이 주어집니다.
해당 바이너리를 분석하여 correct를 출력하는 입력값을 찾으세요!
획득한 입력값은 DH{} 포맷에 넣어서 인증해주세요.
예시) 입력 값이 Apple_Banana일 경우 flag는 DH{Apple_Banana}

분석


문제 파일을 다운 받아서 실행시켜 보면 다음 화면처럼 뜬다.

아무거나 입력하게 되면 wrong을 출력하게 된다.

해당 프로그램이 어떤 구조로 되어있는지 알아보기 위해 ida로 실행시켜 봤다.

문제 설명과 같이 입력값을 검증하여 wrong이나 correct를 출력해주는 것을 볼 수 있다.
해당 부분을 ida의 pseuedo code로 보게 되면 다음 화면처럼 뜨는 걸 확인 할 수 있다.

main 함수를 살펴보면 사용자로부터 Input을 받아 V4에 저장하고 if문의 결과에 따라 correct나 wrong을 출력하고 있다.

if문의 조건문은 다음과 같다.

해당 함수는 인자를 v4로 받아왔기 때문에 a1 = v4라는 것을 알 수 있고
for문이 실행되는 동안 * (a1+i+1) + * (a1+i) = byte_140003000[i] 가 일치한다면 true를 그렇지 않다면 false를 반환하는 것을 알 수 있다.


예를 들어 사용자가 Input에 1234를 넣었다면 i가 0일때

v4 = a1 = 123456

*(a1+ i) + *(a1 + i + 1) = byte_140003000[0]

12 + 34 = byte_140003000[0] 을 구하면 된다는 이야기이다.

왜냐하면 a1의 다음 +1 바이트 값은 34 , 다음 +2 바이트 값은 56이 되기 때문이다.

문제를 풀기 위해선 byte_140003000의 값을 알아야 한다.

byte_140003000의 값은 다음과 같다.

제일 앞에 있는 값인 0ADh는 0xAD를 이야기 한다.
2 dup(0CBh)는 0xCB가 2번 연속 있다는 것을 의미한다.

결국 우리가 찾아야 하는 값은 i 가 0이라고 가정하면 *(a1) + *(a1 + 1) = byte_140003000[0] (0xAD)를 찾아야 한다.

위의 for문이 0x18 (24) 까지 반복되므로 24바이트 만큼 검사한다는 것을 알 수 있다.

주어진 byte_140003000을 24번쨰까지 계산해보면 22번쨰에 0x4c , 23번쨰에 0x00인걸 알 수 있다.
이걸 식에 대입해보면

i가 22일때 *(a1 + 22) + *(a1+22+1) = 0x4c

i가 23일때 *(a1 +23) + *(a1+23+1) = 0x00

i가 22일때 *(a1+22) + *(a1+23) = 0x4c

i가 23일때 *(a1+23) + *(a1+24) = 0x00
이므로

x + y = 0x4c
y + z = 0x00

다시 생각해보면 char v4[256]이므로 그렇다는 건 입력값이 문자형이라는 것이고 아스키코드에는 음수 값은 존재하지 않는다.
그러므로 y >= 0 , z >= 0 인데 만약 y나z가 0보다 크게 되버리면 y+z = 0x00 이 성립되지 않는다.
결국 y = 0 , z = 0 이라는 소리이고 y가 0이 되었기 때문에 x = 0x4c가 된다.
22번째 바이트는 0x4c , 23번째는 0x00 이런식으로 0번째까지 계산해 나가면 0번 인덱스부터 차례대로


41 6c 6c 5f 6c 31 66 65 6c 33 6e 64 73 5f 77 31 74 68 5f 4e 55 4c 4c 00


이 나오게 되는데 마찬가지로 문자형이였기 떄문에 cyberchef에서 From hex로 읽어들이면

해당 문자열이 나오게 되는데 이 문자열을 프로그램에 입력하게 되면

Correct가 뜨는 걸 확인 할 수 있다.

원래는 생각나는대로 손으로 풀어서 exploit 작성을 안했었지만 공부 겸 exploit을 작성하여 추가하였다.

Exploit


Full exploit은 다음과 같다.

#include <stdio.h>

int main(void) {

	int arr[24] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,76,0 };  // 우리가 찾는 값
	int arr2[24] = { 173,216,203,203,157,151,203,196,146,161,
					 210,215,210,214,168,165,220,199,173,163,
					 161,152,76,0 }; //byte140003000의 decimal 

	for (int i = 0; i <23; i++) {
		arr[22-i] = arr2[22-i] - arr[22 - i + 1];
	}

	for (int i = 0; i < 23; i++) {
		printf("%c", arr[i]); //decimal을 문자형으로 출력
	}


	return 0;
}
profile
https://adawn0106.tistory.com/ <- 이쪽으로 옮겨요! / EN blog: https://adawn0106.github.io/

0개의 댓글

관련 채용 정보