Security/Reversing

코드엔진 Basic RCE L01

bonggang 2019. 10. 14. 14:14

문제


https://codeengn.com/challenges/

 

CodeEngn.com [코드엔진] - Challenges

코드엔진은 국내 리버스엔지니어링 정보공유를 위해 2007년 부터 리버스엔지니어링 컨퍼런스 및 비공개 워크숍을 현업 실무자들과 함께 운영하고 있습니다. 리버스엔지니어링이라는 하나의 큰 주제로 소프트웨어 보안에 대한 다양한 시각과 연구주제에 대한 정보공유를 추구하고 있으며, 상업적 이익 없이 작은 예산으로 운영하고 있어 큰 예산으로 운영하는 다른 컨퍼런스에 비해 여러 가지로 부족 할 수 있습니다.

codeengn.com

 

문제 풀이 - Ver.IDA


 

먼저 문제를 실행해보자!

 

 

문제를 실행해보면 [Make me think your HD is a CD-Rom.]이라는 메세지박스가 뜬다. 다음 메시지 박스가 뜰 때까지 실행해보면

 

 

다음 메시지 박스는 Error 메시지가 뜬다.

 

그럼 이제 IDA text view를 살펴보자.

현재 뜨는 메시지는 [Nah... This is not a CD-ROM Drive!]인데 우리가 원하는 것은 [OK, Ireally think that your HD is a CD]이다. 그렇다면 이 메시지를 띄우기 위해서는 어떻게 해야할까?

창을 살펴보았을 때 가장 눈에 띄는 것은 cmp eax, esi와 jz short loc_40103D이다. 아무래도 eax와 esi를 비교해서 판단을 하는 것 같다.

그렇다면 esi와 eax를 건드리는 곳을 찾아야 할 것 같다.

가능 눈에 띄는 것은 단연 GetDriveTypeA 함수를 호출하는 부분이다.

 

 

GetDriveTypeA를 호출한 후 Return 값이 저장되는 EAX(RAX-64bit 버전)의 값은 3이다.

 

MS를 통해 살펴본 리턴값은 다음과 같다.

 

 

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

 

즉, DRIVE_FIXED의 값이다. 하지만 우리가 얻어야 하는 값은 DRIVE_CDROM 값인 5라는 것을 추측할 수 있다.

 

 

 

문제 풀이 - Ver.xdbg


어셈블리를 확인해보면 [cmp eax,esi]와 [je] 구문을 확인할 수 있다. 이 구문을 해석해본다면 만약 eax와 esi가 같을 경우 YEAH! Ok, I really think that your HD is a CD-ROM!을 띄워주는 곳으로 jump하라는 내용임을 확인할 수 있다.

 

 

 

현재 레지스터 창을 살펴보면 EAX와 ESI가 다르다는 것을 확인할 수 있다. 이대로 실행시킨다면 Error가 뜰 것이다.

 

 

EAX와 ESI가 같은 값을 가지도록 수정해주면

 

 

정답 창이 뜨는 것을 확인할 수 있다.

 

 


+)IDA의 디버거 단축키

F2: Break Point

F9: Start Debugging

Ctrl+F2: 종료

F7: Step in

F8: Step out

스페이스바: 디버거 화면 전환

F5: Generate Pseudocode

F6: 다음 탭

 

+)레지스터

EAX(Extended Accumulator Register): 함수의 리턴 값이 저장

EBX(Extended Bse Register): ESI나 EDI와 결합하여 인덱스에 사용

ECX(Extended Counter Register): 반복 명령어 사용 시 반복 카운터로 사용

EDX(Extended Data Register)

ESI(Extended Source Index): Source Data 주소 저장

EDI(Extended Destination Index): Destination 주소 저장

ESP(Extended Stack Pointer): 스택 프레임의 끝 지점 주소 저장, push, pop 명령어에 따라 4bytes씩 변화

EBP(Extended Base Pointer): 스택 프레임의 시작 주소 저장

EIP(Extended Instruction Pointer): 다음에 실행될 명령어 메모리 주소 저장

 

 

+)어셈블리 명령어

INC(increase): 피연산자 +1

DEC(decrease): 피연산자 -1

ADD(add): destination에 source 값을 더해서 destination에 저장

SUB(subtract): destination에 source 값을 빼서 destination에 저장

MUL(Multiply Unsigned Integer): 부호 없는 al, ax, eax의 값을 피연산자와 곱하기.

DIV(Divide Unsigned Integer): 부호 없는 정수의 나눗셈

MOV(move): source에서 destination으로 데이터 복사

LEA(Load Effective Address): source의 유효 주소를 계산하여 destination에 복사

JMP(jump unconditionally to label): 피연산자의 위치로 실행 흐름이 변경

CALL(call a procedure): 함수 호출, JMP 명령어와 차이점은 되돌아올 리턴 어드레스를 스택에 저장한다는 것.

CMP(compare): 두 피연산자를 비교

PUSH(push): 스택에 값을 입력

JE(Jump if Equal): ZF=1이면 점프

 

출처: http://sarghis.com/blog/357/