안 쓰던 블로그

dreamhack rev-basic-5 풀이 본문

CTF/Reversing

dreamhack rev-basic-5 풀이

proqk 2020. 9. 22. 20:40
반응형

굉장히 익숙한 main함수

자연스럽게 함수 들어간다

 

처음에 스택 공간 할당하고 CMP RAX, 18과 MOV EAX, 1이 한 세트니까 for문을 0x18번 돈다는 것을 알 수 있다

플래그가 총 0x18(24)글자라는 걸 생각하고 아래 for문을 본다

for문 안에서는 아래같은 연산을 한다

 

1) 문자열 받은 것과 연산

RAX에 현재 카운터 주소값의 값을 넣고 RCX에는 입력받은 문자열 시작점 주소를 넣는다 

EAX에 [시작점+카운터값]주소의 값을 넣으니까 a[i]가 된다(문자열이 a라고 할 때)

 

MOV ECX, DWORD PTR SS:[RSP]에서 RSP는 지금 돌고 있는 카운터 값이다

카운터 값을 ECX에 넣는다는 의미이다

 

INC는 증감 연산자이다 피연산자++ 동작을 한다

지금은 ECX를 ++하고 있다

RCX에다가 ECX를 넣는다

 

결론적으로 RCX에는 카운터 값+1이 있게 된다

 

2) ADD EAX, ECX

RDX에 문자열 시작점 주소 넣고

RDX+RCX만큼 떨어진 만큼 있는 값을 ECX에 넣는다

근데 RCX는 아까 i+1이었고 a[i+1]이 된다

 

EAX는 아까 구한 a[i]이고, EAX값과 ECX값을 더한다

즉 a[i+1]+a[i] 가 된다

 

두 값을 더한 값이 data한 자리랑 같아야 하니 최종 식은 a[i]+a[i+1]==data[i]

첫 번째 글자+두 번째 글자

두 번째 글자+세 번째 글자.. 이런 식으로 계속 연산해서 구하는 문제였다

 

3) 7FF69B163000주소의 문자열과 비교한다

RCX에 길이를 가져온다

RDX에 7F~주소의 시작값 가져온다

무슨 값인지는 덤프로 확인할 수 있다

ECX에 저 문자열이 들어간다

아까 구한 EAX와 지금 구한 ECX를 비교한다

 

아까 flag 문자열의 길이는 0x18(24)였는데 4C까지 23글자라서 마지막은 0값이었다

마지막이 0이니까, 아까 식 a[i] + a[i+1] = data[i]를 반대로 생각해서 마지막 값부터 저 식대로 채워주면 쉽게 flag를 알 수 있다

반대로 하면 a[i] = data[i] - a[i+1]

 

#include <iostream>
using namespace std;

int main() {
	unsigned char data[] =
	{
		0xAD,0xD8,0xCB,0xCB,0x9D,0x97,0xCB,0xC4,
		0x92,0xA1,0xD2,0xD7,0xD2,0xD6,0xA8,0xA5,
		0xDC,0xC7,0xAD,0xA3,0xA1,0x98,0x4C,0x00,
	};
	char flag[24] = { '\0' };
	for (int i = 22; i >= 0;i--) {
		flag[i] = data[i] - flag[i + 1];
	}
	cout << flag;
}

C++로 그대로 구현을 해 주면 플래그를 얻을 수 있다.

반응형

'CTF > Reversing' 카테고리의 다른 글

VA, RVA, RAW 개념  (1) 2020.09.29
Ghidra 기드라 분석 오류 해결 방법  (0) 2020.09.24
제출 못 한 것들 저장용  (0) 2020.09.22
dreamhack rev-basic-4 풀이  (0) 2020.09.22
x64의 기초  (0) 2020.09.22
Comments