AI 에이전트를 이용한 1인칭 슈팅 게임 디컴파일
요약
자율형 AI 에이전트는 복잡한 소프트웨어를 성공적으로 디컴파일할 수 있지만, 객관적이고 기계적으로 검증 가능한 수용 기준이 없으면 읽기는 가능하지만 의미론적으로는 부정확한 "환각" 코드를 생성합니다. 게임 디컴파일에서 정확성을 보장하는 가장 효과적인 방법은 **바이트 매칭 디컴파일(byte-matching decompilation)**입니다. 이는 재구성된 C++ 코드를 컴파일하여 원본 바이너리와 바이트 단위로 비교하는 방식입니다. 이 접근 방식을 사용하면 바이너리 PASS/FAIL 신호를 제공함으로써 성능이 낮은 모델이라도 고충실도 결과를 생성할 수 있습니다.
오케스트레이션 프레임워크
게임의 기능을 완벽하게 재현하기 위해 Claude와 Codex 모델을 조합한 멀티 에이전트 시스템이 배포되었습니다. 인프라는 자율성과 진행 상황 추적에 중점을 두었습니다:
- 에이전트 역할: 시스템은 디컴파일 및 커밋을 수행하는 작업자 에이전트와 버그를 조정하고 표시하는 검토자 에이전트를 활용했습니다.
- 진행 상황 추적: GitHub Issues를 주요 추적 메커니즘으로 사용했으며, 번역 단위(.cpp 파일)당 하나의 이슈를 할당했습니다.
- 커뮤니케이션: 에이전트들은 공유 Discord 채널을 통해 소통하며 에이전트 간 및 인간-에이전트 간 상호작용을 가능하게 했습니다. CI 실패는 GitHub 웹훅을 통해 이 채널로 전송되었습니다.
- 도구: 에이전트들은 헤드리스 방식의 안정적인 디스어셈블리 및 디컴파일을 위해 Hex-Rays의 공식
ida-mcp를 활용했습니다.
에이전트 드리프트 및 환각 극복
초기 자율 디컴파일 시도에서 에이전트들은 시간이 지남에 따라, 특히 컨텍스트 윈도우가 채워질수록 집중력을 잃고 "드리프트(drift)"하는 경향을 보였습니다. 정렬을 유지하기 위해 팀은 두 가지 핵심 전략을 구현했습니다:
- 공격적인 컨텍스트 압축: 기본 압축 임계값을 90%에서 42%로 낮췄습니다. 이를 통해 이전에 디컴파일된 함수와 같이 휘발성이고 관련 없는 정보를 컨텍스트에서 더 자주 제거했습니다.
- 지침 새로 고침: 매시간 실행되는 크론 작업이 에이전트에게 프로젝트의 목표와 운영 지침을 다시 읽도록 요청하는 명령을 자동으로 주입하여 시간이 지남에 따라 지침이 약화되는 것을 방지했습니다.
인간과 유사한 검토의 실패
게임이 실행되고 메뉴가 렌더링되었음에도 불구하고, 초기 출력물은 의미론적으로 결함이 있었습니다. 에이전트들은 잘못된 함수 서명을 도입하고, 논리를 지어내며, 효율적인 전역 변수 액세스를 비용이 많이 드는 해시 테이블 조회로 대체했습니다.
이러한 실패는 검토자 에이전트에게 객관적인 수용 기준이 없었기 때문에 발생했습니다. 검토자는 원본 바이너리와 코드를 독립적으로 검증하기보다는 커밋 메시지에 담긴 작업자 에이전트의 정당화 내용을 그대로 수용하는 경우가 많았으며, 이는 본질적으로 의도치 않은 프롬프트 주입의 한 형태였습니다.
바이트 매칭 디컴파일 구현
정확성 문제를 해결하기 위해 팀은 "진실의 원천(ground truth)" 오라클 역할을 하는 검증 스크립트를 구현했습니다:
- 프로세스: 스크립트는 원본 게임의 컴파일러를 사용하여 재구성된 C++ 코드를 컴파일합니다. 그런 다음 결과로 생성된 OBJ 파일을 원본 게임 EXE/PDB와 비교합니다.
- 재배치 처리: 절대 메모리 주소가 변경되기 때문에 스크립트는 재배치 바이트를 제외하고, 대신 두 버전이 동일한 오프셋으로 동일한 심볼을 참조하는지 확인합니다.
- 보안 조치: 에이전트가 "부정행위"를 하는 것(예: 인라인 어셈블리 사용 또는 검증 스크립트 수정)을 방지하기 위해 시스템은 특정 구문을 금지하고 CI에서 검증 스크립트를 해싱하여 변조되지 않았는지 확인합니다.
결과 및 트레이드오프
프로젝트가 끝날 무렵, 게임 함수의 99%가 재구성된 소스에 포함되었으며 83%는 바이트 단위로 정확했습니다. 프로젝트 최종 단계에서는 14개의 Luna 모델과 2개의 Opus 5.5 모델이 사용되었습니다.
장점
- 보장된 의미론: 바이트 단위로 정확하게 일치하면 원본 버그를 포함하여 동일한 동작이 보장됩니다.
- 모델 효율성: 정밀한 피드백을 통해 더 저렴하고 성능이 낮은 모델(Luna 또는 Haiku 등)로도 더 똑똑한 모델과 비교할 만한 결과를 생성할 수 있습니다.
단점
- 노력 증가: 에이전트가 레지스터 선택 및 호출 규약과 씨름해야 하므로 함수를 정확하게 일치시키는 데 훨씬 더 오랜 시간이 걸립니다.
- 수익 체감: 비결정적 컴파일러 출력이나 링커 동작(예: COMDAT 폴딩)으로 인해 일부 함수는 바이트 매칭이 불가능합니다.
커뮤니티 관점 및 대안
기술 전문가들 사이의 논의에서는 바이트 매칭의 엄격함 없이 기능적 동등성을 달성하기 위한 대안적인 방법들이 제시되었습니다:
"저에게 효과적이었던 방법은 모든 함수에 대해... 하네스가 가상 머신/시뮬레이터/에뮬레이터에서 원본 함수와 제출된 함수를 모두 실행하는 것입니다... 하네스는 1) RAM에 대한 읽기/쓰기 시퀀스가 원본 함수와 동일하고, 2) 디컴파일되는 원본 함수의 모든 라인 및 분기 커버리지가 완료된 경우에만 구현을 수락합니다." — @handle
다른 비평가들은 이 프로젝트가 6,000억~7,000억 개의 토큰을 소비했을 것으로 추정되는 높은 환경적, 재정적 비용을 지적했으며, 상표권 및 저작권 제한으로 인해 법적으로 공유할 수 없는 프로젝트의 유용성에 의문을 제기했습니다.
Sources
관련
- Dispatch
- Dispatch
- Dispatch
- Dispatch
- Dispatch