[Dreamhack] Fly me to the moon
https://dreamhack.io/wargame/challenges/324
[wargame.kr] fly me to the moon
Description javascript game. can you clear with bypass prevent cheating system?
dreamhack.io
서버 코드가 따로 주어지지 않은 문제다. 게임 사이트인가?
웹 사이트에 접속해보자.
갤러그인가? 한번 실행해보자.
시작하자마자 바로 죽었다. 점수를 31337점을 따야 한다고 나온다.
물론 게임을 주구장창해서 31337점을 얻고 플래그를 얻어내는 방법도 있겠지만, 개발자 도구 콘솔을 이용해서 점수를 조작한 뒤 플래그를 얻어볼 생각이다.
Do cheating. If you can
왠지 킹받는 문구다.
-> VM7:1 이 코드를 살펴보자
웹 사이트의 자바스크립트 코드가 보인다.
여기서 중요한 코드는 뭐가 있는지 살펴보자.
updateTunnel 부분을 보자.
해당 함수는
- 배경 및 터널 상태 업데이트 (bg_val 값 조정, 벽 위치 갱신)
- 플레이어의 위치 업데이트 (ship_x의 위치 조정)
- 점수 업데이트 (BTunnelGame.BincScore() 호출로 점수 증가)
- 종료 조건 검사 (killPlayer() 호출)
- 점수 및 상태 업데이트 결과를 UI에 반영
등의 기능을 하고 있는데, 게임을 조작하다보면 시간이 흐를수록 자동으로 점수가 올라가는 것을 발견할 수 있다.
점수 업뎃 부분으로 가 보자
BTunnelGame.BinScore() 함수는 점수 변경에 관여하는 핵심 함수로, c_s의 값이 20이 넘을 때마다(즉 타이머 값이 20이 넘을 때마다) 해당 함수를 호출해서 점수를 증가시키고 있다. 이 함수에 bp를 걸고 게임을 실행시켜보자.
Exploit
이 부분을 살펴보자.
var _0x32bb = ["\x6B\x69\x6C\x6C\x50\x6C\x61\x79\x65\x72", "\x63\x68\x65\x63\x6B\x4C\x69\x66\x65", "\x67\x65\x74\x53\x63\x6F\x72\x65", "\x42\x69\x6E\x63\x53\x63\x6F\x72\x65", "\x73\x68\x72\x69\x6E\x6B\x54\x75\x6E\x6E\x65\x6C", "\x77\x69\x64\x74\x68\x54\x75\x6E\x6E\x65\x6C", "\x6F\x62\x6A\x65\x63\x74", "\x44\x6F\x20\x63\x68\x65\x61\x74\x69\x6E\x67\x2C\x20\x69\x66\x20\x79\x6F\x75\x20\x63\x61\x6E", "\x77\x61\x72\x6E", "\x6F\x66\x66\x73\x65\x74\x4C\x65\x66\x74", "\x74\x75\x6E\x6E\x65\x6C", "\x67\x65\x74\x45\x6C\x65\x6D\x65\x6E\x74\x42\x79\x49\x64", "\x74\x6F\x70", "", "\x70\x78", "\x63\x73\x73", "\x64\x69\x73\x70\x6C\x61\x79", "\x62\x6C\x6F\x63\x6B", "\x65\x61\x63\x68", "\x69\x6D\x67\x2E\x6C\x65\x66\x74\x5F\x77\x61\x6C\x6C", "\x69\x6D\x67\x2E\x72\x69\x67\x68\x74\x5F\x77\x61\x6C\x6C", "\x23\x68\x69\x67\x68\x5F\x73\x63\x6F\x72\x65\x73", "\x72\x65\x6D\x6F\x76\x65", "\x74\x61\x62\x6C\x65", "\x6E\x6F\x6E\x65", "\x64\x69\x76\x23\x73\x63\x6F\x72\x65\x5F\x74\x61\x62\x6C\x65", "\x63\x6C\x69\x63\x6B", "\x74\x65\x78\x74", "\x73\x70\x61\x6E\x23\x73\x63\x6F\x72\x65", "\x6C\x65\x66\x74", "\x69\x6D\x67\x23\x73\x68\x69\x70", "\x73\x6C\x6F\x77", "\x66\x61\x64\x65\x49\x6E", "\x62\x61\x63\x6B\x67\x72\x6F\x75\x6E\x64\x2D\x70\x6F\x73\x69\x74\x69\x6F\x6E", "\x35\x30\x25\x20", "\x64\x69\x76\x23\x74\x75\x6E\x6E\x65\x6C", "\x72\x61\x6E\x64\x6F\x6D", "\x66\x6C\x6F\x6F\x72", "\x75\x70\x64\x61\x74\x65\x54\x75\x6E\x6E\x65\x6C\x28\x29", "\x66\x61\x64\x65\x4F\x75\x74", "\x50\x4F\x53\x54", "\x68\x69\x67\x68\x2D\x73\x63\x6F\x72\x65\x73\x2E\x70\x68\x70", "\x74\x6F\x6B\x65\x6E\x3D", "\x26\x73\x63\x6F\x72\x65\x3D", "\x61\x6A\x61\x78", "\x68\x74\x6D\x6C", "\x70\x23\x77\x65\x6C\x63\x6F\x6D\x65", "\x75\x70\x64\x61\x74\x65\x54\x6F\x6B\x65\x6E\x28\x29", "\x74\x68\x78\x2C\x20\x43\x68\x72\x69\x73\x74\x69\x61\x6E\x20\x4D\x6F\x6E\x74\x6F\x79\x61", "\x6D\x6F\x75\x73\x65\x6F\x76\x65\x72", "\x23\x63\x68\x72\x69\x73\x74\x69\x61\x6E", "\x6D\x6F\x75\x73\x65\x6F\x75\x74", "\x72\x65\x61\x64\x79", "\x43\x68\x72\x69\x73\x74\x69\x61\x6E\x20\x4D\x6F\x6E\x74\x6F\x79\x61", "\x70\x61\x67\x65\x58", "\x6D\x6F\x75\x73\x65\x6D\x6F\x76\x65", "\x74\x6F\x6B\x65\x6E\x2E\x70\x68\x70", "\x67\x65\x74"];
난독화가 되어있다.
BinScore() 함수 아래에 해당 배열의 두번째 부분을 불러내는 부분이 있는데, 이 부분을 복호화하면,
\x67\x65\x74\x53\x63\x6F\x72\x65
아스키코드 -> 문자로 변환
위의 결과로 'getScore'라는 문자열이 나온다.
즉 아래와 같은 코드는
BTunnelGame[_0x32bb[2]]();
BTunnelGame.getScore();로 해석된다.
의미만 봐서 알듯이, 점수 획득과 관련된 부분으로 생각되어진다.
해당 메소드를 재정의(점수 = 31337로 정의)해보자.
BTunnelGame.getScore = function() {
return 31337;
};
게임을 실행시켜보자. 아까 bp를 걸어놓은 부분에 중간에 멈춘 것을 확인할 수 있다.
콘솔에 위 코드를 입력하고 다시 실행시켜보자.
명심해야 할 건 한번 더 bp에 걸린 후 다시 실행해야 플래그가 출력된다. 안 그러면 cheating에 걸린다...
플래그 출력