[피카츄배구 리버싱] 7

sub_403DD0은 아래와 같습니다.



굉장히 깁니다. 그런데 일단 저희는 이 함수가 무엇을 리턴하는지를 알고 싶습니다. 보면 [ESP+2C]를 EEAX에 넣는데, [ESP+2C]는 sub_402DC0의 리턴값입니다. 중간의 행위들이 무엇인지 잘 모르겠다만 일단 리턴값만 알아봅시다. 이젠 sub_402DC0 안으로 들어가겠습니다.



정말 보기 싫게 생겼네요. IDA로 봅시다.


v9+v21가 252 이하이면 0을 반환하고(즉 공이 바닥에 닿지 않은것이고) 252보다 크면 1을 반환합니다.(공이 바닥에 닿은 것입니다.) 뭔가 *(this+56), *(this+72)를 계속 참조를 하는데 이 값들이 뭔지 도대체 감이 안옵니다. this가 구조체인가 싶기도 하고, 굉장히 답답하네요. 일단 저 값들이 대체 뭐하는 값인지를 알아야 진행이 될 것 같아서 계속 진행을 해가면서 값이 어떻게 바뀌는지 확인했습니다.



ESI의 값은 0x45961E0이니 *(this+56)은 0x4596218, *(this+72)는 0x4596228이 되겠습니다. 공이 왼쪽 끝에서 아래로 자유낙하하는 상황에서 전반적인 값 변화를 보면



살펴보면 0x4596210(this+48)~0x4596244(this+100)까지의 값이 계속 바뀝니다. 매 프레임마다 변화하는 거라면 공과 캐릭터의 위치 / 속도일 것 같아서 2P로 캐릭터는 고정시켜두고 공을 움직여보고 뭐 온갖 삽질을 해서 대충 이정도를 파악했습니다.

0x4596220~0x4596234는 명확하게 뭔지 잘 모르겠는데, 일단 관찰해본 결과 피카츄와 공이 충돌하기 전까지는 아무런 변화가 없다가 충돌을 하면 enter를 동반한 충돌의 경우 0x4596228, 0x459622C가 프레임마다 일정한 값이 증가하거나 빼집니다. 0x459622C는 2씩 빼지기만 하고, 0에 도달하면 더이상 변화하지 않지만 0x4596228은 마치 mod 연산마냥 0x32를 주기로 계속 돕니다. 0x4596230, 0x4596234는 피카츄가 스파이크를 날릴 때만 값이 바뀝니다. 값이 바뀐 후에는 다음 스파이크때까지 고정됩니다. 다만 만약 공이 바닥에 닿으면 0x128, 0x110이라는 값으로 변합니다. 뭔가 느낌상 스파이크를 날린 위치인 것 같습니다.



왜냐하면 이렇게 딱 스파이크를 날린 상황에서 0x4596230에 0x4596238의 값이, 0x4396234에 0x4596240의 값이 들어갔기 때문입니다.
그리고 충돌이 발생하면 스파이크던 아니던 무조건 0x4596220의 값이 변합니다. 딱 충돌할 때에만 바뀝니다. 그리고 0x4596224의 값은 0x0~0x4에서 굉장히 의미없게 막 바뀝니다. 그런데 뭔가 공의 속도가 빠를땐 자주 바뀌고 느릴땐 천천히 바뀝니다.
지금까지 알아낸 성질로 다시 한번 각 값들이 뭘 의미하는지 보면 아래와 같습니다.
여전히 오리무중인게 몇 개 있긴 한데 그래도 그나마 나아진 것 같습니다.


이제 이걸 가지고 코드를 보니 갑자기 깨달음을 얻었습니다.
맨 처음에 v9 + v12가 252이하이면 0, 252 이상이면 1이라고 했는데 v9는 this+52, 즉 공 y의 위치이고 v12는 this+60, 공 y의 속력이었습니다. 즉 다음 공의 위치가 252보다 커지게 되면 땅과 충돌했다고 판단하는 것이었습니다. 그 외의 잡다한 코드는 이 구조체 내의 변수들의 값들을 조정하는 코드입니다. 비록 일부는 뭐할때 쓰이는건지 파악을 못하긴 했지만요. 이 부분을 건드리면 공의 속력을 조정해서 조금 더 게임을 익스트림하게 만들 수도 있고 뭐 할 수 있는게 많겠지만 일단은 땅과 충돌해도 게임이 끝나지 않게 바꿔보겠습니다.

i) 이 함수의 결과를 가지고 처리하는 부분의 JMP문을 손대도 될 것이고
ii) 이 함수의 리턴값을 무조건 0으로 만들어도 될 것이고
iii) 이 함수에서 v9+v12가 252이하인지 체크하는 부분에서 252보다 훨씬 더 큰 값으로 둬도 될 것입니다. 다만 이 때 공이 저 바닥으로 꺼지지 않을까 걱정이 되는데 바닥에도 충돌 판정이 있는 것 같아서 일단 한번 바꿔보겠습니다.

아래와 같이 v9+v12가 252보다 작은지 체크하지말고 0xFFFF보다 작은지 체크하도록 했더니


아래 gif과 같이 망해버렸습니다. 아마 252보다 커졌을 때 들어가는 루틴속에 공의 방향을 위쪽으로 바꾸는 루틴도 같이 있나봅니다.



그러면 다음 방법으로 아래와 같이 이제 MOV EAX, 1을 MOV EAX, 0으로 바꿔 252보다 커졌을 때 들어가는 루틴으로 진입하되 리턴값이 0이 되도록 해보니





성공했습니다! 마치 연습모드 같네요.

이게 되면 당연히 이 함수를 call하는 다른 함수에서 jmp문 가지고 장난치는 짓도 당연히 될 것입니다. 이제 다음 게시글에서는 사용자의 키 입력과 관계된 부분을 살펴보고자 합니다. 마음대로 될지는 모르겠지만요.



'컴퓨터과학 > 리버싱' 카테고리의 다른 글

[피카츄배구 리버싱] 최종  (8) 2018.03.11
[피카츄배구 리버싱] 8  (0) 2018.03.11
[피카츄배구 리버싱] 6  (0) 2018.03.11
[피카츄배구 리버싱] 5  (0) 2018.03.11
[피카츄배구 리버싱] 4  (0) 2018.03.10
[피카츄배구 리버싱] 3  (0) 2018.03.10
  Comments