Try Attack/Reverse Engineering[basic]

EasyCrackMe - reversing.kr

D4tai1 2020. 3. 12.

처음에는 어떤 것도 나와 맞지 않는 것 같지만..

 

어떤 것이든 도전해보세요!

 

 

자석도

 

N극과 S극이 끌리듯이 

 

나와는 맞지 않다고 생각했던 것도

 

반복하다보면 어느순간 가까워져 

 

흥미를 느끼고 있는 분야를 발견할지도 몰라요.

 


우선

 

reversing.kr의 EasyCrackMe부터

 

들여다보겠습니다.

 

1. 정적분석

1) 기초정보확인

[그림1] Detect It Easy로 본 EasyCrack.exe

Type이 PE인 것을 보니 32비트 exe파일이네요.

 

EntryPoint(ImageBase+Address of entrypoint)는 0x401188 입니다.

 

총 4개의 섹션(text, rdata, data, rsrc)이 존재합니다.

 

나와있는 섹션에 대한 간단한 설명을 보태면

 

.text 섹션은

 

코드영역(명령어 서식지)이라고 보면 됩니다.

 

[그림2] .text 섹션

[그림1]에서 ImageBase가 0x400000이니

 

RVA(가상메모리 주소의 오프셋)을 보니 0x1000만큼 떨어져있고,

 

Size of Raw Data(영역의 크기)를 보니 0x4000입니다.

 

즉, .text영역은 0x401000~0x405FFF까지네요.


.rdata는

 

상수로 정의된 내용이 들어있는 읽기전용섹션입니다.

 

보통 런타임 라이브러리에서 사용하는 DLL의 이름이나 에러메세지가 들어있지요.

 

여기는 넘어갈게요. 


.data는

 

전역변수와 지역변수들의 공간입니다.

 

[그림4] .data

RVA(가상메모리 주소의 오프셋)을 보니 0x6000만큼 떨어져있고,

 

Size of Raw Data(영역의 크기)를 보니 0x3000입니다.

 

즉, .text영역은 0x406000~0x408FFF까지네요.

 


.rsrc는

 

음악, 아이콘, 번호 등이 들어있는 리소스영역입니다.

 

여기도 넘어갈게요.

 

7ip) 사실 위에서는

 

파일 상태를 PE View로 확인했지만

 

이뮤니티디버거에서 [Alt + M]을 누르시면

 

[그림5] 이뮤니티디버거에서 [Alt+M]

메모리 내 섹션주소 및 섹션별 접근권한을 알 수 있습니다.

 

나머지는

 

이뮤니티 디버거에 들어가서 보겠습니다.

 


2) 문자열검색

(Search for - All referenced text strings)

[그림6] 문자열 검색

그냥 문자열 나온 것만 가지고 찾아도 되지만 

 

1)에서

 

.rdata(런타임라이브러리 및 상수데이터 서식지)가

 

0x405000~0x405FFF인 것을 알 수 있죠?

 

 

.data(전역변수 및 지역변수 등 존재)가

 

0x406000~408FFF인 것도 알 수 있죠?

 

 

그렇다면

 

[그림6]에서 프로그래머가 넣어서 사용한 변수는

 

0x406000부터 있다는 것을 알 수 있겠네요.

 

7ip) "구지 디버거를 켜야하는 이유를 모르겠다!"

 

싶은 분은 파일을 직접 확인해 보세요!

 

[그림7] EasyCrackMe.exe

파일은 메모리상에 올라가지 않았기 때문에 

 

ImageBase(0x400000)을 제외한 Offset(0x6000)에 가서 확인해보시면 됩니다.

 

[그림6]에서 확인한 문자열들이 보이죠?

 

물론 가독성이 떨어지긴 하지만요.

 

하하


3) API검색

(Search for - All intermodular calls)

 

[그림8] API

PE View에서도 API는 확인할 수 있어요.

 

몇 개 되지 않기 때문에 상상을 해보면?

 

다이얼로그박스를 띄워서 텍스트를 입력받고

 

메세지박스를 띄우고 다이얼로그박스를 닫는 프로그램을 보이네요.

 

 

여기까지 실행하지 않고 확인해 보았구요.

 

다이얼로그박스에서 입력받은 텍스트를 얻어오는 GetDlgItemTextA와

 

메세지를 출력해주는 MessageBoxA에는 

 

아래서 진행할 동적분석을 위해 BP를 걸어두었습니다.

 

7ip) 예를 들어 모든 메세지박스에 BP를 걸고 싶을 경우?

 

[그림9] 특정함수 실행 시 BP걸기

이와 같이 할 경우

 

메세지박스가 호출되는 모든 instruction에 BP를 걸 수 있다는 것은

 

비밀입니다.

 


2. 동적분석

인연은 붙잡아야 운명이 된다고 하져?

 

이게 브레이크 포인트를 걸어야 하는 이유입니다.

 

하하

 

 

문자열에 BP를 걸 수도 있지만

 

저는 [그림9]와 같이 API를 호출하는 부분에 BP를 걸어보았습니다.

 


 

[1] EP(EntryPoint)

 

[그림1]에서 확인한 것과 같이 0x401188이 진입점입니다.

 

[그림10] Entrypoint

여기서 F9를 눌러서 쭉 실행을 해보겠습니다.

 

 

[그림11] 다이얼로그박스

다이얼로그박스가 나왔습니다.

 

저는 "5h4d0\"를 입력 후 확인을 눌렀습니다.

 

Shadow(그림자)..

 

보이지 않게 뒤를 지켜주니 멋있잖아요?

 

하하..

 


 

[2] GetDlgItemTextA

 

[그림12] GetDlgItemTextA

"5h4d0\"를 입력하고 확인을 누르니

 

0x4010AA에서 멈춰있죠?

 

이 함수가 실행되면 EAX의 0x19F7D4의 주소에

 

제가 입력한 "5h4d0\"가 저장되어 있겠죠?

 

[그림13] GetDlgItemTextA 실행 후

[네모1]의 EAX가 6인 것을 보니 입력한 글자수가 6바이트네요.

 

[네모2]를 보니 0x19F7D4의 주소에 입력한 "5h4d0\"가 저장된 것을 알 수 있네요.

 

[네모3]에서는 [ESP+5]가 0x61(소문자 a)와 같은지 비교하고

 

화살표를 따라가보면 현재 ESP는 0x19F7D0입니다.

 

5를 더하면 0x19F7D5의 값을 확인하면 됩니다.(노란색 박스)

 

[네모4]에서는 다르면 0x401135로 넘어가네요.

 

[그림14] 0x401135

부정확한 패스워드를 입력했다는 메세지박스가 출력하는 곳이네요.

 

이곳은 가면 안되겠죠?

 

이로서 두 번째 글자가 a여야 합니다.

 


 

[3] strncmp

 

[그림15] strncmp

0x401150은 복잡하지 않기 때문에

 

들어가서 하나씩 확인해봐도 좋습니다만

 

먼저 함수의 형태를 확인해보겠습니다.

 

 

첫 번째 인자는 ECX(제가 입력한 문자의 세 번째 글자부터 끝까지)

 

두 번째 인자는 "5y"

 

세 번째 인자는 2

 

입니다.

 

그리고 아래 노란 박스의 0x4010CB를 보면 

 

[TEST EAX, EAX] 명령어로 EAX가 0인지 확인합니다.

 

0x4010CD에서는 0이 아니면 0x401135(잘못된 메세지박스)로 이동합니다.

 

즉!! 

 

strncmp("첫 번째 문자열", "두 번째 문자열", "비교할 문자 수")함수와 동일하며

 

strncmp는 두 문자가 동일할 경우 0을 반환하고, 다르면 1을 반환합니다.

 

if(!strncmp(0x19F7D6, "5y", 2)) {
	MessageBoxA(NULL, "Incorrect Password", "EasyCrackMe", MB_OK|MB_ICONHAND|MB_APPLMODAL);
}

 


 

[4] 그 외 나머지 문자열 비교

 

[그림16] 나머지 문자열 비교

 입력한 5번째 글자부터 문자열이 R3versing과 같은지 비교하고 있습니다.

 

방법은 한 글자씩 DL과 BL에 넣고 비교 후 

 

1바이트 증가 후 다시 DL과 BL을 비교합니다.

 

이후 내가 입력한 문자열(EAX)과 R3versing의 앞 2글자씩 지웁니다.

 

아마 1바이트씩 2번 비교했으니 비교한 2개를 빼려고 한 모양입니다.

 

그리고 다시 0x4010DA에 가서 비교하는 것을 반복합니다.

 

틀리면 0x401135(잘못된 메세지박스)로 이동합니다.

 

 

두둔!

 

이제 거의 다왔습니다!!

 

[그림17] 맨 첫 문자 비교

맨 첫 문자가 0x45('E')와 같은지 비교 후 

 

틀리면 0x401135(잘못된 메세지박스)로 이동하고

 

맞으면 아래있는 메세지박스를 출력하고

 

다이얼로그박스를 닫습니다.

 

그리고 프로그램을 종료하네요.

 

Flag = "Ea5yR3versing"

 

여기까지 따라오시느라 고생하셨습니다.

 

벌써 끝나니까 허무한가요?

 

그럼 이 기세를 이어서 

 

Easy Keygen.exe도 풀어보겠습니다.

 

이것은 32비트 exe파일인 것만 확인한 후

 

정적분석을 하지 않고 바로 동적분석으로 넘어가겠습니다.

 

 

[그림18] Easy Keygen.exe 실행화면

 

먼저 실행시키니 이름을 입력하고

 

시리얼번호를 입력하라고 합니다.

 

 

텍스트로 검색 후 BP를 걸어보겠습니다.

 

 

아래 그림은 "Input Name : "을 출력하고 문자열을 입력받은 이후입니다. 

[그림19] "Input Name : " 출력 후 scanf 다음

그냥 한 줄 한 줄 따라서 적기만 하면 되는 부분이라 

 

요약해보면 

 

int xor_data[] = {10, 20, 30};

printf("Input Name : ");
scanf("%s", 0x19FE18);

int ebp = 0;
int esi = 0;

if (strlen(0x19FE18)) {
	do {
		if (3 <= esi) {
			esi = 0;
		}

		ecx = (xor_data[esi] ^ (0x19FE18 + ebp));

		sprintf(0x19FE7C, "%s%02X", 0x19FE7C, ecx);

		ebp++;
		esi++;

	} while(ebp < strlen(0x19FE18));

}

printf("Input Serial : ");
scanf("%s", 0x19FE18);

if (!strcmp(0x19FE18, 0x19FE7C)) {
	printf("Correct!\n");
}
else {
	printf("Wrong\n");
}

17라인의 sprintf부분을 풀어보면

 

"%s%02X"의 내용을 첫 번째 인자인 0x19FE7C에 저장하라는 말이에요.

 

%s는 세 번째 인자인 0x19FE7C의 문자열을

 

%02X는 ecx레지스터에 있는 값을 주소로 본다는 말입니다.

 

(한 자리일 경우 앞에 십의자리에 0으로 표시하면서)

 

풀어보면 기존문자열 + 아스키코드의 값을 실제 숫자로 변경해서 저장한다는 말이겠죠?

 

기존 문자열을 더하는 이유는 반복문을 돌면서 앞에서 찍은 숫자에 이어붙이기 위함이지요.

 

 

키 값은 

 

5B 13 49 77 13 5E 7D 13 을

 

자리수 % 3하여 나온 값이

 

0이면 10과 1이면 20과 2면 30과 해당자리의 16진수와 xor연산 후

 

나온 16진수 값을 아스키코드로 변환하면 됩니다.

 

 

댓글