안드로이드 게임 해킹 - 스피드핵 제작을 위한 사전 지식

스피드핵, 게임의 속도를 사용자가 원하는대로 조절할 수 있게 해주는 툴이다. 일반적으로, 게임을 아주 빠르게 하여 오래 기다려야 될 것을 금방 끝나게 하거나, 게임을 아주 느리게 하여 게임 난이도를 낮추는 식으로 쓰인다. 이 스피드핵은 어떠한 방식으로 구현되는 것일까? 이를 알기 위해서는 스피드핵 동작을 가능케 해 주는 게임의 특성을 먼저 알아 볼 필요가 있다.


모든 게임은 특정 코드가 반복되는 형태로 실행된다. 아주 단순한 게임이 있다고 하자. 캐릭터가 일정한 속도로 달려가는 아주 단순한 게임이다. 해당 게임은 아마도 아래와 같은 형태의 코드를 가질 것이다. 단순히 캐릭터의 위치에 정해진 속도를 반복적으로 더해주는 방식이다.


while

{

    character.xpos = character.xpos + speed;

}


위 코드는 아무 문제가 없는 것 처럼 보인다. 실제로 실행을 해 보아도 아무 문제 없이 잘 돌아간다. 하지만 위 코드에는 아주 중대한 결점이 있는데, 그 누구도 while 문이 1초에 몇 번 실행될 지 알 수 없다는 것이다. 성능이 좋은 컴퓨터라면 1초에 200번 실행되겠지만, 성능이 좋지 못한 컴퓨터에서는 1초에 100번밖에 실행이 되지 않는 등의 문제가 발생한다. 즉, 컴퓨터 성능에 따라 캐릭터가 달려가는 속도가 달라지는 것이다. 이를 해결하기 위해 게임에서는 '델타 타임' 이라는 개념을 사용한다. '델타 타임'은 while 문이 실행되는 간격을 의미한다. 이 '델타 타임'을 캐릭터의 속도에 곱하여 더해주는 것인데, 코드로 보는 것이 이해가 더 빠를 것이다.


int lastTime, nowTime;


while

{

    nowTime = time();

    deltaTime = nowTime - lastTime;

    lastTime = nowTime;


    character.xpos = character.xpos + speed * deltaTime;

}


'델타 타임'에 대한 개념은 위 코드로 이해했을 것이라 생각하고 넘어가겠다. 잘 모르겠다면 구글에 '델타 타임'을 검색해보면 유명한 개념이라 잘 설명되어 있는 글들이 많으니 이를 참고하자. 여하튼, '델타 타임' 개념을 도입함으로써 캐릭터는 컴퓨터 성능에 관계없이 동일한 속도로 달려나갈 것이다.


스피드핵은 바로 이 '델타 타임'을 이용하여 구현된다. 위 코드를 잘 보면 '델타 타임'을 계산하기 위해 time 함수를 사용하여 현재 시각을 구해오고 있는 것을 알 수 있다. 만약, time 함수를 후킹하여 반환되는 시간값을 조작하면 어떻게 될까? 반환되는 시간값을 2배로 조작하면 '델타 타임'은 두 배 더 크게 계산될 것이고, 반환되는 시간값을 1/2배로 조작하면 '델타 타임'은 반값으로 계산될 것이다. 즉, 게임의 속도가 2배 빠르게, 2배 느리게 조작되는 것이다. 이것이 스피드핵의 기본적인 동작 원리다.


즉, 스피드핵을 구현하기 위해 해야할 일은 크게 두 가지다.

① 어떻게 함수를 후킹할 것인가

② 무슨 함수를 후킹할 것인가