본문 바로가기

INTERTLUDE/리버싱 스터디

Codeengn Basic RCE 11

Codeengn Basic RCE 11

 

Q. OEP를 찾으시오. Ex) 00401000 / Stolenbyte를 찾으시오. Ex) FF35CA204000E84D000000 정답인증은 OEP+ Stolenbyte Ex ) 00401000FF35CA204000E84D000000


  • Stolenbyte란 무엇일까? 말 그대로 “훔쳐진 바이트”라는 뜻으로,
    원래 실행 파일의 초기 코드(OEP 근처)에 있어야 할 바이트가 패킹 과정에서 디스크에서는 사라졌다가,
    프로그램이 실제 실행될 때 메모리에서 다시 복구되는 코드 조각을 의미한다.

Q. 왜 이러한 훔쳐진 바이트가 생길까?

UPX와 같은 패커는 프로그램을 압축하기 위해 내부 섹션 구조를 재배치한다.
이 과정에서 아래와 같은 동작이 일어난다.

  1. 원래 OEP 앞뒤의 코드 일부가 디스크에서 제거됨
  2. 실행 시 먼저 언패킹 루틴(PUSHAD → 언패킹 → POPAD) 이 수행됨
  3. 패킹되기 전 OEP의 코드 일부(예: PUSH, MOV 등)가
    스택이나 특정 메모리 위치에 몰래 저장됨
  4. 언패킹이 거의 끝나는 시점에서
    이 “원래 코드”를 POPAD 아래 ~ JMP OEP 사이에서 다시 복원함

디스크에는 없고, 실행 중 메모리에서만 다시 나타나는 “원래 코드” → StolenByte 

 

** UPX의 전형적 언패킹 루틴 구조는 다음과 같다: 

더보기
PUSHAD
[ 압축해제 루프 / 복원 코드 ]
POPAD
[ StolenByte 복구 구간 ]
JMP OEP

여기서 중요한 점은:

  • 패킹되기 전 원래 OEP에 있던 코드 일부를
  • 패커가 스택(PUSH 명령어들) 또는 특정 메모리 영역에 먼저 몰래 저장해 두었다가
  • 언패킹 루틴이 모두 끝나기 직전에 다시 복원해서 실행하도록 만들어 놓는다는 것이다.                                                                                                                    
  • 여기서 POPAD 바로 뒤가 언패킹이 끝나는 지점이고,
    POPAD ~ JMP OEP 사이가 바로 StolenByte가 복구되는 구간이라고 기억하면 된다.

 

해당 문제를 풀기 위해, 11.exe  문제 파일을 다운로드하여 주었다.

 7-Zip File Manager로 압축을 풀고 DIE로 파일 정보를 확인해보려고 한다.

 

압축을 푼 다음에, DIE로 확인해 보니 파일이 패킹이 되어 있음을 알 수 있다. 

그래서 upx-4.2.4-win64 폴더 내에서, CMD를 열고 언패킹 명령어를 입력하였다.

** 언패킹 명령어 :  upx -d -o (저장할 파일명) (원본 파일명) 

 

 

1) 패킹된 채로도 실행해 보고 언패킹 하고도 실행해 보기

  • 원본 11.exe 실행 시
    → abex' 3rd crackme 제목의 메시지 박스에
    → "Click OK to check for the keyfile."라는 정상 문자열이 출력된다.
  • 언패킹 한 11_unpacked.exe 실행 시
    → 여전히 메시지 박스는 뜨지만
    → 내용 부분이?↑P 䧪^? t卞 4Lᄑ처럼 깨진 문자열로 보인다.

즉, 언패킹 과정에서 메시지 박스에 들어가야 할 문자열 관련 코드가 제대로 복구되지 않았다는 의미이고,
여기서 “아, 이 부분이 아마 StolenByte 구간이구나”라고 추측할 수 있었다.

 

Immunity Debugger로 11.exe를 실행시키면, UPX 패커의 전형적 루틴 구조를 확인할 수 있었다. 

PUSHAD
[언패킹 루틴...]
POPAD
JMP OEP

 

 

**  POPAD 아래부터 JMP OEP 사이가 바로
UPX가 원래 OEP 코드를 몰래 넣어두는 자리 = StolenByte 의심 구간이기 때문이기에

 

POPAD 바로 아래부터 JMP OEP 직전까지 코드 몇 줄을 의심스럽게 분석해 보았다. 

...
0040736C  58               POP EAX
0040736D  61               POPAD
0040736E  6A 00            PUSH 0
00407370  68 00204000      PUSH 11.00402000   ; "abex' 3rd crackme"
00407375  68 12204000      PUSH 11.00402012   ; "Click OK to check for the keyfile."
...

 

  • 모든 PUSH 값이 문자열 주소 형태였다. 
  • 00402000 → "abex' 3rd crackme"
  • 00402012 → "Click OK to check for the keyfile."                                                                                                            이 두 문자열은 원본 실행에서 보았던 메시지 박스의 제목/내용과 일치하였다. 
  • 이러한 내용들을 종합해서 ( “주소를 따라가보면 문자열이 확인되고, 이는 실행 시 보았던 메시지와 동일하므로” )                  그렇기에 해당 PUSH 3줄이 메시지 박스를 의미하는 게 아닐까?라고 떠올려볼 수 있었다. 

여기에서 Windows API MessageBoxA의 파라미터 구조를 알고 갈 필요가 있는데.

아래와 같이 호출이 된다. 

int MessageBoxA(
    HWND   hWnd,
    LPCSTR lpText,     // 메시지 내용
    LPCSTR lpCaption,  // 제목
    UINT   uType
);

 

 

 

** 스택은 역순 PUSH 이므로:

 

  • PUSH 0 → uType (MB_OK 등)
  • PUSH 11.00402000 → "abex' 3rd crackme" (제목)
  • PUSH 11.00402012 → "Click OK to check for the keyfile." (내용)인 것이며, 
6A 00 uType = 0 MB_OK 기본값
68 00 20 40 00 제목 주소 따라가면 "abex' 3rd crackme"
68 12 20 40 00 내용 주소 따라가면 "Click OK…"

 

 

 

즉,

이 PUSH 3줄이 원래 MessageBoxA의 인자 세팅 코드이며,
이 코드가 원래는 OEP에서 실행됐어야 하는 부분
그래서 StolenByte인 것이라는 사실을 파악할 수 있었다. 

 

이제 언패킹 된 11_unpacked.exe를 디버거로 열어 OEP(Original Entry Point)를 찾아보았다. 

패킹된 EXE의 EntryPoint는 패커의 언패킹 루틴이 들어가 있어 진짜 OEP가 아니다.

진짜 OEP는 언패킹 루틴 끝에서 JMP로 점프하는 목적지이다.

 

언패킹 된 11_unpacked.exe를 열어보면:

  • EntryPoint = 00401000
  • 해당 위치에는 NOP(90h)가 여럿 있고
  • 그 아래 MessageBoxA 호출 흐름이 이어진다.

NOP = padding이며 OEP가 맞다. 따라서 OEP = 00401000이다. 

 


곧, 문제의 답을 찾기 위해 

StolenByte 최종 정리를 해보자면 

원본 11.exe에서 봤던 POPAD 이후 ~ JMP OEP 직전의 3줄 PUSH가 StolenByte 구간인 것이다. 

0040736E  6A 00            PUSH 0
00407370  68 00204000      PUSH 11.00402000
00407375  68 12204000      PUSH 11.00402012

 

이를 바이트 단위로 적으면:

  • 6A 00
  • 68 00 20 40 00
  • 68 12 20 40 00

따라서 최종 StolenByte 바이트열은 6A 00 68 00 204000 68 12204000

(공백 없이 쓰면 → 6A0068002040006812204000)

 

해당 바이트가 실제로 메시지 박스 인자를 세팅하는 원래 코드임을
깨진 메시지박스(언패킹 파일)와 정상 메시지박스(원본 파일)를 비교하면서 확인할 수 있었다.

 

 

문제에서 요구하는 인증 문자열 형식은

OEP + StolenByte 이므로,

  • OEP : 00401000
  • StolenByte : 6A0068002040006812204000

을 붙이면

004010006A0068002040006812204000

이 되고, 실제로 CodeEngn 인증 페이지의 AuthKey에 위 값을 입력했을 때 정상적으로 정답 인증 성공 되는 것을 확인했다.

 

 

문제 해결 성-공 

'INTERTLUDE > 리버싱 스터디' 카테고리의 다른 글

CodeEngn Advance RCE 3  (1) 2025.11.28
Codeengn Basic RCE 9  (0) 2025.11.26
Codeengn Basic RCE 17  (0) 2025.11.20
Codeengn Basic RCE 13  (0) 2025.11.18
Codeengn Basic RCE 20  (0) 2025.11.17