[codeengn] basic #010

·2025년 6월 30일

CodeEngn 바로가기


문제

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


1. 프로그램 실행

이전 문제까지는 Ollydbg를 사용했지만, 이번 문제 풀이 도중 dump 과정에서 불편함을 느껴 x64dbg를 사용하기로 결정했다. 찾아보니 Ollydbg는 사실상 개발이 중단되었으며 64bit 바이너리 분석에 사용할 수 없다고 한다. 🤔

x64dbg는 x64dbg 깃허브에서 다운받을 수 있다.



프로그램을 실행시키면 다음과 같이 시리얼번호, 이름을 입력할 수 있는 창이 나오지만 실제로는 아무 값도 입력할 수 없다.


x32dbg에서 해당 exe파일을 열어보면 PUSHAD 명령어를 확인할 수 있다. PUSHAD 명령어가 어셈블리 코드에 나타나는 경우 패킹된 파일일 가능성이 있음을 이전 문제들을 통해 확인했다.

그러나 10.exe 이전 문제들과 달리 UPX 패커를 이용해 패킹되지 않았다. ASPack 2.000을 통해 패킹되었음을 PEID 툴을 통해 확인했다.

UPX처럼 언패킹 툴이 존재할 것 같긴 하지만... 일단 버전이 너무 오래된 듯하고 대부분의 풀이에서 manual unpacking 과정을 진행하는 듯하여 수동 언패킹을 진행했다.


2. OEP 찾기

ASPack으로 패킹된 프로그램에서 OEP를 찾기 위해서는 다음과 같은 코드를 찾아야 한다.
해당 사이트를 참고했다.

ret C
push 0
ret


ctrl+F를 통해 바로 ret C 명령어를 찾아도 되고, hardware breakpoint를 이용해서 POPAD를 찾고, 이어지는 ret C 명령어까지 한번에 확인하는 방법도 있다고 한다.

hardware breakpoint를 이용해 찾는 방법

패킹된 프로그램에서 OEP를 찾기 위해선 POPAD 명령어의 위치를 알아야 한다.

PUSHADPOPAD의 기본 개념

패킹(=압축)된 프로그램을 실행시키면 언패킹(=압축 해제) 로직이 실행된다. 이때 프로그램 실행 시 필요한 데이터들이 언패킹 과정에서 다른 값으로 덮어씌워지는 등, 손실이 발생하여 프로그램이 정상적으로 실행되지 않을 수 있다.

따라서 PUSHAD로 레지스터 데이터를 스택에 따로 백업해두고, 압축 해제 로직이 끝나면 POPAD로 스택에서 값을 꺼내 데이터를 복원한다. 이때 스택의 최상단 주소는 ESP 레지스터에 저장된다.

PUSHADPOPAD 동작을 살펴보면, 스택 주소에 접근할 때= POPAD 명령어가 수행될 때이다.

PUSHAD = **스택에 접근**해 데이터 저장
POPAD = **스택에 접근**해서 값을 꺼내 레지스터에 저장

따라서 스택 최상단 주소에 breakpoint를 설정해 POPAD에서 실행이 중지되도록 하여 POPAD가 위치한 주소를 알아낼 수 있다.


x32dbg에서 프로그램을 열면 PUSHAD 명령어를 찾을 수 있다. F7이나 F8을 눌러 PUSHAD가 실행되게 만든 후, ESP 레지스터 값을 확인한다. PUSHAD로 데이터를 모두 저장한 스택의 최상단 주소는 0019FF54다.


우측 상단 레지스터 창에서 ESP > 우클릭 > Follow in Dump

좌측 하단 메모리 창에서 ESP 주소 > 우클릭 > Breakpoint > Hardware, Access > Dword (Ollydbg에는 byte밖에 없었던 것 같은데, byte로 설정해도 POPAD는 찾을 수 있었다.)


BP(Breakpoint)를 설정하고 프로그램을 실행(혹은 재실행)시켜주면 POPAD 직후 jne 구문에서 프로그램이 중지된다.

ret C
push 0		;실행 후 0이 OEP 주소로 변환됨
ret

다음과 같은 구문이 있을 때, ret 다음 실행되는 구문이 OEP 주소라고 한다.


ret 구문에서 F7, 혹은 F8을 눌러 step over한 결과 OEP는 00445834임을 알 수 있다.


3. 분기점 찾기

OEP 지점부터 x64dbg의 플러그인인 scylla를 이용해 dump를 떠서 확인했었는데, 굳이 언패킹된 프로그램을 생성하지 않아도 분기점을 확인할 수 있어서 덤프 과정은 생략한다.


Search for > String reference에서 "register"로 검색하면 에러 메시지 "Not registered..." 는 확인할 수 없지만 등록 성공으로 추측되는 문자열을 발견할 수 있다.


해당 주소 앞뒤로 jne 구문이 2개 이상 존재한다. 그 중에서 "Registered..." 문자열을 포함하는 jne 구문은 004454D4 주소의 jne 구문이므로 분기점의 주소는004454D4이다. 문제에서 요청한 OPCODE는 75 55임을 확인할 수 있다.

따라서, 최종 정답은 004458347555


기타

성공 문자열 앞뒤까지 프로그램이 제대로 실행되지 않아 문자열 포함 여부로 분기점을 파악했는데 다른 방법이 있을지 궁금하다.
그리고 프로그램을 실행할 때 확인할 수 있었던 Not registered... 문자열은 왜 Search for를 통해 확인할 수 없었을까?🤔
추후에 해당 프로그램에 대해 더 공부하면 좋을 것 같다.


코드엔진 깃허브에 가면 다양한 풀이를 확인할 수 있다.

profile
🔥

0개의 댓글