Codeengn Basic RCE 6
Q. Unpack을 한 후 Serial을 찾으시오. 정답인증은 OEP + Serial Ex) 00400000PASSWORD

6.exe 파일을 다운로드하여서, DIE을 통해 열어주면 위와 같이 나타난다.
패커 : UPX ~ 표시를 통해 5번 예제를 풀었을 때와 같이, 언패킹 과정이 필요함을 알 수 있다.
7-Zip File Manager, upx-4.2.4-win64, cmd 툴을 이용해 언패킹 과정을 진행한 이후에, Immunity Debugger로 파일을 연다.

파일을 열면 정상적으로 나타남을 알 수 있다. 동시에 프로그램이 시작되는 OEP는 00401360 임을 확인할 수 있다.
- OEP (Original Entry Point) : 이 프로그램이 시작할 주소 (: 프로그램 실행이 시작되는 최초의 코드 위치 )
- F9 키를 눌러 계속 실행시키다 보면,

이러한 창이 나타난다.
-> 5번 예제와 유사하게, serial number를 입력해야 함을 알 수 있다. 그렇기에 해당 창이 열린 줄에서 우클릭 > Search for > All referenced strings를 하여서 스트링을 살펴본다.

들어가 보면, 누가 봐도 수상해 보이는 0040106E의 AD46DFS547이 눈에 들어온다. 그 밑의 스트링들도 살펴보니, 올바른 serial number인 것 같다는 생각이 들어서 입력 창에 해당 값을 넣어 입력해 보면,

Good job!이라는 화면이 나타난다. 올바른 serial number를 입력하였음을 알 수 있다.
-> 그러므로 OEP + Serial의 값은 (문제의 정답은)
OEP는 00401360, Serial number는 AD46DFS547을 바탕으로 00401360AD46DFS547 이다.
코드를 조금 더 살펴보기 위해서,

이번에는 틀린 serial number인 1234를 입력해 보았다. 1234를 입력하면 Good job! 의 화면이 아닌, Wrong Serial이라는 화면이 나타난다. (올바른 Serial number가 아니라는 의미)

- 위치: 00401069에서 내가 입력한 값("1234")을 스택에 PUSH, 이어서 0040106E에서 정답("AD46DFS547")을 PUSH.
- 프로그램은 입력값과 정답 문자열을 차례로 스택에 밀어 넣은 뒤 비교 루틴으로 진입한다.
- 입력값이 틀린 경우 (내가 입력한 값인 "1234")
두 값이 다르므로 비교 결과 EAX ≠ 0.
따라서 TEST EAX, EAX 실행 후 ZF=0.
직후 JNZ 분기 조건(ZF=0일 때 jump)에 맞아 004010A3으로 분기 → Wrong 메시지 출력. - 입력값이 올바른 경우(정답인 "AD46DFS547" 입력된 경우):
두 값이 같으므로 비교 결과 EAX=0.
따라서 TEST EAX, EAX 실행 후 ZF=1.
이때 JNZ는 분기하지 않고(점프 조건 불충족), 그대로 다음 명령 실행 → MessageBoxA 호출 → “Good Job! / You got it ;)” 성공 메시지 출력.

- 위치: 0040107B TEST EAX, EAX → 0040107D JNZ SHORT 004010A3.
- TEST 명령은 EAX 값을 자기 자신과 AND 연산하여 값이 0인지 검사한다. 현재 EAX=1이라서 ZF=0이 되고, JNZ 분기 조건(ZF=0일 때 jump)에 맞아 Wrong 창 루틴(004010A3)으로 점프한다.
- 레지스터 상태:
- ECX = 내가 입력한 값(“1234”),
- EDX = 정답(“AD46DFS547”),
- EAX = 비교 결과(현재 1 → 틀림).

- 위치: 스택 메모리 영역 (0x0019F688 ~).
- 먼저 입력값 "1234"가 스택에 들어가고, 그 다음에 정답 "AD46DFS547"이 PUSH 됩니다. 스택은 후입선출(LIFO) 구조이며 x86에서는 아래 방향(주소 감소)으로 성장하므로, 나중에 PUSH 한 값(정답)이 더 낮은 주소에 위치하게 됩니다.

-> 문제 해결 완료 -!
** 사용된 개념들 요약정리
- DIE (Detect It Easy): 실행 파일의 패킹 여부 및 사용된 패커 확인.
- 언패킹 (UPX -d): 패킹된 실행 파일을 원래 코드로 복원.
- All referenced strings: 코드에서 참조하는 문자열 테이블 확인 → 시리얼 후보 찾기.
- BreakPoint (BP): 특정 지점(예: TEST EAX,EAX)에 중단점 설정 → 프로그램 상태(레지스터·스택) 확인.
- PUSH: 레지스터나 값을 스택에 저장하는 명령 → 이번 문제에서는 입력값과 정답값을 스택에 순서대로 쌓음.
- 스택 구조: 함수 호출 시 파라미터 전달, 로컬 변수 저장, 복귀 주소 관리에 사용. 후입선출(LIFO)이므로 최근에 PUSH한 값이 먼저 POP됨.
- TEST EAX,EAX (0040107B): EAX 값이 0인지 확인 → 같으면 ZF=1, 다르면 ZF=0.
- JNZ (0040107D): ZF=0일 때 분기 → 입력값과 정답이 다르면 Wrong 창으로 이동.
'INTERTLUDE > 리버싱 스터디' 카테고리의 다른 글
| Codeengn Basic RCE 10 (0) | 2025.09.30 |
|---|---|
| Codeengn Basic RCE 8 (0) | 2025.09.30 |
| Codeengn Basic RCE 5 (0) | 2025.09.30 |
| [리버싱 스터디]_1주차 Codeengn Basic RCE 3 (0) | 2025.09.23 |
| [리버싱 스터디]_1주차 Codeengn Basic RCE 2 (0) | 2025.09.23 |