본문 바로가기
Laboratory

RPG Maker MV 도움말에 있는 Enigma Virtual Box를 분석해보자

by biud436 2020. 2. 3.

RPG Maker MV로 게임을 만들 때, 도움말에서 가이드 한대로 Enigma Virtual Box를 사용하는 사람들이 있을 것이다. 마녀의 집의 경우, Enigma Virtual Box를 이용하지 않았다. 그 이유는 무엇일까? 사실 Enigma Virtual Box는 암호화 툴이 아니다. 단일 실행 파일을 만들어서 파일을 하나로 통합하여 깔끔하게 만들어주는 툴일 뿐이다. 엄밀히 말하면 단일 실행이 아니라 실행하는 데에는 모든 파일이 필요하며 이를 위해 파일을 어딘가에 슬쩍 풀어놓게 된다. Enigma Virtual Box로 만들어진 게임의 실행 파일을 헥스 에디터로 열어본 적이 있는가? 자세히 살펴보면 .enigma1이라는 이름을 가진 섹션이 존재한다. 해당 섹션에 접근하면 파일의 대한 정보가 쭉 나열되어있다는 것을 알 수 있다.

예를 들면, 선택된 부분을 잘 보면 두 줄 (한 줄이 16바이트) 위에 EVB 시그니처가 있다는 것을 알 수 있다. 파일 오프셋 0x1CD8E0 부분으로 버전에 따라 달라질 수 있긴 하지만 대체적으로는 이렇다. 스크린샷에서 선택된 4바이트 값을 보자. 이 값을 리틀 엔디언 방식으로 읽어보면 실행 파일 안에 삽입된 총 데이터의 크기가 나오게 된다. 루비를 사용하여 대략적으로 검산을 해보면 데이터 크기가 일치한다.

프로그램으로 구현하면 아래와 같이 성공적으로 메시지를 띄우게 된다. 섹션을 정확히 찾으려면 PE 헤더에 대한 약간의 지식이 있어야 한다(필자는 최근에 콘솔 출력 시 텍스트 색상을 바꿀 수 있다는 걸 알게 됐다. 놀랍게도 MV의 텍스트 코드와 비슷한 방식이었다)

필자의 경우, 처음에는 PE 헤더를 찾아주는 오픈 소스를 찾아보다가 마음에 드는 게 보이지 않아 리버싱 핵심 원리라는 책을 탐독하면서 해당 섹션 헤더를 직접 찾아냈다. 다음 주소 값들은 파일 오프셋일 뿐이며 런타임에는 다른 주소로 전개된다. 파일 오프셋과 메모리 주소는 다르다.

.enigma1 섹션의 상단에는 파일 압축 여부, 가상화 파일 시스템, 레지스트리 가상화 등 프로그램에서 설정할 수 있는 옵션이 들어가게 된다. 옵션 값은 bool 형이므로 0 아니면 1로 나와있다. 이외에 총 데이터 크기 등도 저장된다.그 다음에는 실질적인 파일 트리가 포함된다. 파일 트리는 루트 폴더가 제일 위에 위치하고, 나머지를 자식으로 포함하는 형태라고 볼 수 있다. 길이가 유동적인 파일명을 제외한 나머지 길이는 고정된 사이즈이다.

파일명을 자세히 보면, 1바이트로 표현하는 SBCS가 아니라 2바이트 유니코드 문자열이라는 것을 알 수 있다. 이것이 굉장히 중요한데 문자열을 2바이트 씩 읽어야 한다는 것이다. 이러한 문자열은 마지막에 NULL로 끝나게 되는데 WBCS에서는 NULL도 2바이트로 처리되어야 한다. 따라서 NULL이 2바이트로 처리된 부분을 확인하면 문자열이 끝났음을 프로그래밍 적으로 알 수 있게 된다.

파일명 다음 값은 폴더인지 파일인지를 구분하는 타입 값으로 추측된다. 이 값은 1바이트이며 열거형으로 보여진다. 폴더일 경우 0x03이 되고 파일이면 0x02가 된다.

다음에 오는 값은 원본 파일 크기에 해당하는 값이다. 이 값은 INT 형이며 4바이트 리틀 엔디언으로 읽게 되면 2058751 바이트가 나오게 된다. 바이너리 값을 자세히 살펴 보면 겹치는 부분이 있다는 것을 알 수 있는데 파일 크기를 나타내는 부분이 두 부분이라는 것을 알 수 있다. 옵션에 압축 기능이 있다는 것을 감안하면 압축 했을 때의 파일 크기일 수도 있다. 필자는 압축을 하지 않았기 때문에 두 값이 일치하는 것으로 보여진다.

붉은 색으로 강조된 부분은 서서히 증가하는 패턴이 관찰되는데 프로그래밍 적 관점에서 볼 때 이 패턴은 파일의 인덱스 값이다. 파일의 인덱스 값은 INT 형 변수이며 4바이트를 차지한다.

파일 순서 다음에 있는 4바이트 값은 여러 파일을 검증해본 결과, 자신이 속한 트리의 깊이와 관련된 값이다. 가장 최상위 루트 폴더인 %DEFAULT_FOLDER%의 깊이가 1이고, Game.exe 등이 있는 메인 폴더가 깊이가 2이고 실제로도 전부 2라고 적혀있다. 이를 이용하여 추출할 때 트리를 배열로 접근하는 자료 구조를 만들면 된다.

추론해보면 예를 들면, 위와 같이 iconv.tlog 폴더에 있는 모든 파일의 깊이는 9가 될 것이다. 확인해보니 실제로도 9가 적혀있다. www 폴더 안에 있는 index.html 파일 등은 0x03이라고 적혀있다.

위 그림에서 파란색 부분은 폴더일 때, 폴더에 포함된 파일의 갯수를 나타낸다. 4바이트 값로 되어있다. 파일 타입일 경우에는 0으로 기록된다. 즉, 이 값은 해당 폴더에 있는 파일 또는 폴더의 갯수로 특정할 수 있다. 특징은 재귀가 아니며 현재 폴더에 있는 파일이나 폴더의 갯수만 나오게 된다.

이외에도 파일 특성(File Attribute) 값도 있다. 파일 특성 값은 파일명이 끝난 지점에서 0x21 오프셋을 지나면 나오게 된다. 2바이트 값으로 리틀 엔디언 방식이며 주요 특징은 비트 플래그로 되어있다는 점이다. 예를 들면 기본적으로 적혀있는 0x2008이라는 값은 다음과 같이 해석될 수 있다.

 

https://en.wikipedia.org/wiki/Design_of_the_FAT_file_system

 

Design of the FAT file system - Wikipedia

FAT12 requirements : 3 sectors on each copy of FAT for every 1,024 clusters FAT16 requirements : 1 sector on each copy of FAT for every 256 clusters FAT32 requirements : 1 sector on each copy of FAT for every 128 clusters FAT12 range : 1 to 4,084 clusters 

en.wikipedia.org

 

 

위 동영상을 보면 실제 파일로 추출할 수 있다는 것을 알 수 있다. 단, 압축이 되어있지 않을 때를 가정한다. 압축이 되어있지 않을 때는 다음과 같이 평문으로 들어가있지만 압축 시엔 알아볼 수 없는 형태로 바이너리 코드가 들어가게 된다. 필자가 다양한 압축 기법(zlib, zip, lz777, lzma2, run-langth)을 조사해봤지만 해당되는 것이 없었다. 손수 구현한 압축 기법이 아닌가 생각되는데, 이런걸 디버깅 없이 분석하기는 까다롭다. 대략적으로 연속으로 등장하는 문자를 다른 문자로 치환하는 방식으로 보여지고 압축률은 178바이트에서 109바이트로 39 % 정도 압축되는 것으로 보여진다. 보통 오픈 소스를 이용하면 라이센스 문서에 길게 나오게 되는데 이 프로그램은 라이센스 파일에 아무런 문서가 없다. 즉, 최소 자체 구현했거나 상용 엔진을 구입하여 라이센스를 클리어한 상태일 것이다.

파일 트리가 끝나면 실제 실행되어야 하는 실행 파일의 바이너리 코드가 위치하게 된다. 필자도 시행착오를 많이 겪었는데 정확한 계산을 하지 않으면 모든 파일이 제대로 추출되지 않게 된다.


지금까지 Enigma Virtual Box가 암호화 툴이 아닌 이유에 대해서 알아봤다. Enigma Virtual Box로 만들어진 게임을 실행하면 <사용자 명>/AppData/Temp 폴더에 고스란히 복구된 파일이 나오게 된다. 실제로도 암호화가 되어있지 않다. 종료 시 추출된 파일을 삭제 옵션에 체크하면, 게임을 종료할 때 임시로 만들어놓은 폴더를 삭제하고, 그렇지 않으면 폴더가 남게 된다. 따라서 Enigma Virtual Box를 사용하면 쓸데 없는 오버헤드가 더 생기게 될 수 있다. 실행 파일 내부에서 파일을 추출까지 해야 하므로 시간이 걸리는 것이다(자바스크립트로 구현했을 땐 느리지만, 실제 프로그램은 다중 쓰레드로 예상보다 빨리 풀리게 된다) 파일을 읽으면 램에 해당 내용을 저장해둬야 하므로 메모리도 많이 사용할 것이다. 파일을 복제했으니 용량도 쓸데 없이 갑자기 늘어날 것이다. 메모리 이슈는 생각하고 싶지 않지만 최근에 포럼에서 읽은 바로는 메모리 누수 현상도 있다고 한다. (찾아보니 Enigma Virtual Box v9.00 Build 20180626에 메모리 이슈를 해결했다는 로그가 있다)

 

그런 점에서 RPG Maker VX Ace는 Enigma Virtual Box보다는 발전된 형태이지 않나 생각한다. 비슷한 구조이지만 그나마 암호화를 해놓았기 때문에 파일 트리와 파일 내용을 알아볼 수 없다. 물론 디버거를 이용하면 의미를 쉽게 알 수 있지만 일반인은 웬만하면 알아볼 수가 없기 때문이다. RPG Maker VX Ace가 이용하는 XOR 암호화가 엄밀히 말하면 굉장히 낮은 수준이라 암호화도 아니긴 하지만 Enigma Virtual Box보다는 낫다. MV에서도 부분적으로 XOR 암호화를 쓰긴 하지만, 헤더 한 줄을 변형하는 정도이므로 암호화라 부르기 어렵다.


 

필자는 사전에 세운 이론을 바탕으로 상당한 시간을 들여 코드를 짰었고, 결과물을 깃허브에 올려뒀었다. 하지만 이미 이러한 디크립터가 웹상에 공개되어 있었고, 개발 또한 별로 각광 받을 수 있는 행동 또한 아니기 때문에 링크를 따로 올리진 않겠다. 그리고 해당 소스는 Enigma Virtual Box의 새로운 버전이 나오면 deprecated 될 수도 있다. 필자의 작업은 2019년 11월 버전에 기반한다.