StolenByte를 구하시오 Ex) 75156A0068352040
![]() | ![]() |
|---|
프로그램을 실행하면 위와 같은 알림창이 나타난다.

Ollydbg로 09.exe를 열었을 때 PUSHAD 명령어를 확인할 수 있다.

그런데, 언패킹 후 프로그램을 실행하면 언패킹 전과 달리 프로그램이 정상적으로 시작되지 않는다.

언패킹한 코드의 OEP부분은 다음과 같다. MessageBoxA 함수 윗부분이 NOP로 비어있는 것을 확인할 수 있다.

언패킹한 프로그램 실행 시 메세지 박스가 제대로 출력되지 않았기 때문에, 이 부분에 문제가 발생했을 것이라고 추측할 수 있다.

MessageBoxA 함수에 대해 조금 자세히 알아보자. Microsoft 공식문서를 확인해보면 MessageBox는 hWnd, lpText, lpCaption, uTyep 4개의 인자를 갖고있으며, uType 인자는 필수 인자이다. 그러나 코드를 살펴보면 hWnd 인자만을 갖고 있는 것을 확인할 수 있다. 따라서 MessageBoxA의 인자 호출 부분이 Stolen 된 것으로 유추할 수 있다.

패킹된 코드를 다시 살펴보면 다음과 같이 POPAD 이후 몇 개의 명령을 수행하고 JMP 명령어를 통해 OEP로 이동한다. 이때 패킹된 프로그램을 실행시켜보면 POPAD 바로 뒤에 나오는 PUSH 명령의 데이터가 정상적인 MessageBoxA 함수를 실행했을 때 확인할 수 있는 문자열임을 알 수 있다.


JMP 명령어를 따라 0040100C 오프셋으로 이동해보면 CALL 구문으로 MessageBoxA 함수를 실행하는 것을 확인할 수 있다.
MessageBoxA 함수 내부로 들어가면 MessageBoxTimeoutA 함수 호풀을 위해 다시 PUSH로 인자를 전달하고 있다.
💥 여기서 잠깐!!
이전 문제들에서도 많이 확인했지만, 한 번 더 짚고 넘어가보자. 어셈블리 코드에서는 PUSH 명령어로 함수에 전달할 값을 스택에 저장하고, MOV명령어를 이용해 스택에 저장된 데이터를 꺼내와 사용한다.
; 함수 functionA에 대한 인자 전달
PUSH arg3
PUSH arg2
PUSH arg1
CALL functionA
; 함수 functionA 내부
MOV EAX, [ESP+4] ; 첫 번째 인자
MOV EBX, [ESP+8] ; 두 번째 인자
따라서 POPAD 이하에 있는 PUSH문이 MessageBoxA 함수에서 사라진 함수 인자 전달 부분이라고 추측할 수 있다. (인터넷을 찾아보니 POPAD 뒤에 연속적으로 보이는 PUSH 코드는 StolenByte일 가능성이 높다는 게 잘 알려진 사실인 것 같다.)

0040736E . 6A 00 PUSH 0
00407370 . 68 00204000 PUSH 09.00402000
00407375 . 68 12204000 PUSH 09.00402012
언패킹한 프로그램의 경우 위 코드들이 복원되지 않아 제대로 프로그램이 실행되지 않았기 때문에, 6A 00 68 00204000 68 12204000 를 NOP 부분에 작성해주면 문제가 해결될 것으로 보인다.

패킹된 프로그램을 아이다나 Ollydbg에서 열어서 stolen byte를 작성해준다. Ollydbg의 경우 스페이스바를 눌러 assemble이 가능하다.
아이다의 경우 00401000 주소를 누르고 Edit > Patch program > Change byte 입력창에 6A 00 68 00 20 40 00 68 12 20 40 00 6A 00 E8 8C 를 입력한다.

이후 F9 단축키로 프로그램을 실행시켜주면 언패킹한 파일에서도 정상적으로 프로그램이 실행되는 것을 확인할 수 있다.
패킹된 프로그램을 실행할 때, PUSHAD부터 POPAD까지 압축 해제 과정을 거친다고 한다.
패킹된 프로그램을 실행할 땐 stolen byte들을 스택에 저장하고, MessageBoxA 함수에서 스택을 참조하는 방식으로 인자를 전달했기 때문에 프로그램이 문제 없이 실행됐다.
그럼 언패킹한 과정에서는 왜 동일한 방식으로 MessageBoxA 함수에 인자를 전달할 수 없었을까? 언패킹 과정과 프로그램 실행 시 압축 해제 과정이 다른 건가?
찾아보니 프로그램 실행 시 압축 해제 과정과 언패킹 시 압축 해제 과정은 동일하지만, 언패킹한 파일의 경우 JMP로 이동한 원본 코드의 엔트리 포인트부터 메모리를 덤프하고 별도로 저장하기 때문에 압축 해제 코드 및 JMP 이전 코드가 포함되지 않는다고 한다. MessageBoxA 함수 인자는 POPAD 이후에 스택에 저장됐기 때문에 언패킹한 파일에서는 스택에 저장된 데이터는 포함되지 않는 것 같다.
코드엔진 깃허브에 가면 다양한 풀이를 확인할 수 있다.