이번에는 여태 썼던 것들을 응용하는 Step
이제 여태 썼던 것들을 하나씩 적용하는 게 아닌 여러 방면으로 적용하는 단계인 거 같습니다.
어떤 문제인지를 한 번 봐보죠.
우선 플레이어가 4명이 있고 게임을 진행하는거 같습니다. 설명상으로는 체력 부분에서
코드를 공유한다...라고 표현이 되어있는데 아마 체력값을 하나의 명령어에서 다 처리하는 모양입니다.
Autoplay를 실행해봤을 때 저희 팀이 졌다고 합니다.
보면 Player 1과 Player 2가 Dead라고 되어있습니다. 결국 이 문제에서 요구하는 건 Player 1과 2가 이기게끔
만들면 된다... 라는 것이겠죠? 일단 어떤 방법을 쓸지 확인하기 위해 체력 부분을 한 번 봅시다.
우선 힌트상으로 체력은 Float형으로 구성한다고 되어 있으니 Float로 스캔을 해볼게요.
우선 Player 1의 체력값을 확인했는데 디버깅을 한 번 걸어보겠습니다.
일단 디버깅에 걸리는게 4개입니다. 하지만 서두에서 코드가 공유된다고 하였으니 이 명령어가 모든 플레이어의
피통을 관리하는 곳일겁니다. 그러면 여기 부분을 후킹을 하여 Player 1과 Player 2는 체력 감소를 안 되게 하거나
하는 식으로 해결을 해볼 수 있겠죠? 그러면 우선 포인터를 찾아보도록 하죠. Restart Game을 누르면 포인터가
바뀌게 되니까 이 점은 유의하도록 합시다.
오프셋이 888이라.. 일단은 다음거 스캔했을 경우 "Tutorial-x86_64.exe"+325B10 이 부분이
베이스 주소임을 찾았습니다. 그러면 체력값이 공유 된다고 했으니 888 이 오프셋이 아마 Player 1을
가리키는 오프셋일거고 여기서 Player 2,3,4를 가리키는 오프셋이 다를 거라고 예측을 해볼 수 있습니다.
위의 방식으로 찾아볼 경우 순서는 다음과 같습니다.
Player 1 = 오프셋이 888
Player 2 = 오프셋이 890
Player 3 = 오프셋이 898
Player 4 = 오프셋이 8A0
즉 8의 배열마다 배치를 해주는 것을 알 수가 있습니다. 그러면 이 정보를 이용하여 예외처리를 하면 됩니다.
간단하게 처리 스크립을 짜봤습니다. 한 번 같이 보실까요?
우선 저는 후킹 지점을 2F206으로 선정했습니다. 뭐 이 부분은 본인이 원하는대로 하셔도 상관은 없습니다만..
2F206~2F20E 부분이 딱 16Byte 길이로 후킹 되는 14Byte + nop 2Byte를 부여하면 깔끔하게 떨어지기 때문에
여기를 선정한 것입니다.
처음에 rdx를 스택에 저장해 줍니다. 왜냐하면 이 rdx 레지스터에다가 포인터 주소를 담아 비교하는 용도로
쓰기 위함이죠. 다음을 보시면 Player 1,2,3,4 구분인 오프셋 888,890,898, 8A0을 차례로 담아서 rbx와 비교합니다.
왜 rbx를 썼냐 하면 이 함수 자체에서 movss xmm0,[rbx+08] 이 명령어 때문에 어떤 플레이어인지를 rbx에 넣기
때문에 최대한 흐름을 안 깨는 선에서 했습니다. 비교문이 끝나면 아까 스택에 넣어놨던 rdx를 다시 pop 명령어로
꺼내줍니다.
그런 다음 각각 일치할 경우 Player 1,2,3,4로 점프하게끔 해놨고 je Player4 밑에는 혹시나 이상한 값 들어올까 봐
처리해놓은 예외처리입니다. 사실 이 프로그램에서는 딱히 할 필요는 없겠더라고요.
다음은 조건에 의해 각 Player 1,2로 가게 됐을 경우 처리하는 방법입니다. 아까 스택을 썼으니 다시 정리해주고요.
cvtsi2ss xmm0,esi 이 명령어의 경우 esi에 3~4가 들어가게 되는데 이를 xmm0에다가 실수형으로 변환하여
집어넣어주는 명령어라고 보시면 되겠습니다. 그 후 기존에 체력값에다가 addss 명령어를 통해 실수형 더하기를
함으로써 체력이 증가하는 식으로 해놨습니다.
Player 3,4로 가게 됐을 경우 스택을 썼었으니 정리를 해주고 원래의 흐름인 subss 명령어 쪽으로 가게끔 내버려두었습니다.
자 그러면 이 스크립트를 적용하고 결과를 한 번 보실까요?
자 이렇게 후킹이 된 모습을 보실 수 있고 다시 autoplay로 진행을 해보았습니다.
처음의 결과와는 반대가 됐군요. 플레이어 1,2가 이기고 3,4가 죽었습니다. 저는 이렇게 문제를 해결하였습니다.
아마 이렇게 안 하고도 그냥 Player 1,2의 체력 주소를 구한 후 프로즌 하는 형식으로도 되기는 될 겁니다.
하지만 앞에서 썼던 방식들을 그대로 살려내서 복습하는 겸 이런 식으로 해결을 해봤네요.
이로써 Cheat Engine Tutorial 과정도 끝났습니다. 이 다음은 제가 초반에 다루었던
게임 튜토리얼로 이어집니다. 궁금하신 분들은 밑의 링크를 타고 가주세요.
'Reversing & Cheat Engine' 카테고리의 다른 글
37. 하드 밴이 무엇인가 (0) | 2024.04.10 |
---|---|
36. 기본적인 보안에 대한 개요 (0) | 2024.03.21 |
34. Cheat Engine Tutorial 7 (0) | 2024.03.19 |
33. Cheat Engine Tutorial 6 (0) | 2024.03.18 |
31. Cheat Engine Tutorial 4 (0) | 2024.03.16 |