본문 바로가기

리버싱

리버싱 #04 abex crackme 2 분석

crackme2 실행

crackme2 실행 파일을 실행시키면 로그인 창(?) 같은 것이 출력됩니다.

name에는 abcd를 Serial에는 1234를 입력한 후 check를 누르게 되면

 

시리얼 번호가 틀렸다는 오류 메시지 박스가 출력됩니다.

이문제에서의 목표는 crackme1과 같이 성공 메시지 박스가 출력되도록 하는 것과 올바른 시리얼 번호를 찾는 방법입니다. 

Entry Point

디스 어셈 코드로 돌아와서 시작 주소는 00401238입니다.

스택에 00401 E14 주소를 입력하고 다음 수행 명령어인 CALL 명령어의 변숫값 출력 창을 보게 되면 어떤 함수를 call 하는지 알 수 있습니다. 

변숫값 출력 창은 어셈블리 코드 창 바로 아래에 위치하고 있습니다.

0040123D주소 변수값 출력창

CALL명령어에서는 00401232 주소에서 JMP명령어로 ThunRTMain() 함수로 가게 됩니다.

ThunRTMain() 함수를 분석하기 전에 ThunRTMain() 함수로 가는 방식이 이전과 다르게 직접적으로 call 하는 것이 아닌

00401232 주소에 JMP명령어를 통해 함수로 가는 방식입니다.

 

이번장에서는 ThunRTMain() 함수를 다루는 것이 아니기 때문에 잠시 접어두고 crackme분석을 해보겠습니다.

Crackme1과는 다르게 어디서부터 시작하기가 참 막막하기 때문에 문자열 검색 기능을 사용해서

이전에 하나하나 분석하는 것보다 간단한 방법으로 접근하겠습니다.

 

문자열 검색 기능 사용학 위해서는 코드 영역에서 마우스 우클릭 -> [Search for] -> [All referenced text strings]로 가면 아래와 같은 창이 나타나게 됩니다.

문자열 검색 기능 사용

스크롤을 해서 문자열들을 살펴보면 "Congrtulations!"의 성공 문자열과 "Nope, this serial is wrong!"의 실패 문자열이 있는 것을 확인할 수 있습니다.

 

그럼 성공 메시지 박스인 "Congratulations!"문자열을 더블 클릭하여 00403372 주소로 이동하겠습니다. 

 

성공 문자열로 이동

성공 메시지 박스와 실패 메시지 박스가 출력은 비교를 통해 결정될 것입니다.

"Congratulations" 문자열이 있는 00403372 주소에서 위에 있는 코드들을 보게 되면 조건 분기 명령어인 JE 명령어가 바로 위에 있는 TEST AX AX 코드의 수행 결과를 통해 점프를 할지 말지를 결정합니다. 

 

 

TEST명령어에서 비교하게 되는 AX는 바로 위 CALL명령어에서 호출된 vbaVarTstEq() 함수의 리턴 값입니다.

그럼 vbaVarTstEq() 함수에서 입력한 문자열을 비교할 것이라고 유추할 수 있고 vbaVarTstEq() 함수 위에 오는 PUSH 명령어 EDX, EAX 2개는 함수의 파라미터가 될 것입니다.

 

EDX, EAX값을 위해 해당 스택에 있는 주소를 Follow in dump를 통해 덤프 값을 확인하면

EDX EAX 스택

EDX에는 시리얼 값이 EAX에는 사용자가 입력한 시리얼 값이 있는 것을 확인할 수 있습니다. 

프로그램을 올바른 시리얼 값을 입력하여서 다시 실행하면 성공 메시지 박스가 출력되는 것을 확인할 수 있습니다.

올바른 시리얼 값 입력 실행

 

책의 내용을 빌려 시리얼 값이 생성되는 알고리즘을 보면 Name값을 기반으로 시리얼 값이 결정되다는 것을 확인할 수 있습니다. 

 

물론 시리얼 값을 얻어 성공 메시지 박스가 출력되는 것까지는 했지만 시리얼 값이 생성되는 과정 또한 분석하고 이번장을 마무리하겠습니다.

 

시리얼 넘버를 생성하는 함수는 아마도  name과 시리얼 값을 입력한 후 [Check] 버튼을 눌렀을 때 생성될 것입니다.

이전에 보았던 조건 분기 명령어 또한 [Check] 버튼이 누른 뒤에 그에 대한 결과로 메시지 박스를 출력하기 때문입니다.

 

 

Button event handler

이전에 한 것처럼 메시지 박스에 있는 문자열로 이동하면 해당 위치가 [Check] 버튼의 이벤트 핸들러 일 것입니다. 

그럼 위로 드레그 하여서 시작 부분부터 분석해 나가겠습니다.

 

하지만 이전에 crackme 1처럼 적은 양의 코드가 아니기 때문에 약간의 책의 지식을 빌려 빠르게 찾아가겠습니다.

( 저는 처음 리버싱을 할 때 아무 지식 없이 함수 시작부터 코드 하나하나 분석해나갔습니다. 한 번쯤은 해보는 것도 추천합니다. )

 

책의 내용을 빌려서

  • Name 문자열을 GetWodowText, GetDlgItemText 등의 API를 사용하여 읽어 드릴 것이고
  • 루프를 돌면서 해당 문자열을 암호화를 할 것입니다.

위 2가지 내용을 가지고 생각해보면 결국 함수를 불러오는 CALL명령어를 집중적으로 분석하면 시리얼 넘버 생성 알고리즘을 찾을 수 있을 것입니다.

 

가장 먼저 디버깅을 하다 보면 Name의 문자열을 읽어 오는 함수를 찾을 수 있습니다.

 

Name 읽어 오는 함수 

그리고 읽어온 문자열( abcd )을 0019F170 주소에 저장해 놓을 것을 확인할 수 있습니다.

저장된 Name 문자열

 

이다음에 00403197주소 부터 00403197 주소까지 반복문이 등장합니다.

 

반복문 시작
반복문 끝

그리고 이 반복문이 이전에 읽어드렸던 문자열 ( abcd )를 암호화하는 루프가 됩니다. 

 

문자열 암호화하는 과정

 

루프를 디버깅하다 보면 주소 004031F0에 vbaStrVarVal() 함수의 반환 값으로 문자열의 첫 값을 가지고 옵니다.

EAX 덤프창

vbaStrVarVal() 함수 수행 후 반환 값이 저장되는 EAX의 덤프를 따라가면 Name 문자열의 첫 값인 " a "가 저장되어 있는 것을 확인할 수 있습니다.

 

rtcAnsiValueBstr() 함수 반환 값

바로 다음에 오는 rtcAnsiValueBstr() 함수는 이전에 받아온 문자열 " a "의 아스키코드 값인 61을 EAX 레지스터에 저장되어 있는 것을 확인할 수 있습니다.

생성된 시리얼 값

이후 계속 진행하다 보면 첫 시리얼 값인 " C5 "가 EDX 레지스터에  저장돼있는 것을 확인할 수 있습니다.

C5라는 값이 생성되는 이유는 rtcAnsiValueBstr() 함수의 동작 과정을 분석해보면 문자열에 64를 더하여서 시리얼 값을 생성하게 됩니다. ( 즉   a --> 61 --> 61 + 64 --> C5 )

 

시리얼 값 연결

마지막으로 vbaVarCat() 함수에서 생성된 시리얼 값을 연결해줍니다.

 

그렇다면 마무리하기 전에 반복문은 어떤 식으로 반복되는지 살펴보고 마무리하겠습니다.

물론 직접 디버깅을 했기 때문에 반복문이 4번 돈다는 것을 확인할 수 있습니다.

 

조금 더 코드를 살펴보면 반복문이 시작되는 부분과 마지막 코드 2 코드를 통해 반복문이 결정되는 것을 확인할 수 있습니다.

 

반복문 시작 부분 2코드

반복문의 시작부터 EAX가 0인지 아닌지를 확인하고 0일 때 점프하는 점프 문이 있습니다.

이 점프문이 이동하는004032A 5 주소는 반복문의 마지막 코드인 점프 문 다음입니다.

즉 EAX가 0이면 반복문이 끝난다는 것을 알 수 있습니다.

그럼 이제 EAX레지스터에 값을 결정하는 함수는 반복문의 끝부분에 있는 varVarForNext() 함수를 통해 결정 되게 됩니다.

vbaVarForNext() 함수를 더 깊숙이 살펴보겠습니다.

함수를 [F7]을 통해 디버깅을 하다 보면 위와 같은 코드를 AX와 EBX + 8 값을 비교하게 됩니다.

[EBX + 8] 주소에 저장된 값

EBX + 8에는 4 값이 들어가 있고 AX의 값이 4보다 크면 점프하게 되고 그렇지 않으면 1을 PUSH한뒤 함수를 종료하게 됩니다. ( EAX 값은 1이 저장됩니다. )

만약 AX의 값이 5가 되면 EAX에는 0이 할당 되기 때문에 반복문의 끝이 될 것입니다.

 

 

 

암호화 과정까지 분석했기 때문에 길어졌던 것 같습니다.... 이상입니다.

 

'리버싱' 카테고리의 다른 글

리버싱 #03 abex crackme 1 분석  (0) 2021.01.22
리버싱 #02 Hello world 디버깅  (0) 2021.01.19
리버싱 #01 리버싱 스토리  (3) 2020.12.28
리버싱 #00 intro  (2) 2020.12.27