본문 바로가기

공부/리버싱

리버싱 공부 08

<리버싱 핵심 원리>로 공부하였다.

 

08 abex' crackme #2

8.1. abex' crackme #2 실행

crackme2.exe

일단 바로 실행시켜보았다. 이름과 시리얼 키를 입력하는 칸이 있고 체크, about, 나가기 버튼이 있다.

아무것도 입력하지 않고 check를 누르면 위 대화 상자가 뜬다.

다시 4글자 이상 치고 시리얼키를 0글자 이상 친 후 check를 누르면 위 대화 상자가 뜬다. (틀렸을 때의 대화 상자겠지)

About 버튼을 누르면 위의 대화상자가 뜨고, Quit 버튼을 누르면 프로그램이 종료된다.

대략적인 구성은 알았으니 이제 디버거를 통해 확인해 보자.

 

8.2. Visual Basic 파일 특징

그 전에 abex' 2nd crackme 파일은 Visual Basic으로 제작되었다고 한다. Visual Basic 파일의 특징을 알아보자.

 

8.2.1. VB 전용 엔진

VB 파일은 MSVBVM60.dll 이라는 VB 전용 엔진을 사용한다. VB 엔진의 사용 예는 메시지 박스를 출력하고 싶을 때 VB 소스코드에서 MsgBox() 함수를 사용한다. VB 컴파일러는 MSVBVM60.dll!rtcMsgBox() 함수가 호출되도록 만들고, 함수 내부에서 Wind32 API인 user32.dll!MessageBoxW() 함수를 호출해주는 방식으로 동작한다. (VB 소스코드에서 user32.dll!MessageBoxW()를 바로 호출하는 것도 가능)

 

8.2.2. N(Native) code, P(Pseudo) code

VB 파일은 컴파일 옵션에 따라 N, P code로 컴파일이 가능하다. N code는 일반적인 디버거에서 해석 가능한 IA-32 Instruction을 사용하지만 P code는 인터프리터 언어 개념으로 VB 엔진으로 가상 머신을 구현해 자체적으로 해석 가능한 명령어를 사용하는 것이다. 따라서 VB의 P code를 정확히 해석하려면 VB 엔진을 분석하여 에뮬레이터를 구현해야 한다.

 

P code는 자바(Java Virtual Machine), 파이썬(Python 전용 엔진) 등의 언어들과 비슷하다고 생각하면 된다.

이런식으로 사용하면 이식성이 좋다는 장점이 있다.

 

8.2.3. Event Handler

VB는 주로 GUI 프로그래밍을 할 때 사용되며, IDE 인터페이스 자체도 GUI 프로그래밍에 최적화되어 있다. 

즉 VB 프로그램은 Windows 운영체제의 Event Driven 방식(=이벤트에 반응하여 동작을 변경하는 방식)으로 동작하기 때문에 main() 혹은 WinMain()에 사용자 코드(우리가 디버깅을 원하는 코드)가 존재하는 것이 아니라, 각 event handler에 사용자 코드가 존재한다. 그러므로 abex' crackme #2에서는 Check 버튼 handler에 사용자 코드가 존재할거라 추측할 수 있다.

 

8.2.4. undocumented 구조체

VB에서 사용되는 각종 정보들은 내부적으로 구조체 형식으로 파일에 저장된다. Microsoft에서는 이러한 구조체 정보를 정식으로 공개하지 않았기 때문에 VB 파일의 디버깅에 어려움이 있다.

 

8.3. Start debugging

Entry Point

EP 주소는 401238이다. EP 코드에서 처음 하는 일은 VB 엔진의 메인 함수를 호출하는 것이다. 

401238 : MainStruct 구조체 주소(401E14)를 스택에 입력.(ThunRTMain의 파라미터)

40123D : ThunRTMain으로 점프한다.

이 세 줄의 코드가 startup 코드이다. 

 

8.3.1. 간접호출

40123D 주소의 함수호출은 JMP 명령을 통해서 가는 간접 호출 방식을 쓰고 있다. 이는 VB 컴파일러에서 많이 이용된다.

 

8.3.2. RT_MainStruct 구조체

RT_MainStruct 구조체는 ThunRTMain() 함수의 파라미터로 여기서는 401E14 주소에 존재한다.

이 구조체는 공식적으로는 공개하지 않았지만, 인터넷에 분석된 자료가 공개되어있다.

RT_MainStruct 구조체의 멤버는 또 다른 구조체의 주소들이다. 즉 VB 엔진은 파라미터로 넘어온 RT_MainStruct 구조체를 가지고 프로그램의 실행에 필요한 모든 정보를 얻는다는 걸 알 수 있다. 

 

8.3.3. ThunRTMain() 함수

ThunRTMain() 코드 시작 부분

이 부분은 ThunRTMain() 코드 시작 부분으로 MSVBVM60.dll 모듈의 주소 영역이다. 즉, VB 엔진의 코드이다.

 

8.4. crackme 분석

8.4.1. 문자열 검색

처음에 본 메시지 박스의 문자열들을 확인할 수 있다. 해당 부분으로 이동해보자.

자 그럼 이 시점에서 우리는 참조할 수 있는 문자열에서 Congratulations가 있는 것으로 보아 비교문을 통해 실패시, 성공시 나뉘는것을 추측할 수 있다. 그럼 그 비교문은 wrong serial 대화상자 코드의 위쪽에 있을 거라고 예상 가능하다. 

AX는 EAX의 16비트 부분이고, EAX는 일반적으로 함수의 리턴값을 저장하는 레지스터이다.

위 사진 속 403329 주소에서 vbaVarTstEq 함수(Name과 Serial을 검사하는 함수라고 짐작)의 리턴값을 AX에 저장하였고,

리턴 값(AX)을 비교 한 후(TEST 명령어가 비교 역할을 수행하게 되는 것 -> AX가 0이라면 TEST AX, AX의 결과도 0이므로 ZF를 1로 세팅한다.)

40332 주소의 조건 분기에 의해 두 갈래로 나뉘게 된다. (JE -> ZF가 1이면 점프, 0이면 다음 줄)

 

8.4.2. 문자열 주소 찾기

403329 주소에서 문자열 비교 함수 위에 두 개의 PUSH 명령어는 비교 함수의 파라미터가 될 것이다.

403321 주소에서 의미하는건 스택 내의 주소를 의미하는데 즉, 이 말은 로컬 객체의 주소를 뜻한다는 것이다.

'공부 > 리버싱' 카테고리의 다른 글

리버싱 공부 10  (0) 2022.01.16
리버싱 공부 09  (0) 2022.01.16
리버싱 공부 07  (0) 2022.01.09
리버싱 공부 06  (0) 2022.01.09
리버싱 공부 05  (0) 2022.01.09