Tutorial 6
문제: pointer의 값을 5000으로 바꾼 후 값을 얼려라.
change value 버튼: 포인터가 가리키는 값을 바꾸는 버튼. 누를 때마다 값이 바뀜.(포인터가 가리키는 값이 바뀜) change pointer 버튼: 포인터 자체를 다른걸로 바꾸는 기능. 외관상 똑같이 값이 바뀌는 것 같지만 pointer가 갖고 있는 값 자체가 바뀌는 것임.(포인터가 바뀜)
- change value 버튼을 클릭해서 현재 내 값이 497이기 때문에 497을 value로 갖는 address를 스캔함. 더블클릭하여 아래에 있는 주소 리스트에 추가해주었음.
- change pointer 버튼을 눌렀고 화면에 출력된 값이 바뀐 걸 확인할 수 있음.
- 그러나 1.에서 등록한 주소 리스트의 value는 변하지 않았음.
이렇게 프로그램에 포인터를 사용하면 우리가 치트엔진 같은 프로그램을 이용해서 어떠한 값을 추적하는 것이 굉장히 어려워진다는 것을 알 수 있다.
포인터를 사용하는 프로그램을 어떻게 추적할 수 있을까?
- New Scan 버튼으로 치트엔진을 리셋하고 현재 프로그램에 출력된 값이 166이기에 166을 First scan한다.
- 프로그램에서 Change value 버튼을 누르고 치트엔진의 address에서 바뀐 값을 체크하고 주소 리스트에 넣어준다.(나의 경우 166→422로 바뀌었음)
- 이제 Pointer 자체를 찾기 위해 주소리스트에 등록된 값을 우클릭 > Find out what accesses this address 을 누른다. 이 기능은 어떤 부분이 이 주소에 접근하는지, 참조하는지를 확인할 수 있다. 포인터 변수를 찾을 때 사용하는 기능이다.
- 프로그램에서 다시 값(value)를 변경하면 다양한 기계어가 색출된다. 클릭한 영역은 [edx]에 참조하여 eax에 들어있는 값을 [edx]에 넣어준다는 뜻이다. 우클릭 후 More info로 들어가보자.
- EDX 레지스터의 값이 01A508C0인 것을 알 수 있다. 어떤 포인터 변수가 이 값을 갖고 있겠구나, 어떤 포인터 변수의 값이 이 주소가 되어야지 그 포인터 변수는 여기에 접근해서 어떠한 값(eax)을 넣어줄 수 있겠구나 를 추측할 수 있다.
- New Scan을 누른 후 Value의 hex에 체크한 후 01A508C0를 스캔하고 나온 주소를 주소 리스트에 등록한다.
- Add Address Manually 버튼을 눌러 수동으로 포인터 변수를 등록할 수 있다. 우리가 등록할 값이 포인터임을 알리기 위해 Pointer에 체크를 하고 새로 뜨는 아래 화면 입력란에 포인터변수의 주소값인 006566B0을 입력한다. 그럼 → 뒤의 주소(변수)에서 그 변수가 갖고 있는 값이 540이라는 것을 확인할 수 있다.(실제로 프로그램상에서도 540이 출력되어 있음)
- Ok 버튼을 누르면 포인터 변수 자체가 주소 리스트에 등록된 것을 확인할 수 있다. 이 상태에서는 프로그램에서 포인터의 값을 변경하더라도 추적이 되는 것을 확인할 수 있다.
- 포인터 변수의 값을 5000으로 바꾼 뒤에 Active에 체크에 값을 얼려준다(고정한다).
- 이제 프로그램에서 Change Pointer를 눌러 포인터 변수를 바꿔준다 해도 계속해서 동일한 위치를 가리키게 되며 문제가 풀린다.
Password: 013370
Tutorial 7
문제: 프로그램 실행 중간에 껴서 우리가 원하는 코드를 삽입하라. (Hit me 버튼을 누를 때 마다 값이 1씩 감소하는 프로그램이 있는데 버튼을 누를 때마다 값이 2씩 증가하도록 Code Injection 수행하기.)
- 맨 처음 디폴트 값이 100이니까 100으로 First Scan을 수행하고 Hit me 버튼을 눌러 값을 계속 감소시키면서 따라 감소하는 address를 찾아 주소 리스트에 등록한다.
- 주소리스트에 들어있는 값을 우클릭 > Find out what writes to this address를 클릭한다. 이 기능은 이 주소에 접근하는 기계어를 볼 수 있다. 프로그램에서 Hit me 버튼을 눌러 다시 값을 감소시키고 나온 Instruction을 더블클릭해 상세정보를 확인한다. sub 명령을 이용해서 [ebx+ ...]의 주소에 담긴 값을 1만큼 감소시킨다고 해석할 수 있다.
- OK 버튼을 누르고 빠져나와 Show disasseambler 버튼을 누르면 더 상세하게 어셈블리코드를 볼 수 있다. Tools > Auto assemble을 눌러 자동으로 코드 인젝션을 위한 준비를 한다. Template > Code Injection > OK 를 누르면 코드 인젝션을 위한 기본 템플릿이 사진과 같이 마련된다.
add dword ptr [ebx+000004A4], 02
- line 10을 건드려 2씩 값이 증가하게 코드를 조작하고 execute 버튼을 누른다.
- 프로그램으로 돌아와 Hit me 버튼을 누르면 값이 2씩 증가하는 것을 볼 수 있다.
Password: 525927
Tutorial 8
문제: (4 개의 포인터가 중첩되어 있다.) 특정한 변수를 가리키는 포인터의 포인터의 포인터의 포인터의 포인터를 발견해서 그 값을 5000으로 얼려라.
- 현재 프로그램의 value인 1774를 치트엔진에 검색해 주소리스트에 등록시키고 우클릭 > Find out what accesses this address 로 들어가 다시 프로그램에서 change value를 누르고 치트엔진을 확인한다. [esi+18]에 eax값을 넣는다는 것을 볼 수 있다. 따라서 어떠한 포인터는 esi값을 갖고 있다는 것을 알 수 있다. esi의 값을 복사해준 이후에 나와준다.
- esi값 01AC8D78을 치트엔진에서 hex를 누르고 First Scan 해주고 나온 address를 주소 리스트에 넣어준다.(여러개 나오면 묶어서 한꺼번에 넣어준다.) 1.의 방식과 마찬가지로 이 주소를 참조하는 다른 포인터를 확인해준다. 실질적으로 mov가 어떠한 값을 넣어주는 명령이므로 이 라인을 보면 된다. esi에 [esi] 주소에 들어있는 값을 넣어주라는 의미이다. 현재 우리 포인터 변수의 주소값(을 어떤 address가 갖고 있는지 다시 New Scan 해서 알아보자.
- 똑같이 앞에서 했던 작업들을 수행하고 mov 명령 라인을 보자. [esi+14]에 담긴 값을 esi로 넣으라는 명령이다. 참고로 [esi+14]는 특정한 주소에 14h를 더해서 참조하겠다는 의미이다. 다시 말해, 현재 주소값에서 14h를 뺀 주소를 어떠한 포인터 변수가 갖고 있다는 의미이다. 즉 현재 우리 address 주소가 01A5A35C인데 여기에 14h를 뺀 값(01A5A348)을 어떠한 포인터 변수가 참조하고 있다는 얘기이다.
- New Scan 하고 01A5A348를 검색해 또 같은 작업들을 수행해보자. 3.에서와 동일한 구조로 나왔다. 즉, 현재 주소에서 0C를 빼준 주소를 또 어떤 포인터 변수가 참조하고 있다는 소리이다. 현재 주소는 01A29214이니 0C를 빼면 01A29208이다. 다시 New Scan 해보자.
일반적으로 address에 초록색 표시가 된 주소가 다중 포인터의 시작 주소일 가능성이 크다.
- 그럼 이제 최종적으로 이 포인터의 출발점인 포인터 변수가 뜬다. 이를 주소리스트에 등록시킨다.
- 지금까지 모은 다중 포인터들을 처리하기 위해 Add Address Manually 버튼을 눌러 수동으로 등록해준다. Pointer에 check를 해주고 출발주소인 006566E0을 하단 메시지박스에 입력하고 바로 위에 오프셋이라고 할 수 있는 0C를 더해준다. 그리고 add Offset을 눌러 다중 포인터를 만들 수 있게 해주고 차차 더해준다. 결과적으로 현재 기록되어 있는 1174를 찾을 수 있게 된다. Description에는 등록할 다중 포인터의 이름을 지정해준다.
- 만들어준 다중 포인터의 value를 5000으로 바꾼 후 Active 체크박스를 눌러 얼리고 프로그램에서 Change pointer를 눌러 바꾸더라도 실제적으로 시작 포인터가 가리키고 있는 값은 5000으로 고정되어 있는 것을 확인해볼 수 있다.
Password: 31337157
Tutorial 9
문제: Player1,2는 우리팀, 3,4는 상대팀이다. 우리팀은 체력 100, 상대팀은 500으로 시작하는 상황에서 게임을 실행했을 때 우리팀이 이기도록 하라. (우리팀이 공격을 받아도 체력이 안 깎이게 만들기)
Player 1과 그의 Health, Attack은 하나의 구조체로 묶여 있을 것이다. 다른 플레이어들에게도 마찬가지.
- Dave의 체력값(float형)의 위치를 확인하고 주소 리스트에 등록한다. Attack 버튼을 눌렀을 때 공격이 수행되기 때문에 그 기능을 막기 위해서 우클릭 > Find out what writes to this address에 들어가 프로그램을 한 번 더 실행시키고 출력되는 기계어를 확인한다. eax에 담긴 값을 [ebx+04]의 주소에 담겠다는 뜻이다. ebx에는 061F3210값이 담겨 있다.
- Dave의 구조체 형태의 변수를 확인하기 위해 주소리스트의 값을 우클릭 > Browse this memory region을 눌러 실질적으로 메모리 영역상에서 061F3210가 어디에 있는지 확인한다. 마지막이 10으로 끝나는 위치(파란블록)를 찾아 왼쪽 아래를 확인하면 잘 찾았다는 것을 의미한다. 파란 블록부터 구조체가 시작하는 부분이라고 추측할 수 있다. 또 아래에는 Player의 이름 정보가 있는데 여기에서(061F3225) 시작주소를 빼면 15h가 나오고 15h가 오프셋이라는 것을 알 수 있다.
- 다시 1.의 화면으로 돌아와 Show disassembler > Tools > Auto assemble > Template > Code injection을 눌러 코드 템플릿을 생성하고 Dave의 체력값이 깎이지 않게 코드를 수정한다. 원본 코드에서는 체력을 깎는 명령을 수행한 후 exit하는데 우리는 Player의 이름이 Dave일 경우 체력을 감소시키지 않겠다는 명령을 작성할 것이다.
newmem:부분에서 Player의 아이디값을 검증하는 코드를 작성한다.
- line 8: 구조체의 시작주소에서 15h를 더한 값이 ‘Dave’의 시작주소였으니까 ‘D’와 비교하는 코드를 작성했다. line 9: 앞 라인이 참이면 exit으로 점프한다. line 15: 원본 코드에서 mov 명령(체력을 깎는 명령)을 수행하고 알수없는 명령을 실행했는데 이 명령은 우리가 조작하려던 코드가 아니므로 exit: 에 넣어준다.
- execute를 하고 프로그램에서 Restart game and autoplay를 눌러주면 Dave를 제외한 플레이어가 체력이 깎여 죽어있다는 것을 볼 수 있다.
'4-6. 2022-1 심화 스터디 > 모바일 게임 해킹' 카테고리의 다른 글
[2022.05.14] 치트엔진으로 포켓몬스터 파이어 레드 게임 해킹하기 (0) | 2022.05.14 |
---|---|
치트 엔진(Cheat Engine)을 활용한 게임 해킹 강좌 튜토리얼 1~5 정리 (0) | 2022.04.04 |
[2022.03.26] 모바일 게임 해킹(Unity편) - Part 2.2 ~ Part 3.2 (0) | 2022.03.27 |
[2022.03.19] 모바일 게임 해킹(Unity편) - Part 0 ~ Part 2.1 (0) | 2022.03.19 |
[2022.03.12] APK 구조 분석 및 decompile&repackaging (0) | 2022.03.13 |