더 나은 모델이 바꾼 것
2026년 8월부터 프로그램에 접근하고 결과를 검증할 수 있는 에이전트가 리버스 엔지니어링을 어디까지 수행할 수 있는지 탐구해 왔습니다. 경험의 대부분은 게임, 특히 동방 재구성에서 얻었습니다. 모델을 바꿔 가며 작업하는 동안 저장소에는 각 세션이 무엇을 복구했는지 기록이 쌓였습니다.
이 작업의 상당 부분은 정확한 재구성이 목표입니다. 고정된 당시 도구 모음으로 유지보수 소스를 컴파일해 대상 함수를 재현하는지 확인합니다. 이전에 막혔던 문제를 나중 모델이 해결하면, 소스 변경에서 무엇이 진전을 가능하게 했는지 볼 수 있습니다.
임시 값들의 수명이 겹쳐야 했습니다
TH09 공격 함수의 로직은 대부분 재구성했지만, 컴파일러가 임시 결과를 저장하는 방식은 여전히 원본과 달랐습니다. 남은 문제는 그 결과를 언제까지 유지하고 저장 공간을 언제 재사용할 수 있느냐였습니다.
일반적인 소스 구성을 여러 가지 시험한 뒤 GPT-6-Sol 체크포인트에 이 불일치가 기록됐습니다. GPT-6.1-Sol이 문제를 다시 살펴보며 임시 값의 수명에 관한 유용한 가설을 찾아냈습니다.
함수는 임시 결과를 만들어 애니메이션 위치에 복사했습니다. C++에서 임시 결과는 이를 사용하는 표현식이 끝날 때까지 유지됩니다. 실제 연산을 하나의 표현식으로 묶자 결과들의 수명이 겹쳤고, 컴파일러는 더 이상 모두에 같은 저장 공간을 재사용할 수 없었습니다.
한 결과는 나중에 충돌 검사에 쓰이는 값과 여전히 저장 공간을 공유했습니다. 그 값에 별도의 수명을 부여하자 남아 있던 겹침이 해결되었습니다. 여러 차례의 표적 실험 끝에 클린 리빌드로 함수 전체가 일치함을 확인했습니다.
흥미로운 점은 발견과 테스트가 맞물린 방식입니다. 수명 가설은 에이전트에게 새로운 방향을 제시했고, 컴파일러 피드백은 가설을 구체화해 일치하는 소스 구성을 찾도록 도왔습니다.
다른 제어 흐름 그래프
두 번째 TH09 함수는 새로운 방향이 왜 중요한지 보여줍니다. 문제는 여러 분기가 마지막 처리를 공유하는 방식이었습니다. GPT-6.1-Sol의 이전 작업에서 함수 일부는 일치했지만 분기가 합쳐지는 방식은 여전히 원본과 달랐습니다.
GPT-6-Astra가 주변 제어 흐름 그래프를 변경했습니다. 이제 주요 경로는 공유된 최종 업데이트와 반환으로 이어졌습니다. 해당 소스 구조에서 컴파일러는 원본과 동일한 방식으로 분기를 결합했습니다. 함수 전체가 일치했으며, 별도의 리빌드 검사로 이를 확인했습니다.
표현을 바꾸자 더 생산적인 탐색 공간이 열렸습니다. 두 사례는 범용 모델의 역량을 중요하게 볼 이유가 됩니다. 에이전트가 주변 코드를 더 잘 표현할 방법을 찾기 전까지 오랫동안 부분적인 변형만 시도할 수도 있기 때문입니다.
한편 후속 세션은 이전 소스와 실패 기록에서 출발했습니다. 축적된 작업도 이점의 일부였습니다. 이력에서 발견과 검증 과정을 살펴볼 수 있지만, 모델 자체의 효과와 물려받은 경험의 효과를 구분하려면 조건을 맞춘 비교가 필요합니다.
여기서 질문이 흥미로워집니다. 일부 진전은 새로운 표현을 찾은 덕분이었고, 나머지 작업의 상당 부분은 익숙한 컴파일러로 소스 형태를 시험하는 일이었습니다. 얼마나 폭넓은 추론이 필요하고, 얼마나 많은 부분을 그 컴파일러와 코드를 반복해서 경험하며 배울 수 있을까요?
특화 모델은 왜 잘할 수 있을까요?
동방은 경험이 도움이 될 것이라 기대할 구체적인 이유를 제공합니다. 게임 코드 대부분의 저자가 ZUN이므로 반복되는 습관이 있다고 가정할 만합니다. 저장소의 사례도 이를 뒷받침합니다. 비슷한 루프와 보조 함수 구성이 게임을 넘나들며 가설의 단서가 됐습니다.
컴파일러까지 고려하면 소스 패턴은 더 구체적이 됩니다. 특정 버전과 옵션에서는 작은 소스 변경이 기계어 코드에 반복 가능한 차이를 만듭니다. 그중에는 뜻밖에 미묘한 차이도 있습니다.
예를 들어 TH095에서는 지역 변수의 이름만으로도 VC7.1의 저장 위치가 바뀔 수 있었습니다. 선언 위치만 옮겨서는 배치가 해결되지 않았지만, 앞서 분석한 배경 함수에서 컴파일러의 선택에 영향을 주는 이름 패턴을 발견했습니다. 이는 Supervisor::LoadDat의 재구성에 더 유망한 가설을 제공했습니다.
파일 크기 변수에도 그 패턴을 재사용하자 저장 공간을 추가하지 않고도 필요한 배치가 만들어졌습니다. 그러자 함수 전체가 일치했습니다.
이런 세부 사항은 범용 모델이 처음부터 알기 어렵습니다. 이 컴파일러에 특화된 모델은 비슷한 사례를 많이 접하며 어떤 소스 변형을 먼저 시험할지 배울 수 있습니다.
이미 동작을 이해하고 마지막 차이를 맞추는 문제에서 가능성이 특히 뚜렷합니다. 관찰된 명령어를 이 컴파일러가 어떤 일반적인 소스로부터 생성하는지 묻는 단계입니다. 특화 학습은 후보를 더 효율적으로 제안하게 해줄 수 있으며, 가설의 통과 여부는 여전히 대상이 결정합니다.
유용한 패턴에는 적용 조건도 함께 남아야 합니다. TH08은 TH095·TH09보다 오래된 Visual C++를 사용합니다. TH04는 DOS 시대의 다른 컴파일러를 사용하며, 플레이어 코드 재구성에는 소스 패턴과 링크 방식에 관한 다른 가설이 필요했습니다. 같은 저자라는 사실은 사전 가정을 주지만 적용 여부는 각 대상에서 확인해야 합니다. 이 맥락을 구별하는 것도 특화 모델이 배울 일입니다.
경험을 어디에 담아야 할까요?
패턴을 모델 훈련으로 가르치기 전에 저장소에 이미 쌓인 지식을 살펴보고 싶습니다. 이전 에세이에서는 저장소가 프로젝트의 작업 기억이 되어 간다고 썼습니다. 여기에는 컴파일러에 관한 교훈과, 그 교훈을 유용하게 만든 소스와 실패한 실험도 담겨 있습니다.
에이전트는 기록을 검색해 알려진 결과에서 시작하고, 거기 도달한 과정을 살펴볼 수 있습니다. 같은 맥락에서 이미 실패한 대안도 피할 수 있습니다. 모델의 가중치를 바꾸지 않고도 출발점이 나아집니다.
TH09의 적 생성 함수를 재구성할 때 GPT-6-Luna-max 세션은 TH08의 관련 소스 계열에서 가설을 얻었습니다. 이전 소스는 루프 구성과 내부 실패 처리의 단서를 줬습니다. TH09 자체의 증거로 게임별 세부 사항을 채우고, 클린 빌드로 전체 일치를 확인했습니다.
“모델이 컴파일러 특성을 몰랐다”와 “알아도 활용하지 못했다”는 다른 문제입니다. 검색으로 첫 문제를 풀 수 있지만, 그 사실을 유용한 후보로 만드는 일은 여전히 필요합니다. 후보가 실패하면 그 결과가 다음 시도에 무엇을 뜻하는지 판단해야 합니다. 관련 패턴을 아는 것은 시작일 뿐입니다.
그래서 비교에는 검색을 잘 활용하는 작은 범용 모델도 포함하고 싶습니다. 같은 경험 자료를 주면 학습이 후보 생성, 피드백 후의 판단, 혹은 둘 모두를 얼마나 개선하는지 구분할 수 있습니다.
다음 유용한 실험 학습하기
제가 가장 연구하고 싶은 것은 피드백 이후의 판단입니다. 에이전트 중심 재구성에서 모델은 설명을 제안하고 프로그램과 대조해 검증합니다. 후보가 실패해도 결과는 남은 가능성을 좁히고 다음에 유용할 실험을 제시할 수 있습니다.
임시 결과 사례를 다시 보세요. 최종 소스는 성공한 구성을 보여주지만 거기에 도달한 과정에는 더 많은 정보가 있습니다. 아래 실험들은 무엇을 더 바꿔야 하는지 알아내는 데 도움이 됐습니다.
| 실험 | 결과에서 배운 점 |
|---|---|
| 다른 방식으로 결과 복사 | 복사 코드는 바뀌지만 함수는 여전히 다릅니다. |
| 반환된 값을 직접 사용 | 복사는 원본 패턴을 따르지만 임시 저장 공간은 여전히 다릅니다. |
| 임시 결과들의 수명을 겹치게 유지 | 별도 저장 공간이 생기지만 하나는 이후 충돌 판정에 쓰는 값과 여전히 겹칩니다. |
| 충돌 판정 값을 별도로 유지 | 클린 빌드로 함수 전체의 일치를 확인합니다. |
위 공격 함수 재구성 실험에서 배운 내용을 기준으로 묶은 사례입니다.
이 순서를 보존한 학습 기록은 최종 소스만으로는 알 수 없는 것까지 가르칠 수 있습니다. 제안한 변경, 관찰한 결과, 다음 판단을 연결하기 때문입니다. 효과가 없던 변형도 중요합니다. 같은 맥락에서 어떤 가설을 이미 시험했는지 다음 에이전트에게 알려줍니다.
모델이 피드백을 활용하는 법을 배우면 좋겠습니다. 변화 없는 결과는 변형을 재고할 이유가 되고, 달라진 불일치는 다른 원인을 가리킬 수 있습니다. 부분 수정에서 더 이상 정보를 얻지 못하면 소스 표현을 다시 생각하거나 증거를 재검토할 수 있어야 합니다.
이런 선택을 배우려면 자율성이 필요합니다. 다음에는 코드를 또 수정해 컴파일하기보다 다른 호출 함수를 살펴보는 편이 유용할 수도 있습니다. 정해진 재작성 순서를 강제하면 그 선택과 함께 우리가 학습시키려는 행동의 일부도 사라집니다.
리버스 엔지니어링이 강화 학습에 흥미로운 이유
범위를 정한 재구성은 이런 선택을 연구할 실용적인 환경입니다. 대상과 컴파일러를 고정하면 많은 소스 실험에서 빠르고 반복 가능한 피드백을 얻습니다. 에이전트는 후보를 컴파일하고 불일치를 살핀 뒤 그 관찰로 다음 단계를 고를 수 있습니다.
강화 학습으로 이런 피드백을 통한 의사 결정을 훈련할 수 있습니다. 정의된 검사를 통과한 후보는 구체적인 성과가 되고, 시도 순서를 보면 거기 도달하는 데 들인 작업량을 알 수 있습니다.
이 방향을 뒷받침하는 연구도 있습니다. LLM4Decompile은 디컴파일 특화 모델을 연구합니다. AutoDecompiler는 컴파일러와 실행 피드백으로 여러 차례 개선하는 과정을 학습시킵니다. 두 연구는 기능 복원에 집중합니다. 저는 이를 출발점 삼아 당시 컴파일러의 출력과 일치하는 소스를 찾는 관련 과제를 연구하고 싶습니다.
다만 잘 정의된 과제를 만들려면 먼저 함수가 무엇을 소유하는지 밝히거나 새로운 런타임 측정을 설계해야 할 수 있습니다. TH08에서는 충돌 판정 차이를 추적하다 원본의 부동소수점 계산 방식에 도달했습니다. 에이전트는 유용한 수정을 시험하기 전에 무엇을 측정할지 알아내야 했습니다.
이는 폭넓은 역량을 가진 모델의 또 다른 역할을 보여줍니다. 문제를 검증 가능한 형태로 만드는 일입니다. 검증 수단을 마련한 뒤에는 학습된 탐색 전략으로 어디까지 갈 수 있는지 살펴볼 수 있습니다.
오라클이 틀렸을 때
검사를 기준으로 학습시키면 그 검증 범위도 모델이 배우는 내용의 일부가 됩니다. 저는 이 참조 기준이나 검사기를 오라클이라고 부릅니다. 답이 매번 같더라도 그 답이 무엇을 검증하는지 이해해야 합니다.
TH08은 검증 범위 밖에 얼마나 많은 문제가 숨어 있을 수 있는지 보여 주었습니다. 재구성된 일부 함수는 잘못된 부동 소수점 상수를 사용하고도 정확한 일치 비교를 통과했습니다. 비교기는 명령어를 검사하기 전에 재배치된 주소를 조정했지만, 그 주소가 가리키는 값은 검증 대상으로 명시적으로 기록된 경우에만 확인했습니다. 그 밖의 리터럴 참조는 값을 검사하지 않은 채 통과할 수 있었습니다.
허점을 메우기 위한 확대 점검에서 이미 통과한 함수들의 잘못된 상수를 발견했습니다. 한 계산은 원본이 32.0f을 더하는 곳에서 재구성 소스가 1.0f를 더했습니다.
이전 검사로 보상받는 모델은 잘못된 재구성을 학습할 수 있었습니다. 이 오라클로 RL 모델을 훈련한 것은 아니며, 실제 실패는 검사 자체에서 관찰됐습니다. 하지만 이를 보상으로 썼다면 같은 사각지대가 학습 환경의 일부가 됐을 것입니다.
기능 테스트에도 비슷한 사각지대가 있습니다. LLM 디컴파일러의 차등 퍼징 연구는 제공된 테스트 밖에서 동작 차이를 발견했습니다. 따라서 테스트 통과는 실행한 사례 범위에서 해석해야 합니다. 명령어 일치도 실제로 확인한 바이트와 데이터 범위에서 해석해야 하는 것과 같습니다.
어느 검사를 보상으로 쓰든 의도적으로 실패하는 사례로 시험하고 싶습니다. 최종 수용 기준은 후보의 수정 가능한 소스 밖에 두어 재구성으로 검사를 만족하게 해야 합니다. 그렇지 않으면 대상에서 복사한 바이트 배열만으로도 유용한 소스를 복구하지 않은 채 단순한 점수를 얻을 수 있습니다.
학습 모델과 오라클의 개선은 같은 연구 과제입니다. 모델이 주어진 피드백을 더 잘 최적화할수록 그 피드백 자체를 이해하는 일도 중요해집니다.
시도해 볼 만한 비교
검증 체계를 갖춘 뒤 고정된 VC7.1 과제군에서 비교를 시작하고 싶습니다. 먼저 강력한 범용 모델과 작은 모델의 기준 성능을 측정합니다. 작은 모델에 저장소 지식을 더해 검색의 효과를 봅니다. 이어서 지도 학습으로 특화한 버전과 RL 학습 버전으로 훈련이 더하는 효과를 살펴봅니다.
유의미한 비교를 위해 각 모델에 같은 대상 증거와 도구를 제공합니다. 훈련 효과를 비교할 때는 기반 모델과 활용 가능한 지식도 고정합니다. 반복 실험으로 믿을 만한 탐색 전략과 우연히 성공한 후보를 구별할 수 있습니다.
출발 조건도 둘로 나누고 싶습니다. 명령어에서 함수를 재구성하는 과제와, 유지보수 소스에 남은 마지막 차이를 맞추는 과제입니다. 특화 모델은 후자에 뛰어나고 범용 모델은 거기에 도달하기 위한 작업 대부분을 수행할 수도 있습니다. 따로 측정하면 역할 분담이 드러납니다.
두 과제 모두 학습에서 확실히 제외된 예제가 필요합니다. 관련 동방 게임은 엔진 코드를 공유하므로 게임 이름만 제외하면 거의 같은 함수가 학습에 남을 수 있습니다. 대신 소스 계열 전체를 분리하고, 검증된 정답을 학습과 검색 양쪽에서 제외하고 싶습니다.
측정할 성과는 전체가 독립적으로 검증된 일치 결과입니다. 후보 제안 수나 컴파일 횟수를 같게 제한하면 탐색 품질을 비교할 수 있습니다. 컴파일을 포함한 경과 시간과 총비용은 그 품질이 효율적인 작업으로 이어지는지 알려줍니다. 훈련 비용도 따로 계산해야 합니다.
두 관점 모두 중요합니다. 제안 자체가 저렴해도 정보 없는 컴파일을 늘리면 전체 작업은 비싸집니다. 반대로 느린 모델도 유용한 실험을 빨리 찾으면 비용을 만회할 수 있습니다. 비교에는 이 비용까지 포함해야 합니다.
통과한 결과를 세면 중간 진전도 적절히 평가할 수 있습니다. TH09의 리플레이 저장 후보는 함수 크기가 예상과 같아 유망해 보였지만, 전체 비교에서는 여전히 큰 차이가 있었습니다. 명령어 배치가 바뀌어 근본 문제는 그대로인데 더 가까워 보일 수도 있습니다. 이런 진단은 다음 실험을 안내하지만, “더 가까워짐”에 주는 보상도 전체 수용 기준과 대조해 검증하고 싶습니다.
결과 전반의 패턴도 궁금합니다. 특화 모델이 익숙한 컴파일러 계열에서 잘한다면 도구 모음이 바뀌어도 우위가 유지될까요? 두 모델 모두 검색을 잘 활용하면 학습은 얼마나 더 도움이 될까요? 각 모델이 어디서 가장 유용한지 판단할 단서가 됩니다.
어떤 에이전트가 필요할까?
모델마다 도움이 되는 단계가 다르다면, 폭넓게 일하는 에이전트가 특화 모델을 도구로 쓰는 구성이 유용할 수 있습니다. 과제가 익숙한 컴파일러 탐색으로 좁혀지면 특화 모델에 후보를 요청합니다. 결과가 이해되지 않으면 범용 에이전트가 대상 증거로 돌아가거나 측정 자체를 조사합니다.
이 구성에서는 특화 모델이 조사 진행에 따라 선택할 수 있는 도구가 됩니다. 에이전트는 앞선 돌파구를 가능하게 했던 방향 전환의 자유를 유지합니다.
이는 앞선 에세이에서 설명한 산업적 전환과 자연스럽게 이어집니다. 훨씬 많은 실험을 실행할 수 있으면 작업을 조직하는 방식도 달라집니다. 어떤 판단에 폭넓은 역량이 필요하고 어떤 판단은 특정 분야의 반복 경험으로 나아지는지 물어볼 이유도 생깁니다.
지금까지 가장 강력한 범용 모델은 제가 풀지 못한 문제를 해결하며 제 작업에서 자리를 잡았습니다. 그래서 성공 과정을 더 자세히 살펴보고 싶습니다. 얼마나 많은 부분이 모델의 폭넓은 역량 덕분이며, 이런 재구성에 특화해 학습한 모델은 어디까지 맡을 수 있을까요?
저장소를 통해 이 질문을 검증할 수 있습니다. 그 기록으로 비교 실험을 구성하고 무엇을 배우게 될지 살펴보고 싶습니다.
증거와 사용 모델 명시
상세 증거 기록에 비교 결과와 실험 맥락이 담겨 있습니다.
예제는 연결된 커밋에 기록된 과거의 함수 단위 비교입니다. 전체 게임의 런타임 검증은 별도 이정표입니다. 소스와 일치 기록은 2026년 10월 13일에 검토했습니다.
TH09의 gpt-dots 라벨은 GPT-6-Astra를 가리킵니다. gpt-web은 당시 사용한 모델에 따라 달라졌으므로 그 라벨만으로는 개별 실행을 식별할 수 없습니다. 다른 인용 커밋에 명시된 모델 이름으로 기록상 어떤 모델이 사용되었는지 확인할 수 있습니다. 이 기록들에는 실행별 비용이나 추론 노력에 대한 일관된 측정값이 없습니다.
- TH09 임시 값의 수명: 이전 맥락 검토와 완전한 콜드 재구성.
- TH09 Front 콜백: 일치하지 않은 진단 구간, Astra의 새 제어 흐름 그래프, 통과한 재컴파일 재현.
- 컴파일러 지식: TH095 식별자 버킷 재사용, TH04 플레이어 소스와 링크 순서, Luna의 TH09 적 생성 함수 완성.
- 검증과 진단: TH08 부동소수점 리터럴 점검, TH08 수치 조사, TH09 리플레이 저장 재구성.
특화 모델과 RL 비교는 앞으로 해볼 실험입니다. 프로젝트 이력이 동기를 제공하지만, 이 글에서 학습된 특화 모델을 평가하지는 않았습니다.