Basic RCE L06 - 코드 엔진

2020. 3. 19. 00:48문제연습/CodeEngn (REC)

반응형

 

본 티스토리 블로그는 PC에 최적화되어 있습니다.

모바일 유저분들은 아래 네이버 블로그를 이용해 주세요.

Basic RCE L06 - 코드 엔진

본 네이버 블로그는 모바일에 최적화되어 있습니다.PC 유저분들은 아래 티스토리 블로그를 이용해 주세요...

blog.naver.com

 

 

안녕하세요, ICMP입니다.

이번 시간에는 코드 엔진의 여섯 번째 문제Basic RCE L06를 풀어보도록 하겠습니다.

 

What is OEP???

 

 

1. 문제 내용

Unpack을 한 후 Serial을 찾으시오.

정답 인증은 OEP + Serial

Ex) 00400000PASSWORD

 

Author: Raz0r

File Password: codeengn

 

 

2. 문제 해설

7z 압축을 풀고 PE를 분석해 보니 UPX 패킹이 감지되었습니다.

 

 

 

일단 파일을 언 패킹하도록 하겠습니다.

 

 

언 패킹 한 파일을 한번 실행해 보도록 하겠습니다.

 

 

 

 

음, 한번 아무 값을 넣고 실행해 보도록 하겠습니다.

 

 

 

ERROR 창을 띄우는군요.

이제 본격적으로 디버깅을 시작하도록 하겠습니다.

 

 

 

일단 프로그램에 존재하는 모든 텍스트 스트링을 검색해 보도록 하겠습니다.

 

 

 

텍스트 중 의심되는 문구를 찾았습니다.(아까 실행하고 나온 ERROR 창에 나온 문구입니다.)

이 주소로 들어가 보도록 하겠습니다.

 

 

 

WOW!!! 우리가 원하는 부분이 나온 것 같습니다!!!

화면 출력을 위해 MessageBoxA 함수를 이용해 화면 팝업을 띄웠었군요.

 

일단 함수의 프롤로그 부분에 중단점을 설정하여 프로그램의 동작을 분석하도록 하겠습니다.

(중단하려는 지점을 클릭하고 F2를 눌러 중단점 설정, F9를 눌러 중단점 이전 지점까지 실행)

 

 

일단 실행 창에 ICMP를 입력하고 Check Serial을 누른 후 동작을 분석하니 아래와 같은 동작이 나타났습니다.

 

 

 

즉, 사용자가 입력한 데이터가 004235D4에 저장되고, 이 주소에 저장된 값을 06Unpack.00401290 함수의 인자로 집어넣고 있습니다.

 

흠, 그런데 00422A30 주소에 있는 "AD46DFS547"를 06Unpack.00401290 함수의 인자로 들어가고 있습니다. 일단 동작을 확인해보기 위해 call 지점으로 들어가 보도록 하겠습니다.

(call 명령어 지점을 클릭하고 Enter)

 

(F7을 이용하여 주소 안드로 들어가서 실행하도록 하겠습니다.)

 

 

가까 push 했던 문자열이 각각 EDX, ECX에 복사되고 있습니다.

계속해서 분석하도록 하겠습니다.

 

 

 

EDX와 3을 서로 TEST 하고 있습니다.

저번 문제에서 TEST는 첫 번째 오퍼랜드와 두 번째 오퍼랜드끼리 and 연산을 진행합니다.

만약, and 연산의 결과가 0이면 ZF=1, 반대로 0이 아니면 ZF = 0으로 설정됩니다.

 

결과를 보니 ZF가 1로 설정되었는데, ASCII와 정수가 비트 연산하는 부분은 조금 더 조사한 후에 보충하도록 하겠습니다.

 

 

 

이다음이 가장 중요합니다. (아래 사진을 확인해 주세요.)

 

 

ECX = "ICMP", EDX = "AD46DFS547"가 있습니다.

 

지금 EAX에 dword ptr DS:[EDX]을 넣고 있습니다.

(dword ptr DS:[EDX] : EDX에 4byte 만큼의 데이터를 읽어온다는 말입니다.)

 

그러고 나서 AL과 BYTE PTR DS:[ECX] 비교하고 있습니다.

(BYTE PTR DS:[ECX] : ECX에 1byte 만큼 데이터를 읽어온다는 말입니다.)

(참고로 1byte = 8bit입니다.)

 

현재 제가 레지스터와 바이트에 대한 지식이 부족하지만 아는 한도까지 풀어보도록 하겠습니다.

 

 

위의 레지스터와 비트를 잘 확인해 주세요.

 

현재 EAX에 저장된 값은 36344441입니다.

(상위 24bit인 363444는 왜 저장되는지는 모르겠습니다.)

 

이렇게 되면 ax는 eax를 반으로 나눈 하위 16bit 값을 가지므로 ax = 4441입니다.

또, ax를 반으로 나누어 상위 8bit는 ah, 하위 8bit는 al이므로, ah=44, al=41이 됩니다.

즉, cmp 어셈블리 코드에서 나온 al=41("A")입니다.

(아스키코드는 7bit 지만 오류 검출을 위해 1bit를 추가하여 사용하기에 실제로는 8bit로 사용됩니다.)

 

또한 BYTE PTR DS:[ECX] : ECX에 1byte 만큼 데이터를 읽어온다는 말이므로

현재 ECX = "ICMP"인데, 1byte라면 'I'를 의미합니다. (그럼 BYTE PTR DS:[ECX+1] = 'C'겠지요???)

 

그런데 eax와 ecx가 32bit=4byte여서 4글자씩 비교하고 eax, ecx에 4를 더하여 다음 4글자를 다시 비교하는 루틴이라는 것을 알 수 있습니다.

 

만약 비교하여 글자가 일치하지 않으면 004012A0로 이동하고, 반대로 모든 글자가 일치하면 EAX를 xor 한 뒤 이전 call 주소로 이동합니다.

 

 

만약 문자가 하나라도 일치하지 않으면 004012D6으로 점프한 다음 SBB를 합니다.

SBB는 sub와 다르게 CF(carry flag)도 빼므로 EAX - EAX - CF(=1)= 0 - CF = FFFFFFFF가 됩니다.

 

(0-1=FFFFFFFF 되는 이유는 아래 링크를 참고해 주세요.)

캐리와 오버플로우 - Carry & Overflow

1 서론 캐리(Carry)와 오버플로우(Overflow)는 종종 혼돈되기도 하는데 그 차이점을 알아보자. 간략화를 ...

blog.naver.com

 

이후 shl(Shift left) 1연산을 하여 EAX을 비트 비트 단위로 1칸 왼쪽으로 한 칸 옮기고

(EAX=FFFFFFFF이고 shl을 적용해도 ffffffff인데 fffffffe로 뜨는 이유는 모르겠습니다. 아시는 분은 댓글 부탁드립니다!!!)

1을 더한 후 이전 주소로 돌아갑니다. (EAX = FFFFFFFF)

 

다시 원 주소로 돌아왔습니다.

 

 

만약 test 처리한 결과가 0이 아니면 ERROR 창을 띄우는 것 같습니다.

 

 

 

 

아까 문자 검사를 해서 모든 같이 일치하면 eax가 xor 연산을 해서 0로 초기화하는데, eax가 0으로 설정되면 Good~~~ 화면을 출력할 것입니다.

 

 

전반적인 루틴을 정리해 보도록 하겠습니다.

 

1. 사용자로부터 문자를 입력받는다.

 

2. 06Unpack.00401290 함수 인자로 "AD46DFS547"와 사용자가 입력한 문자를 넣고 서로 비교한다.

(서로 일치하면 eax=0으로 초기화)

 

3. test를 통해 팝업창을 띄움

(EAX=0이면 Good~~~, 아니면 Wrong~~~~)

 

4. 다시 입력을 받기 위해 프로그램 시작점으로 이동.

 

5. 위 과정을 무한 반복

 

 

그럼 AD46DFS547을 입력해 결과를 확인해 보도록 하겠습니다.

 

 

Wow!!! 우리가 분석한 내용이 맞았습니다!!!

 

그럼 Serial :AD46DFS547입니다.

그런데 OEP는 어디에 있는 걸까요???

OEP(Original Entry Point)는 프로그램의 실제 시작 지점이라고 했습니다.

만약 프로그램을 패킹하게 되면 OEP가 변조된다고 했는데, 우리는 시작하기 전에 언 패킹하고 분석을 진행하였기에

OEP는 디버거에 넣고 나오는 시작 주소인 00401360이 됩니다.

 

 

따라서 Basic RCE L06의 정답은 아래와 같습니다.

00401360AD46DFS547

 

이번 문제는 제가 제대로 정리하지 못한 비트 연산과 레지스터의 저장 방식을 묻는 부분이 존재했습니다.

(다시 레지스터를 정리해야겠군요.)

 

 

오늘은 여기까지입니다.

다음 시간에는 Basic RCE L07를 풀어 보도록 하겠습니다.

이상, ICMP였습니다!!!

 

반응형

'문제연습 > CodeEngn (REC)' 카테고리의 다른 글

Basic RCE L09 - 코드 엔진  (0) 2020.11.23
Basic RCE L07 - 코드 엔진  (0) 2020.11.17
Basic RCE L05 - 코드 엔진  (0) 2020.03.18
Basic RCE L04 해설 - 코드 엔진  (0) 2020.03.17
Basic RCE L01 해설 - 코드 엔진  (0) 2020.03.13