11.1 실행
크랙하려는 파일을 먼저 실행해보면 위와 같은 화면이 출력된다. [확인] 버튼을 누르면 아래와 같은 창이 나온다.
전형적인 serial crackme이다. 화면의 파란 글씨를 읽어보면 registration을 위해 'SmartCheck'을 사용하라고 되어있다. 그리고 처음 나오는 nags를 없애라는 말도 같이 써있다. 실행을 통해 우리가 해야하는 것이 2가지임을 알 수 있다.
1. Nags 화면 없애기(메시지 박스 제거)
2. Regcode 찾기
11.2 분석
1. 목표(1) - 메시지 박스 제거
Nags화면(메시지 박스)는 파일을 처음 실행시킬 때와 Nags 버튼을 눌렀을 때 출력이 된다.
OllyDbg로 파일을 열면 8장 실습에서 보았던 Visual Basic 코드를 볼 수 있다. 해당 파일의 코드를 예측해보면, 메시지 박스를 제거하기 위해선 메시지 박스의 주소를 알아야 한다. Visual Basic에서 메시지 박스 출력함수는 MSVBVM50.rtcMsgBox이다. Search for - All intemodular calls 명령어를 사용해 메시지 박스의 주소를 찾는다.
메시지 박스 함수 하나를 골라 위와 같이 BP를 건다. 이후 Destination을 누르면 메시지 박스 함수들이 맨 위로 올라온다.
이 상태에서 실행[F9] 시키면 BP가 설치된 곳에서 멈추게 된다.(메시지 박스가 있는 곳)
402CFE 주소에서 실행이 멈췄다. 해당 주소에서 스크롤을 위로 올리면 파일 실행시 보았던 메시지 문자열들을 볼 수 있다. 다시 실행 [F9]를 실행시키면 메시지 박스가 출력되고 확인 버튼을 누르면 메인 화면이 나온다. 이때 [Nags?] 버튼을 누르면 같은 주소에서 멈추게 된다. 이는 처음 나타나는 화면의 메시지 박스와 메인 화면의 Nags 버튼을 통해 나타나는 메시지 박스 모두 같은 코드에서 실행되고 있다는 것이다. 따라서, 한 곳만 패치하면 두 화면 모두 수정이 가능하다.
2. 패치(1) - 메시지 박스 제거
메시지 박스 호출을 제거하는 방법은 2가지가 있다.
1. CALL 명령어 제거하기
2. CALL 명령어가 속한 함수(상위 함수)를 호출하지 못하게 하기
먼저 CALL 명령어를 제거하는 방법부터 적용해보면,
CALL <JMP.&MSVBVM50 .#595>
기존 명령어를 아래와 같이 수정하면 된다.
ADD ESP, 14
NOP
NOP
CALL은 5바이트의 명령어이기 때문에 ADD 명령어(3바이트) 이후 1바이트의 NOP으로 채워야한다. 그리고 ADD 함수를 쓰는 이유는 CALL명령어로 호출한 함수의 파라미터를 정리하기 위함이다. 해당 함수의 파라미터의 크기가 14인 것을 확인하는 방법은 직접 해당 함수 안으로 들어가 RETN 값을 확인하였다. (RETN 14 - stdcall 형식)
CALL 명령어로 함수를 호출한 후 리턴 값을 특정 변수에 저장한다. 그리고 여기서 함수(메시지 박스)의 리턴 값은 1([확인] 버튼의 의미)이어야 한다. 1 이외의 값이 지정되면 프로그램은 종료된다. 따라서 CALL 명령어를 제거하는 방식을 이용하면 1 이외의 값이 지정되어 프로그램이 종료되기 때문에 다른 방법을 사용해야 한다.
+) 그렇다면 NOP 대신에 MOV EAX, 1 명령어를 넣으면 된다?
==> 이렇게 수정한 코드는 총 8바이트이기 때문에 뒤쪽 코드를 침범하게 된다.
두 번째 방법인 CALL 명령어가 속해있는 상위 함수의 호출을 막는(or 바로 리턴하기)것을 적용해보자.
먼저 메시지 박스를 CALL 하는 명령어가 속한 함수의 시작 부분(스택 프레임 생성)을 찾는다. 메시지 박스 함수 호출 명령어의 상위 함수를 호출 하지 못하게 하거나 바로 리턴해버리면 메시지 박스 출력 함수는 호출되지 않는다. 따라서 위 사진에 표시된 두 명령어를 아래와 같이 수정한다.
여기에서 알아야 할 점은 함수에 전달된 파라미터만큼 스택을 보정해야 한다는 것이다. 보정을 위해선 전달된 파라미터의 개수를 알아야한다. 파라미터의 개수를 확인하는 방법은 아래와 같다.
먼저 해당 함수를 호출한 주소를 찾아야 한다. Return Address는 함수를 호출한 주소의 다음 주소이다.
Return Address의 값은 7401E5A9이고 msvbvm50.dll 모듈 영역이다. Return Address로 이동하면 아래와 같다.
7401E5A7 주소가 함수를 호출한 곳이다. 파일을 다시 실행시켜 이 주소에 BP를 걸고 실행시키면 EAX 값을 알 수 있다.
EAX 값은 402656인것을 알 수 있고 JMP 명령어로 초기의 402C17주소로 이동하는 것을 알 수 있다. 따라서 CALL EAX 명령어 실행 전과 후의 스택 주소를 확인하면 402C17주소의 파라미터 개수를 알 수 있다.
파라미터의 개수 = 19FABC - 19FB8 = 4
3. 목표(2) - Registration Code 찾기
Registration Code에 아무 값이나 입력하면 에러 메시지 박스가 출력된다.
파일 실행을 통해 에러 메시지 문자열이라는 단서를 얻을 수 있다. 이후 OllyDbg에서 해당 문자열을 검색해보면
402A69 주소에 있다는 것을 알 수 있다. 더블 클릭으로 해당 주소로 이동한다.
위 코드에서 스크롤을 조금 올리면 402A2A 주소에 "I'mlena151"이라는 문자열과 바로 아래 주소에 __vbaStrCmp() 함수 호출 코드를 볼 수 있다. 해당 함수는 VB에서 문자열을 비교하는 함수이다. 즉, 사용자가 입력한 값과 "I'mlena151" 문자열을 비교한다는 것을 알 수 있다. 스크롤을 조금 더 올려보면
정확한 값을 입력했을 때 성공 메시지 박스를 출력하는 코드를 볼 수 있다. 에러 메시지 박스와 동일하게 4028BD 주소에 "I'mlena151" 문자열이 있고 그 아래에 __vbaStrCmp 함수가 있다. 따라서 Regstration Code가 "I'mlena151"이라는 것을 알 수 있다.
해당 값을 입력하면 성공 메시지 박스를 출력한다!
출처 : 리버싱 핵심원리(이승원, 인사이트)
'리버싱 핵심원리' 카테고리의 다른 글
[리버싱 핵심원리] 22장 - 악의적인 목적으로 사용되는 키로거 (0) | 2023.05.09 |
---|---|
[리버싱 핵심원리] 21장 - Windows 메시지 후킹 (0) | 2023.05.09 |
[리버싱 핵심원리] 10장 - 함수 호출 규약 (0) | 2023.05.05 |
[리버싱 핵심원리] 8장 - abex' crackme #2 (0) | 2023.05.05 |
[리버싱 핵심원리] 7장 - 스택 프레임 (0) | 2023.05.01 |