본문 바로가기

해킹/리버싱

[reversing.kr] Direct3D FPS

우선, 실행을 시켜보았다. 

그러면 위와 같이 나오게 되는데 뭔가 엄청 재밌어 보인다. 근데 이속이 느려서 개답답함..

요런 귀여운 녀석이 있는데, 총을 마구 쏴도 데미지가 다는건지 마는건지.. 가만히 있기만 하다.

게임 내를 둘러봤지만, 이속도 매우 느리고 답답해서 그냥 나왔다. 딱히 별거는 없고, 저런 녀석들이 매우 많이 있다.
(근데 뭐 어쩌라는 건지..)

이제 직접 디버거로 까보자.

문자열 참조로 Game Clear!를 찾으면 위와 같은 루틴을 찾을 수 있는데, eax가 0x309194부터 0x210씩 커지며, 0x30F8B4와 크거나 같아지면 clear가 된다. 이 때 eax의 주소에 있는 값이 전부 1이 아니어야 한다. (flag같으므로, 0이어야 함을 예상할 수 있다.)

위의 MessageBoxA를 보면, Game Clear! 외에도 0x307028에 있는 문자열을 내용으로 출력해주는데, 그 위치로 가면

위와 같이 전혀 알수없는 문자열이 나오게 된다. 

어찌됐든 0x309194부터 0x210씩 0x30F8B4까지 모든 값이 0이어야 하는데, 이게 뭘 의미하는 걸까 하던 도중에 다시 게임을 켰다.

위의 녀석들이 너무 귀여워서 적인지 아군인지 피아식별이 안됐는데, 내가 그녀석들에게 다가가서 가만히 있으니, HP가 0으로 깎이면서 Game Over가 뜨게 된 것으로 보아, 적이라는 것을 알 수 있다.

그래서 혹시 위의 0, 1은 각각 녀석들을 죽였는지 안죽였는지를 나타내는 것이 아닐까 하는 생각이 들어서, 한놈에게 총을 마구 갈겼으나, 상당히 총을 많이 쏴야 사라졌다. 그래서 죽인 후 메모리를 확인해보니 eax의 여러 값중 하나가 0이 된 것을 확인할 수 있었다. 그래서 '이 녀석들을 모두 죽이는 문제' 라는 것을 깨달았다. 

그래서 녀석들을 모두 찾아서 죽여서 Clear!!

 

 

 

 

 

는 아니고, 플레이어 이속이 너무 느린데다가 한명 죽이는 데도 시간이 엄청 많이 걸려서, 직접 죽이는 것은 불가능하다.

그래서 문자열 참조를 통해 다음의 루틴으로 갔다.

위의 루틴은 총을 쏠 경우 총의 사운드를 켜주는 녀석인데, 이 녀석은 마우스 클릭을 트리거로 실행되는 루틴일 테니, 녀석들을 죽이는 루틴과 관련이 있을 것 같아서 찾아보았다. 

그러면서 근처를 둘러보던 중 다음과 같은 루틴을 발견하였다. 

여기서 딱 봐도, 0x307028 위치에 xor을 하고 있으니, 이는 위에서의 알아볼 수 없는 문자열을 복호화 해주는 루틴일 것이다. 그러므로, 위의 루틴이 핵심적인 녀석일 것이다.

여기서 조금 관찰을 해주면 (말만 조금이지 몇십분동안 죽어라 관찰만 한 듯..)

위 루틴을 실행할 때, 총을 허공에 쏘면 FFFFFFFF가 나오고, 총을 적에게 쏘면 적에 따라 각각 다른 숫자가 나온다. 얘를들어 A를 쏘면 0x01 B를 쏘면 0x27이 나오는 식으로 말이다. 

그리고 위의 루틴을 읽어보면 eax의 숫자에 따라서, 0x309190에서부터 eax * 0x210 한 것을 ecx에 넣고, 0x309190 + ecx위치의 값을 꺼낸다음 이녀석이 0인지 아닌지를 검사한다. 

즉 A를 쏴서, 0x01이 eax라면 ecx는 0x210이고, 0x309190 + 0x210 인 0x3093a0 위치의 값이 0인지 아닌지 검사하는 것이다. 

여기서도 모든 ecx + 0x309190 값을 검사했지만, 모두 0x64일 뿐 0은 찾을 수 없었다. 그래서 문득 이게 적 각각의 HP를 나타내는 게 아닐까 하는 생각이 들었다. 심지어 위 루틴에서 0인 경우 복호화를 해주고, 그것에 더불어 위의 1로 설정되어 있던 것도 0으로 설정해준다. 

그리고 적을 쏠때마다 피가 2씩 주는 것을 확인하여, 이게 맞다는 확신을 가지게 되었다.

그래서 해당 문제는 '저 녀석들을 모두 죽이는 문제'이지만 hp는 각각 0x64 즉 100씩 있고, 총쏠때마다 2씩 까이며, 각각의 적들이 자신 고유의 id가 있으며 이 녀석들을 죽일 때마다 문자열 하나가 복호화 되는 방식이었다. 

사실 여기까지 왔으면 문제는 다 풀었다. 단지 hp를 디버거에서 0으로 설정해준다음 한번씩만 쏴주면 쉽게 clear 되기 때문이다. 또는 복호화 방식도 알아냈기 때문에, 그냥 수학적으로 계산해서 복호화를 해주어도 된다. (프로그램을 짜도 되고..)

그런데 위의 방식은 조금 귀찮다는 생각이 들어서, 패치를 해주기로 했다.

패치의 목적은 1. 모든 적의 hp를 자동으로 0으로 설정한다. 2. 허공에다가 쏴도 자동으로 0~0x31(최대 id가 0x31임)의 적들을 차례로 쏘도록 만든다.

패치할 코드를 삽입해주기 위해서 .text 섹션에서 적당한 위치를 찾았으나, PE의 virtual section size가 정확히 딱 떨어지게 설정되어 있어서, detect it easy라는 PE 포맷 읽기 or 수정 툴을 통해서 virtual size를 오류가 안나는 선에서 최대로 조정해줬다. 

아래의 사진은 패치 가능한 영역. 이미 명령어가 있는 것은 패치를 해주었기 때문이다. 

코드에 박힌 메모리 주소는 매 실행마다 갱신해주어야 했다. ASLR 때문인듯..

ASLR을 고려해서 새로 패치를 했다.

어쨌든 아까 총을 쏘고 hp를 0으로 검사하는 루틴에 위의 함수를 실행하는 문장을 넣어주었다.

아까는 허공에 쏜 총이라면 넘어가는 루틴이 있었는데, 이를 위에 적은 함수로 바꾸어주어서, 이제 허공에 쏠때마다 함수가 실행될 것이다. 

위의 어셈은, 알아서 읽어보시길... (매우 쉽다.)

패치를 진행한 뒤, 게임 허공에 총을 51번 쏘면 게임이 clear된다. 

아래의 파일은 완성된 패치파일인데, 허공에 클릭만 해도 문제가 풀리도록 변경한 것이다. 심심하면 실행해봐도 좋을듯.. 그런데, 만약 문제가 된다면 삭제하도록 하겠다.

FPS_patched_with_ASLR.exe
0.02MB

'해킹 > 리버싱' 카테고리의 다른 글

[reversing.kr] position  (0) 2021.04.09
[reversing.kr] easyELF  (0) 2021.04.09