코드엔진 Basic RCE L01
문제
https://codeengn.com/challenges/
문제 풀이 - 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를 통해 살펴본 리턴값은 다음과 같다.
즉, 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이면 점프