이제는 실제 게임 플레이하는 루틴 내부로 들어가서 분석을 하고 싶은데 큰 문제가 발생했습니다.
breakpoint를 하나도 안 걸어두고 F9로 진행을 시키는데도 계속 PAUSED 상태로 빠집니다. shift + F9로 계속 진행을 하면 게임 시작을 하지 못한채 죽어버립니다.
고전 게임에 디버깅 탐지 장치가 들어있지는 않을거고, 경로 상에 한글이 들어가있어서 그런걸까 관리자 권한으로 실행해서 그런걸까 뭐 온갖 방법을 다 써보았지만 마땅히 해결되지 않았고, 어쩔 수 없이 미리 실행시킨 후에 attach하는 방식으로 일단 게임 루틴 안으로 진입했습니다.
여기 있는 Attach를 이용해서요.
그 후에 GetMenu에 전부 breakpoint를 걸어줍니다.
메뉴에서 게임 점수를 바꾸거나, 속도를 바꿀 때 breakpoint가 걸리면 어떤 값이 어떻게 바뀌는지 분석하기 쉬울 것이라고 판단했습니다.
첫 번째로 게임 속도를 바꾸어보겠습니다. 보통에서 느리게로 변경할 것입니다.
게임 속도를 변경하려고 하면 0x40179A에서 break가 걸립니다. GetMenu는 내가 선택한 menu의 handle을 반환해줍니다. 그 핸들을 EBX에 넣고, CheckMenuItem을 2번 호출하는데 Flag를 볼 때 첫 번째 CheckMenuItem은 체크를 해제하고 두 번째 CheckMenuItem은 체크를 하는 것으로 보입니다. 즉 첫 번째에는 "보통"의 item ID가, 두 번째에는 "느리게"의 item ID가 들어가겠네요. 일단 Resource에서 menuitem은 아래와 같이 기록이 되어있고,
이제 F8로 조금씩 전진하면서 값이 어떻게 바뀌는지 보겠습니다.
예상하던대로 첫 번째 CheckMenuItem의 ItemId로 40005를 실어보냅니다.
그리고 두 번째 CheckMenuItem의 ItemID로 40004를 실어보냅니다.
이렇게 체크박스는 해결헀는데 실제로 시간을 조절하는 부분은 아직 안보이네요. F8로 계속 진행해보겠습니다. 진행하다보면 현재 함수를 끝나 반환되는 곳이 0x40156D임을 알 수 있습니다.
그리고 알아서 RETURN을 계속 하다가 끝납니다. 저런, CheckMenuItem 이전에 시간 조절이 끝난 것 같습니다. 그러면 0x401790을 call하기 전에 뭔가 이미 일이 끝났다는 소리네요. 그런데 바로 위에 보면 되게 낯익은 값이 있습니다.
[ESI+50], 저만 익숙한가요? 바로 처음 이미지 로딩할 때 TimeGetTime 비교용으로 쓰였던 변수입니다.(3번 게시글을 참고하세요.) 그 당시에는 0x28과 비교해서 그런가보다 했는데, "느리게"로 했더니 0x32를 [ESI+50]에 넣습니다. 뭔가 얻어걸린 것 같지만 찾아냈습니다! 0x401561번지에서 0x32를 대입하고, 주위를 둘러보면 0x4015C1번지에서 0x28을 대입하고 0x4015DA번지에서 0x21을 대입하는 것을 확인할 수 있습니다.
그럼 이제 내가 택한 것에 따른 분기가 어떻게 일어나는지를 확인하겠습니다.
0x401534에서 EDI에 현재 택한 Item의 ID인 40004 40005 40006중 어느 하나의 값이 들어갑니다. 그리고 40001을 뺀 값을 EAX에 넣고, EAX가 0C보다 작으면 [EAX*4+401650]으로 jump합니다. Switch문의 형태이고 친절하게 왼쪽에 알아서 주석도 잘 달아줬네요. "느리게"는 40004(=0x9C44)이니 0x401555E로 넘어갑니다.
운좋게 게임 점수 부분도 한방에 해결이 가능해졌습니다. 게임 점수는 40009~40011의 값을 가지고 이는 0x9C49, 0x9C4A, 0x9C4B입니다. switch문을 타고 가보면 다시 GetMenu를 하는 함수 0x4017D0으로 넘어와지고 이 함수의 밑 부분을 확인하면 EDI에 기록된 ItemID의 값에 따라 EAX에 5, 0xA(10), 0xF(15)를 기록하는 것을 확인할 수 있습니다.
함수의 두 번째 인자로 EAX를 실어서 0x405000을 호출하고 0x405000을 확인하면 이를 넘겨받아 [ECX+1C](=0x47819DC)에 기록합니다.
이제 게임을 시작하고 나서 더 알아봐야하겠지만 아마 각자의 점수가 어느 변수에 들어가있고 0x47819DC에 기록된 값에 도달하는 플레이어가 생기면 경기를 종료하는 식으로 처리가 될 것으로 예상됩니다.
빠르게 부분의 값을 0x21에서 0x10으로 변경하자
아래 영상과 같이 정말 빨라졌네요. 흥겹습니다. 왼쪽이 정상적인 프로그램이고 오른쪽이 속도를 변경한 프로그램입니다. 따로 녹화는 안했지만 최대 점수 또한 비슷하게 조작할 수 있습니다.
'컴퓨터과학 > 리버싱' 카테고리의 다른 글
[피카츄배구 리버싱] 8 (0) | 2018.03.11 |
---|---|
[피카츄배구 리버싱] 7 (0) | 2018.03.11 |
[피카츄배구 리버싱] 6 (0) | 2018.03.11 |
[피카츄배구 리버싱] 4 (0) | 2018.03.10 |
[피카츄배구 리버싱] 3 (0) | 2018.03.10 |
[피카츄배구 리버싱] 2 (0) | 2018.03.10 |