본문 바로가기

[치트엔진 6.8.1] 튜토리얼 Step 6 : 포인터 (Pointer)

728x90
728x90




6단계 : 포인터 (Pointer)


 포인터(Pointer)란 무엇인가요?

포인터 위키백과로 더 알아보기

포인터 나무위키로 더 알아보기

c언어에서의 포인터

- 메모리에는 바이트 단위로 그 위치를 식별할 수 있는 물리적인 주소값이 있다. 주소값은 0번지부터 차례로 부여된다. 만약 메모리의 용량이 64키로바이트라면 주소값은 0번지부터 65535번지까지 존재할 것이다. (1kbyte = 1024byte ∴ 64kbyte = 65536byte) 변수를 선언하면 그 자료형의 크기만큼 메모리에 연속된 바이트의 기억공간이 할당되고 자동으로 주소값을 가지게 된다. 예를 들어, Int 형 변수를 선언하면 메모리에 4바이트가 할당되고, 그 시작 주소값이 100번지라면 100번지부터 103번지까지의 주소값을 갖게 될 것이다. 이 때 시작 주소값 100번지를 포인터라고 한다. 프로그램에서 변수명은 알 수 있지만 그 변수가 실제 메모리의 몇 번지에 할당되는지 알 수 없다. 따라서 포인터를 사용하기 위해서는 먼저 그 주소값을 알아 내는 과정이 필요하다. 이 포인터에는 아주 특별한 정보가 숨겨져 있는데 바로 자신이 어떤 자료형으로부터 만들어졌는지에 대한 정보를 가지고 있다는 것이다. 포인터가 특정 자료형에 대한 정보를 가지고 있다는 것을 나타낼 때 간단히 "가리킨다"는 표현을 사용한다. 즉, 포인터의 값 자체는 메모리에서 1바이트의 주소값이지만 연속된 바이트를 대표하는 의미를 가지는 것이다. (-뇌를 자극하는 C 프로그래밍/한빛미디어)





이전 단계에서 코드 찾기를 사용하여 변화하는 위치를 처리하는 방법을 설명했습니다. 그러나 그 방법만으로 원하는 값을 설정하기 위한 주소를 찾기가 어렵습니다.


그래서 포인터가 있는 이유입니다.


Step 6 튜토리얼 창 맨 아래에 두 개의 단추가 있을 겁니다. 하나는 Value(값)를 변경하고 다른 하나는 Value(값)와 Pointer(포인터, 값의 위치) 둘 모두를 변경합니다.




이 단계에서 당신은 어셈블러를 알 필요는 없지만, 알고있다면 많은 도움이 될 것입니다.


먼저 값의 주소를 찾으십시오. 발견했다면 해당 주소를 더블클릭하여 주소리스트에 추가 시키고 또 다시 해당 주소를 마우스 오른쪽 클릭하여 Find out what accesses this address(이 주소에 접근하는 것이 무엇인지를 알아내라) 기능을 눌러 사용하십시오. 주소를 클릭한다음 단축키를 사용해도 좋습니다.




Change value(값을 변경) 버튼을 클릭하면 방금 열은 창 목록에 항목이 나타납니다. 일단 4개중 첫번째 해당하는 항목을 더블클릭하십시오. 또는 항목을 한 번 누르고 More information(추가 정보)를 클릭해도 됩니다.


(4개의 명령어가 떴습니다. 이는 값에 변화를 주었을 때 관여하는 명령어들이란 얘기입니다. 대충 어떤 명령인지 해석해보면 대괄호는 포인터라는 뜻이고 mov eax, [rax]는 [rax]가 가르키는 곳의 값을 eax에 저장해라 라는 뜻입니다.)



그렇다면 새 창 즉 Extra info 창이 열리고 명령이 실행될 때 어떤 일이 발생했는지에 대한 자세한 정보가 함께 표시됩니다.


(1번 문구에 "아마도 포인터 주소가 00000184 일 것이다" 라고 말하고 있습니다. 이 주소를 기억하거나 대괄호 즉 빨간색으로 칠해진 '[ ]' 사이의 문구와 상응하는 Hex 주소값을 아래에서 찾을 수 있고 창을 띄운 채로 적어도 됩니다. 이 주소는 저마다 다르니 자신이 찾은 주소를 알아 두셔야 합니다.)



어셈블러 명령어에서 '['  ']' 사이에 아무것도 없는 경우에는 목록에 있는 다른 항목을 사용하십시오. 만약 그렇게 한다면, 자기가 생각하는 당신이 필요한 포인터의 값을 보여줄 겁니다. (그러니까 대괄호 안이 비어있으면 다른 항목을 이용해라 이 말입니다.)


주 치트엔진 창으로 돌아간 다음 기억해둔 Hex(16진수, Hexadecimal) 주소값을 입력하고 4바이트로 스캔하십시오.


스캔이 완료되면 1개 또는 수 백 개의 주소를 반환할 수도 있습니다. 당신이 필요한 대부분의 시간은 가장 작은 주소가 될 것입니다.


이제 (수동으로 주소 추가)를 클릭하고 (포인터 확인란)를 체크하십시오.




창이 바뀌면 그곳에

'오프셋offset[각주:1]()' 

'포인터 주소()' 를

입력할 수 있습니다.


방금 스캔하여 찾아진 주소를 포인터 주소 입력란에 입력하여 OK(확인)버튼을 누르면 하단 주소목록에 추가됩니다. 모든 것이 정상적으로 행해졌다면 추가된 목록의 주소가 P->xxxxx로 표시되고, xxxxx는 검색한 값의 주소가 된다. 만약 그게 틀렸다면, 당신이 뭔가 잘못했다는 겁니다.


그게 아니고 Value 값이 ?? 으로 나온다면 그 포인터는 우리가 원하는 것이 아니니 위에서 찾은 4개의 어셈블리 명령어중 첫번째를 제외한 나머지 3개도 똑같이 작업해 튜토리얼의 현재값과 비교하여 같은 값이 떴다면 성공이라고 할 수 있습니다.


어셈블러 명령어 끝에 계산식(예: [esi+12])이 있는 경우 오프셋 입력란에 값을 입력하십시오. 그게 아니라면 0으로 그냥 두십시오.

만약 그것이 좀 더 복잡한 명령이였다면, 다음의 계산을 살펴보아주십시오.



 [보다 복잡한 명령의 예]

[EAX*2+EDX+00000310] eax=4C 및 edx=00801234


이 경우 EDX는 포인터일 것이고,

EAX*2+00000310이므로, 입력할 오프셋은 4C*2+00000310='3A8'이 된다(모두 Hex이다).


Hex(16진수) 계산을 위해 윈도우 계산기에서 프로그래머용으로 바꾼 뒤 Hex로 계산해주면 편하다.





 여기까지 잘 따라왔다면 포인터를 이용하여

에서

으로

값을 변경하고


Freeze(여기서는 Active에 체크)

하십시오.


그런 다음 튜토리얼 Step 6 창에서 Change pointer(포인터 변경)를 클릭하고 모든 작업이 완료됐다면 Next(다음)이라는 버튼이 활성화될 겁니다.


추가:


그리고 당신은 또한 포인터 스캐너 기능을 사용하여 이 주소에 대한 포인터를 찾을 수 있다는 걸 알아두시라!





  1. 오프셋이란, 두 번째 주소를 만들기 위해 기준이 되는 주소에 더해진 값을 의미한다. 예를 들어, 만약 아래의 수식에서 C가 100번지의 주소를 가리키고 있다면, 그 수식의 결과는 107번지를 의미할 것이다. < C + 7 > 여기서 이 수식 내의 "7"이, 바로 오프셋이다. 오프셋을 이용하여 주소를 나타내는 것을 상대주소 지정방식이라고 부르는데, 그 이유는 결과 주소가 다른 지점의 상대적인 위치가 되기 때문이다. 오프셋을 다른 말로 "변위"라고도 부른다. (출처-http://www.terms.co.kr) [본문으로]
728x90
728x90