본문 바로가기

INTERTLUDE/리버싱 스터디

Codeengn Basic RCE 10

Codeengn Basic RCE 10

Q. OEP를 구한 후 '등록성공'으로 가는 분기점의 OPCODE를 구하시오. 정답인증은 OEP + OPCODE EX) 00400000EB03

 

해당 파일을 다운로드하여서 1) 7-Zip File Manager로 압축부터 풀고, 2) DIE로 열어보았다.

 

그러하였더니, 사진처럼 나타남을 알 수 있었다. 그런데 이전까지의 파일을 패커 : UPX ~ 로 되어 있었는데, 그렇지 않은 것을 통해 패킹이 되어 있지만, UPX를 통한 패킹을 아님을 확인할 수 있다. 

 

그래서 이번에는 다운로드한 디버깅 툴인 VMUnpacker를 사용해서 언패킹을 해보았다. 

언패킹 성공 -! 

 

 

 Immunity Debugger를 사용하여서 해당 파일을 열면, 

OEP (Original Entry Point)를 확인할 수 있다. 해당 파일의 OEP는 00445834이다. 

 

OEP (Original Entry Point) : 이 프로그램이 시작할 주소 (: 프로그램 실행이 시작되는 최초의 코드 위치 )      

 

이후에 프로그램을 계속 실행하다 보면,

이러한 화면이 나타나는 것을 확인할 수 있다.

 

해당 과정을 실행한 이후에, 우클릭 > Search for > All referenced strings를 열어보면 "Name must be at least 5 characters long!"와 "Registered... well done!"이라는 주요 문자열을 확인할 수 있다.

  • 두 문자열 사이에 분기 루틴이 존재할 것으로 추측할 수 있으며, 특히 "Registered ... well done!"이 성공 메시지임을 알 수 있다 --> 따라서 이 문자열과 가까운 분기문(JNZ)을 찾아내는 것이 핵심이다. 

 

  • "Registered... well done!"이라는 문자열을 찾을 수 있었기에 그대로 그 부분을 따라가고, 해당 문자열 근처의 코드 흐름을     살펴본 결과 004454D4 주소에 위치한 JNZ SHORT 0044552B 분기문이 가장 근접해 있음을 확인할 수 있다. 
  • JNZ는 ZF=0일 때 점프하는 조건 분기 명령으로, 조건이 맞으면 성공 메시지("Registered ... well done!") 부분을 건너뛰고  실패 루틴으로 분기한다.                                                                                                                                                                        1) 입력이 맞을 때 (ZF=1): JNZ 조건이 불충족되어 점프하지 않고, 그대로 아래 줄을 실행하여 성공 메시지(Registered … well done!)가 출력된다.                                                                                                                                                                                            2) 입력이 틀릴 때 (ZF=0): JNZ 조건이 충족되어 점프가 발생하고, 성공 메시지를 건너뛰고 XOR EAX,EAX 등 실패 루틴으로 이동한다.
  • 따라서 이 JNZ (004454D4)가 성공 메시지 실행을 결정짓는 분기점임을 확인할 수 있다. 
  • 해당 명령의 OPCODE는 75 55이며, 문제에서 요구하는 답은 OEP(00445834) + OPCODE(7555) = 004458347555 이다.

 

더보기
  •  OPCODE: CPU가 실제로 실행하는 기계어 바이트. 어셈블리 창에서 각 명령어의 주소 옆에 표시됨. 
  •  OEP (Original Entry Point): 언패킹 후 프로그램이 실제로 시작하는 최초 코드 주소
  •  분기점 찾기: 성공 메시지 문자열 근처에서 가장 의미 있는 조건 분기(JNZ)를 확인 → 등록 성공 여부 결정 지점. 

 

 


더보기

1. 비교 명령(CMP / TEST)의 원리

  1. CMP A, B
    • 실제로는 A - B 연산을 한 뒤 결과는 버리고, 플래그(ZF, CF, SF 등)만 갱신합니다.
    • 만약 A와 B가 같으면 A - B = 0 → 결과 0 → ZF=1
    • 다르면 A - B ≠ 0 → 결과 0이 아님 → ZF=0
  2. TEST EAX, EAX
    • EAX & EAX를 수행합니다. 자기 자신과 AND 연산 → 사실상 “EAX가 0이냐 아니냐”만 판정합니다.
    • EAX=0 → 결과 0 → ZF=1
    • EAX≠0 → 결과 0 아님 → ZF=0

2. 성공/실패와 ZF의 관계

  • 입력이 정답일 때
    • 비교했을 때 결과가 0 (같으니까 차이 없음)
    • → 결과 0 → ZF=1
  • 입력이 틀릴 때
    • 비교했을 때 결과가 0이 아님 (차이가 남)
    • → 결과 ≠0 → ZF=0

3. 그래서 JNZ가 동작하는 방식

  • JNZ (Jump if Not Zero)는 말 그대로 “결과가 0이 아닐 때” 분기하라는 뜻.
  • CPU는 프로그램이 맞았는지 틀렸는지 모릅니다. 단순히 결과가 0인지 아닌지만 보고 움직입니다.
    • 결과 0 (ZF=1) → 점프 ❌ → 아래 줄 실행 (→ 성공 메시지)
    • 결과 ≠0 (ZF=0) → 점프 ⭕ → 다른 주소로 이동 (→ 실패 루틴)

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

CodeEngn Basic RCE 4  (0) 2025.10.07
Codeengn Basic RCE 7  (0) 2025.09.30
Codeengn Basic RCE 8  (0) 2025.09.30
Codeengn Basic RCE 6  (0) 2025.09.30
Codeengn Basic RCE 5  (0) 2025.09.30