34. Cheat Engine Tutorial 7
본문 바로가기
Reversing & Cheat Engine

34. Cheat Engine Tutorial 7

by boosting 2024. 3. 19.
728x90

이번에는 다중 포인터

지난번에 포인터에 대해 간단하게 다뤘던 챕터가 있습니다. 그때는 한개의 포인터 주소가 있었죠.

그런데 이 포인터도 한개가 아닌 여러개가 존재하는 경우가 있습니다. 제일 대표적인건 인원수

같은 여러개의 객체가 존재하는 경우겠죠. 이외에도 코딩에 따라 여러 경우가 있겠습니다.

인원수로 따질때 한 포인터에다가 모든 사람의 정보를 담아 넣을 수 없으니 나눠야 할겁니다.

 

간단히 예를 들어보자면 우선 플레이어라는 정보를 담은 곳으로 향하는 포인터가 있다할 때

이 플레이어가 1명이 아니기에 각 플레이어의 지점으로 향하는 포인터가 또 존재할 것입니다.

이런식으로 여러개의 포인터로 구성이 된다고 보시면 되겠습니다. 우선 문제를 보죠.

 

튜토리얼

 

저번 문제와 해결 방법은 동일합니다. 포인터 구성을 찾고 이를 프로즌 하여 3초간 벨류가 5000으로

고정일 경우 통과로 처리 한다고 합니다. 그러면 이 2076 부분을 담고 있는 주소를 찾아봅시다.

사실상 이 튜토리얼 프로그램 자체가 큰 편이 아니라서 2076 정도면 따로 Change value 안해도

1개일거 같네요.

 

튜토리얼

 

우선 찾았으니 이 부분에다가 디버깅을 걸어보도록 합시다.

 

튜토리얼

 

걸고 난뒤에 Change Value를 눌러서 걸린 명령어를 보니 [rsi+18]을 다루고 있습니다.

이렇게 되면 rsi가 이 영역의 베이스 주소가 되고 18은 오프셋이 됩니다.

즉 01536018이란 주소에서 18을 뺀 01536000이 베이스 주소가 되는거죠.

 

튜토리얼

 

이렇게 베이스 주소를 스캔할 경우 따로 포인터 주소를 암호화 시켜 놓은게 아닌 이상 뜹니다.

그러면 이 0159A9C0 부분에 디버깅을 걸고 위의 과정을 반복해봅시다.

 

튜토리얼

 

이번에는 따로 오프셋이 없습니다. 그러면 이 주소 자체가 베이스 주소가 되는겁니다.

0159A9C0을 다시 스캔을 해줍시다. 그러면 또 주소가 뜰겁니다.

 

튜토리얼

 

그러면 이 부분에도 그대로 위의 과정을 진행해줍니다.

 

튜토리얼

 

다시 오프셋이 18이 나왔습니다. 그러면 0159A758에서 18을 뺀 주소가 베이스 주소겠죠.

위의 과정을 한번 더 하면 또 오프셋이 10이 나옵니다. 그러면 거기서 10을 빼고 또 스캔을 합니다.

이 과정을 반복하다 보면 초록색 모듈 주소가 뜹니다.

 

튜토리얼

 

이 주소의 경우 클라이언트 패치가 없을 경우 영원히 고정인 주소입니다.

즉 이 주소가 이 Step 8에서 벨류를 담고 있는 포인터에서 고정으로 시작 주소라는 말이죠.

그러면 위에 오프셋이 나왔던 순서가 18, 0, 18, 10으로 나왔으니 이걸 역산으로 배치해줍니다.

 

튜토리얼

 

이렇게 보시면 현재 담겨있는 135와 제가 포인터 배열로 해놓은 곳의 벨류가 135로

똑같은 것을 확인할 수 있습니다. 이제 이렇게 했으니 Change pointer를 눌러볼게요.

 

튜토리얼

 

이런식으로 옮겨져도 잘 따라가지는 것을 확인할 수 있었습니다.

이전처럼 포인터 스캔을 눌러도 아마 나오기는 할겁니다. 하지만 이 디버깅 식으로 포인터 찾는걸

익혀야 하는 이유는 포인터 주소들이 암호화 되어 있을 경우 그 암호화를 풀어주는 작업을 사람이

해야하는데 포인터 스캔 기능의 경우 이 암호화를 풀어주는 역할이 따로 없습니다.

그렇기 때문에 온라인 게임에서 사용하신다 하면 알아둘 필요가 있는 것이지요.

 

튜토리얼

 

우선 문제 해결은 완료 했습니다. 또 다른 방식으로 보는 방법은 맨 처음의 명령어를 봐 봅시다.

 

튜토리얼

 

맨 처음 디버깅을 걸면 아마 이 명령어가 뜰텐데요. 이 명령어에서 우클릭을 눌러 Select Current Function을

눌러보시면 이 명령어가 속해 있는 함수의 첫 시작 부분과 끝 부분을 다 선택해줍니다. 편리한 기능이죠.

 

 

* 단 함수가 가상화 되어 있다거나 그럴 경우 다 선택이 되진 않습니다.

 

튜토리얼

 

이 경우 보시면 mov rsi,["Tutorial-x86_64.exe"+325B00] 로 베이스 주소를 담고 있는 명령어가

바로 나오게 됩니다. 암호화가 안 되어 있을 경우 따로 디버깅을 하고 주소를 스캔하고 하는 과정을

생략하고 이런식으로 명령어들만 보면서 추리가 가능해집니다.

 

Tutorial-x86_64.exe+2E826 - 48 8B 35 D3722F00     - mov rsi,[Tutorial-x86_64.exe+325B00] { (015360C0) }
Tutorial-x86_64.exe+2E82D - 48 89 F0              - mov rax,rsi < 이 부분에서 0
Tutorial-x86_64.exe+2E830 - 8B 50 04              - mov edx,[rax+04]
Tutorial-x86_64.exe+2E833 - 3B 10                 - cmp edx,[rax] 
Tutorial-x86_64.exe+2E835 - 75 31                 - jne Tutorial-x86_64.exe+2E868 < 점프할 것임

 

Tutorial-x86_64.exe+2E868 - 48 83 7E 10 00        - cmp qword ptr [rsi+10],00 { 0 } < 점프한 곳
Tutorial-x86_64.exe+2E86D - 0F84 34010000         - je Tutorial-x86_64.exe+2E9A7 < 0이 아니므로 점프 x
Tutorial-x86_64.exe+2E873 - 90                    - nop 
Tutorial-x86_64.exe+2E874 - 48 8B 76 10           - mov rsi,[rsi+10] < 오프셋 10
Tutorial-x86_64.exe+2E878 - 48 89 F0              - mov rax,rsi

Tutorial-x86_64.exe+2E87B - 8B 50 04              - mov edx,[rax+04]
Tutorial-x86_64.exe+2E87E - 3B 10                 - cmp edx,[rax]
Tutorial-x86_64.exe+2E880 - 75 2E                 - jne Tutorial-x86_64.exe+2E8B0 < 점프할 것

 

Tutorial-x86_64.exe+2E8B0 - 48 83 7E 18 00        - cmp qword ptr [rsi+18],00 { 0 } < 점프한 곳
Tutorial-x86_64.exe+2E8B5 - 0F84 EC000000         - je Tutorial-x86_64.exe+2E9A7 < 0이 아니므로 점프 X
Tutorial-x86_64.exe+2E8BB - 90                    - nop 
Tutorial-x86_64.exe+2E8BC - 48 8B 76 18           - mov rsi,[rsi+18] < 오프셋 18
Tutorial-x86_64.exe+2E8C0 - 48 89 F0              - mov rax,rsi
Tutorial-x86_64.exe+2E8C3 - 8B 50 0C              - mov edx,[rax+0C]
Tutorial-x86_64.exe+2E8C6 - 3B 50 08              - cmp edx,[rax+08]
Tutorial-x86_64.exe+2E8C9 - 75 31                 - jne Tutorial-x86_64.exe+2E8FC < 점프할 것

 

Tutorial-x86_64.exe+2E8FC - 48 83 3E 00           - cmp qword ptr [rsi],00 { 0 } < 점프한 곳
Tutorial-x86_64.exe+2E900 - 0F84 A1000000         - je Tutorial-x86_64.exe+2E9A7 < 0이 아니므로 점프 X
Tutorial-x86_64.exe+2E906 - 66 90                 - nop 2
Tutorial-x86_64.exe+2E908 - 48 8B 36              - mov rsi,[rsi] < 오프셋 0
Tutorial-x86_64.exe+2E90B - 48 89 F0              - mov rax,rsi
Tutorial-x86_64.exe+2E90E - 8B 50 04              - mov edx,[rax+04]
Tutorial-x86_64.exe+2E911 - 3B 10                 - cmp edx,[rax]
Tutorial-x86_64.exe+2E913 - 75 2B                 - jne Tutorial-x86_64.exe+2E940 < 점프할 것

 

Tutorial-x86_64.exe+2E940 - B9 A00F0000           - mov ecx,00000FA0 { 4000 }
Tutorial-x86_64.exe+2E945 - E8 C612FEFF           - call Tutorial-x86_64.exe+FC10 < 랜덤으로 벨류 계산
Tutorial-x86_64.exe+2E94A - 89 46 18              - mov [rsi+18],eax < 오프셋 18
Tutorial-x86_64.exe+2E94D - 48 8D 4D F8           - lea rcx,[rbp-08]
Tutorial-x86_64.exe+2E951 - E8 BAA5FDFF           - call Tutorial-x86_64.exe+8F10
Tutorial-x86_64.exe+2E956 - 8B 4E 18              - mov ecx,[rsi+18]

 

이런식으로 어셈 명령어 배치로도 추리가 가능하긴 합니다. 정확하게 보려면 디버깅을 해야 한다는 점을

고려해보면 그냥 첫번째 방법이 오히려 나을지도 모르겠습니다.

728x90

'Reversing & Cheat Engine' 카테고리의 다른 글

36. 기본적인 보안에 대한 개요  (0) 2024.03.21
35. Cheat Engine Tutorial 8  (0) 2024.03.20
33. Cheat Engine Tutorial 6  (0) 2024.03.18
31. Cheat Engine Tutorial 4  (0) 2024.03.16
30. Cheat Engine Tutorial 3  (2) 2024.03.15