본문으로 바로가기

파일의 IT 블로그

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

[Cheat Engine Game] 치트엔진 튜토리얼 게임 Step #2 풀이

· 댓글개 · KRFile

Step2:
당신의 캐릭터보다 체력도 많고 데미지도 더 쌘 두 명의 적 캐릭터가 있습니다. 파괴하십시오.

팁 / 주의 : 적 캐릭터와 당신 캐릭터는 관련이 있습니다.

(클릭 시 숨김)

 

안녕하세요 파일입니다. 이번엔 튜토리얼 게임 Step 2 풀이입니다. 튜토리얼 게임은 그냥 튜토리얼이랑 다르게 설명이 간단해서 마음에 드네요 ㅋㅋ 이번 문제는 설명을 읽어보시면 알다 싶이 내 캐릭터보다 훨씬 쌘 적 캐릭터 2개를 파괴 하는 것 입니다. 당연히 적 캐릭터도 공격을 하기 때문에 내 캐릭터는 죽지 않고, 적 캐릭터 2개를 파괴해야 합니다.

 

Tip / Warning 부분에 의미심장한 말이 있는데 바로 "적 캐릭터와 당신 캐릭터는 관련이 있습니다" 입니다.

이번 문제는 저번 튜토리얼 #9번 문제와 비슷합니다. 거의 똑같다고 봐도 무방합니다. 마치 이번건 저번 #9번 문제를 게임으로 만든 느낌이랄까요?

 

Try 1 - 기초적인 방법

총알 발사(키 : Space) 를 해보시면 알겠지만 적 캐릭터는 2명이라 다굴을 치는데 체력도 ㅈㄴ 안답니다. 내 캐릭터는 체력이나 공격력이나 빈약 그자체...

이대로 전투하면 절대로 이길 수가 없습니다. 이제 치트로 이걸 해결해봅시다.

 

먼저 튜토리얼 #1번에서 했던 가장 기초적인 방법으로 해당 문제를 풀어봅시다.

화면에 보이는 캐릭터의 체력 (100) 을 검색합니다.

 

적 캐릭터에게 공격을 받고 다시 체력을 검색하면 쉽게 내 캐릭터의 체력을 찾을 수 있습니다.

 

이제 내 캐릭터의 체력을 큰 값으로 고정합니다.

 

다만.. 내 캐릭터 공격력이 너무 약해서 잡는 시간도 너무 오래걸리고 이렇게 푸니깐 좀 가오(?) 도 안사네요. 앞 튜토리얼에서 코드 인젝션도 배우고 어셈블리어 패치도 배우고 했는데 

 

 

?? 한 마리 잡았더니 갑자기 You will pay for this (너 대가를 치를거야!) 라면서 megabomb 가 3초 뒤 활성화 된다네요

 

하하 역시 이렇게 쉽게 보내줄리가 없죠. 체력을 7자리수까지 늘렸는데도 한 방에 터져버리네요. 무조건 즉사인가봅니다?? 코드 인젝션이나 다른 방법을 사용해서 문제를 풀어봅시다.

 

Solution 1

우선은 적 캐릭터 체력과 내 캐릭터 체력의 메모리 값을 찾아놓은 상태서 시작합니다.

적 캐릭터의 체력은 저번 튜토리얼 게임 #1편에서 했던 방법인 Unknown initial value & Changed Value (또는 Decreaed Value) 를 사용하면 쉽게 찾을 수 있습니다.

 

적 체력은 4바이트 정수값이며 최대 체력일 때 200, 내 캐릭터에게 한 대 맞을때마다 1씩 감소합니다. (내 캐릭터의 공격력은 1)

 

내 캐릭터의 최대 체력 100, 적 캐릭터 최대 체력 200을 기준으로 값을 잘 찾아내세요. (여기까지 오셨으면 이 정도 과정은 생략합니다.)

 

 

참고로 해당 값은 죽어서도 계속 유지됩니다. 게임이 초기화 되어도 그대로 유지 되고 있다는 뜻입니다.

이전처럼 새로운 공간을 만들어서 포인터로 가리켜 계속 바꾸는 형태는 아닌 거 같고 고정된 공간을 이용하는 거 같습니다.

(그렇다고 해당 값에 대한 포인터가 존재하지 않는 건 아님 그냥 새로운 공간을 매번 할당하는게 아닐뿐인듯.)

 

 

플레이어 체력에 어떤 기계어가 작성하는지 확인 하기 위해 Find out what writes... 로 기계어를 추적합니다.

이전에 하던대로 Find out what accesses 를 이용해 포인터를 찾을 수도 있으나 이번 문제는 포인터를 그다지 찾을 이유가 없는 거 같습니다. 일단 문제 해결에만 집중하도록 해보겠습니다.

 

보다 싶이 플레이어가 적 캐릭터에게 피격당했을 때 체력을 감소시키는 sub 명령어를 실행하고 있습니다. Count가 2인 이유는 적 캐릭터에게 총알을 2방 맞았기 때문입니다.

 

여기서 저 명령어를 바로 NOP으로 패치할 수도 있지만 그 전에 이 코드가 다른 객체 또한 공유하고 있는지 확인해야 합니다. 튜토리얼 #9번을 풀어보셨거나 문제 설명을 읽어보셨으면 알다 싶이 (적 캐릭터와 당신 캐릭터는 관련이 있습니다.) 저 명령어가 오직 플레이어의 체력 감소에만 사용한다는 보장이 없으니깐요.

 

적 캐릭터가 내 캐릭터에 의해 피격 당하면 체력을 감소시키기 위해 똑같이 저 명령어를 돌려쓸 수 있습니다.

 

해당 명령어가 어떤 주소에 접근하고 있는지 파악해봅시다.

오른쪽 클릭 - Find out what addresses.. 를 선택합니다.

 

역시 해당 명령어는 플레이어 체력 감소에만 개입하고 있는게 아닌, 전체 플레이어 (적, 내 캐릭터 전부 포함) 체력 감소에 개입하고 있습니다.

 

제가 왼쪽에 있는 적 캐릭터와 오른쪽에 있는 캐릭터를 각각 맞췄는데 체력이 195인 쪽이 왼쪽 적이고, 198인 쪽이 오른쪽 적입니다. 체력이 72인건 제 캐릭터구요. (Count 가 4인건 4방 맞았기 때문입니다. 적이 2명이라 내가 2발쏘면 적은 4발쏘기 때문에;;)

 

체력 감소 코드인 sub [rax+60],edx 의 입장에서 보자면, 이 코드는 각 캐릭터 객체에게 공유되어서 실행 당한 코드입니다. 저번 #9번과 마찬가지로  공유된 코드라는 것이죠. 

 

각 캐릭터 객체를 코드 실행을 시킨 주체로 보면, 각 캐릭터가 맞을때마다 sub [rax+60],edx 를 실행시켜서 각 캐릭터 체력에 접근하고 있는 셈이 됩니다. 

위에 각 Address 로 표시되는 게 각 캐릭터의 체력값 입니다.

 

그럼 이번에도 저번 문제 풀이할때와 동일하게 각 캐릭터 별 구조체가 존재해서 객체로써 관리되고 있으며, 이 객체에 특정 연산을 가해서 체력을 조정하고 있을 것이라는 합리적 의심이 듭니다. (특정 연산은 위에서 확인한 sub [rax+60],edx)

 

내 캐릭터와 적캐릭터 2개의 체력 값을 주변으로 구조체를 파악해보겠습니다.

저 값들을 모두 선택하고 Open dissect data with selected addresses 클릭

 

구조체 생성시 무언가 창이 뜨면 전부 Yes 눌러주세요.

뜨는 창에 관해선 #9번에서 이미 설명을 드렸습니다.

 

 

그럼 이런식으로 구조체가 분석이 됩니다. 0000 오프셋에 존재하는 포인터를 구조체 시작으로 정의한다면, 여기서 +60 오프셋으로 접근중인게 각 캐릭터의 체력입니다.

 

사실 다른 값들은 무슨 의미를 가지는지 솔직히 잘 모르겠어서 여기 Float 값으로 되어 있는걸 2로 수정해봤습니다.

 

그랬더니 저기 왼쪽 적이 절반으로 찌그러지더라구요 ㅋㅋ 

아마 캐릭터 크기 렌더링이랑 관련된 값인듯 싶습니다. 재밌네요

2를 주면 2배 찌그러지고, 0.5를 하면 2배 늘어납니다.

 

그리고 저기 Float 값으로 되어 있는건 좌표입니다. 

 

그리고 이건 캐릭터를 돌려보면서 알았는데 돌릴때 각도랑 연관이 있는 값인거 같습니다.

캐릭터 방향을 돌릴때마다 값이 증가하거나 계속 감소합니다.

다만. 적 캐릭터 방향을 돌려보고 싶었는데 조정이 안되더라구요. 

 

이건 보여줄때만 사용하는 임시값이고 실제 각도는 어디선가 관리되고 있나봅니다.

 

그리고 이 밑에 있는 값은 각 캐릭터의 최대 체력을 나타내는 걸로 보입니다. 근데 이것도 역시 조작이 안되네요 아쉽.

 

플레이어의 좌표는 어짜피 고정이니깐 이를 이용해서 코드인젝션 해 내 캐릭터를 무적으로 만들어 보겠습니다.

 

이 위치에 코드 인젝션을 하면 됩니다.

코드 인젝션에 관련된 내용은 앞 튜토리얼에서 매우 많이 설명드렸으므로 과정은 생략하도록 하겠습니다.

 

alloc(newmem,2048,"gtutorial-x86_64.exe"+400E3)
label(returnhere)
label(originalcode)
label(exit)

newmem: //this is allocated memory, you have read,write,execute access
//place your code here

originalcode:
cmp [rax+24], 0 //캐릭터의 한 좌표가 0이라면 확실히 내캐릭터임
je mycharacter
jne enemy

mycharacter:
//sub [rax+60],edx
ret
add [rax],al
jmp exit

enemy:
sub [rax+60],edx
ret
add [rax],al
jmp exit

exit:
jmp returnhere

"gtutorial-x86_64.exe"+400E3:
jmp newmem
nop
returnhere:

 

해당 코드 원리 : 적 캐릭터와 내 캐릭터는 좌표 자체가 고정이므로 24 오프셋에 존재하는 좌표가 0이면 확실히 내 캐릭터가 코드를 실행하고 있음을 알 수 있음.

 

또한 따로 설명드리지 않았지만 rax 레지스터에 저장된 값이 어떤 포인터가 가리키는 값입니다.

rax 레지스터의 값은 각 캐릭터 구조체의 시작 주소를 가리키고 있습니다.

이번 문제 역시 객체를 가리키는 포인터가 존재함.

 

이렇게 패치하면 내 캐릭터는 아무리 맞아도 안죽고 적 캐릭터는 데미지를 입게 됩니다.

Megabomb 를 맞아도 데미지는 전혀 들어오지 않습니다.

 

참고로 이렇게 코드 인젝션을 하지 않고 적 캐릭터 체력을 1,1로 설정한다음에 잡는게 훨씬 쉽게 푸는 방법이긴 합니다. 다만 적 캐릭터를 1,1로 설정하고 한 마리를 잡으면 그 이후에 남은 적 캐릭터의 체력이 20으로 회복되니 이때 다시 1로 체력을 조정하고 싸워야 합니다.

 

내 캐릭터랑 적 캐릭터랑 동시에 죽는 러브샷이 떠도 적 캐릭터 2마리만 잡으면 클리어 인정 됩니다. 참고하세요.

체력 조절해서 푸는건 아래 선생님이 친절하게 알려주십니다.

 

문제 풀이에 도움이 될만한 영상

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

 

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

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