노트 | 2026. 10. 18. 17:27

요즘 핫한 AI 리버싱 도구 REA로 WeMod(Wand) 뜯어봤습니다 ㅋㅋ

요즘 GitHub에서 화제가 되고 있는 REA(Reverse Engineer Anything)라는 AI 리버싱 도구가 있길래 한번 테스트해 봤습니다.

분석 대상으로 선택한 프로그램은 WeMod(현 Wand) 입니다.

WeMod는 게임에서 체력 무제한, 자원 무제한, 경험치 배율 같은 치트 기능을 제공하는 트레이너 프로그램인데요.

평소 사용하면서 내부 구조가 좀 궁금했습니다.

  • 치트 테이블을 다운로드해서 실행하는 구조일까?
  • 아니면 별도의 DLL을 다운로드해 게임 프로세스에 인젝션하는 방식일까?

그래서 이번 기회에 REA와 AI 에이전트를 활용해서 실제로 분석해 봤습니다.

결론부터 말하면, 게임별 DLL 내부에서 Cheat Engine의 Auto Assembler와 사실상 동일한 형식의 치트 스크립트를 발견했습니다. ㅋㅋ

심지어 해당 스크립트를 추출해서 Cheat Engine용 CT 파일로 변환한 뒤 실제 게임에서 작동하는 것까지 확인했습니다.

1. WeMod의 API와 내부 구조 분석

먼저 WeMod가 Electron 기반으로 만들어져 있어서 JavaScript 코드부터 분석했습니다.

게임 정보를 가져오고, 트레이너를 선택하고, 다운로드하는 과정이 어떻게 구성되어 있는지 추적했는데요.

실제로 다음과 같은 API가 확인됐습니다.

GET /v3/games/{gameId}/trainer
GET /v3/games/{gameId}/trainers
GET /v3/trainers/{trainerId}
GET /v3/trainer_artifact/{artifactId}
POST /v3/trainer/backend

게임 ID와 트레이너 ID를 기준으로 치트 옵션, 실행 정보, 다운로드할 바이너리 등을 관리하고 있었습니다.

다만 API에 직접 접근했을 때는 Cloudflare 403 응답이 나와서 데이터를 바로 가져오지는 못했습니다.

대신 WeMod의 Chromium LevelDB 로컬 캐시를 분석했고, 여기서 트레이너 메타데이터와 실제 DLL 다운로드 주소를 확보할 수 있었습니다.

이번에 분석한 대상은 Path of Idle: Old Gods Rising 이라는 게임입니다.

Game ID    : 122912
Trainer ID : 50134
Loader     : trainerlib

실제 게임별 DLL은 다음 CDN 주소에서 다운로드되고 있었습니다.

https://storage-cdn.wemod.com/trainers/bin/1789516455-6aa9daa75c212

다운로드한 파일은 약 2MB 크기의 Windows x64 DLL이었으며, 로컬 캐시에 기록된 SHA-256 해시와 일치하는 것도 확인했습니다.

즉, 단순히 설정값이나 암호화된 텍스트 테이블을 받는 구조가 아니라 게임별 실행 코드를 포함한 DLL을 별도로 다운로드하는 구조였습니다.

2. 다운로드한 DLL은 어떻게 실행될까?

다음으로 DLL을 실제 게임에 어떻게 적용하는지 살펴봤습니다.

분석 결과 WeMod에는 TrainerLib_x64.dll이라는 공통 실행 계층이 존재했습니다.

전체 흐름을 단순화하면 다음과 같습니다.

WeMod / Wand
      │
      ▼
게임별 트레이너 API
      │
      ▼
Trainer DLL 다운로드
      │
      ▼
공통 TrainerLib 실행 계층
      │
      ▼
게임별 DLL의 치트 함수 호출
      │
      ▼
게임 메모리 검색 및 패치

UI에서 체력 무제한 버튼을 누른다고 WeMod가 직접 게임 메모리 주소를 수정하는 건 아니었습니다.

예를 들어 다음과 같은 변수와 값을 실행 계층으로 전달하는 구조였습니다.

unlimited_health = 1
unlimited_mana = 1
unlimited_resources = 1
xp_multiplier = 2

이후 게임별 DLL에 등록된 콜백이 실행되면서 실제 메모리 패치가 적용됩니다.

통신 방식도 흥미로웠습니다.

기존 TrainerLib 경로에서는 Windows Named Pipe를 사용하고 있었고, 앱 코드에는 TopHat이라는 로컬 gRPC 기반 실행 경로도 존재했습니다.

다만 이번 게임이 실제 WeMod 실행 중 두 경로 중 어느 쪽을 사용했는지까지는 확인하지 않았습니다.

그래도 API부터 DLL 다운로드, 로컬 실행 계층, 실제 치트 함수까지 이어지는 전체적인 구조는 파악할 수 있었습니다.

3. DLL 내부를 뜯어봤더니... 의외의 결과가 ㅋㅋ

이제 가장 궁금했던 게임별 DLL을 분석할 차례였습니다.

그런데 DLL에 보호 및 압축 처리가 적용되어 있어서 일반적인 디컴파일만으로는 핵심 코드가 제대로 보이지 않았습니다.

그래서 압축된 데이터를 복원하고, Unicorn으로 보호 로더를 에뮬레이션한 뒤 메모리에서 원래 코드와 데이터를 추출했습니다.

이후 REA와 Ghidra를 활용해 함수와 콜백을 분석했습니다.

대략 이런 과정이었습니다.

게임별 Trainer DLL
        ↓
보호 및 압축 구조 분석
        ↓
압축 데이터 복원
        ↓
보호 로더 에뮬레이션
        ↓
분석용 PE 재구성
        ↓
REA / Ghidra 분석
        ↓
치트 스크립트 발견!

그런데 여기서 정말 예상하지 못했던 부분이 나왔습니다.

DLL 내부에 Cheat Engine에서 사용하는 Auto Assembler(AA) 형식의 치트 스크립트가 포함되어 있었습니다.

AOB(Array of Bytes) 패턴으로 특정 메모리 위치를 검색하고, 해당 위치에 점프나 명령어 패치를 적용하는 방식이었습니다.

쉽게 말해 Cheat Engine의 Auto Assemble 스크립트에서 사용하는 것과 매우 유사한 구조였던 겁니다.

다만 정확히는 Lua가 아니라 Auto Assembler 스크립트이고, WeMod가 Cheat Engine 프로그램 자체를 사용하거나 연동한다는 의미는 아닙니다.

처음부터 Cheat Engine을 염두에 두고 분석한 게 아니어서 이 부분이 가장 놀라웠습니다. ㅋㅋ

실제로 복원된 치트 기능

기능내부에서 확인한 동작

체력 무제한 체력 계산값을 9,999,999로 변경
쉬운 처치 적 체력 계산값을 0으로 변경
마나 무제한 마나값을 999,999로 변경
자원 무제한 자원값을 9,999,999로 변경
경험치 배율 경험치 증가량에 배율 적용

특이하게도 체력 무제한과 쉬운 처치는 동일한 메모리 훅을 공유하고 있었습니다.

대상이 플레이어인지 적인지 구분해 서로 다른 값을 적용하는 방식이었습니다.

마나나 자원 무제한도 소비를 아예 막는 게 아니라, 특정 코드가 실행될 때 큰 값으로 덮어쓰는 형태였습니다.

실제로 다음과 같은 AOB 패턴도 추출할 수 있었습니다.

Health / Easy Kills
F3 0F 10 43 20 F3 41 0F 5D C0 F3 0F 11 43 20

Mana
F3 0F 10 48 24 45

Resources
6A 8B 7F 14 45 33 C0

결과적으로 네 개의 Auto Assembler 스크립트로 다섯 가지 치트 옵션을 처리하는 구조를 확인했습니다.

4. 추출한 스크립트를 Cheat Engine으로 검증해 봤습니다

여기까지 분석하고 나니 한 가지 궁금해졌습니다.

"이거 Cheat Engine의 AA 스크립트와 같은 방식이라면 CT 파일로 옮겨서 실행할 수도 있겠는데?"

그래서 실제로 해봤습니다. ㅋㅋ

DLL에서 추출한 스크립트를 Cheat Engine용 치트 테이블로 변환했습니다.

물론 그대로 복사해서 끝난 건 아니었습니다.

경험치 배율의 경우 트레이너에 포함된 원본 AOB 패턴이 현재 게임 버전과 일치하지 않았습니다.

게임 코드에서 사용되는 CPU 레지스터가 일부 변경되어 있어서 현재 게임에 맞게 수정해야 했습니다.

최종적으로 다음과 같은 Cheat Engine 테이블을 만들었습니다.

Path of Idle - Trainer 50134
│
├─ Health / Easy Kills
│   ├─ 체력 무제한
│   └─ 쉬운 처치
│
├─ 마나 무제한
├─ 자원 무제한
│
└─ 경험치 배율
    └─ 배율 설정

그리고 실제 게임에 적용해 보니...

정상 작동했습니다! ㅋㅋ

체력 계산값이 9,999,999로 변경되는 것을 확인했고, 마나와 자원 역시 실제 값이 변경되는 것을 확인했습니다.

경험치 배율은 수정한 코드 경로가 실행되는 것까지 확인했지만, 정확한 배율 효과까지 정량적으로 검증한 것은 아닙니다.

어쨌든 원본 DLL에서 추출한 메모리 패치 로직을 다른 도구로 재현할 수 있다는 점에서 상당히 재미있는 결과였습니다.

5. 이번 분석으로 알게 된 점

처음에는 WeMod가 암호화된 치트 테이블을 다운로드하는 건지, 아니면 게임마다 별도의 바이너리를 실행하는 방식인지 궁금했습니다.

분석해 보니 이번 게임은 API 메타데이터 + 게임별 Trainer DLL + 공통 실행 계층 + 메모리 패치 스크립트라는 구조였습니다.

그중에서도 가장 흥미로웠던 건 게임별 DLL 내부에 Cheat Engine의 Auto Assembler와 같은 형식의 스크립트가 포함되어 있었다는 점입니다.

물론 이번 결과만으로 모든 WeMod 게임 트레이너가 동일한 구조라고 단정할 수는 없습니다.

하지만 적어도 이번 게임에서는 DLL에 포함된 치트 구현을 추출하고, Cheat Engine에서 별도로 재현하는 것까지 가능했습니다.

단순히 내부 코드를 구경하는 수준이 아니라 분석 결과가 실제로 맞는지 검증까지 가능했다는 점이 만족스러웠습니다.

마무리

이번에는 REA라는 AI 리버싱 도구가 궁금해서 시작했는데, 어쩌다 보니 WeMod의 API와 게임별 DLL 실행 구조까지 분석하게 됐습니다. ㅋㅋ

물론 REA만으로 모든 과정이 자동 해결된 것은 아니고, 보호 코드 복원에는 별도의 에뮬레이션과 바이너리 분석 작업이 필요했습니다.

그래도 AI 에이전트와 리버싱 도구를 조합하니 생각보다 깊은 수준까지 분석할 수 있더군요.

무엇보다 DLL 내부에서 익숙한 Cheat Engine 스타일의 스크립트를 발견하고, 실제 CT 파일로 변환해서 작동까지 확인한 게 이번 실험의 하이라이트였습니다.

AI 리버싱, 생각보다 재미있습니다. 다음에는 다른 프로그램도 한번 분석해 보고 싶네요. ㅋㅋ

 


 

플랫폼: Steam

게임 버전: 1.1.4

PathOfIdle.CT
0.23MB

FrostK

FrostK

Writer

기록용