이전 글에서 아이작 게임의 기본 구성에 대한 어셈블리어 동작 분석과 변조를 진행했다. 이번 게시물에서는 캐릭터 능력치에 대해 분석과 변조를 진행할 것이다.
1. 기본 구성(체력, 폭탄, 돈, 열쇠) 핵 만들기
2. 캐릭터 능력치(공격력, 공격속도, 이동속도 등) 핵 만들기
분석 환경
게임/버전 : Binding OfIsaac Rebirth 1.0
분석 도구 : Cheat Engine 7.4
분석
캐릭터 능력치
게임을 진행할 때 ESC를 누르면, 현재 능력치 창이 뜬다. 해당 능력치는 공격력, 공격속도, 사거리 등 다양한 능력치가 있다. 해당 능력치는 프로그램 메모리 어딘가에 저장되어 있을 것이다.
먼저, 검색을 통해 해당 능력치의 칸별 값 및 범위를 확인할 수 있었다. 해당 표는 아래 표와 같다.
능력치별 오프셋
치트엔진에서 Type을 지정하고, Value 값을 설정 후, Scan을 하게 되면, 지정된 프로세스 메모리 안에 해당하는 값을 모두 띄워준다. 서칭으로 찾았던 칸 별 능력치 값을 적절하게 계속 스캔하여 각 능력치 값을 가지고 있는 메모리 주소를 찾을 수 있다.
위 사진 과 같이, 체력을 줄여가면서 값을 조회하면서 찾을 수 있다. 해당 아이작 버전에서는 체력 반칸 당 1의 값을 가지고 있기 때문에 현재 하트가 2개이므로, 4의 값을 가진다.
체력을 담고 있는 주소는 15CDEC38인 것을 알 수 있다. 체력과 같이 눈물 속도, 공격 속도, 데미지, 이동속도 또한 찾아낼 수 있다.
각 캐릭터에 대한 상태 및 능력치는 메모리 위치가 가까웠다. 캐릭터 자체에 대한 정보들을 하나의 구조체로 표현하고 있는 것으로 추측했다.
게임을 여러번 실행하면서 캐릭터 능력치의 구조체를 찾아냈다. 캐릭터의 이동 방향인 HeadDown을 구조체 시작지점으로 생각했다. 캐릭터가 왼쪽을 바라보면 HeadLeft와 같이 변경된다.
위 사진들을 보면, 올라간 주소가 다 다른 것을 확인할 수 있다. 하지만, Head 라는 값은 동일한 것을 볼 수 있다. 이 외에도 정확한 구조체 멤버의 역할은 알 수 없지만, 값이 변하지 않는 부분이 있었다.
Lua Script에서는 특정 부분의 값으로만 Hex Array를 검색해서 메모리 주소 값을 가져올 수 있다.
따라서, 프로그램을 다시 실행해도 Head~ 로 시작하는 부분의 메모리 주소를 얻어낼 수 있는 것이다. 게임을 여러 번 반복하면서 얻은 Hex Array는 다음과 같다.
48 65 61 64 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 00 00 0F 00 00 00 ?? ?? ?? ?? ?? ?? ?? ?? 06 00 00 00
📌 heart(0x160d98b8) - HeadDown(0x160d9894) = 0x24
캐릭터의 능력치의 시작 지점이라고 생각했던 HeadDown 부분과 캐릭터의 체력을 담고 있는 heart 주소의 거리는 0x24였다. 이 값은 다시 실행해서 구해도 동일하다.
이러한 오프셋을 통해 캐릭터 각각의 능력치 메모리에 접근하여 값을 변조할 수 있다. 캐릭터의 능력치는 매우 많지만, 그 중에서 이동속도, 공격력, 공격속도에 대해서만 구현했다.
HeadDown으로부터 능력치 오프셋은 다음과 같다.
이동속도 : HeadDown + 0x188
공격속도 : HeadDown + 0xB0
공격력 : HeadDown + 0xC0
스피드 핵
앞서 캐릭터의 이동속도는 앞서 구한 오프셋으로 HeadDown + 0x188이다. 또한, float 자료형을 사용한다.
📌 이동속도 1마다 10진수로 4194304 차이가 났다.
Lua Script Code
[ENABLE]
Aobscan(_aob1, 48 65 61 64 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 00 00 0F 00 00 00 ?? ?? ?? ?? ?? ?? ?? ?? 06 00 00 00)
registersymbol(_aob1)
_aob1+188:
db 00 00 20 40
unregistersymbol(_aob1)
[DISABLE]
Aobscan(_aob1, 48 65 61 64 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 00 00 0F 00 00 00 ?? ?? ?? ?? ?? ?? ?? ?? 06 00 00 00)
registersymbol(_aob1)
_aob1+188:
db 00 00 00 40
unregistersymbol(_aob1)
구현은 disable 시 이동속도가 2이며, enable 시에는 값을 바꿔주기 때문에, 이동속도가 빨라진다.
공격 속도 핵
캐릭터의 공격속도는 앞서 구한 오프셋으로 HeadDown + 0xB0 이다. 또한, 공격 속도 능력치는 1바이트만 사용했다.
여러 분석을 통해 공격속도는 값이 낮을 수록 빨라지는 것을 확인할 수 있었다.
Lua Script Code
[ENABLE]
Aobscan(_aob1, 48 65 61 64 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 00 00 0F 00 00 00 ?? ?? ?? ?? ?? ?? ?? ?? 06 00 00 00)
registersymbol(_aob1)
_aob1+B0:
db 00
[DISABLE]
_aob1+B0:
db 06
unregistersymbol(_aob1)
앞서 Aobscan을 동일하게 해주고, 오프셋을 더한 주소의 값을 변경해주었다.
캐릭터 기본 공격속도가 6의 값을 가지고 있어서 disable 시에는 6으로 설정해주었고, enable 시 0으로 설정했다.
공격력 핵
공격력의 주소는 HeadDown + 0xC0 이다.
공격력은 float 형식을 가지고 있으며 아래와 같다.
- 공격력 3.5 : 1080033280 (00 00 60 40)
- 공격력 5 : 1084227584 (00 00 A0 40)
- 공격력 10 : 1092616192 (00 00 20 41)
Lua Script Code
[ENABLE]
Aobscan(_aob1, 48 65 61 64 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 00 00 0F 00 00 00 ?? ?? ?? ?? ?? ?? ?? ?? 06 00 00 00)
registersymbol(_aob1)
_aob1+C0:
db 00 00 40 41
[DISABLE]
_aob1+C0:
db 00 00 A0 41
unregistersymbol(_aob1)
disable 시, 공격력이 5로 설정되며, enable 시 엄청나게 강해지게 된다.
시현 영상
지금까지 아이작 게임의 메모리를 분석하고 변조도 진행해보았다. 치트 엔진이라는 도구를 이용해서 손쉽게 특정 메모리 주소를 찾아낼 수 있었다.
다음에는 다양한 게임을 분석해보고 싶고, DLL 인젝션으로 특정 함수를 후킹하는 것도 해보고 싶다.
📌 아래 게시물에서 치트 엔진으로 구현된 핵을 exe 파일로 만들 수 있다.