SEO

[GHA] The Battle for Wesnoth 코드 패치 실습 - 비정상적 함수 실행 본문

Security/Game Hacking

[GHA] The Battle for Wesnoth 코드 패치 실습 - 비정상적 함수 실행

Crain 2025. 1. 13. 20:20
반응형

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

 

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


 

The Battle for Wesnoth에서는 게임 캐릭터가 특정 타일 위에 존재할 때만 유닛을 모집할 수 있습니다.

따라서 유닛을 모집할 때는 다음과 같은 로직을 가지고 있을 것이라 추측할 수 있습니다.

check_tile_locate()
    show_menu()
        handle_menu()	
	          recruit_unit()    
	              select_unit_cost()
	                  sub_gold()

https://scorchingnraining.tistory.com/159

 

즉, 앞선 포스팅에서 확인하였던 골드 감소 로직보다 다양한 함수가 먼저 호출됩니다.

이러한 추측을 바탕으로 오늘 실습을 진행하겠습니다.

 

x32dbg에서는 Execute till return이라는 기능을 지원합니다. 해당 기능은 함수에서 return을 만날 때까지 실행하는 기능입니다.

위 코드에서 return까지 실행시키면 골드를 감소하는 함수의 가장 마지막 코드로 이동합니다. 이후 이 함수를 빠져나오면 골드를 감소하는 함수를 호출하는 로직을 확인할 수 있습니다.

 

Step over 버튼을 클릭해서 함수를 빠져나올 수 있습니다.

 

방금 빠져나온 0x7CB7E0 함수가 골드 값을 감소 시키는 로직이었습니다.

이제 같은 방법으로 함수를 나오면서 handle_menu까지 로직을 찾아가보겠습니다.

handle_menu는 사용자가 선택한 메뉴 값을 받아서 일치하는 값에 대한 함수를 호출할 테니, switch 문이나 if문 같은 조건문을 굉장히 많이 사용했을 것이라 추측할 수 있습니다.

 

call some_address
jmp to_end
call some_address
jmp to_end
call some_address
jmp to_end

어셈 코드가 대충 위처럼 생겼겠죠?

 

위 구문이 switch문으로 구성된 handle_menu 함수임을 추측할 수 있습니다.

recruit과 관련된 함수는 방금 빠져나온 0xCCAF20 주소에서 call되는 함수임을 알 수 있습니다.

또한 handle_menu의 함수 구현을 살펴보면 정적으로 코드를 호출하징 않고, 메모리에 저장된 위치(eax+0x54)를 찾아 호출합니다. 모든 함수 호출에 대해 dword(4바이트)의 크기로 값을 가져오는 것으로 보아, 하나의 원소에 대해 4바이트 크기를 가지는 배열에 함수들이 저장되어있음을 추측할 수 있습니다.

 

C언어로 바꾸면 다음과 같겠죠?

struct SomeStruct {
    void (*func1)();
    void (*func2)();
    void (*func3)();
    // ...
};
void (*functions[])() = {
    func1,
    func2,
    func3,
    // ...
};

동적으로 메모리에 로드되는 것으로 보아 함수 포인터 배열이나 구조체를 사용하여 구현을 하였을 것 같네요.

 

오른쪽 마우스 클릭 → 바이너리 → 편집 을 통해 eax+54에서 불러오던 함수의 주소를 eax+40에서 불러오도록 패치해보겠습니다.

 

처음과 같이 recruit 버튼을 선택하였음에도 Load Game 창이 떴습니다.

아마도 eax+0x40 주소에 들어있던 함수는 Load Game 과 관련된 함수였던 것 같습니다.

이렇게 코드 패치를 통해 개발자가 원하지 않았던 로직을 실행시킬 수 있습니다.

반응형