본문으로 바로가기

파일의 IT 블로그

  1. Home
  2. 보안 강좌/CheatEngine
  3. [Cheat Engine] 치트엔진 튜토리얼 #9 풀이 [完]

[Cheat Engine] 치트엔진 튜토리얼 #9 풀이 [完]

· 댓글개 · KRFile

 

9단계: 공유 코드 (PW=31337157)
이 단계에서는 동일한 유형의 다른 객체에서 사용되는 코드를 처리하는 방법을 설명합니다.
유닛이나 플레이어의 체력을 찾았을 때 종종 본인에게 영향을 끼치는 코드를 제거하면 적들에게도 영향을 미치는 경우가 많습니다. 이 경우 자신과 적의 객체를 구별하는 방법을 찾아야 합니다. 때로는 플레이어에 대한 고유 위치를 가리키는 함수 포인터 테이블의 첫 4바이트를 확인하는 것만으로 충분할 때도 있고, 팀 번호나 플레이어 이름에 대한 포인터를 여러 번 따라가야 할 때도 있습니다. 이 모든 것은 게임의 복잡성과 운에 따라 달라집니다.
가장 쉬운 방법은 찾은 코드가 쓰는 주소를 찾은 다음, 분해 데이터 기능을 사용하여 두 개의 구조 (당신의 유닛/플레이어 및 적)를 비교하는 것입니다. 그런 다음 구별하는 방법을 찾아냅니다. 이후에는 조건을 확인하고 코드를 실행하지 않거나 다른 작업을 수행하는 어셈블러 스크립트를 삽입할 수 있습니다. (예: 원샷 킬) 또는 "바이트 배열" 문자열을 만들어서 검색에 사용할 수도 있으며, 이는 모든 자신 또는 적의 플레이어 목록을 가져올 수 있습니다.
이 튜토리얼에서는 당신이 플레이할 수 있는 가장 멋진 게임을 구현해 두었습니다. 4명의 플레이어가 있으며, 그 중 2명은 당신의 팀에 속하고 2명은 컴퓨터 팀에 속합니다. 당신의 임무는 체력을 쓰는 코드를 찾아서 자신의 체력을 얼리지 않고 게임에서 이기는 것입니다.
계속하려면 "게임 다시 시작 및 자동 재생" 버튼을 눌러서 코드가 올바른지 확인하세요.

팁: 체력은 Float입니다.
팁2: 다양한 해결 방법이 있습니다.

 

안녕하세요 파일입니다. 오늘은 어떻게 보면 치트엔진 튜토리얼의 마지막이라고 볼 수 있는 #9번 문제에 관한 풀이입니다. 물론 뒤로 Step1, Step2와 같이 게임 형태로 된 문제가 더 나오긴 하는데 튜토리얼 프로그램의 생김새 자체가 조금 달라지기 때문에 이런 디자인(?) 으로 만들어진 치트엔진 튜토리얼 문제는 일단 마지막입니다.

 

문제를 요약하자면 Player1, Player2 는 우리팀이고, Player3와 Player 4는 컴퓨터 팀, 즉 적입니다.

우리팀의 체력을 고정시키지 않고, autoplay 버튼을 눌러서 자동 전투를 시켜서 우리팀을 이기게 하는게 목적입니다.

 

자동 전투(Restart game and autoplay) 이전에 테스트 용도로 아래 Attack 을 눌러서 우리팀과 컴퓨터 팀에 공격을 수동으로 가해볼 수 있는데, 상대방은 체력도 훨씬 많고 Attack을 눌러도 체력이 1씩 밖에 안다는 반면에 우리팀 유닛들은 체력도 100밖에 안되고 맞을때마다 체력이 팍팍 까입니다.

 

이상태로 자동 전투를 시키면 당연히 지게되겠죠. 자동 전투를 시키면 바로 발립니다.

 

참고로 자동 전투를 시켰는데 게임에서 패배했으면 Restart game and autoplay 버튼 위에 있는 Restart game 버튼을 눌러서 리셋하면 됩니다.

 

이 불합리한 게임을 이기는 방법을 생각해봅시다!!

 

참고로 혼란을 방지하고자 글에서 Restart game 이라고 하는건 저 맨 위에 있는 초기화 버튼을 의미하는거고

autoplay는 Restart game and autoplay 버튼인 자동 전투를 의미하는 것으로 이해하시면 됩니다.

 

글에서 Restart game = 초기화 버튼 (위에 있는 버튼) = Restart game

autoplay = 자동 전투 버튼 (아래에 있는 버튼) = Restart game and autoplay

 

Solution

[참고*오늘은 64bit 치트엔진 튜토리얼 (Tutorial-x86_64.exe) 이 아닌 32bit 치트엔진 튜토리얼 (cheatengine-i386.exe) 프로그램으로 진행합니다.*]

 

일단 위 튜토리얼 번역문을 읽어보시면 알다 싶이 이 문제는 해결 방법이 매우 많습니다.

우리팀이 공격을 받아도 체력이 달지 않게 한다던가, 오히려 체력이 회복되게 한다던가, 우리팀의 체력을 무식하게 늘리면 될 거 같습니다. 다만 WITHOUT freezing your health 라고 하는걸 보아 우리팀 플레이어 체력값을 찾아서 고정 시키는 방법은 이용하지 말라고 하네요.

 

시도 1

체력이 Float 라고 했으므로 우리팀 플레이어의 체력을 검색하고 체력을 무식하게 늘려봤습니다.

 

적용은 됐고 이상태서 전투를 시켜보면??

 

그래도 지네요. 체력이 아무리 많아도 우리팀 Dave랑 Eric이 공격 능력이 전무한가봅니다 ;

아니면 autoplay를 한 순간에 체력을 100으로 초기화 시켜버리고 전투를 진행했을 수도 있구요.

 

그리고 Restart game을 눌러서 게임을 초기화 한 순간 값은 100으로 초기화 되는데 저희가 찾아놓은 값은 더이상 사용되지 않습니다. 저번 #6번 문제가 #8번 문제처럼 포인터를 사용하는거 같습니다.

Restart game을 한 순간에 새로운 공간에 데이터를 잡아서 포인터로 가리켜 다시 접근하는것으로 보입니다.

 

 

값을 다시 찾고 P1, P2에 접근하는 포인터를 찾아보겠습니다.

항상 하던대로 포인터 찾기는 Find out what accesses..!

 

디버깅을 건 순간에 여러가지 어셈블리 명령억아 보이는데요. fusbr이나 fld는 저도 처음 보는 명령어네요.

어쨌던 간에 중요한건 mov [메모리 주소], 값 과 같은 형태의 명령어 입니다.

 

저기 마침 mov [ebx+04] , eax 명령어가 보이네요. 저기서 ebx 값이 어떤 포인터 변수가 가리키는 주소고, +04 (16진수) 가 오프셋이 되겠네요.

왜 이렇게 되는진 저번 #8번에서 입이 닳도록 설명드렸으므로 생략하도록 하겠습니다.

 

ebx의 값은 042B00F0 입니다. 어떤 포인터 변수가 이 주소를 분명히 가리키고 있을것이므로, 이 값을 가지는 포인터 변수를 찾아봅니다.

 

검색해보면 5개나 나오는데요.

지금은 이 문제에서 몇 중 포인터를 사용하고 있는진 추정이 안되는 상황입니다.

 

일단 2중 포인터를 염두에 두고 포인터 변수들에 대한 포인터 변수가 있는지 한번 조사해보겠습니다.

5개의 변수에 각각 what accesses 로 디버깅을 걸고, P1 Dave의 체력을 조작해보면서 무언가 변화가 있는지 확인해보면 됩니다. 참고로 여기서 5개 메모리 값을 한꺼번에 디버깅하다가 튜토리얼 프로그램이 튕겼습니다 ㅠㅠ

 

이유는 모르겠는데 저는 여러 값들에 디버깅을 한꺼번에 걸면 프로그램이 자꾸 튕기더라구요. 여러분도 주의하시길 바랍니다. 어쨌던 바로 앞과 주소가 달라졌긴 해도 계속 해봅시다.

 

what access 를 걸어 놓고 P1 dave에 Attack 을 눌러서 반응이 오는건 01A19F78 이라는 값 밖에 없었습니다.

what access 에 접근 명령어가 보여서 더블 포인터가 있나? 싶었지만 지금까지 포인터 변수로 접근하는 구문의 경우

what access 에서 mov [메모리 주소], 값 과 같은 형태로 왼편에 메모리 접근 모드가 있었기 때문에 더블 포인터로 접근하는건 아닌거 같습니다.

 

이외에도 what writes 로 5개의 변수를 검사해봤는데 아무 미동도 없었습니다.

 

결론적으로 포인터 변수와 관련이 있는건 이거 하나밖에 없는 거 같네요.

이게 포인터 변수 인 거 같습니다.

이놈 역시 what writes 에는 아무 반응이 없고 what access 에만 반응이 있는데 좀 특이하긴 하네요.

 

다음과 같이 포인터를 수동으로 추가합니다.

가리키는 공간의 Type이 Float이므로 타입을 반드시 float로 설정해주세요.

그리고 오프셋은 4였으니 적어주시면 됩니다. (항상 16진수임에 유의, 물론 16진수 4는 10진수 4랑 똑같지만..)

 

일단 P1에 대한 포인터 변수 등록이 완료되었습니다.

 

autoplay를 해서 죽인후에

 

Restart Game을 하면 이렇게 포인터 변수를 찾아내서 값이 제대로 추적되는걸 확인할 수 있습니다.

 

P1에 대한 포인터가 중요한 것이므로 나머지는 다 지우고 P1 Pointer만 남겨줍니다.

 

사실 여기서 이제 P1 포인터가 가리키는 곳에 Freeze 를 걸고 autoplay를 하면 쉽게 이길 수 있긴 합니다만.. 튜토리얼 설명에서도 값 고정은 하지 말라고 했으므로 다른 방법을 찾아 봐야 할 거 같습니다.

 

 

시도2

포인터만 찾아놓은 상황에서 일단 돌아옵니다.

 

포인터 변수에 대고 다시 what accesses...

 

그러면 이 변수는 포인터라고 어떤 옵션을 고를지 나오는데요

여기서 밑에 길게 적 혀있는 Find what accessess the address pointed at by this pointer 버튼을 누릅니다.

이걸 누르면 지금 포인터 변수가 가리키고 있는 곳 , 그러니깐 체력값이 어떻게 accesses 되고 있는지 알 수 있습니다.

 

여기서 Dave의 Health 를 변화시키고 명령어들을 보면 아시겠지만 아까 전에 체력값에 대한 포인터를 찾기 전에 체력값에서 find what accesses 를 했을때 화면과 동일합니다.

 

지금은 포인터를 찾아놓고, 포인터 입장에서 포인터가 가리키는 곳, 즉 Health 가 어떻게 accesses 되고 있는지 찾아내려 한것이므로 똑같은 창이 나오는 것이지요.

 

Health 값을 찾아놓은건 이미 지우기도 했고 포인터 밖에 가지고 있지 않을때 가리키는 곳이 어떻게 accesses 되고 있는지 알고 싶으면 다음과 같이 하면 됩니다.

 

어쨌던...

아까전에도 봤듯이 포인터 변수를 이용해서 값을 바꾸는 핵심 명령어는 이 부분입니다. 메모리 접근 모드 (대괄호 [ ]) 가 왼쪽에 위치한 명령어죠.

 

ebx가 확인했듯이 포인터 변수가 가리키는 주소였구요 그렇죠?

그리고 eax 에는 바꿀 체력값이 들어가 있을 겁니다.

 

그러면! 아 지금 Dave라는 놈의 체력은 mov [ebx+04], eax 라는 명령어를 통해 포인터로 바꾸고 있군. 저 코드를 잘 변조해서 Dave를 무적으로 만들면 되겠어. 라는 생각이 들겁니다.

 

mov [ebx+04], eax 명령어를 Single Line Assembler(어셈블리 코드 한줄 바꾸는 기능) 로 직접 바꿔도 되는데 저번시간에 배운 코드 인젝션을 활용해보겠습니다.

 

mov [ebx+04], eax 라는 코드 부분에 우리가 원하는 코드를 끼워 놓는 것입니다.

 

이 창에서 바로 Show dissassembler 를 누릅니다.

 

삽입할 위치가 선택되었고 Tools - Auto Assemble

 

Template - Code Injection 을 활용해 코드인젝션을 위한 코드 템플릿을 생성합니다.
저거 누르고 어떤 Dialog 창이 뜨면 OK 눌러주세요.

 

originalcode 에 원래 코드 부분이 보입니다. 그리고 fldz 라고 어셈블리어 명령어가 하나 더 추가됐는데 찾아보니 st0 에 0을 push 하는 명령어라고 하는데 치트엔진이 저 코드를 왜 자동삽입한지는 솔직히 잘 모르겠네요.

일단은 mov [ebx+04], eax 부분만 건들면 됩니다.

 

저 original code: 아래 부분이 삽입할 코드인데, 그냥 냅두면 원래 코드 그대로라서 이상태로 Execute를 눌러서 삽입하면 원래 코드가 그대로 실행됩니다.

 

그러므로 원래 코드는 주석처리하고, Dave가 체력에 변동이 있을때마다 바뀔 체력인 eax 값을 가져오는게 아니라 회복(Heal) 이 되도록 dave의 체력에 1을 더하겠습니다.

 

이러면 dave가 맞아도 체력이 1씩 차는 좀비가 되겠죠!!

 

Execute를 누르고 나오는 창에 이번엔 Yes - Yes를 누릅니다.

 

빈 메모리에 코드가 잘 삽입되었습니다.

저번하고 동일합니다.

 

이제 Dave 를 Attack 해보면 체력이 소수점 아래부터 계속 올라가는걸 볼 수 있습니다. 다만 Float라서 저렇게 1씩 그냥 더해버리면 실제로 정수값 1을 더하는 효과는 아닌가 봅니다.

 

다만 autoplay를 하기 전에 이 방법엔 한가지 문제가 있습니다.

 

 

난 분명 Dave만 건들였는데 Eric이나 HAL이나 모든 플레이어가 Attack 당할때마다 체력이 같이 올라버립니다.

이건 왜이럴까요..?

 

아까도 말했듯이 이번 튜토리얼 9번의 제목은 공유된 코드(Shared Code) 입니다.

 

mov [ebx+04], eax

사실 포인터로 체력을 조작하는 위 코드는 Dave만의 것이 아닙니다.

모든 플레이어가 포인터를 이용해 자신의 체력을 바꾸고 있고, 함수로써 위의 코드를 계속 재활용함으로써 모두가 저 코드를 공유하고 있습니다.

 

한마디로 체력을 변경하는 위 코드는 Dave만의 것이아니라, 모두가 공유하면서 사용하고 있는 코드입니다.

그러므로 우리는 Dave만 바꿨다고 생각했지만 모든 플레이어가 저 체력 변경 코드를 공유 하고 있어서 같은 현상이 발생하는 것입니다.

 

사실 그럴법도 한게, 컴퓨터 입장에선 체력을 바꾸는 코드를 공유해서 쓰는게, 각 플레이어 별로 체력 변경 코드를 생성하는 것보다 코드를 훨씬 줄일 수 있고 효율적이기 때문입니다 ^^;;

 

그럼 이제 어떻게 해야할까요? 저 체력 변경 코드를 모두가 공유한다는 사실을 알았으니 저 코드를 조작할때, 만약에 실행자가 Dave 라는 플레이어면 체력을 1씩 증가시키고, 아니면 그냥 원래대로 체력을 깎는 Logic 을 어셈블리어로 작성해야 할 겁니다.

 

그러면 지금 저 명령어를 실행하는 사람이 Dave 라는건 어떻게 알죠? 라고 질문하실 수 있습니다.

그걸 알아보겠습니다.

 

글을 쓰는데 튜토리얼 프로그램이 또 튕겼네요.. 에휴.. 게임켜놓고 해서 그런가?

어쩔 수 없이 처음으로 다시 돌아오겠습니다.

 

튜토리얼 재시작후 Dave의 체력값 포인터는 찾지 않고 일단 체력값만 먼저 찾아놨습니다.

 

다시 Find out what access 탭으로 가서 포인터 접근을 확인합니다.

그리고 체력을 변경하는 코드인 mov [ebx+04], eax 가 선택된 상태에서 Show disassembler를 펼칩니다.

 

현재 EBX 값은 072850F8 이며, 이는 포인터 변수가 가리키고 있는 주소와 일치합니다.

아까도 확인한 부분이죠. 포인터 변수까지 찾아봤고..

 

이제 프로그램에 대해서 다시 추론을 해보는 시간입니다.

 

과연 Player의 이름과 Health는 메모리 상에서 따로 관리되고 있는가, 아니면 한 묶음으로 관리되고 있는가?

아마 똑똑한 프로그래머라면.. 아니 어느정도 상식이 있는 프로그래머라면 캐릭터 데이터를 관리할 때 한 묶음으로 관리할 것입니다. Player의 이름이 Dave라는 것과 체력이 90 이라는것을 한번에 묶어서 관리하지 않을까요?

 

우리는 C언어에서 배운 배열이나 구조체를 떠올려볼 수 있습니다. 배열은 알다 싶이 같은 자료형을 연속된 메모리 공간에 나열해 관리하는 것이고, 구조체는 서로 다른 자료형을 연속된 메모리 공간에 한 묶음으로 관리하는 것입니다.

지금 Dave는 문자열 형태고, Health는 Float니깐 아마 구조체와 같은걸 사용해서 플레이어 데이터를 묶음으로 관리하고 있지 않을까요?  

 

현재 포인터 변수가 가리키는 주소 072850F8 (화면상으론 EBX 레지스터의 값) 을 이용해 접근하고 있으므로 RAM에서 이 데이터가 실제로 어떻게 표현되고 있는지 보겠습니다.

 

위 부분은 CPU가 실행시켜야 할 명령어 부분, 아래는 RAM이 실제로 데이터를 저장하고 있는 부분입니다.

아래 RAM 부분에 아무곳이나 클릭하고 Ctrl + G 를 누른 뒤 072850F8 를 입력해 RAM에서 072850F8 위치로 순간이동합니다.

 

RAM 부분에서 포인터 변수가 가리키는 곳을 유심히 살펴보면 Health를 표현하는 부분을 넘어서 뒤쪽에 Dave라는 반가운 이름이 등장하는걸 확인할 수 있습니다.

 

이제 안 사실은, Health를 기준으로 -4 만큼 떨어진 포인터 변수를 사용해서 Health를 표시하고 (아까 확인한 오프셋 4입니다.), 이후 다시 몇 바트 떨어져서 플레이어 이름을 접근하고 있다는 사실요.

 

구조체로 Health와 모르는 변수 N개, 그리고 Name을 묶어놓은 거 같습니다.

mov [ebx+04], eax

어쨌던 확실해진게 위 코드를 돌려 쓰면서 모든 플레이어가 포인터를 이 용해서 체력 데이터를 수정하고 있고, 몇 바이트 떨어진 위치에서 체력과 이름을 접근할 수 있다는 사실입니다.

 

Dave 문자열이 포인터 변수를 기준으로 얼마나 떨어져있는지 Offset 계산을 위해 시작 문자열인 D 위치의 RAM 바이트를 누르고 왼쪽 아래에 주소 값을 확인합니다.

 

Dave 라는 문자열 중에서 D라는 문자가 위치한 곳은 주소 0728510D 입니다.

 

프로그래머용 계산기로 계산해보면 이는 포인터 변수가 가리키는 곳으로부터 15 만큼 떨어져있습니다.

ebx가 포인터 변수랑 가리키는 곳이 일치했으므로 ebx + 15 로 플레이어의 시작 이름을 계산할 수 있겠네요.

 

이제 mov [ebx+04], eax 부분에 코드를 삽입할 시간입니다.

코드 인젝션을 다시 걸어주겠습니다. (위에서 했으므로 과정은 생략)

 

어셈블리 코드는 다음과 같이 적겠습니다.

 

현재 체력 반영 코드 실행시 플레이어 이름이 D로 시작하면 +1 하고 종료. 아닌 경우 그냥 체력을 반영하고 종료입니다.

cmp 할때 한글자 비교이므로 4바이트가 아니라 1바이트 (char) 를 비교해야해서 byte ptr 로 작성해주는거 잊지마세요. dword ptr로 4바이트 비교하면 안됨니다.

 

참고로 부동 소수점 연산이 들어가 있어서 저기 fldz 명령어를 실행시키지 않으면 오류가 발생합니다. 어떻게 하던간에 fldz는 꼭 실행시켜주세요.

 

Execute 해서 코드 인젝션을 끝마칩니다.

 

테스트를 해보면 Dave를 제외한 모든 플레이어는 Attack 시 체력이 달고 Dave는 맞으면 체력이 오히려 차는걸 볼 수 있습니다. 마조히스트 완성 사실 완벽한 승리를 위해선 Eric에도 같은 코드를 작성해야 하는데 일단은 우리팀 한명이라도 남으면 승리니깐 Dave만 작업하도록 하겠습니다.

 

전투를 시켜보면 Dave가 계속 구타를 당했음에도 체력이 계속 차서 이긴걸 볼 수 있습니다.

참고로 Eric에도 적용하고 싶으면 아래 구문을 하나 똑같이 복사해서 추가해주면 됩니다.

해보니깐 코드 인젝션 창만 계속 띄어놓고 Execute 해서 인젝션한 코드를 계속 새롭게 수정할 수 있더라구요.

 

 

예.. 완승입니다. 튜토리얼 따라오느라 고생 많으셨고, 이제 다음 게임형태의 치트 연습인 Step1, Step2에서 뵙도록 하겠습니다. 글 읽어주신 여러분 모두 감사드립니다.

 

시도3 (번외 & 치트엔진 기능 이용)

위에선 코드를 돌려 쓴다는 사실을 Code Injection 이후 알았고, 구조체 파악도 RAM 창에서 직접 찾았지만 이번에는 치트엔진의 기능들을 이용해 이 2가지 내용을 쉽게 알아내는 방법을 알아보겠습니다.

 

체력값의 포인터는 찾지 않고 일단 체력값만 찾아 놓은 상태에서 시작합니다.

 

다시 what accesses 탭을 이용해 이 값을 포인터를 활용해 어떻게 바꾸고 있는지 파악해봅니다.

 

그럼 똑같이 포인터 접근 명령어가 보일건데요. mov [ebx+04], eax 가 실제로 값을 반영하는 명령어란거 확인했죠?

 

여기서 중요한데 mov [ebx+04], eax 명령어에 오른쪽 클릭 후 Find out what addresses this code accesses 를 선택합니다.

이 기능을 활용하면 해당 코드가 어떤 주소에 접근하고 있는지(접근당하고 있는지) 알 수 있습니다.

 

아까전에는 이 mov [ebx+04], eax 명령어가 모든 캐릭터가 공유하여 실행하고 있다는 사실을 몰랐지만, 이 기능을 활용하면 어떤 주소에서 이 코드가 돌려쓰고 있는지 단번에 파악할 수 있습니다.

 

이런창이 나올껀데요. 여기서 이 코드는 몇개의 객체가 접근하고 있는지! 어느 주소에서 실행되고 있는지 까지 알 수 있습니다.

 

각 캐릭터 (Dave, Eric, HAL, KITT) 별로 Attack 을 한번씩 눌러서 확인해봅시다.

 

그러면 해당 창에서 코드 검출이 되며 어느주소로까지 접근하고 있는지 확인이 되네요.

 

이 주소들은 참고로 각 플레이어의 체력 주소입니다.

이로써 1차적으로 해당 코드가 모든 객체에서 공유되고 있다는 사실을 알았네요.

 

 

이 상태서 이 체력값들을 기준으로 구조체를 파악해보겠습니다.

저 값들을 모두 선택하고 Open dissect data with selected addresses 를 선택합니다.

이 기능을 사용하면 메모리 구조를 분석해, 구조체를 분석할 수 있습니다.

 

이런 창이 뜨면 OK를 누르거나 <New window>를 더블클릭

 

구조체의 이름은 원하는대로 설정

 

사용중인 주소에서 기초 타입을 치트엔진이 자동으로 정할 수 있게 도와준다고 하는데, Yes를 누릅니다.

 

구조체의 크기를 결정할건데 4096바이트는 너무 크니깐 2048정도로 조정합니다.

 

그러면 이런식으로 체력값을 기준으로 자동으로 주변 메모리를 분석해 구조체 형태로 표시를 해줍니다.

 

큰 메모리 흐름도가 나오지만 구조체로써 의미를 가지는건 아마 이 15바이트가 아닐까 싶습니다.

각 플레이어에 해당하는 구조체를 다음과 같이 파악 가능합니다.

 

 

참고로 저기 0000 으로 시작하는 저 F818088 이 체력값에 접근할 때 사용하던 그 포인터였습니다. (ebx 값에 저장해서 사용했던 포인터이며, 구조체로 접근하는 형태라서 어떻게 보면 구조체 포인터라고 해야 맞을 수도 있겠군요)

 

저 Health Pointer를 기준으로 +4 만큼 연산을 통해 체력을 읽고, +15만큼 연산해 이름을 읽을 수 있었습니다.

물론 Health Pointer은 Dave의 것이고, 각 플레이어 역시 포인터를 가져서 각 플레이어 구조체 시작주소를 가리키는 4개의 포인터가 존재하게 됩니다. 귀찮아서 그림은 다 안그리고 Dave 꺼만 그렸습니다 ㅎ;

 

예.. 어쨌던 이렇습니다. 그리고 좀 특이한점은 Health Pointer이 구조체의 시작주소를 가리키게 되는데, 시작주소 위치에 또 static 포인터가 존재하네요. 저 static 포인터는 다른분 강의를 들어보니 가상화 함수 테이블과 관련된 것으로 추정하신다고 합니다. 

 

또 Offset +4 위치의 값이 Health 고, +15위치가 Player Name 인거까진 파악되지만 다른 값들은 사실 잘 모릅니다. 어쨌던 같은 구조로 묶여 있다는건 각 플레이어를 구조체로 관리할 때 무언가 연관이 있다는 내용인데, 그렇게 중요한 사실은 아니니 Health와 Name 이외의 값들은 전부 무시하셔도 됩니다.

 

 

 

 

 

참고

https://www.youtube.com/watch?v=e9ROya00KpI 

https://www.youtube.com/watch?v=HSi004W9uXo&t=673s 

 

SNS 공유하기
💬 댓글 개
이모티콘창 닫기
울음
안녕
감사해요
당황
피폐

이모티콘을 클릭하면 댓글창에 입력됩니다.