본문 바로가기

dreaMhack/Reverse Engineering

[드림핵] rev_basic_5 풀이/어셈블리어 해석

https://dreamhack.io/

 

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

문제 파일을 다운로드받고 압축을 풀어준다

 

 

 

1. x64bug 해석

ctrl+f9를 누르며 진행하다 화면에 wrong이 출력됐을 때 함수 코드

본 함수의 코드들인데 여기에서 주목해야 할 점은 correct와 wrong을 출력해주는 부분이다

이 이전에 있는 함수에서 해당 문자열을 고를 반환값을 줬을 가능성이 높기 때문이다

call challo.7FF6A2B91000

따라서 위의 코드 속 함수 주소를 더블 클릭 해주면 우리가 해석해야하는 함수의 코드들이 나오게 된다

 

이 함수에서 쓰이는 어셈블리어 함수 종류

mov 두 번째에서 첫 번째로 데이터 이동 jmp 무조건 분기
movzx 길이가 일치하지 않아도 이동(빈 공간 0) jae 결과가 크거나 같으면 분기(부호화 안 된 수)
movsxd 길이가 일치하지 않아도 이동(빈 공간 1) je 결과 값 0이면 분기(이동)
sub 캐리 포함하지 않은 뺄셈 lea 오프셋(데이터 영역) 값을 레지스터로 로드
add 캐리 포함하지 않은 덧셈 xor 배타논리합(값이 달라야 1)
inc 내용 1 증가 ret 스택에 push된 주소로 복귀(리턴)

 

mov: 이전에 사용했던 rcx 속에 있는 수를 rsp+8에 저장해두고

sub: rsp에 18을 빼 메모리를 확장해준다

 

rsp, jmp: 반복 횟수를 0으로 초기화해주고 movsxd 명령어가 있는 위치로 무조건 분기한다

movsxd: 반복 횟수를 rax에 넣은 후

cmd, jae: 저장된 반복 횟수가 누적 18을 넘기거나 같아지기 전까지는 jae 명령어를 무시한다

 

movsxd: 반복 횟수를 rax에 저장해두고

mov, movzx: rcx에 입력값을 넣은 후 입력값의 반복 횟수 번째에 있는 문자를 eax에 넣는다

mov, inc: 다시 반복 횟수를 ecx에 저장해주고 그 값을 1 증가시킨다

movsxd: 바로 위에서 증가시킨 수를 rcx에 넣는다

 

mov, movzx: 입력값을 rdx에 넣고, 위에서 증가시킨 수 번째에 있는 문자를 ecx에 넣는다

add: 반복 횟수 번째에 있는 입력값 문자에 위에서 계산한 문자를 더해준다

 

movsxd: 반복 횟수를 rcx에 넣고

lea: 해당 주소에 있는 정답 문자열을 rdx에 넣는다

movzx: 위의 두 수를 더해서 정답 문자열의 반복 횟수 번째 문자를 ecx에 넣어준다

cmp, je: 정답 문자열과 전 사진에서 계산한 eax 값을 비교해 수가 같을 때

jmp chall5.7FF6A2B91012로 분기해 for문을 반복하고

xor: 수가 같지 않을 때는 함수의 반환값을 0으로 만들어 주고

jmp: ret가 있는 곳으로 무조건 분기해 함수를 끝내버린다

 

 

 

 

2. Ida 해석

프로그램을 시작하고 f5(디컴파일)를 누르면 나오는 화면

ida는 익숙한 C언어 형태로 디컴파일해줘서 x64dbg보다 훨씬 쉽게 해석할 수 있다

위의 코드를 봐도 correct를 프린트해주는 곳의 if문만 잘 보면 해결할 수 있을 것 같다는 생각이 든다

 

if 문 안에 있는 함수(sub_140001000)를 더블클릭하면 내부로 들어와진다

함수의 디컴파일 버전을 보니까 x64dbg보다 훨씬 이해하기 쉬운 형태를 보여주고 있다

byte_140003000에 있는 정답 문자열이 입력값과

연산 결과값과 같아야 correct를 프린트한다는 걸 알 수 있다

 

정답 문자열 = (입력값 + 1) + 입력값

즉, 입력값 n+1 번째 문자 + 입력값 n 번째 문자

 

입력값 = 정답 문자열 - 입력값[n+1]

 

정답 문자열이 있는 주소를 더블 클릭하면

Hex View-1창에 해당 위치에 있는 문자열들이 나열돼 있다

우리가 유추한 식을 이용해 c언어를 코딩해 정답을 알아보자

 

#include <stdio.h>

int main() {
	unsigned char chars[] = { 0xAD, 0xD8, 0xCB, 0xCB, 0x9D, 0x97, 0xCB, 0xC4, 0x92, 0xA1, 0xD2, 0xD7, 0xD2, 0xD6,
		0xA8, 0xA5, 0xDC, 0xC7, 0xAD, 0xA3, 0xA1, 0x98, 0x4C, 0x00 };
	unsigned char res[24] = {0, };

	for (int i = 22; i >= 0; i--) {
		res[i] = chars[i] - res[i+1];
	}

	for (int k = 0; k < 23; k++) { 
		printf("%c", res[k]);
	}
	return 0;
}

 

 

 

 

 

 

정답: DH{All_l1fe_3nds_w1th_NULL}