2017년 2월 12일 일요일

오버워치 에임핵 ct 템플릿

이 강좌를 제대로 이해하기 위해 ct 스크립트를 참고해야 할 필요가 있다. 여기에 ct를 업로드해 놓는다. 꼭 동작하는 ct라고 보장할 순 없다.

오버워치 에임핵 ct의 모든 것 4 - 원리편

내가 아는 어셈블리로 실수를 다루는 방법은 2가지가 있다. 옛날에 32비트로 된 게임을 다루었을 때는 주로 f문 계열을 통해 실수를 조작한다. fld, fadd, fmul 같은 것들이다. 이런 f문 계열은 호랑이 담배피던 시절부터 있었던 게임(ex. 메이플스토리)에서부터 계속 쓰여 왔다.

최근 CPU는 대부분 SSE를 지원한다. SSE는 xmm 레지스터를 사용하고 그것을 다루는 명령어셋이다. SSE는 float, double, int 등 산술 연산에 필요한 모든 자료형을 지원하고, 다소 복잡한 계산도 하나의 명령어로 충분하게 해준다. 또한 병렬 연산이 가능하여 3차원 벡터를 다루는데 매우 편리하다. 오버워치에서는 SSE를 통해 실수를 다룬다. 따라서 필자도 이 메타에 따라서 제대로 SSE를 쓰는 것을 보여주겠다. 다르게 말하자면 이전 ct를 확 뜯어 고칠 것이다. 좀 귀찮게 생각될 수도 있지만 이것이 설명하기도 더 편하고 스크립트 길이도 확 줄어 든다. 필자는 SSE4.1 명령어셋까지 활용할 것이며 치트 엔진이 인식 못하는 명령어도 있다. 예를 들어서 DPPS 명령어가 있다.

작성중....

2017년 2월 11일 토요일

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

지금까지 MouseHook, SpeedUp 부분을 살펴보았고, 마지막 남은 후킹 포인트는 VisibleHook 부분이다. 이전 포스팅에서 벽구분 결과를 파인드하면 나오는 옵코드가 mov [rbx+78],al 였는데 바로 거기다. 이해가 안되면 아래 영상을 다시 보도록 하자. 당연히 여러 같은 결과들 중에서 콜을 몰아 준곳만 후킹한다.

먼저 적 번호에 대한 이야기를 하겠다. 아래 사진을 보자.

mov rbx,[rsi+60] 에 적 번호를 넣어주는 것을 알 수 있다. 에임핵에서 적 번호는 많은 적 중에서 마우스 이동을 최소로 하는 적을 찾아 내기 위해 활용된다. Overwatch.exe+113EC5B - inc [rsi+60] 는 적 번호를 증가시키는 코드다. 좀더 아래를 보면 적 번호를 가지고 루프를 도는 것도 알 수 있다. 눈치가 있다면 총 적 수를 어떻게 구하는지도 감이 올 것이다. 바로 Overwatch.exe+113EC6B - cmp eax,[rsi+50] 에 나와 있다. 게임이 패치됬을 때는 적 번호를 어떻게 구하는지 옵코드를 다시 살펴보고 스크립트를 수정하면 된다.


두번째로 적 좌표와 자신의 좌표를 넣는 구간이다. 아래를 보자.


스크립트 주석에 친절하게도 enemy, me라고 적혀져 있다. 이전 포스팅에서도 말했지만 Overwatch.exe+113EC29 - lea rcx,[rbp+000000A0] 여기가 적과 나의 좌표가 모두 있는 곳이라고 설명했다. 따라서 xmm0 레지스터엔 오프셋 0인 [rbp+A0], xmm1 레지스터엔 오프셋 10인 [rbp+B0]의 내용이 복사된다. 게임이 패치되면 적절히 옵코드를 다시 살펴보고 스크립트를 수정하면 된다.

VisibleHook 스크립트의 나머지 부분은 위와 같이 얻은 적 번호와 좌표를 가지고 연산을 하여 조준점이 적을 향하게 한다. 지금까지 ct패치법은 모두 설명했다. 다음 장부터 설명할 내용은 에임핵의 원리에 대한 내용이다.

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 에서 마저 다루도록 하겠다. 

오버워치 에임핵 ct의 모든 것 1 - 조준점편 - MouseHook 패치법

오버워치에서 에임핵을 실현하려면 조준점을 적이 있는 방향으로 변경할 수 있어야 한다. 오버워치가 조준 방향을 어떻게 처리하는지 알아보고 해킹해 보자.

오버워치에서는 조준 방향을 일반적으로 고등학교때 배우는 방향벡터로 표시한다. 단 계산이 편하게 벡터 크기는 1로 정규화되어 있다. 좀더 간지있게 말하면 직교좌표계라고 한다. 오버워치는 에임핵 구현이 쉬운 편에 속한다. 왜냐하면 구면좌표계를 사용하는 게임에서 에임핵을 구현하려면 직교좌표계와 구면좌표계의 변환이 필요하기 때문이다.

직교좌표계는 실수 값 3개, 구면좌표계는 실수 값 2개로 표현하지만 어떤 좌표계를 취하던 간에 조준점을 이리저리 돌리면 메모리 안에 값이 바뀐다. 따라서 이 값의 주소를 찾으려면 마우스를 이리저리 돌리며 스캔하면 된다. 영상을 보자.

찾은 3개의 float값에 각각 제곱을 하여 모두 더하면 1이 됨을 확인할 수 있다. 궁금하면 직접 계산기를 돌려 보시라. 찾은 주소에 파인드를 걸어보면 몇 가지 결과가 나온다.

필자는 이 중에서 빈번하게 콜되는 가장 위의것을 후킹 지점으로 삼도록 하였다. 메모리 뷰어를 통해 좀 더 자세히 살펴보자.

Overwatch.exe+105BFE4 - movaps xmm0,[rdx+00000D20] 여기에서 rdx+D20이 조준점 벡터값의 주소를 나타낸다. rdx는 상위 함수에서부터 세팅된 파라미터이고 특별히 rdx를 변경하는 곳도 없기 때문에 후킹 장소는 주변에 아무데나 골라 잡아도 된다. 하지만 현재 치트엔진에는 디버깅을 걸면 xmm 레지스터가 클리어되는 버그가 있기 때문에, xmm 레지스터를 활용되기 전에 후킹 포인트를 잡아야 한다. 따라서 적절한 후킹 지점은 함수의 제일 처음 부분, 즉 push ebx가 있는 부분이다.

마지막으로 현재 에임핵 ct에서 조준점 벡터의 주소를 저장해두는 곳을 살펴 보도록 하자. ct의 MouseHook 부분을 보자.

Overwatch.exe+105bf90 - push rbx 에서 rip를 MouseHook 으로 변경한다. 그리고 [mouse] 변수에 조준점 벡터의 주소를 넣어 두고 원래 코드로 귀환시킨다.  [mouse] 값은 실제로 적이 있는 곳을 가리키도록 할 때 활용된다. 나중에 계산편을 보면 [mouse]값이 어떻게 다뤄지는지 알 수 있을 것이다.

마지막으로 ct 패치법에 대해 간략히 말하겠다. 게임이 패치되면 다시 디버깅을 해서 파인드를 통해 옵코드를 보고 [mouse]에 다시 올바른 값을 넣도록 MouseHook 코드를 변경하면 된다. 물론 후킹 주소와, 복귀 주소같은 것도 적절히 설정해 주어야 한다. 오버워치는 패치마다 옵코드가 바뀌기 때문에 리버서의 재량이 조금은 필요하다. (지금까지 열심히 설명했으니 조금 필요하다고 한 것이다.) 어쨋든 직접 눈으로 직접 파악하고 패치하는 수밖에 없다. 다른 파트도 마찬가지이므로 이 뒤 포스팅부터는 설명을 줄이겠다.