2017년 2월 10일 금요일

오버워치 에임핵 ct의 모든 것 2 - 좌표편1 - SpeedUp 패치법

오버워치 에임핵에서 중요한 재료가 2가지 있다. 조준점을 원하는 방향으로 변경할 수 있어야 하다. 이것은 지난 포스팅에서 다루었다. 이번에는 조준점의 방향을 잡기 위해 적과 나의 위치를 파악하는 법을 다룬다.

fps 게임에서 적의 좌표를 찾는 디버깅 방법은 여러 가지가 있다. 생각하기 쉬운 방법중 하나로 적의 위치가 메모리 어딘가에 있다고 생각하고 스캔을 반복하는것이다. 이때 타인의 도움이 필요할 수도 있다. 친구를 불러서 방을 하나 만들고 친구가 캐릭을 움직이고 나는 스캔하고 이런 식이다. 생각하기는 쉽지만 실천하기는 어렵다.

하지만 현재 오버워치 에임핵 ct에서 적과 나의 위치를 구하는 수법은 다르다. 벽구분 함수를 찾아서 그 함수의 파라미터를 이용하는 방식이다. 벽구분 함수는 파라미터로 좌표 두 개와 맵 데이터를 주고 그 좌표 사이가 뚫려 있는지 막혀 있는지 판단한다. 보통 자신의 좌표와 적 좌표가 들어 있으므로 여길 후킹하면 된다.

벽구분 함수를 찾는 방법은 매우 간단하다. 어떤 적 하나를 대상으로 스캔을 하되, 적이 보이면 1, 적이 안보이면 0 이런 식으로 스캔을 진행하면 바로 나온다. 훈련장에서 봇 하나를 대상으로 스캔을 진행하면 된다. 아래는 그 영상이다.

집중해야 할 곳은 벽구분 함수 결과를 메모리에 "쓰는" 부분이다. 왜냐하면 그 주변에 벽구분 함수가 있을 테니까. 따라서 mov [rbx+78],al 쪽을 집중해서 살펴보자. 결과가 여러개 나오는데 해당 루틴들은 모두 다 같다. 이는 오버워치가 최근에 에임핵을 막기 위해 조취한 것으로 나루토마냥 분신술을 쓴것이다. 해당 사항은 좀 더 나중에 살펴보도록 하자.

mov [rbx+78],al 에서 조금 위에 call Overwatch.exe+D2F340 이 보인다. 함수는 리턴할 때 eax값에 리턴값을 넣기 때문에 저 함수가 벽구분 함수다. 아까 말했듯이 벽구분 함수는 좌표 두개를 파라미터로 넣는다. 따라서 바로 위에 rdx와 rcx 둘 다 살펴보아야 한다. 디버깅을 해 보면 rdx는 좌표와 관련이 없고 rcx가 범인이라는 것을 알 수 있다. rcx를 살펴보면 오프셋 0과 오프셋 0x10에 각각 float값 3개씩 있는 것을 알 수 있는데 이는 순서대로 적 좌표와 자신 캐릭터의 좌표이다.

이제 에임봇의 중요한 재료를 모두 구했다. 남은 일은 벽구분함수 주변을 후킹하여 구한 좌표 두쌍을 가지고 방향벡터를 구하고 그 벡터를 길이 1로 정규화하는 것이다. 이는 고등수학 과정을 배운 학생도 다 할 수 있는 일이다. 다만 어셈블리를 통해 실수를 조작하려면 나름대로 지식이 있어야 한다. 이는 뒷 포스팅에서 따로 다루도록 하겠다.

이제 최근에 블리자드가 행한 "분신술 패치"에 대한 얘기를 하겠다.

패치 전에는 벽구분 결과에 파인드를 걸어도 mov [rbx+78],al 는 하나밖에 나오지 않았다. 따라서 거길 후킹하면 별 문제가 없었다. 지금은 여러개의 동일한 mov [rbx+78],al 패턴이 있고 주기적으로 사용하는 패턴을 바꾼다. 무슨 일이 일어나는지 잠깐 살펴보기 위해 상위 함수로 가 보았다.


call rax 에서 벽구분 함수가 있는 함수를 콜하는 것을 알 수 있다. 디버깅을 해보면 rax는 주기적으로 계속 값이 바뀌는 것이 보이고 이것이 분신술 패치의 영향임을 알 수 있다.

우회법은 아주 간단하다. 저곳을 후킹해서 콜을 한군데로 몰아주면 된다. 안그래도 저곳은 원래 반응성 향상을 위해 후킹하던 곳이다. 보안 패치를 했는데 우회하기 위한 코스트가 없다는 뜻이다. 적어도 블리자드 직원들은 분신술 패치를 하거든 인라인 함수라도 쓰는 정성을 보였으면 좋겟다.

마지막으로 ct의 SpeedUp 부분을 살펴보자 코드는 간단하다.

Overwatch.exe+11368AA - call rax 부분에서 rip가 SpeedUp으로 변경된다. call rax를 쓰지 않고 직접 원하는 곳으로 콜하는 것을 알 수 있다. 주소를 어떻게 구했는지는 직접 생각해 보시라. 코드를 보면 루프를 돌면서 여러번 콜을 하는데 이를 통해 에임핵의 정밀도가 올라간다. 초창기에 SpeedUp이 없었는데 에임핵이 부드럽게 않고 툭툭 끊긴다. 이게 어떤 효과인지 알고 싶으면 cmp [Count],10에서 10을 1로 변경해보면 된다. 마지막으로 rcx를 세팅하는 코드가 있는데 원래 코드에서 add rcx,r14가 보이는데 디버깅해보면 rcx값이 항상 0이다. 따라서 후킹할때는 mov rcx,r14를 쓴다. 콜이 끝나면 rcx값이 바뀌기 때문에도 mov문을 써야 한다. 

게임이 패치가 되면 다시 디버깅을 해서 옵코드를 살펴보고, 콜주소와 rcx를 적절히 세팅하도록 SpeedUp쪽 스크립트를 바꿔주면 되겠다.

남은 사항은 좌표편2 에서 마저 다루도록 하겠다. 

댓글 없음:

댓글 쓰기