아주 간단한 crackme 샘플을 분석하여 디버거와 어셈블리 코드에 익숙해집시다. 가능한!
🤓책 '리버싱 핵심원리'를 읽고 정리한 공부 내용입니다.
크랙 연습 목적으로 작성되어 공개된 프로그램
간단한 구글링을 통해 다운 받을 수 있는 유명한 프로그램이지만
내 컴퓨터에서는 window보안에 막혀 실행되지 않았따. 아마 어셈블리 코드들을 악성 코드로 인식 한 것 같다. 무시하고 진행해도 되지만 불안하니 가상머신 환경에서 진행하려고 했는데?! 왜 칼리 리눅스에 dbg가 없을까...
당황해서 일단 책으로 먼저 읽어보자는 결론을 내렸다.
파일을 실행시키면 위의 메시지 박스가 출력된다고한다
C드라이브의 타입을 얻어오는 것을 수행하는데 (대부분 HDD타입) 이걸 조작해서 CD-ROM타입으로 인식하도록 만드는 것!
Windows 프로그래밍을 안해봐서 해석 아니었으면 몰랐을 뻔 했다.
책에서는 OllyDbg라는 툴으로 디스어셈 코드를 봤나보다. 확실히 어셈블리어로 보는 것보단 직관적이다.
파일의 디스어셈 코드를 살펴보면 매우 짧은 것을 확인 할 수 있는데, 이는 이 파일이 어셈블리 언어로 만들어진 실행파일이기 때문
짧은 코드니까 한줄씩 분석해보자! 근데 다 적진 않았고 제일 중요한 부분만 추려서 작성했습니다
정신건강과 손가락 건강을 위해 주소 입력은 생략하였습니다 :)
; MessageBoxA()호출
PUSH 0 ;Style설정
PUSH 402000 ;타이틀 "abex' 1st crackme"
PUSH 402012 ;text = "Make me think your HD is a CD-Rom"
PUSH 0 ;h0wner = NULL
CALL 0040161 ;MassageBoxA
;함수 내부에서 ESI = FFFFFFFF로 세팅
; GetDriveTypeA()호출
PUSH 402094 ; RootPathName = "c:\\"
CALL 00401055 ; GetDriveTypeA
; 리턴값 (EAX)은 3(DRIVE_FIXED)
INC ESI ; ESI = 0
DEC EAX ; EAX = 2
JMP SHORT 00401021 ; 의미없는 JMP 명령;;
INC ESI ; ESI = 1
INC ESI ; ESI = 2
DEC EAX ; EAX = 1
;조건분기
CMP EAX ESI ; EAX(1), ESI(2) 비교
JE SHORT 0040103D ; JE(Jump if Equal) 조건분기 명령 - 같으면 점프
헷갈리는 점 fffffffff가 왜 0이지??????????? 16진수 아닌가..?
CMP | 주어진 두 개의 operand 비교 SUB명령어와 동일하나 operand값이 변경되지 않고 EFLAGS 레지스터만 변경 (동일하다면 SUB결과는 0, ZF=1로 세팅) |
---|---|
JE | 조건분기 ZF=1이면 점프 |
이제 패치해서 프로그램을 크랙해보자!
리버싱에서 기존의 코드나 데이터를 의도적으로 다른 코드로 덮어 쓰는 행위를 "패치"시키다라고 한다.
크랙방법은 간단하다!
출력이 결정되는 조건분기에서 JE
를 없애거나 JNE
로 변경해주면 된다.
위 MessageBoxA()함수를 호출하는 부분을 살펴보면
함수를 호출하기 전 4번의 PUSH명령어로 필요한 파라미터를 역순으로 입력한다.
C언어로 번역하면
MessageBox(NULL, "Make me think your HD is a CD-Rom.", "abex' 1st crackme", MB_OK|ME_APPLMODAL);
=> 실제 C소스코드에서 함수에 넘기는 파리미터의 순서가 어셈블리 언어에서는 역순이라는 점 기억하기!
(FILO구조의 스택 메모리 구조이기 때문)
x86 환경에서 스택은 아래로자라기(주소가 작아지는 방향)때문에 디버거에서 스택을 보면 함수의 첫째 파라미터가 제일 위에 보이고 마지막 파라미터가 아래에 쌓임
=> 함수 내부에서 스택에서 파라미터를 하나씩 꺼내쓰기 가능