본 글은 졸업작품(안티치트 시스템 개발)을 위한 학술 목적의 보안 연구입니다. 치트의 동작 원리를 분석하여 탐지 및 방어 방안을 설계하는 데 활용합니다.
이전 글(#5)에서 메모리에서 6개 속도 필드의 오프셋을 추출했다. 이번 글에서는 그 오프셋을 클라이언트 측 핵 프레임워크에 정식 모듈로 통합하는 작업을 정리한다.
핵 본체는 팀원들이 이미 스켈레톤을 만들어 둔 상태였다. dllmain 진입부터 ImGui + Kiero(DX11 Hook) 오버레이, MinHook, 그리고 PlayerCheats(GodMode / Stamina / Hunger 등) 까지의 MemoryCheats 패턴이 자리 잡혀 있다. 내가 할 일은 그 패턴을 그대로 따라서 MovementCheats 모듈을 9개 파일에 끼워 넣고, 종류별 ±버튼 UI와 edge detection 로직까지 다듬어 내는 것이다.
이 글에서 다루는 내용:
- 팀원들이 만들어둔 MemoryCheats 패턴 (Offsets.h → Pal.cpp → Menu → Tick)
- #5 서버 분석에서 얻은 6개 속도 오프셋이 클라이언트에도 그대로 통하는 이유
- 그 패턴 위에 SpeedHack을 끼워넣는 9개 파일 수정 흐름
- ON→OFF 전이를 감지해 기본값으로 1회 복귀시키는 edge detection 패턴
- 종류별 ±버튼 UI에서 PushID/PopID, BeginDisabled 활용
- 안티치트 설계 관점: 클라이언트 변조 vs 서버 변조의 탐지 전략 차이
분석/구현 환경:
| 항목 | 내용 |
| 타겟 프로세스 | Palworld-Win64-Shipping.exe (Steam 클라이언트) |
| 게임 버전 | Palworld v0.7.2.87654 |
| 엔진 | Unreal Engine 5.1.1 |
| SDK 덤프 | Dumper-7 |
| 인젝터 | 자체 제작 LoadLibrary 인젝터 (Pal_Injector.exe) |
| 핵 본체 | C++ Internal DLL + Dear ImGui + Kiero (DX11 Hook) + MinHook |
1단계: 스켈레톤이 채택한 방식 — Internal DLL
핵 프레임워크가 이미 클라이언트 측 Internal DLL 인젝션 기반으로 깔려 있다. SpeedHack 모듈을 추가하기 전에, 이 방식이 왜 채택되어 있는지부터 정리해 둔다. 모듈을 어디에 어떻게 끼워야 하는지가 이 결정으로부터 나오기 때문이다.
전제부터 짚어두면, 팰월드는 클라이언트에 별도의 안티치트가 활성화되어 있지 않다. 실제로 #5에서도 Cheat Engine으로 PalServer 프로세스에 어태치한 뒤, GWorld → Pawn → CharacterMovement 의 포인터 체인을 따라가서 6개 속도 필드를 그대로 읽고 쓸 수 있었다. 클라이언트 프로세스(Palworld-Win64-Shipping.exe)에 대해서도 같은 External 접근이 기술적으로는 가능하다.
그럼에도 우리 스켈레톤이 굳이 DLL을 게임 프로세스 안에 주입하는 방식을 채택한 이유는, 이 프로젝트의 목적이 치트 자체를 만들어 쓰는 것이 아니라 안티치트를 설계하기 위해 공격자의 도구를 재현해 보는 것이라는 점에서 나온다.
1. 현실의 위협 모델과 일치한다. 게이밍 커뮤니티에서 유통되는 상용 핵의 절대다수는 Internal DLL 인젝션 + ImGui 메뉴 + 함수 후킹의 조합이다. 안티치트가 실제로 막아야 할 대상이 이런 형태이므로, 같은 구조로 직접 만들어 봐야 의미 있는 탐지 설계가 나온다. CE 어태치는 학습 단계에서는 유용하지만 실전에서 마주칠 위협 형태와 거리가 멀다.
2. 인-게임 시연이 가능하다. INSERT 키 한 번으로 메뉴를 띄우고, 종류별로 토글하면서 게임 화면 안에서 즉시 결과를 확인할 수 있다. CE 방식은 매 게임 실행마다 GWorld 베이스부터 포인터 체인을 다시 추적해야 하고, 게임 창과 별도의 외부 창을 오가며 봐야 해서 시연 효율이 떨어진다. 졸업작품 발표에서 그대로 보여줄 수 있는 형태가 필요했다.
3. 다음 단계의 함수 후킹으로 자연스럽게 연결된다. Track 2에서 다룰 TakeDamage 같은 함수 후킹, 이동 패킷 가로채기 같은 작업은 외부에서는 원천적으로 불가능하다. 게임 함수의 첫 몇 바이트를 점프 코드로 바꿔치려면 그 코드가 게임과 같은 메모리 공간 안에 있어야 한다. SpeedHack 단계까지는 External로도 만들 수 있지만, 그 다음 단계로 가려면 어차피 Internal 인프라가 필요하다.
Internal vs External
External: ReadProcessMemory / WriteProcessMemory 등 외부 API로 다른 프로세스 메모리에 접근.Cheat Engine이 대표적.
Internal: 자기 프로세스 안의 변수처럼 직접 read/write. 한 번 인젝션되면 게임 코드와 동일한 권한으로 메모리에 접근, 함수 후킹까지 가능
따라서 SpeedHack 모듈도 이 환경 안에서 동작한다 즉 #5에서 추출한 오프셋을 외부 메모리 쓰기 API가 아니라 내부 포인터 역참조로 풀어내는 코드를 짜면 된다는 뜻이다.
2단계: 아키텍처 — Internal DLL + ImGui + SDK 모듈화
본 글은 SpeedHack 모듈을 어떻게 끼워 넣었는지를 정리하는 것이 목적이다. 스켈레톤 자체(DLL 진입 절차, Kiero가 DX11 SwapChain을 후킹하는 내부 동작, ImGui와 D3D11DeviceContext의 연결 같은 것들)는 팀원이 미리 만들어둔 것이며, 그 깊은 구현 디테일은 본 글의 범위 밖이다. 이 챕터에서는 내가 만든 모듈을 어디에 어떻게 끼워야 하는지 이해할 정도의 흐름까지만 본다.
핵 본체 구조는 다음과 같다
Project/
├── Core/ ← DLL 진입점 (dllmain.cpp) + 메인 루프 (HackMain.cpp)
├── GUI/ ← ImGui 메뉴 (Menu.cpp) + DX11 후킹 (Overlay.cpp)
├── Memory/ ← AOB 스캐너, MinHook 래퍼, 시스템 후킹
├── SDK/ ← Offsets.h + Pal.cpp/h (게임 데이터 접근 헬퍼)
├── Cheats/
│ ├── MemoryCheats/ ← Track 1: 오프셋 기반 변조 (이번 글의 영역)
│ └── HookCheats/ ← Track 2: AOB + 함수 후킹 (다음 글 예정)
└── Vendor/ ← ImGui, MinHook, Kiero (서드파티)
위 폴더 트리에 등장하는 외부 도구들을 먼저 한 줄씩 정리한다:
dllmain : DLL이 게임 프로세스에 주입된 순간 OS가 자동으로 호출해 주는 진입 함수. C++ DLL의 시작점
ImGui (Dear ImGui) : 게임 화면 위에 메뉴 / 체크박스 / 버튼 UI를 그리는 라이브러리. 핵 만들 때 사실상 표준 도구
Kiero : 게임의 DX11 그래픽 함수(Present)를 가로채서 우리 ImGui 메뉴를 매 프레임 화면에 끼워 넣게 해주는 도우미
MinHook : 임의의 C++ 함수를 가로채는(=후킹하는) 라이브러리. 함수의 시작 몇 바이트를 우리 함수로 점프하는 코드로 바꿔치기 → 게임이 그 함수를 부를 때마다 우리 코드가 먼저 실행되게 함. 다음 글의 함수 후킹(Track 2)에서 본격 활용
이제 DLL이 주입된 순간부터 매 프레임 동작까지의 흐름을 단계별로 본다.
[1] DLL 진입 — 인젝션 직후 1회
Pal_Injector.exe가 우리 DLL을 게임에 집어넣는 순간, OS가 dllmain.cpp 의 진입 함수를 자동 호출한다. 여기서 핵 동작 전용 스레드(MainThread)를 하나 띄운다. 이후 모든 작업은 이 스레드 안에서 일어난다. 게임 본체 스레드와 분리해서 게임 흐름에 끼어들지 않게 하기 위함.
DLL Injection = "우리 DLL을 남의 프로세스 안으로 운반해서, 그 프로세스가 자기 발로 우리 DLL을 load 하게 만드는 행위". load 되는 순간 우리 코드가 남의 메모리 공간 안에서 실행 가능.
[2] 초기화 — MainThread 시작 직후 1회
MainThread(우리 핵 전용 스레드)가 막 시작된 직후, 본격적으로 핵을 돌리기 전에 환경 세팅이 한 번만 일어난다. 게임을 처음 켤 때 키보드/마우스 설정 한 번 잡아두는 단계와 비슷하다. 이 작업을 HackMain::Initialize() 함수가 담당하며, 안에서 다음 세 가지 준비가 차례로 진행된다.
(a) 디버그용 콘솔 창 띄우기 : 게임은 그래픽 프로그램이라 기본적으로 콘솔 창(검은 명령 프롬프트)이 따라붙지 않는다. 그래서 printf 같은 출력문을 코드에 적어도 결과가 어디로 가는지 보이지 않는다. 핵이 잘 도는지 디버그 메시지로 확인하고 싶을 때 곤란해진다. 해결책으로 윈도우 API AllocConsole() 한 줄을 호출해 강제로 콘솔 창을 하나 띄운다. 이후부터는 게임 화면 옆에 검은 콘솔이 같이 떠 있고, printf("WalkSpeed = %.0f", val) 같은 식으로 찍는 메시지가 거기 출력된다. "GWorld 주소 추적 OK", "포인터 NULL 감지" 같은 내부 상태를 눈으로 확인할 수 있게 되는 것이다.
(b) MinHook 라이브러리 초기화 : MinHook은 함수 후킹(어떤 함수가 호출될 때 우리 함수가 먼저 실행되도록 가로채는 작업)을 도와주는 외부 라이브러리다. 새 도구상자를 처음 쓸 때 한 번 준비를 해둬야 그 뒤의 사용 명령들이 통하듯이, MinHook도 처음에 MH_Initialize() 한 줄을 호출해 내부 자료구조를 빈 상태로 세팅해 줘야 한다. 이걸 거르면 그 다음에 후킹 명령(MH_CreateHook(...))을 부를 때 에러가 난다.
이 시점에는 준비만 하고, 실제로 어떤 함수를 후킹하는 건 바로 이어지는 (c)에서 일어난다.
(c) Kiero로 DX11 Present 함수 후킹 :
1. DX11은 윈도우 게임이 그래픽카드와 통신할 때 쓰는 표준 API(통신 규약)다.
2. 그 API에 Present 라는 함수가 있다. 의미는 "이번 프레임 다 그렸으니 모니터에 띄워라". 게임이 한 프레임을 다 그릴 때마다 마무리로 호출하는 함수이며, 60FPS 환경이라면 1초에 60번 호출된다. 캐릭터가 움직이든 가만히 있든 무관하게 매 프레임 호출되는 마무리 함수다.
3. ImGui 메뉴를 게임 화면 위에 띄우려면, 게임이 화면을 띄우려는 바로 그 순간(=Present가 호출되는 그 시점)에 끼어들어 메뉴를 한 겹 덧그려야 한다.
4. 끼어드는 방법이 후킹인데, 후킹을 하려면 Present 함수가 메모리에 있는 주소를 알아야 한다. 그런데 이 주소는 게임 빌드/실행 환경에 따라 달라서 직접 찾기가 까다롭다.
5. Kiero는 바로 이 주소를 대신 찾아주는 외부 라이브러리다. Kiero가 알려준 주소를 (b)에서 준비한 MinHook에 넘기면, 게임의 Present 호출이 그 시점부터 우리가 만든 함수 Overlay::hkPresent로 가로채지게 된다.
이 후킹이 완료되는 순간부터, 게임이 매 프레임 화면을 띄우려 할 때마다 우리 코드가 먼저 실행되는 길이 열린다. 그 자리에 ImGui 메뉴를 그리면 게임 그림 위에 메뉴가 자연스럽게 덧씌워져 보인다. 1초에 60번 이상 자동으로 호출되는 진입점이라, 메뉴 갱신용으로는 더할 나위 없는 자리인 셈이다.
세 가지가 끝나면 핵이 본격 동작할 환경이 갖춰진다.
[3] 매 10ms 치트 동작 — MainLoop 백그라운드 루프
위와 별도로 HackMain::MainLoop()가 10ms 주기의 무한 루프로 돈다. 왜 단발이 아니라 반복이냐 하면, 게임 코드도 같은 변수를 자기 로직에 따라 다시 덮어쓸 수 있기 때문이다. 우리가 한 번만 써두면 게임이 곧 기본값으로 되돌릴 수 있어서, 짧은 주기로 다시 쓰며 항상 우리 값이 마지막에 남도록 유지한다. 이 루프 안에서 활성화된 치트 모듈들의 Tick() 함수가 차례대로 호출된다.
Tick 은 "한 박자마다 호출되는 함수" 라는 게임 프로그래밍 관용어
이번에 추가하는 SpeedHack은 MemoryCheats 에 속한다. 친구가 이미 만들어둔 PlayerCheats(GodMode, Stamina, Hunger, ShieldHP 등)의 패턴을 그대로 따른다.
| 단계 | 역할 |
| SDK/Offsets.h | 오프셋 상수 등록 |
| SDK/Pal.h + Pal.cpp | 포인터 체인을 추상화한 getter/setter (오프셋 직접 노출 X) |
| GUI/Menu.h + Menu.cpp | ImGui 토글/슬라이더 UI, 상태는 Menu::Config에 보관 |
| Cheats/MemoryCheats/MovementCheats.cpp | 매 프레임 호출되는 Tick() — 토글 상태 보고 SDK 함수 호출 |
| Core/HackMain.cpp | MainLoop 안에서 Tick() 한 줄 호출 |
| CMakeLists.txt | 새 .cpp를 빌드 대상에 등록 |
이 구조의 핵심 가치는 GUI는 오프셋을 모른다는 점이다. 메뉴는 Menu::Config.bSpeedHack 만 토글하고, 실제 메모리 접근은 MovementCheats가, 포인터 체인 추적은 SDK::Pal이 책임진다. 책임 분리 덕에 한 곳이 깨져도 다른 모듈에 영향이 없다.
3단계: 6개 속도 필드의 오프셋
#5에서 추출한 오프셋은 다음과 같다:
| 오프셋 | 필드 | 타입 | 기본값 | 분류 |
| 0x01F8 | MaxWalkSpeed | float | 350 | UE5 엔진 |
| 0x01FC | MaxWalkSpeedCrouched | float | 250 | UE5 엔진 |
| 0x0200 | MaxSwimSpeed | float | 250 | UE5 엔진 |
| 0x0204 | MaxFlySpeed | float | 600 | UE5 엔진 |
| 0x1140 | SprintMaxSpeed | float | 500 | 팰월드 전용 |
| 0x114C | GliderMaxSpeed | float | 500 | 팰월드 전용 |
이 오프셋들은 클라이언트와 서버 둘 다 동일하다. 이유는 두 프로세스가 같은 SDK 정의를 공유하기 때문이다.
다른 것은 단 하나, GWorld 진입점이다.
서버 GWorld: PalServer-Win64-Shipping-Cmd.exe + 0x882DA60
클라이언트 GWorld: Palworld-Win64-Shipping.exe + 0x090D3030
GWorld 이후의 체인(+0x158 → +0x2A8 → +0x308 → +0x320 → +0x1F8)은 동일하다.
클라이언트 GWorld 주소 0x090D3030은 우리 프로젝트 스켈레톤의 SDK/Offsets.h::Module::GWorld에 이미 등록되어 있었다. 친구가 GodMode 만들 때 추적해 둔 값이다.
4단계: 9개 파일 수정 워크플로우
이제 실제 코드를 보자. 정리하면 9개 파일을 변경해야한다.
[1] SDK/Offsets.h — 오프셋 등록
Pawn 네임스페이스에 CharacterMovement = 0x320 한 줄 추가하고 파일 하단에 Movement 네임스페이스 통째로 신설한다.

포인터 체인 Pawn → CharacterMovement → 속도 필드 에서 가운데 한 단계가 빠지면 6개 속도 필드 어디에도 도달할 수 없으므로, 이 한 줄이 SpeedHack 전체의 최초 분기점이다.

6개 속도 필드는 전부 UCharacterMovementComponent 의 멤버이므로 한 네임스페이스로 묶었다. 기준 객체별로 네임스페이스를 분리해 두면 호출이 Offsets::Movement::MaxWalkSpeed 같은 풀 경로 가 되어, 같은 0x1F8 이라도 다른 객체의 0x1F8과 헷갈리지 않는다.
[2] SDK/Pal.h / SDK/Pal.cpp — 포인터 체인 헬퍼
SDK::Pal의 설계 원칙은 각 함수가 체인의 한 단계만 진행한다는 점이다. 새 치트는 자기에게 필요한 분기점부터 재사용 가능하다.
기존 GetLocalPawn()까지의 헬퍼는 그대로 두고, 거기서 +0x320 점프하는 GetCharacterMovement()만 추가한다.

SDK/Pal.cpp 는 포인터 체인을 한 칸씩 따라가는 Step() 과 마지막 자리에 값을 적는 WriteFloatField() 를 한 곳에 모아둔 파일이다. 이 두 헬퍼 위에 6개 setter가 한 줄짜리로 깔끔하게 얹히는 구조다.


[3] GUI/Menu.h / Menu.cpp — UI 상태와 위젯
Settings 구조체에 마스터 토글, 6개 종류 토글, 6개 정수 배율을 추가한다.

UI는 종류별로 [v] [-] 현재배율 [+] (실제속도) 를 한 줄에 배치한다.
각 위젯의 의미:
[v] = 체크박스 (이 종류 켤지/끌지)
Walk = 라벨 (어떤 속도인지)
[-] = 배율 1 감소 버튼
5x = 현재 배율 (정수 표시)
[+] = 배율 1 증가 버튼
(1750) = 실제로 메모리에 써질 값 (기본 350 × 5배 = 1750), 회색 글씨로 참고용
ImGui의 BeginDisabled로 마스터가 꺼지면 모든 행이 회색이 되도록 처리한다.

PushID/PopID는 ImGui가 위젯을 라벨로 식별하는 특성 때문에 필요하다 그리고 밑의 사진은 실제 인-게임 메뉴에서 6종류 속도 행이 가지런히 정렬된 모습이다.

[4] Cheats/MemoryCheats/MovementCheats.cpp — Tick 함수
이 파일은 신규 작성이다.
MainLoop 가 매 박자 호출하는 진입점 Tick() 한 함수가 이 모듈의 전부이며, 그 안에서는 단 두 가지 일만 한다.
첫째, Menu::Config 의 토글/배율 상태를 읽는다.

둘째, 그 상태에 맞게 SDK setter 6개를 호출해 게임 메모리에 새 값을 써넣는다.

즉 메뉴(상태 보관)와 SDK(메모리 접근) 사이를 잇는 다리 역할이다. 메뉴는 자기가 어떤 오프셋에 쓰이는지 모르고, SDK는 사용자가 어떤 토글을 눌렀는지 모른다. 그 둘을 알고 있는 유일한 곳이 이 파일이다.
이제 그 다리를 어떻게 짰는지 본다. 기본값 6개는 파일 상단에 constexpr 상수로 박아둔다.

이 값들이 두 곳에서 쓰인다. 첫번째로 토글이 켜져 있을 때 boosted 값을 만들기 위한 곱셈의 기준이고, 두번째로 토글이 꺼지는 순간 메모리를 깨끗이 되돌리기 위한 복원값이기 때문이다.
여섯 종류는 모두 같은 처리 패턴을 따른다. "활성이면 boosted 쓰기, 방금 꺼졌으면 base 1회 복귀".

그 동일 패턴을 Apply() 라는 템플릿 헬퍼 한 곳에 모으면, Tick() 본문은 종류별로 한 줄씩 총 6줄로 정리된다. 헬퍼가 없었다면 같은 if-else 가 6번 복붙되어 30줄이 넘었을 코드가, 함수 정의 1개 + 호출 6개로 압축되는 셈이다. 한 군데 고치면 6종류 전부 동일하게 반영되므로 유지보수도 쉬워진다.
[5] Core/HackMain.cpp — 와이어링
MainLoop 는 핵 전체에서 유일하게 일정한 주기로 깨어나는 백그라운드 루프다. 10ms 간격으로 한 박자씩 진행하면서 활성화된 치트 모듈들의 Tick() 을 차례대로 호출하며, 각 모듈은 그 시점에 메뉴 상태를 한 번 보고 그에 맞게 게임 메모리를 갱신한다. 즉, 사용자가 메뉴에서 토글을 누르는 행위는 단지 Menu::Config 의 bool 값 하나를 바꿀 뿐이고, 그 변화를 실제 메모리 쓰기로 옮겨주는 책임은 전적으로 이 루프 안의 Tick() 호출에 있다.
따라서 새로 추가된 MovementCheats.cpp 도 누군가 Tick() 을 불러주지 않으면 단 한 줄도 실행되지 않는다. HackMain.cpp 의 루프 본문에 호출 한 줄을 끼워 넣는다.

상단의 #include 한 줄은 컴파일러에게 "이 함수가 어딘가에 정의되어 있다" 는 사실을 알려주는 역할이다. C++ 컴파일러는 한 파일씩 따로 읽기 때문에, HackMain.cpp 안에서 MovementCheats::Tick() 을 호출하려면 그 이름이 다른 파일(MovementCheats.h)에 선언되어 있다는 것을 먼저 끌어와야 한다. 인클루드를 빼먹으면 "식별자 MovementCheats 가 정의되지 않음" 에러로 빌드 자체가 실패한다. 그래서 상단에 헤더 인클루드 한 줄을 추가 했다.

[6] CMakeLists.txt — 빌드 등록
지금까지 추가한 코드를 실제로 빌드하려면 마지막 한 단계가 남아있다. CMakeLists.txt 는 프로젝트가 어떤 .cpp 파일들로 구성되는지 적어두는 빌드 설정 파일이다. 컴파일러는 폴더 안에 있는 모든 파일을 자동으로 읽지 않고, 이 목록에 적힌 파일만 컴파일 대상으로 삼는다. 즉, 파일을 새로 만들어 디스크에 두는 것만으로는 빌드에 포함되지 않으며, 이 목록에 한 줄을 추가해야 비로소 컴파일러가 그 존재를 인식한다. 따라서 우리가 새로 작성한 MovementCheats.cpp 도 소스 목록에 등록해줘야 한다. 기존 GodMode.cpp 바로 아래에 한 줄을 끼워 넣는 것으로 끝난다.

이 한 줄이 빠져 있으면 코드가 아무리 정확해도 링커 단계에서 "MovementCheats::Tick 의 정의를 찾을 수 없음" 에러로 빌드가 막힌다. 9개 파일 수정 흐름의 마지막 매듭이자, 새 모듈을 빌드 시스템에 합류시키는 가장 단순한 한 줄이다
5단계: 빌드 / 인젝션 / 동작 확인
핵 본체와 인젝터는 별도의 CMake 프로젝트로 분리되어 있다. 두 프로젝트를 각각 빌드하면 다음 경로에 결과물이 생성된다.
| 프로젝트 | 빌드 대상 | 결과물 경로 |
| JBU_Pal_Hack/Project/ | 핵 본체 DLL | out/build/x64-Debug/JBU_Pal_Hack.dll |
| JBU_Pal_Hack/Injector/ | 인젝터 EXE | out/build/x64-Debug/Pal_Injector.exe |
생성된 Pal_Injector.exe 를 실행하면 자동으로 같은 환경의 DLL을 게임 프로세스(Palworld-Win64-Shipping.exe)에 매핑한다. 이후 솔로 월드에 진입해 INSERT 키로 메뉴를 열고 다음과 같이 설정했다.

확인한 항목들:
- 포인터 체인 진입: GWorld → ... → CharacterMovement 까지 NULL 없이 도달 (콘솔 로그로 단계별 주소 출력해 확인).
- 6개 setter 동작: 마스터 ON 상태에서 W키 걷기 시 350 → 2450 (7배), Shift 달리기는 2500 (5배), 글라이더/수영/비행펫까지 각 배율로 즉시 반영.
- Edge detection: 마스터를 OFF 했을 때 캐릭터가 즉시 기본 속도로 복귀 → 켜져 있던 모든 종류가 한 번씩 base 값으로 정상 복귀하는 것 확인.
- ImGui ID 격리: 6개 행의 +/- 버튼이 행마다 독립적으로 동작 (PushID/PopID 적용 전에는 한 행 클릭하면 모든 행이 같이 바뀌는 버그가 있었음).
- Crouch 토글: 기본값 OFF로 둔 항목도 메뉴에서 켜면 즉시 적용, 끄면 250으로 복귀.
요약하면 9개 파일의 통합이 의도대로 동작하고, 친구들 스켈레톤의 MemoryCheats 패턴이 MovementCheats에도 그대로 통한다는 것을 확인했다.
'캡스톤 디자인 > 정보보호 프로젝트실습' 카테고리의 다른 글
| [팰월드 안티치트 프로젝트] #10 전용서버 메모리 분석 - 온도 시스템 (0) | 2026.04.18 |
|---|---|
| [팰월드 안티치트 프로젝트] #9-1 전용서버 메모리 분석 - ESP (0) | 2026.04.16 |
| [팰월드 안티치트 프로젝트] #8 전용서버 메모리 분석 - 재료 무소비, 아이템 복제, 무한 획득" (0) | 2026.04.16 |
| [팰월드 안티치트 프로젝트] #7 전용서버 메모리 분석 - 텔레포트 (0) | 2026.04.10 |
| [팰월드 안티치트 프로젝트] #6 전용서버 메모리 분석 - 포획률 (0) | 2026.04.07 |