사람들이 PHP 기반의 플래시 게임의 최고 점수 테이블을 해킹하는 것을 막는 가장 좋은 방법은 무엇입니까


212

점수 상한이 없으며 동작 등을 재생하여 서버에서 점수를 확인할 수있는 액션 게임에 대해 이야기하고 있습니다.

내가 정말로 필요한 것은 Flash / PHP에서 가능한 가장 강력한 암호화와 사람들이 내 Flash 파일이 아닌 다른 PHP 페이지를 호출하지 못하게하는 방법입니다. 과거에는 단일 점수를 여러 번 호출하고 체크섬 / 피보나치 시퀀스 등을 완료하고 Amayeta SWF Encrypt를 사용하여 SWF를 난독 처리하는 간단한 방법을 시도했지만 결국 해킹당했습니다.

- StackOverflow의 반응 덕분에 지금은 어도비에서 몇 가지 추가 정보를 발견했다 http://www.adobe.com/devnet/flashplayer/articles/secure_swf_apps_12.htmlhttps://github.com/mikechambers/as3corelib - 내가 생각 암호화에 사용할 수 있습니다. 그래도 CheatEngine을 해결할 수 있는지 확실하지 않습니다.

AS2와 AS3 모두에 대해 최상의 솔루션을 알고 있어야합니다.

주요 문제는 TamperData 및 LiveHTTP 헤더와 같은 것으로 보이지만 CheatEngine (Mark Webster 덕분에)과 같은 고급 해킹 도구가 있음을 알고 있습니다


당신은 점수 한도를 넣어해야합니다, 당신이 그것을 할 수없는 이유가 없다, 레벨 당, 전체적으로, 요법 ...
mpm

첫 번째 링크는 더 이상 사용할 수 없습니다
Mike

답변:


415

이것은 인터넷 게임 및 콘테스트의 고전적인 문제입니다. Flash 코드는 사용자와 함께 게임 점수를 결정합니다. 그러나 사용자는 신뢰할 수 없으며 Flash 코드는 사용자의 컴퓨터에서 실행됩니다. 당신은 SOL입니다. 공격자가 높은 점수를 얻지 못하도록하기 위해 할 수있는 일은 없습니다 :

  • 바이트 코드가 잘 문서화되어 있고 고급 언어 (Actionscript)를 설명하기 때문에 Flash는 생각보다 리버스 엔지니어링이 훨씬 쉽습니다. 플래시 게임을 게시 할 때 소스 코드를 게시하고 있습니다. 알고 있든 없든

  • 공격자는 Flash 인터프리터의 런타임 메모리를 제어하므로 프로그래밍 가능한 디버거를 사용하는 방법을 알고있는 사람은 언제든지 변수 (현재 점수 포함)를 변경하거나 프로그램 자체를 변경할 수 있습니다.

시스템에 대한 가장 간단한 공격은 프록시를 통해 게임의 HTTP 트래픽을 실행하고 점수를 많이 저장 한 후 더 높은 점수로 재생하는 것입니다.

예를 들어 게임 시작시 클라이언트에 암호화 된 토큰을 전송하는 등의 각 최고 점수 저장을 게임의 단일 인스턴스에 바인딩하여이 공격을 차단할 수 있습니다.

hex-encoding( AES(secret-key-stored-only-on-server, timestamp, user-id, random-number))

(세션 쿠키를 같은 효과로 사용할 수도 있습니다).

게임 코드는이 토큰을 높은 점수 저장과 함께 서버로 에코합니다. 그러나 공격자는 여전히 게임을 다시 시작하고 토큰을 얻은 다음 해당 토큰을 즉시 재생 된 최고 점수 저장에 붙여 넣을 수 있습니다.

따라서 다음으로 토큰 또는 세션 쿠키뿐만 아니라 높은 점수의 암호화 세션 키도 제공합니다. 이것은 128 비트 AES 키이며, 플래시 게임에 하드 코드 된 키로 자체 암호화됩니다.

hex-encoding( AES(key-hardcoded-in-flash-game, random-128-bit-key))

이제 게임에서 최고 점수를 올리기 전에 최고 점수 암호화 세션 키를 해독합니다. 이는 최고 점수 암호화 세션 키 암호화 키를 Flash 바이너리로 하드 코딩했기 때문에 가능합니다. 이 해독 된 키를 사용하여 최고 점수의 SHA1 해시와 함께 최고 점수를 암호화합니다.

hex-encoding( AES(random-128-bit-key-from-above, high-score, SHA1(high-score)))

서버의 PHP 코드는 토큰을 확인하여 요청이 유효한 게임 인스턴스에서 온 것인지 확인한 다음 암호화 된 최고 점수를 해독하여 최고 점수가 최고 점수의 SHA1과 일치하는지 확인합니다 (이 단계를 건너 뛰는 경우) , 해독은 단순히 임의의, 아마도 매우 높고 높은 점수를 생성합니다).

이제 공격자는 플래시 코드를 디 컴파일하고 AES 코드를 신속하게 찾아냅니다. AES 코드는 아픈 엄지 손가락처럼 튀어 나오지만 15 분 안에 메모리 검색 및 추적 프로그램으로 추적되지는 않습니다. 이 게임에 대한 내 점수는 666입니다. 메모리에서 666을 찾은 다음 해당 값에 해당하는 모든 작업을 포착하십시오. 세션 키를 사용하면 공격자가 플래시 코드를 실행할 필요조차 없습니다. 그녀는 게임 시작 토큰과 세션 키를 잡고 임의의 높은 점수를 다시 보낼 수 있습니다.

이제 대부분의 개발자가 포기하고 --- 다음 몇 가지 방법으로 공격자와 엉망이되는 몇 달을 포기합니다.

  • XOR 조작으로 AES 키 스크램블

  • 키 바이트 배열을 키를 계산하는 함수로 교체

  • 바이너리 전체에 가짜 키 암호화 및 높은 점수 게시를 흩뿌립니다.

이것은 대부분 시간 낭비입니다. 말할 것도없이 SSL도 도움이되지 않습니다. SSL은 두 SSL 엔드 포인트 중 하나가 악한 경우 보호 할 수 없습니다.

고득점 사기를 실제로 줄일 수있는 몇 가지 사항은 다음과 같습니다.

  • 게임을 플레이하려면 로그인이 필요하고, 로그인으로 세션 쿠키를 생성하고, 동일한 세션에서 여러 개의 미해결 게임을 실행하거나 동일한 사용자에 대해 여러 개의 동시 세션을 허용하지 마십시오.

  • 가장 짧은 실제 게임보다 오래 지속되지 않은 게임 세션에서 높은 점수를 거부합니다 (보다 정교한 접근 방식을 위해서는 평균 게임 지속 시간보다 2 표준 편차 미만으로 지속되는 게임 세션에 대해 "정리"높은 점수를보십시오). 서버 측 게임 시간을 추적하고 있는지 확인하십시오.

  • 한 번 또는 두 번만 게임을 한 로그인에서 높은 점수를 거부하거나 격리하여 공격자가 생성하는 각 로그인에 대해 합리적인 모양의 게임 플레이를 "종이 추적"해야합니다.

  • "하트 비트"는 게임 플레이 중 점수를 매기므로 서버는 한 게임 플레이 동안 평생 동안 점수가 증가하는 것을 볼 수 있습니다. 합리적인 점수 곡선을 따르지 않는 높은 점수를 거부합니다 (예 : 0에서 999999로 점프).

  • 게임 플레이 중 "스냅 샷"게임 상태 (예 : 탄약의 양, 레벨에서의 위치 등)는 나중에 기록 된 중간 점수와 조정할 수 있습니다. 시작하기 위해이 데이터에서 이상을 탐지 할 방법이 없어도됩니다. 당신은 그것을 모으기 만하면, 물고기가 비린 것처럼 보이면 돌아가서 분석 할 수 있습니다.

  • 보안 검사 중 하나에 실패한 사용자의 계정을 비활성화합니다 (예 : 유효성 검사에 실패한 암호화 된 최고 점수를 제출 함).

여기서는 높은 점수의 사기 만 저지한다는 사실을 기억하십시오. 없습니다 아무것도 당신이 경우에 방지하기 위해 할 수있는가. 게임에 돈이 있으면 누군가가 당신이 생각 해낸 시스템을 물리 칠 것입니다. 목표는 이 공격 을 막는 것이 아닙니다 . 게임을 정말 잘하고 치는 것보다 공격을 더 비싸게 만드는 것입니다.


23
나는 온라인 게임 커뮤니티를 만들었고 우리는 전체 득점 시스템을 설계하여 최고 득점자가 아닌 최고 10 번째 백분위 점수를 보상하고 훌륭하게 해결 했으므로 문제를 회피하는 것도 도움이됩니다!
grapefrukt

1
좋은! 간단히 말해서, 게임 서버에서 실행 되거나 최소한 서버에서 정상 상태 점검이 실행되지 않는 한 악용을 방지 할 수 없습니다. 멀티 플레이어 슈터와 동일한 문제 : 더 나은 조준을 위해 클라이언트를 수정하면 네트워크 프로토콜에서이를 방지 할 수 없습니다.
Kerrek SB 2014

3
또한 모든 사용자 작업을 기록하고 서버에서 재생하여 최고 점수를 확인 / 결정할 수 있다고 생각합니다.
I3ck

25

당신은 잘못된 질문을 할 수 있습니다. 사람들이 최고 점수를 올리는 데 사용하는 방법에 중점을 둔 것처럼 보이지만 특정 방법을 차단하는 것은 지금까지만 진행되었습니다. TamperData에 대한 경험이 없으므로 말할 수 없습니다.

당신이 물어봐야 할 질문은 "제출 된 점수가 유효하고 확실한지 어떻게 확인할 수 있습니까?" 구체적인 방법은 게임에 따라 다릅니다. 매우 간단한 퍼즐 게임의 경우 특정 시작 상태 및 이동 상태와 함께 점수를 넘겨 종료 상태로 만든 다음 동일한 이동을 사용하여 서버 쪽에서 게임을 다시 실행할 수 있습니다. 명시된 점수가 계산 된 점수와 동일한 지 확인하고 일치하는 경우에만 점수를 수락하십시오.


2
이것은 과거에 투표 시스템에 사용했던 기술입니다. 사람들이 부정 행위를하는 것을 막을 수있는 방법은 없지만, 자신의 행동을 기록하여 부정 행위가 있는지 확인할 수 있습니다. 투표 시스템에서는 타임 스탬프와 IP 주소를 저장했습니다. [계속]
Luke

1
그렇게하면 최소한 부정 행위의 패턴을보고 필요할 때 사람들을 실격시킬 수있었습니다. 우리는 그것을 여러 번 성공적으로 사용했습니다.
Luke

19

이 작업을 수행하는 쉬운 방법은 점수와 함께 최고 점수 값의 암호화 해시를 제공하는 것입니다. 예를 들어, HTTP GET을 통해 결과를 게시 할 때 : http://example.com/highscores.php?score=500&checksum=0a16df3dc0301a36a34f9065c3ff8095

이 체크섬을 계산할 때는 공유 비밀을 사용해야합니다. 이 비밀은 네트워크를 통해 전송되지 않아야하지만 PHP 백엔드와 플래시 프론트 엔드 내에서 하드 코딩되어야합니다. 위의 체크섬은 " secret " 문자열 앞에 " 500 "을 붙여 md5sum을 통해 실행 하여 만들어졌습니다 .

이 시스템은 사용자가 임의의 점수를 게시하는 것을 방지하지만 사용자가 이전에 계산 된 점수와 해시 조합을 다시 게시하는 "재생 공격"을 방지하지는 않습니다. 위의 예에서 점수 500은 항상 동일한 해시 문자열을 생성합니다. 해시 될 문자열에 추가 정보 (예 : 사용자 이름, 타임 스탬프 또는 IP 주소)를 통합하면 이러한 위험을 완화 할 수 있습니다. 이렇게해도 데이터가 재생되지는 않지만 한 번에 한 명의 사용자에게만 데이터 집합이 유효하게됩니다.

방지하기 위해 모든 발생에서 재생 공격을 시도 - 응답 시스템의 일부 유형은 다음과 같이 작성되어야 할 것이다 :

  1. 플래시 게임 ( "클라이언트")은 http://example.com/highscores.php 의 HTTP GET을 매개 변수없이 수행합니다 . 이 페이지는 무작위로 생성 된 솔트 값과 공유 비밀과 결합 된 해당 솔트 값의 암호화 해시 라는 두 가지 값을 반환합니다 . 이 솔트 값은 보류중인 쿼리의 로컬 데이터베이스에 저장해야하며 1 분 후에 "만료"될 수 있도록 타임 스탬프가 연결되어 있어야합니다.
  2. 플래시 게임은 솔트 값을 공유 비밀과 결합하고 해시를 계산하여 이것이 서버에서 제공 한 것과 일치하는지 확인합니다. 이 단계는 솔트 값이 실제로 서버에 의해 생성되었는지 확인하므로 사용자가 솔트 값을 변경하는 것을 방지하기 위해 필요합니다.
  3. 플래시 게임은 솔트 값을 공유 비밀, 높은 점수 값 및 기타 관련 정보 (닉네임, ip, 타임 스탬프)와 결합하고 해시를 계산합니다. 그런 다음 솔트 값, 높은 점수 및 기타 정보와 함께 HTTP GET 또는 POST를 통해이 정보를 PHP 백엔드로 다시 보냅니다.
  4. 서버는 클라이언트와 동일한 방식으로 수신 된 정보를 결합하고 해시를 계산하여 클라이언트가 제공 한 정보와 일치하는지 확인합니다. 그런 다음 보류중인 쿼리 목록에 나열된대로 솔트 값이 여전히 유효한지 확인합니다. 이 두 조건이 모두 해당되는 경우 최고 점수를 최고 점수 테이블에 기록하고 서명 된 "성공"메시지를 클라이언트에 반환합니다. 또한 보류중인 쿼리 목록에서 솔트 값을 제거합니다.

공유 비밀이 사용자가 액세스 할 수있는 경우 위의 기술 중 하나의 보안이 손상됩니다.

대안으로, 클라이언트가 HTTPS를 통해 서버와 통신하도록하고 클라이언트가 사용자가 액세스 할 수있는 특정 인증 기관이 서명 한 인증서 만 신뢰하도록 미리 구성하여 이러한 앞뒤를 피할 수 있습니다. .


11

나는 tpqf가 말한 것을 좋아하지만, 부정 행위가 발견 될 때 계정을 비활성화하는 대신 허니팟을 구현하여 로그인 할 때마다 해킹 된 점수를보고 트롤로 표시된 것으로 의심하지 않습니다. "phpBB MOD Troll"에 대한 Google을 사용하면 독창적 인 접근 방식이 나타납니다.


1
이러한 접근 방식의 문제점은 이러한 치트가 게시판 등에서 서로 자랑하기 때문에 실제로 막을 수는 없다는 것입니다.
Iain

7
동의하지 않습니다. 이것은 매우 영리한 접근법처럼 들립니다.
bzlm 2016 년

4

허용 된 답변에서 tqbf는 점수 변수에 대한 메모리 검색을 할 수 있다고 언급합니다 ( "내 점수는 666이므로 메모리에서 숫자 666을 찾으십시오").

이 문제를 해결할 방법이 있습니다. 여기에 수업이 있습니다 : http://divillysausages.com/blog/safenumber_and_safeint

기본적으로 점수를 저장할 객체가 있습니다. setter에서는 전달한 값에 임의의 숫자 (+ 및-)를 곱하고, getter에서는 저장된 값을 임의의 곱셈기로 나눠서 원래 값을 가져옵니다. 간단하지만 메모리 검색을 중지하는 데 도움이됩니다.

또한, 해킹에 대처할 수있는 여러 가지 방법에 대해 설명하는 PushButton 엔진 뒤에있는 일부 사람들의 비디오를 확인하십시오. http://zaa.tv/2010/12/the-art-of-hacking-flash- 게임 / . 그들은 수업의 배후에서 영감을 받았습니다.


4

나는 일종의 해결 방법을 만들었습니다 ... 점수가 증가하는 곳을주었습니다 (항상 +1 점수를 얻음). 먼저 임의의 숫자부터 계산하기 시작했습니다 (14라고 말하십시오). 점수를 표시 할 때 점수를 마이너스 14로 표시했습니다. 그래서 크래커가 예를 들어 20을 찾으면 찾을 수 없습니다 ( 메모리에 34가됩니다). 둘째, 다음 포인트가 무엇인지 알고 있기 때문에 ... 다음 포인트 무엇인지에 대한 해시를 만들기 위해 어도비 암호화 라이브러리를 사용했습니다 .. 점수를 증분해야 할 때 증분 점수의 해시가 해시와 같은지 확인합니다. 크래커가 메모리의 포인트를 변경 한 경우 해시는 동일하지 않습니다. 나는 서버 측 검증을 수행하고 게임과 PHP에서 다른 포인트를 얻었을 때 부정 행위가 관련되어 있음을 알고 있습니다. 다음은 내 코드 스 니펫입니다 (Adobe Crypto libraty MD5 클래스와 임의의 암호화 소금을 사용하고 있습니다. callPhp ()는 서버 측 유효성 검사입니다)

private function addPoint(event:Event = null):void{
            trace("expectedHash: " + expectedHash + "  || new hash: " + MD5.hash( Number(SCORES + POINT).toString() + expectedHashSalt) );
            if(expectedHash == MD5.hash( Number(SCORES + POINT).toString() + expectedHashSalt)){
                SCORES +=POINT;
                callPhp();
                expectedHash = MD5.hash( Number(SCORES + POINT).toString() + expectedHashSalt);
            } else {
                //trace("cheat engine usage");
            }
        }

이 기술 + SWF 난독 화를 사용하여 크래커를 중지 할 수있었습니다. 또한 점수를 서버 측에 보낼 때 자체의 작은 암호화 / 복호화 기능을 사용합니다. 이와 같은 것 (서버 측 코드는 포함되어 있지 않지만 알고리즘을보고 PHP로 작성할 수 있음) :

package  {

    import bassta.utils.Hash;

    public class ScoresEncoder {

        private static var ranChars:Array;
        private static var charsTable:Hash;

        public function ScoresEncoder() {

        }

        public static function init():void{

            ranChars = String("qwertyuiopasdfghjklzxcvbnm").split("")

            charsTable = new Hash({
                "0": "x",
                "1": "f",
                "2": "q",
                "3": "z",
                "4": "a",
                "5": "o",
                "6": "n",
                "7": "p",
                "8": "w",
                "9": "y"

            });

        }

        public static function encodeScore(_s:Number):String{

            var _fin:String = "";

            var scores:String = addLeadingZeros(_s);
            for(var i:uint = 0; i< scores.length; i++){
                //trace( scores.charAt(i) + " - > " + charsTable[ scores.charAt(i) ] );
                _fin += charsTable[ scores.charAt(i) ];
            }

            return _fin;

        }

        public static function decodeScore(_s:String):String{

            var _fin:String = "";

            var decoded:String = _s;

            for(var i:uint = 0; i< decoded.length; i++){
                //trace( decoded.charAt(i) + " - > "  + charsTable.getKey( decoded.charAt(i) ) );
                _fin += charsTable.getKey( decoded.charAt(i) );
            }

            return _fin;

        }

        public static function encodeScoreRand(_s:Number):String{
            var _fin:String = "";

            _fin += generateRandomChars(10) + encodeScore(_s) + generateRandomChars(3)

            return _fin;
        }

        public static function decodeScoreRand(_s:String):Number{

            var decodedString:String = _s;
            var decoded:Number;

            decodedString = decodedString.substring(10,13);         
            decodedString = decodeScore(decodedString);

            decoded = Number(decodedString);

            return decoded;
        }

        public static function generateRandomChars(_length:Number):String{

            var newRandChars:String = "";

            for(var i:uint = 0; i< _length; i++){
                newRandChars+= ranChars[ Math.ceil( Math.random()*ranChars.length-1 )];
            }

            return newRandChars;
        }

        private static function addLeadingZeros(_s:Number):String{

            var _fin:String;

            if(_s < 10 ){
                 _fin = "00" + _s.toString();
            }

            if(_s >= 10 && _s < 99 ) {
                 _fin = "0" + _s.toString();
            }

            if(_s >= 100 ) {
                _fin = _s.toString();
            }           

            return _fin;
        }


    }//end
}

그런 다음 다른 가짜 변수와 함께 변수를 보내면 길에서 잃어 버릴 수 있습니다 ... 작은 플래시 게임에는 많은 작업이지만 상이 관련된 곳에서는 욕심 많은 사람들이 있습니다. 도움이 필요하면 PM을 작성하십시오.

건배, 이코


3

알려진 (개인) 가역 키를 사용하여 암호화하는 것이 가장 간단한 방법입니다. 나는 모두 AS에 있지 않으므로 어떤 종류의 암호화 공급자가 있는지 잘 모르겠습니다.

그러나 게임 길이 (다시 암호화) 및 클릭 수와 같은 변수를 포함 할 수 있습니다.

이와 같은 모든 것은 리버스 엔지니어링 될 있으므로 사람들을 향기에서 던지기 위해 많은 정크 데이터를 던지는 것을 고려하십시오.

편집 : 일부 PHP 세션에서도 척킹 할 가치가 있습니다. 그들이 게임 시작을 클릭하면 세션을 시작하고 (이 게시물에 대한 의견에서 알 수 있듯이) 시간을 기록하십시오. 그들이 점수를 제출하면 실제로 오픈 게임을 받았으며 너무 빨리 또는 너무 큰 점수를 제출하지 않았 음을 확인할 수 있습니다.

스칼라를 운동하여 초당 최대 득점이 몇 분인지 알 수 있습니다.

이러한 것들 중 어느 것도 우회 할 수는 없지만 사람들이 그것을 볼 수있는 플래시에는없는 논리를 갖는 것이 도움이 될 것입니다.


이 방법을 따르는 사람은 시간도 포함해야하고 시간을 확인해야합니다. 그렇지 않으면 재생 공격에 취약합니다.
Tom Ritter

3

내 경험상 이것은 프로그래밍 문제보다는 사회 공학 문제로 가장 잘 접근합니다. 부정 행위를 불가능하게하는 데 초점을 맞추는 대신, 부정 행위에 대한 동기를 제거하여 지루하게 만드는 데 집중하십시오. 예를 들어, 주요 인센티브가 공개적으로 높은 점수를 얻는 경우 높은 점수가 표시 될 때 지연을 설정하면 사기꾼의 긍정적 피드백 루프를 제거하여 부정 행위를 크게 줄일 수 있습니다.


12
그러나 이는 실제 플레이어에 대한 즉각적인 높은 점수에 대한 긍정적 인 피드백을 제거하므로 게임 품질을 떨어 뜨립니다.
Chris Garrett

3

클라이언트가 반환하는 데이터는 신뢰할 수 없습니다. 서버 측에서 유효성 검사를 수행해야합니다. 저는 게임 개발자는 아니지만 비즈니스 소프트웨어를 만듭니다. 두 경우 모두 돈이 관련 될 수 있으며 사람들은 고객 측 난독 화 기술을 깰 것입니다.

데이터를 정기적으로 서버에 다시 보내고 유효성 검사를 수행 할 수 있습니다. 응용 프로그램이있는 곳에 있더라도 클라이언트 코드에 집중하지 마십시오.


2

최고 점수 시스템이 Flash 응용 프로그램이 네트워크를 통해 암호화되지 않은 / 서명되지 않은 최고 점수 데이터를 전송한다는 사실을 기반으로 할 때마다이를 가로 채서 조작 / 재생할 수 있습니다. 그 대답은 다음과 같습니다. 암호화 (적절하게!) 또는 암호로 최고 점수 데이터에 서명합니다. 최소한 SWF 파일에서 비밀 키를 추출해야하기 때문에 최고 점수 시스템을 크랙하기가 더 어려워집니다. 많은 사람들이 아마 거기에서 포기할 것입니다. 반면에, 열쇠를 뽑아 어딘가에 게시하는 유일한 사람입니다.

실제 솔루션에는 Flash 응용 프로그램과 최고 점수 데이터베이스 간의 더 많은 통신이 포함되므로 후자는 주어진 점수가 다소 현실적인지 확인할 수 있습니다. 어떤 종류의 게임에 따라 복잡 할 수 있습니다.


2

SWF를 쉽게 디 컴파일 할 수 있기 때문에 완전히 해킹 할 수있는 방법이 없으며, 숙련 된 개발자 해커가 코드를 추적하여 사용중인 암호화 된 시스템을 우회하는 방법을 알아낼 수 있습니다.

TamperData와 같은 간단한 도구를 사용하여 아이들의 부정 행위를 막으려면 시작시 SWF에 전달하는 암호화 키를 생성 할 수 있습니다. 그런 다음 http://code.google.com/p/as3crypto/ 와 같은 것을 사용하여 PHP 코드로 다시 전달하기 전에 높은 점수를 암호화하십시오. 그런 다음 데이터베이스에 저장하기 전에 서버 쪽에서 암호를 해독하십시오.


2

"클라이언트 트러스트"문제에 대해 이야기하고 있습니다. 클라이언트 (이 현금으로 브라우저에서 실행되는 SWF)가 설계된 작업을 수행하고 있기 때문입니다. 높은 점수를 저장하십시오.

문제는 임의의 HTTP 요청이 아니라 "동영상 저장"요청이 플래시 무비에서 오는지 확인하려는 것입니다. 이에 대한 가능한 해결책은 서버가 생성 한 토큰을 요청시 ( flasm 사용 ) 높은 점수를 저장하기 위해 요청과 함께 SWF에 인코딩하는 것 입니다. 서버가 해당 점수를 저장하면 토큰이 만료되어 더 이상 요청에 사용할 수 없습니다.

이것의 단점은 사용자가 플래시 무비를로드 할 때마다 하나의 높은 점수 만 제출할 수 있다는 것입니다. 새 스코어를 다시 재생하려면 SWF를 새로 고치거나 다시로드해야합니다.


2

나는 보통 게임 세션의 "유령 데이터"를 최고 점수 항목과 함께 포함합니다. 레이싱 게임을하는 경우 리플레이 데이터를 포함시킵니다. 종종 재생 기능 또는 고스트 레이싱 기능 (마지막 레이스에 대한 재생 또는 리더 보드의 친구 # 14의 유령에 대한 재생)에 대한 재생 데이터가 이미 있습니다.

이를 확인하는 것은 매우 수동적 인 노동이지만, 콘테스트에서 상위 10 개 항목이 합법적인지 확인하는 것이 목표라면 다른 사람들이 이미 지적한 보안 조치의 무기고에 유용한 추가 기능이 될 수 있습니다.

다른 사람을 보지 않고 최고 점수를 온라인으로 유지하는 것이 목표라면, 그다지 큰 도움이되지는 않을 것입니다.


2

인기있는 새로운 아케이드 모드는 플래시에서 PHP로 데이터를 보내고 플래시로 다시로드하거나 다시로드하는 것입니다. 이를 통해 데이터를 비교하고 포스트 데이터 / 암호 해독 해킹 등을 우회하려는 모든 작업을 수행 할 수 있습니다. 이를 수행하는 한 가지 방법은 php에서 2 개의 무작위 값을 플래시에 할당하고 (실시간 플래시 데이터 그래버를 실행하더라도 잡을 수 없거나 볼 수 없음) 수학 공식을 사용하여 임의의 값으로 점수를 추가 한 다음이를 사용하여 확인하는 것입니다. 마지막에 PHP로 갈 때 점수가 일치하는지 확인하기 위해 그것을 뒤집는 동일한 공식. 이러한 임의의 값은 거래가 발생하는 시간과 거래가 발생한 경우에도 표시되지 않습니다.

당신이 나에게 묻는다면 이것은 꽤 좋은 해결책처럼 보입니다. 아무도이 방법을 사용하는 데 문제가 있습니까? 아니면 가능한 방법?


Wireshark. Wireshark는 항상 구멍입니다.
aehiilrs

그래, 필자는이 정확한 방법을 시도했다 ... 글쎄 ... 어떻게 든 합법적 인 사용자가 사기꾼으로 기록되고있어 (기능은 내 컴퓨터에서 항상 작동하지만 다른 컴퓨터에서는 작동하지 않음) ... 그래서 나는 단지 부정 행위 허용 ... 나는 위의 확인을 통과하지 않는 사람들을 기록 & 나는 정말 높은 점수를 가진 사람들을 기록하고 수동으로 그들을 학대 ... 점수를 * * -1 : P 그들은 보통 농담을 잘합니다.
Sigtran

1
"이 작업을 수행하는 한 가지 방법은 php에서 2 개의 무작위 값을 플래시에 할당하는 것입니다 (실시간 플래시 데이터 그래버를 실행하더라도 잡을 수 없거나 볼 수 없습니다)"-PHP에서 값을 전달할 수있는 방법이 있습니까? 방화범 또는 다른 도구로 모니터링하지 않고 플래시?
mkto

2

게임에서 추가 할 점수를 등록 할 때마다 RegisterScore (score)와 같은 함수를 호출 한 다음 인코딩하고 패키지화하여 PHP 스크립트에 문자열로 보내는 것이 가장 간단한 방법이라고 생각합니다. PHP 스크립트는 올바르게 디코딩하는 방법을 알고 있습니다. 점수를 강요하면 압축 해제 오류가 발생하므로 PHP 스크립트에 대한 모든 호출을 중지합니다.


2

서버 측에서 모든 게임 로직을 유지하는 것만 가능하며, 이는 사용자에 대한 지식없이 내부적으로 점수를 저장합니다. 경제적이고 과학적인 이유로 인류는이 이론을 턴제를 제외한 모든 게임 유형에 적용 할 수 없습니다. 예를 들어 물리를 서버 측에 유지하는 것은 계산 비용이 많이 들고 손의 속도로 반응하기가 어렵습니다. 심지어 체스를하는 동안 누구나 AI 체스 게임 플레이를 상대와 일치시킬 수 있습니다. 따라서 더 나은 멀티 플레이어 게임 에는 주문형 창의성이 포함되어야합니다.


1

실제로 원하는 것을 달성하는 것은 불가능합니다. Flash 앱의 내부는 항상 부분적으로 액세스 할 수 있습니다. 특히 CheatEngine 과 같은 것을 사용하는 방법을 알고있을 때 웹 사이트와 브라우저 <-> 서버 통신의 보안 수준에 관계없이 여전히 극복하기가 비교적 간단합니다.


1

AMFPHP 를 통해 백엔드와 통신하는 것이 좋습니다 . 적어도 게으른 사람들은 브라우저 콘솔을 통해 결과를 푸시하려고 시도하지 않아야합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.