본문 바로가기

컴퓨터와 보안/리버싱

abex' crackme #1 분석

crackme라는 프로그램은 말 그대로 크랙 연습 목적으로 작성되어 공개된 프로그램이다.

abexcm1.exe
0.01MB

위의 파일을 이용해 크랙 연습을 진행해 보겠다.

 

파일을 실행시키면 다음 문구가 뜬다. HD를 CD-Rom처럼 생각하게 하라니 무슨 소리일까?

 

ollydbg를 켜서 파일을 분석해본다.

 

ollydbg

다음과 같이 나온다. (EP코드가 매우 짧은 이유는 abex' crackme 파일이 어셈블리 언어로 만들어 졌기 때문이라고 한다.)

 

일단 F8키를 쭉 쓰면서 파일이 어떻게 진행되는지 파악해본다.

(아직 디버깅과 친숙하지 않기도 하고 파일이 짧아 초심자의 기운을 살려 처음부터 F8연타를 하면서 어떻게 진행되는지 알아보았다.)

F8연타를 하다보니 알게된 점이 있다.

바로 

아랫부분의 ok, I really think that your HD is a CD-ROM! 이 JMP SHORT abexcm1.00401050이라는 명령어로 인해 실행되지 않고 바로 ExitProcess로 넘어가 버린다는 것이다.

 

이를 통해 유추할 수 있는 건 JMP라는 명령어를 통해 주소를 뛰어넘을 수 있고 이미 이 파일 안에는 정답을 띄울 수 있는 부분이 존재한다는 것이다.

 

이 사실을 통해 오답메세지를 띄우는 명령어의 윗쪽에 JMP 명령어가 존재하는지 살펴보았다.

 

찾아보니 있다! 저 JMP 명령어는 바로 아래주소로 넘어가게 하는 역할을 한다.

위 명령어를 살짝 손보면 정답을 끌어낼 수 있을 거 같다.

 

점프 위치를 무자비하게 수정해버린다.

 

그러면 정답이 뜨는 것을 확인할 수 있다.

또 다른 풀이로는

 

무자비하게 문자열 버퍼를 직접 수정하는 방법이다. 

뭔가 허접하긴 하지만 말은 된다.

Hello world! 리버싱3 포스팅해서 했던 방법 2가지 전부 사용이 가능하다.

근데 이게 맞나 싶다;;

CD-ROM을 진짜 수정해서 HD로 인식하게 하는 방법이 또 따로 있을까?

 

우선 풀었으니 책을 보면서 확인해본다.

 

책을 보니 위 코드에서 사용된 어셈블리 명령어를 정리해준다.

 

명령어 설명
PUSH 스택에 값을 입력
 CALL 지정된 주소의 함수를 호출
INC 값을 1 증가
DEC 값을 1 감소
JMP 지정된 주소로 점프
CMP 주어진 두 개의 operand 비교
*SUB 명령어와 동일하나 operand 값이 변경되지 않고 EFLAGS 레지스터만 변경됨
(두 operand의 값이 동일하다면 SUB 결과는 0이고 ZF = 1로 세팅됨)
JE 조건 분기(Jump if equal)
*ZF = 1이면 점프

근데 크랙 방법은 내가 한 것과 동일하게 진행한다.

다만 스택에 파라미터를 전달하는 방법을 설명하는데 이 또한 유용한 정보인 거 같아 정리한다.

 

스택에 파라미터를 정리하는 방법

00401000~0040100E 주소 사이의 명령어를 보면 MessageBoxA() 함수를 호출하기 전에 4번의 PUSH 명령어를 사용하여 필요한 파라미터를 '역순'으로 입력하고 있다.

 

위 어셈블리 코드를 C언어로 번역하면 다음과 같다.

MessageBox(NULL, "Make me think your HD is a CD-Rom.", "abex' 1st crackme", MB_OK|MB_APPLMODAL);

 

실제 C 언어 소스코드에서 함수에 넘기는 파라미터의 순서가 어셈블리 언어에서는 '역순'으로 넘어가는 것에 유의하면 될 거 같다.

왜 역순으로 입력될까? 이는 '스택 메모리 구조'의 FILO 특성 때문이다.

 

디버거를 이용해 EIP = 0040100E 시점까지 진행한 다음 스택을 보면 아래 이미지와 같다.

x86 환경에서 스택은 아래로 자라기때문에 디버거에서 스택을 보면 위 이미지와 같이 MessageBoxA() 함수의 첫째 파라미터가 스택의 제일 위에 보이고, 마지막 파라미터가 아래에 쌓인다.

 

따라서 MessageBoxA() 함수 내부에서는 스택에서 파라미터를 하나씩 꺼내게 될 텐데, 스택의 FILO 구조에 따라서 첫 번째 파라미터부터 꺼낼 수 있게 되는 것이다. 즉 파라미터를 꺼내서 사용하는 MessageBoxA() 함수 입장에서는 스택에 파라미터의 순서대로 들어 있는 셈이 되는 것이다.

 

즉 자료를 정리할 때 API 함수가 사용되는 시점을 위주로 정리한다고 생각하면 될 거 같다!

'컴퓨터와 보안 > 리버싱' 카테고리의 다른 글

Lena's Reversing for Newbies  (0) 2021.04.15
abex' crackme #2 분석  (0) 2021.04.12
프로세스 메모리 구조와 스택 프레임 구조  (1) 2021.04.04
어셈블리어와 레지스터  (0) 2021.04.04
PE File Format - pestudio  (0) 2021.04.02