SEO

[GHA] The Battle for Wesnoth 코드 패치 실습 - Code Cave 본문

Security/Game Hacking

[GHA] The Battle for Wesnoth 코드 패치 실습 - Code Cave

Crain 2025. 1. 19. 21:52
반응형

 

https://gamehacking.academy/pages/2/07/

 

이 글은 Gamehacking Academy의 자료를 참고하여 작성된 것입니다.


 

앞선 두 번의 실습에서 게임 코드를 변경하여 비정상적인 로직을 만들었습니다. 하지만 해당 코드 패치는 현재 실행 중인 게임에만 적용되는 1회성인 코드 패치였습니다. 또한 단순히 코드를 nop으로 패치했기 때문에 어떤 로직에서 어떤 오류가 발생할지 모르는 상황입니다.

 

이러한 상황에서 원래 명령어를 유지하면서 다른 명령어를 실행시키도록 하면 프로그램이 정상적으로 동작할 수 있겠죠?

이때 사용할 수 있는 것이 Code Cave 라는 개념입니다.

 

Code Cave란?

Code Cave는 실행 파일의 빈 공간에 코드를 삽입해 동작을 변경하거나 새로운 기능을 추가하는 기법입니다. PE 파일의 패딩이나 미사용 섹션에 코드를 넣고, 프로그램의 흐름을 조작해 삽입된 코드를 실행합니다. 또한 파일 크기를 크게 변경하지 않아 탐지가 어려우며, 주로 JMP 명령어로 흐름을 제어합니다.

 

Code Cave는 게임 해킹에서 캐릭터 속도 변경, 무한 자원 생성, 또는 치트 기능 구현을 위해 자주 사용됩니다. 또한 대부분의 게임은 함수 사이 또는 실행 파일의 끝에 사용되지 않는 메모리에 Code Cave가 많이 생성됩니다.

 

저번 실습에서 Recruit 함수 대신 Load Game 함수를 실행시켰습니다.

이번 실습에서는 gold 변수를 300으로 조작하고 Recruit 함수를 실행시켜 어떠한 그룹이든 생성할 수 있게끔 조작해보겠습니다.

 

지난번 실습에서 확인한 Recruit 함수를 Call 하는 명령어는 다음과 같습니다.

0x00CCAF20 call dword ptr ds:[eax+54]

 

Code Cave가 있다는 가정하에 다음과 같이 코드를 수정할 수 있습니다.

0x00CCAF20 jmp code_cave_addr

[Code Cave Memory]
0x???????? pushad
0x???????? mov gold_memory, 0x12C
0x???????? popad
0x???????? call dword ptr ds:[eax+0x54]
0x???????? jmp original_logic

 

위와 같은 로직의 코드를 생성하기 위해서는 다음 정보들이 필요합니다.

  1. gold 변수의 메모리 상의 위치
  2. cave skeleton 생성 위치
  3. 코드 실행 후 돌아올 함수 위치

 

gold 변수의 메모리 상의 위치

https://scorchingnraining.tistory.com/149

해당 글에서 실습한 방법을 통해 현재 프로세스에서 할당된 골드 변수의 메모리 주소를 확인합니다.

 

cave skeleton 생성 위치

프로세스에서 코드 케이브가 생성되는 곳은 많지만, 대부분의 모듈에서 text 섹션이 끝날 때 쯤에 비교적 큰 크기의 코드 케이브를 찾을 수 있습니다. 위 경우에서도 text 섹션이 끝날 때 쯤에 opcode 00으로 이루어진 code cave를 발견하였습니다.

저는 0x1343E55 주소에 Code Skeleton을 생성하겠습니다.

 

코드 실행 후 돌아올 함수 위치

현재 로직을 분석해보면 사용자가 메뉴에서 선택한 함수를 실행 시킨 후 eax 레지스터에 1이라는 값을 옮기고 CCA8FD 로직으로 돌아가는 것을 확인할 수 있습니다.

 

저는 코드 케이브에서 코드를 실행시킨 후 0x00CCAF25이 아닌 0x00CCAF25 주소로 돌아올 것인데 그 이유는 다음 섹션에서 말씀드리겠습니다.

 

Code Cave Skeleton 생성

현재 0x00CCAF20 주소는 총 3바이트의 명령어로 구성되어있습니다.

 

하지만 제가 0x00CCAF20 주소에 작성하고 싶은 명령어는 jmp 0x1343E55로 총 5바이트입니다. 이렇게 되면 코드를 수정할 때 0x00CCAF23 주소에 있는 명령어를 덮어버리게 됩니다. 따라서 Code Cave에서 사라져버린 0x00CCAF23 주소에 있는 명령어를 다시 추가하여 원래의 로직과 같이 동작하도록 할 것 입니다.

 

그래서 Code Cave에서 돌아올 주소는 0x00CCAF25가 됩니다.

 

코드를 수정하면 위 사진과 같이 mov al, 1 명령어가 덮어씌워진 것을 확인할 수 있습니다.

 

 

코드 실행

Gold 변수의 메모리 주소를 덤프 화면에서 따라가보면 해당 명령어 실행 후에 0x12C 값이 할당된 것을 확인할 수 있습니다.

 

또한 recruit 함수 호출 시에 사진과 같이 사용자 이벤트를 기다리는 모습을 확인할 수 있는데, Gold의 값이 300(0x12C)으로 변경되어있고, 정상적으로 recurit 메뉴가 동작하는 것을 볼 수 있습니다.

이후에도 모든 코드 실행 시에 게임이 정상적으로 동작하는 것을 확인할 수 있습니다.

 

 

 


 

재작년에 Putty 특정 버전의 코드 케이브에 코드를 삽입하여 계산기를 실행시키는 PoC를 봤었습니다. 그때 시간 상의 문제로, 해당 PoC를 직접 작성하지는 못하고, 결국 다른 악성코드 기법을 개발했었는데, 이번 공부를 통해 다시 상기되었네요. 조만간 Putty Code Cave에 악성코드를 삽입하는 글을 포스팅해보도록 하겠습니다.

반응형