"골드 9,999,999" — 텍스트 편집기 하나에 무너지는 게임 경제
수백 번의 테스트를 거쳐 플레이 밸런스를 설계하고, 정교한 인앱결제(IAP) 모델을 구축해 두었더라도 결코 안심할 수 없습니다. 공격자가 로컬 기기에 저장된 세이브 파일 하나를 열어 재화 수치를 고치는 데는 단 몇 분조차 걸리지 않기 때문입니다. 만약 클라이언트가 디스크에 저장된 데이터를 아무런 교차 검증 없이 그대로 신뢰한다면, 게임 내 경제 시스템 전체가 단 하나의 파일에 휘둘리는 매우 취약한 구조가 되고 맙니다.
세이브 파일 변조는 고도의 해킹 기술이나 전문적인 분석 도구가 없어도 시도될 수 있다는 점에서 위협적입니다. 범용 텍스트 편집기나 루팅된 기기의 파일 탐색기만으로도 게임 데이터를 직접 수정할 수 있으며, 이렇게 조작된 '슈퍼 계정'은 멀티플레이 생태계의 공정성을 심각하게 훼손하고 정상적인 유저들의 유료 콘텐츠 구매 동기를 꺾어버립니다.
이번 글에서는 세이브 파일이 실제로 어떤 경로를 통해 변조되는지, 클라이언트 측의 단순 암호화가 왜 완전한 해결책이 되지 못하는지, 그리고 소중한 게임 데이터를 지키기 위한 실효성 있는 다계층 방어 전략은 무엇인지 살펴봅니다.
세이브 파일은 어디에, 어떤 형태로 저장되는가
유니티(Unity) 게임에서 플레이 데이터가 저장되는 물리적 경로는 운영체제(OS) 플랫폼에 따라 다르지만, 결국 기기의 파일 시스템 어딘가에 위치하게 됩니다.
- Android: 주로
/data/data/<패키지명>/files/내부나 외부 저장소(External Storage)에 위치합니다. 일반 기기에서는 접근이 제한되지만, 루팅(Rooting)된 기기나 에뮬레이터 환경에서는 자유롭게 접근할 수 있습니다. - iOS: 앱 샌드박스(Sandbox) 내부에 저장되나, 탈옥(Jailbreak)된 기기나 서드파티 백업 추출 도구를 통해 파일 시스템에 접근할 수 있습니다.
- PC (Windows):
%AppData%\LocalLow\<회사명>\<게임명>\폴더에 파일로 저장되거나, 레지스트리(PlayerPrefs)에 기록됩니다. OS 구조상 사용자가 별다른 권한 우회 없이 즉시 접근하고 수정할 수 있습니다.
저장 형식은 게임의 설계에 따라 JSON, XML, 바이너리, 혹은 유니티의 기본 PlayerPrefs 등 다양합니다. 만약 데이터가 별도의 암호화나 난독화 없이 평문(Plaintext)으로 저장되어 있다면, 공격자는 파일 구조를 단번에 파악하고 원하는 값을 마음대로 주무를 수 있습니다.
세이브 파일 변조의 실제 흐름
공격자의 관점에서 세이브 데이터 조작은 비교적 단순하고 직관적인 절차를 따릅니다.
세이브 파일 위치 확인 ──> 파일 추출 및 내용 분석 ──> 수치 수정 ──> 덮어쓰기 ──> 게임 재실행
1단계: 파일 추출 및 구조 파악 루팅/탈옥된 모바일 기기나 PC 환경에서 타깃 파일을 추출합니다. JSON이나 XML 포맷이라면 메모장과 같은 기본 텍스트 편집기로도 직관적인 열람이 가능합니다. 바이너리 포맷이라 하더라도 헥스 에디터(Hex Editor)를 이용해 특정 수치가 변하는 패턴을 대조하면 목표 데이터 필드의 오프셋(Offset)을 특정해 낼 수 있습니다.
2단계: 수치 및 플래그 수정
데이터 구조를 파악한 공격자는 "gold": 1200을 "gold": 9999999로 부풀리거나, 캐릭터의 레벨과 스탯, 심지어 보유하지 않은 유료 아이템의 소유 플래그(Flag)를 true로 강제 수정합니다.
3단계: 덮어쓰기 후 재실행 조작을 마친 파일을 원래의 시스템 경로에 덮어씌운 뒤 게임을 실행합니다. 클라이언트가 파일의 무결성을 점검하는 로직을 갖추고 있지 않다면, 조작된 값은 그대로 게임 메모리에 로드되어 즉각 반영됩니다.
클라이언트 단 단순 암호화만으로는 부족한 이유
이 대목에서 "그럼 세이브 파일을 텍스트 에디터로 못 읽게 암호화(Encryption)하면 되지 않나?"라는 의문이 생길 수 있습니다. 물론 클라이언트 단의 암호화는 공격의 난이도를 높이는 1차적인 허들이지만, 단독으로는 치명적인 구조적 한계를 갖습니다.
파일을 암호화하고 복호화하기 위한 '키(Key)'와 '로직'은 필연적으로 게임 클라이언트의 실행 파일 어딘가에 존재해야만 합니다. 앞선 IL2CPP 역분석 글에서 살펴본 것처럼, 공격자는 global-metadata.dat 덤프나 런타임 분석을 통해 복호화 함수와 하드코딩된 암호화 키를 비교적 쉽게 추출할 수 있습니다. 키가 노출되는 순간, 암호화는 단지 조금 번거로운 인코딩 방식에 불과해집니다.
또한, 파일 암호화를 완벽하게 지켜내어 정상적으로 복호화했다고 가정하더라도, 클라이언트가 그 값을 메모리에 로드하여 사용하는 런타임 순간에 메모리 변조 도구로 값을 직접 조작하는 경로는 여전히 활짝 열려 있습니다. 즉, 단순 암호화는 "열기 번거로운 자물쇠"일 뿐, 데이터의 위변조 자체를 원천 차단하는 완전한 검증 수단이 아닙니다.
실효성 있는 저장 데이터 보호 전략
소중한 게임 데이터를 지키기 위해서는 클라이언트의 방어벽을 높이는 동시에, 단일 지점의 검증 실패가 전체 시스템의 붕괴로 이어지지 않도록 다계층(Defense-in-depth) 접근이 필요합니다.
(1) 서버 측 권위 (Source of Truth) 확보 핵심 재화(골드, 프리미엄 화폐), 유료 아이템 구매 내역, 멀티플레이 랭킹 등 민감한 데이터는 클라이언트가 주장하는 값을 곧이곧대로 신뢰해서는 안 됩니다. 서버가 보유한 정식 데이터베이스 기록을 권위 있는 원본으로 취급하고, 불일치가 발생할 경우 서버의 값을 우선하도록 설계해야 합니다. 로컬 세이브 파일은 네트워크 지연을 줄이기 위한 UI 표시용 캐시 정도로 활용하는 것이 이상적입니다.
(2) HMAC 서명을 활용한 파일 무결성 검증 오프라인 플레이를 지원하여 로컬 세이브가 필수적인 게임이라면, 저장 데이터에 서버 또는 안전하게 보관된 비밀 키를 이용한 HMAC(Hash-based Message Authentication Code) 서명을 첨부하는 것이 좋습니다. 클라이언트가 데이터를 로드할 때 서명 정합성을 검증하여, 단 한 바이트라도 변조된 파일은 로드를 거부하고 손상된 데이터로 판별합니다.
(3) 클라우드 세이브(Steam Cloud 등) 환경을 고려한 보안 설계 로컬 파일의 무단 복사나 변조를 막기 위해 기기의 고유 정보(Hardware ID)에만 의존해 암호화 키를 생성하는 실수를 종종 범합니다. 이 경우 보안성은 높아지지만, 유저가 데스크톱과 Steam Deck을 오가며 플레이하는 클라우드 세이브 동기화 환경이 완전히 깨지게 됩니다. 따라서 저장 데이터를 보호하면서도 정상적인 이기종 간 동기화를 지원하려면, 기기가 아닌 유저 계정(Steam ID 등) 기반의 식별자와 연동하여 무결성을 검증하는 유연한 암호화 아키텍처가 필수적입니다.
(4) 런타임 메모리 변조 탐지 병행 파일 레벨의 보호(암호화 및 HMAC)를 거쳐 무사히 데이터가 로드되더라도, 메모리 상에 존재하는 런타임 수치를 조작하려는 시도는 계속됩니다. 이를 방어하기 위해 핵심 수치 필드의 무결성을 Native 계층에서 실시간으로 모니터링하여, 파일 조작 이후 단계에서 발생하는 메모리 덮어쓰기 공격을 추가로 억제해야 합니다.
(5) 비정상 수치에 대한 서버 측 논리 검증 서버 단에서 플레이어의 획득 가능 재화 최대치, 시간당 성장 한계치, 퀘스트 보상 구간 등을 논리적으로 점검(Sanity Check)해야 합니다. 단일 세션에서 정상 범위를 아득히 초과하는 재화가 발생하면 이를 비정상 신호로 간주하고 조치할 수 있어야 합니다.
OZero Security는 조작된 데이터가 게임에 직접적인 영향을 미치는 것을 막기 위해, 런타임 메모리 값 변조 탐지 및 환경 무결성 검증 기능을 Native C++ 계층에서 강력하게 지원합니다. 또한, Steam Cloud와 같은 크로스 디바이스 환경에서도 파일 무결성을 잃지 않고 안전하게 세이브 데이터를 연동할 수 있는 유연한 보안 체계를 제공합니다. 로컬 디스크에서의 파일 접근을 물리적으로 완벽히 차단하기는 어렵지만, 변조된 값이 메모리에 적재되어 로직에 개입하는 시점을 정밀하게 탐지해 냄으로써 서버 검증과 결합된 견고한 다층 방어망을 구축할 수 있습니다.
요약 및 정리
- 세이브 파일은 파일 시스템에 직접 접근할 수 있는 환경(루팅/PC)에서 별도의 고급 해킹 없이도 쉽게 텍스트 기반으로 수정될 수 있습니다.
- 데이터 암호화는 필수적이지만, 복호화 키의 노출 위험과 런타임 메모리 변조 취약점으로 인해 단독 방어책으로는 부족합니다.
- 오프라인 위주 게임이라면 HMAC 서명을 통해 파일의 위변조 여부를 엄격히 차단해야 하며, 이때 클라우드 동기화를 해치지 않는 계정 기반의 식별 체계가 고려되어야 합니다.
- 디스크 보호뿐만 아니라 런타임 메모리 탐지 기술을 결합하여, 파일 변조 이후 메모리로 넘어오는 2차 조작 경로까지 입체적으로 방어해야 실효성을 거둘 수 있습니다.
게임의 세이브 파일은 플레이어가 게임을 즐긴 시간과 노력에 대한 신뢰의 증표입니다. 그 신뢰가 허점이 되지 않도록 꼼꼼히 설계하고 검증하는 것이 안전한 게임 서비스의 시작입니다.