반응형




안녕들 하시죠 !


드디어 개인적으로 첫번째 목표인 crackme 부분까지 오게 됬습니다.

이부분을 공부하며 어셈블리어와 친숙해지고 싶습니다.

abex' crackme #1 파일을 가지고 조금 시간이 걸리더라도 하나하나 분석해서 알고 넘어가볼 생각입니다.

아래의 샘플을 사용하시면 됩니다.


abex' crackme #1.exe


한번 실행을 해보겠습니다.


내가 생각하게 만들어라 너의 HD가 CD-Rom이라고... 뭔소리지 했습니다.

확인을 눌러보면,


요런 식으로 Error가 뜨네요.


Ollydbg로 열어보겠습니다.


요런식으로 뜨네요.

음 추측을 해보자면... 출력부를 보면 여기가 Main문인것 같긴하고, 40103D부분을 출력하게되면 성공하는것 같네요.

책을 찾아보니 401013주소의 GetDriveType() API로 C드라이브의 타입을 얻어오는데 이걸 조작해야 합니다.


Win32 API 코드를 아예 몰라서 MessageBoxA() 부분만 한번 가볍게 찾아봤습니다.

crackme #1 같은 경우 이정도만 알아도 이해가 가능했습니다.

추후에 더 공부해보고 틀린 부분이있다면 수정하겠습니다.


MessageBoxA( ①, ②, ③, ④ )


① : hOwner ( 메시지 박스의 오너 윈도우. 메시지 상자를 소유한 윈도우를 말하며 메시지 박스가 떠있는동안 다른 행위를 할수없다 )

② : text ( MessageBox에 출력할 텍스트, 여기에선 Make me think your HD is a CD-Rom 부분 )

③ : title ( MessageBox 윗부분의 텍스트, 여기에선 abex' 1st crackme 부분 )

④ : style ( MB_OK = OK버튼 1개, MB_OKCANCEL = OK와 CANCEL 총 2개 버튼 등 몇몇 종류의 값이 있습니다.)


abex' crackme #1 파일은 어셈블리 언어로 만들어졌기 때문에 보시는바와 같이 코드가 간결합니다.

VC++, VC, Delphi 등의 개발툴을 사용하면 Stub Code가 추가되서 저번시간처럼 복잡한 코드를 보게 되는거였습니다.


먼저, 어셈블리 명령어를 알아보고 한줄한줄씩 직접 이해하고 넘어가보겠습니다.


명령어 

설명 

 PUSH

스택에 값을 입력 

 CALL

지정된 주소의 함수를 호출 

 INC

값을 1 증가 

 DEC

값을 1 감소 

 JMP

지정된 주소로 점프 

 CMP

주어진 두 개의 operand 비교

* SUB 명령어와 동일하나 operand 값이 변경되지 않고 EFLAGS 레지스터만 변경됨 ( 두 operand의 값이 동일하다면 SUB 결과는 0이고 ZF = 1로 세팅됨 )

 JE

조건분기( JUMP if equal ) *ZF = 1이면 점프 


아래 이미지를 보시면, 

Title = "abex' 1st crackme" 는 402000 주소에 들어있구요.

Text = "Make me think your HD is a CD-ROM. 은 402012 주소에 들어있습니다.




이제 코드를 한번 봐보겠습니다.


401000 주소에서 MessageBoxA()를 호출하고 있고,

Title, Text, hOwner가 우리가 아는 MessageBoxA함수 순서와 반대로 들어있는거같네요 ?

실제 C 소스코드는 MessageBox(NULL, "Make me think your HD is a CD-ROM.", "abec' 1st crackme", MB_OK|MB_ARRPLMODAL); 입니다.


스택 메모리 구조는 먼저 들어간것이 나중에 나오는 형태( FILO )이기 때문에 파라미터를 역순으로 넣어주면 받는 쪽에서 올바른 순서로 꺼낼 수 있기 때문입니다.


40100E주소의 MessageBoxA를 실행하면 


딱 요까지 나오고 확인을 누르면 꺼집니다.


다음 코드를 보면,


GetDriveType() API로 C드라이브 타입을 얻어오는 부분입니다.

401018주소를 지나면서 우측에 있는 Registers 창의 값들이 변하는걸 봤습니다.


우선 첫번째,

401026 주소의 JE( Jump if Equal ) 명령어를 JMP( 점프 ) 명령어로 바꿔주어 EAX 와 ESI의 값에 상관없이 원하는 출력을 하게 만들겠습니다.


# 40101F주소의 JMP명령어를 보시면 바로밑의 주소로 점프를 하라고 하는데 이러한 경우 의미없는 garbage code 라고 합니다.


# 401024 주소의 CMP EAX, ESI 

   401026 주소의 JE SHORT 40103D

   = EAX와 ESI 값을 비교하여 두 값이 같으면 40103D로 점프, 다르면 바로 밑에 있는 주소( 401028 )로 진행.



성공했습니다 !


이제 두번째 방법으로 궁금했던 EAX와 ESI값을 수정해서 성공시켜보겠습니다.


GetDriveTypeA 함수를 지나며 오른쪽 Registers 창의 EAX와 ESI를 잘 보셔야 할 것 같습니다.

하드디스크 c 드라이브를 인식한 후 EAX는 3으로 세팅이 되고, ESI는 주소값 401000으로 나옵니다.


그래서 c 드라이브의 EAX 값에는 어떤 종류가 있을까 싶어 찾아봤습니다. 


https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-getdrivetypea


구글에 GetDriveTypeA 로 검색한 결과입니다.


검색 결과를 보니 Hard drive나 flash drive는 3, CD-ROM은 5로 나타나고 있으니 맞는 것 같습니다.


자, 그럼 이제 EAX와 ESI 값을 변경하여 JE 명령어를 실행할 때 같은값으로 인식하게 만들겠습니다.


401024 주소까지 진행을 하게되면 EAX = 1, ESI = 401003 의 값을 가지고 있는것을 확인할수 있습니다.

그럼 EAX의 값을 401003으로 바꿔 보겠습니다.



성공했습니다.


이제 NOP( 아무것도 하지 않음 ) 명령어로 수정해보겠습니다.



무식한 방법이지만 성공했습니다.

이외에도 INC와 DEC를 수정해보는 방법도 있을것 같습니다.


오늘은 여기까지 입니다 감사합니다 !




참고서적 이승원 「리버싱 핵심원리」 인사이트(2018) p67~74


+ Recent posts