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

StackOverflow https://stackoverflow.com/questions/73947

문제

나는 점수 상한선이 없고 동작을 다시 실행하여 서버에서 점수를 확인할 방법이 없는 액션 게임에 대해 이야기하고 있습니다.

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

StackOverflow 응답 덕분에 이제 Adobe에서 더 많은 정보를 발견했습니다. http://www.adobe.com/devnet/flashplayer/articles/secure_swf_apps_12.html 그리고 https://github.com/mikechambers/as3corelib - 암호화에 사용할 수 있을 것 같아요.그래도 이것이 CheatEngine을 둘러볼 수 있을지 확신할 수 없습니다.

AS2와 AS3가 서로 다른 경우 둘 다에 대한 최상의 솔루션을 알아야 합니다.

주요 문제는 TamperData 및 LiveHTTP 헤더와 같은 것 같지만 CheatEngine과 같은 고급 해킹 도구도 있다는 것을 알고 있습니다(Mark Webster에게 감사드립니다).

도움이 되었습니까?

해결책

이것은 인터넷 게임과 콘테스트의 전형적인 문제입니다.Flash 코드는 사용자와 협력하여 게임 점수를 결정합니다.그러나 사용자는 신뢰할 수 없으며 Flash 코드는 사용자의 컴퓨터에서 실행됩니다.당신은 SOL입니다.공격자가 높은 점수를 위조하는 것을 방지하기 위해 할 수 있는 일은 없습니다.

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

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

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

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

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

(동일한 효과를 위해 세션 쿠키를 사용할 수도 있습니다.)

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

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

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 코드를 신속하게 찾습니다. 이 코드는 눈에 띄게 튀어나오지만, 그렇지 않더라도 메모리 검색 및 추적 프로그램을 사용하여 15분 안에 추적할 수 있습니다("나는 알고 있습니다). 이 게임의 내 점수는 666이므로 메모리에서 666을 찾은 다음 해당 값에 닿는 모든 연산을 잡아보겠습니다. --- 아 보세요, 높은 점수의 암호화 코드입니다!").세션 키를 사용하면 공격자는 플래시 코드를 실행할 필요조차 없습니다.그녀는 게임 시작 토큰과 세션 키를 잡고 임의의 높은 점수를 다시 보낼 수 있습니다.

이제 대부분의 개발자가 포기하는 지점에 도달했습니다. --- 다음과 같이 몇 달 동안 공격자와 장난을 치는 데 시간이 걸릴지 여부는 다음과 같습니다.

  • XOR 연산으로 AES 키 스크램블링

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

  • 바이너리 전체에 가짜 키 암호화와 높은 점수 게시를 분산시킵니다.

이것은 대부분 시간 낭비입니다.말할 필요도 없이 SSL도 도움이 되지 않습니다.두 개의 SSL 끝점 중 하나가 악의적인 경우 SSL은 사용자를 보호할 수 없습니다.

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

  • 게임을 플레이하려면 로그인이 필요하고, 로그인 시 세션 쿠키가 생성되며, 동일한 세션에서 여러 개의 미해결 게임 실행 또는 동일한 사용자에 대한 여러 개의 동시 세션이 허용되지 않습니다.

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

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

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

  • 게임 플레이 중 "스냅샷" 게임 상태(예: 탄약 양, 레벨 내 위치 등). 나중에 기록된 중간 점수와 대조하여 조정할 수 있습니다.처음부터 이 데이터에서 변칙을 감지할 방법이 필요하지 않습니다.그냥 수집하면 되고, 문제가 있으면 돌아가서 분석할 수 있습니다.

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

여기서는 높은 점수의 사기를 막는 것뿐이라는 점을 기억하십시오.있다 아무것도 아님 만약을 방지하기 위해 할 수 있습니다.게임에 돈이 걸려 있다면 누군가가 당신이 만든 시스템을 무너뜨릴 것입니다.목적은 그렇지 않다. 멈추다 이 공격;단지 게임을 정말 잘하고 이기는 것보다 공격 비용을 더 비싸게 만드는 것입니다.

다른 팁

당신은 잘못된 질문을 하고 있을 수도 있습니다.당신은 사람들이 높은 점수 목록에 오르기 위해 사용하는 방법에 초점을 맞춘 것처럼 보이지만 특정 방법을 차단하는 것은 지금까지만 가능합니다.나는 TamperData에 대한 경험이 없기 때문에 이에 대해 말할 수 없습니다.

당신이 물어봐야 할 질문은 다음과 같습니다"제출 된 점수가 유효하고 정통인지 어떻게 확인할 수 있습니까?" 이를 수행하는 구체적인 방법은 게임 의존적입니다.매우 간단한 퍼즐 게임의 경우 특정 시작 상태 및 종료 상태를 초래한 일련의 동작과 함께 점수를 보낸 다음 동일한 동작을 사용하여 서버 측에서 게임을 다시 실행할 수 있습니다.명시된 점수가 계산된 점수와 동일한지 확인하고 일치하는 경우에만 점수를 수락합니다.

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

이 체크섬을 계산할 때 공유 비밀을 사용해야 합니다.이 비밀은 네트워크를 통해 전송되어서는 안 되며, PHP 백엔드와 플래시 프런트엔드 모두에 하드 코딩되어야 합니다.위의 체크섬은 "라는 문자열을 앞에 추가하여 생성되었습니다.비밀" 점수에 "500"를 입력하고 md5sum을 통해 실행합니다.

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

방지하기 위해 어느 재생 공격이 발생하지 않도록 하려면 다음과 같은 일부 유형의 시도-응답 시스템을 만들어야 합니다.

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

사용자가 공유 비밀에 액세스할 수 있는 경우 위 기술의 보안이 손상된다는 점을 명심하세요.

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

나는 tpqf의 말을 좋아하지만 부정 행위가 발견되었을 때 계정을 비활성화하는 대신 허니팟을 구현하여 로그인할 때마다 해킹된 점수를 보고 트롤로 표시되었다는 의심을 결코 하지 않도록 하십시오.Google에서 "phpBB MOD Troll"을 검색하면 독창적인 접근 방식을 볼 수 있습니다.

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

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

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

또한 해킹에 맞서 싸울 수 있는 다양한 방법에 대해 이야기하는 PushButton 엔진 뒤에 있는 일부 사람들의 비디오를 확인하십시오. http://zaa.tv/2010/12/the-art-of-hacking-flash-games/.그들은 수업 뒤에 영감을 주었습니다.

나는 일종의 해결 방법을 만들었습니다 ...나는 점수가 증가하는 곳을 가졌습니다 (당신은 항상 +1 점수를 얻습니다).먼저 무작위 숫자(예: 14 )부터 세기 시작했고 점수를 표시할 때 점수 var 빼기 14만 표시했습니다.이는 크래커가 예를 들어 20을 찾고 있다면 그것을 찾지 못할 것이기 때문입니다(메모리에는 34가 있을 것입니다).둘째, 다음 요점이 무엇인지 알고 있기 때문에 ...나는 다음 포인트의 해시를 생성하기 위해 Adobe 암호화 라이브러리를 사용했습니다. 해야한다.점수를 증가시켜야 할 때, 증가된 점수의 해시가 해시와 같은지 확인합니다.크래커가 메모리의 포인트를 변경한 경우 해시는 동일하지 않습니다.서버측 검증을 수행하고 게임과 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을 보내주세요.

건배, 이코

알려진(개인) 가역 키를 사용하여 암호화하는 것이 가장 간단한 방법입니다.저는 AS에 전념하지 않아서 어떤 종류의 암호화 제공업체가 있는지 잘 모르겠습니다.

하지만 게임 길이(암호화됨) 및 클릭 횟수와 같은 변수를 포함할 수 있습니다.

이런 것들이 다 ~할 수 있다 역엔지니어링이 필요하므로 사람들이 냄새를 맡지 못하도록 많은 정크 데이터를 던지는 것을 고려하십시오.

편집하다:일부 PHP 세션에서도 시도해 볼 가치가 있을 수 있습니다.게임 시작을 클릭하면 세션을 시작하고 (이 게시물의 댓글에서 알 수 있듯이) 시간을 기록합니다.그들이 점수를 제출할 때 실제로 공개 게임이 있고 점수를 너무 이르거나 너무 크게 제출하지 않았는지 확인할 수 있습니다.

플레이의 초당/분당 최대 점수가 무엇인지 확인하려면 스칼라를 계산해 볼 가치가 있습니다.

이들 중 어느 것도 피할 수 없는 것은 아니지만 사람들이 볼 수 있는 플래시에 없는 논리를 갖는 것이 도움이 될 것입니다.

내 경험에 따르면 이는 프로그래밍 문제보다는 사회 공학 문제로 접근하는 것이 가장 좋습니다.부정 행위를 불가능하게 만드는 데 집중하기보다는 부정 행위에 대한 인센티브를 제거하여 지루하게 만드는 데 집중하십시오.예를 들어 주요 인센티브가 공개적으로 높은 점수를 얻는 것이라면 높은 점수가 표시되는 시점을 지연시키는 것만으로도 부정 행위자에 대한 긍정적인 피드백 루프를 제거하여 부정 행위를 크게 줄일 수 있습니다.

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

주기적으로 데이터를 서버로 다시 보내고 유효성 검사를 수행할 수도 있습니다.애플리케이션이 클라이언트 코드에 있는 경우에도 클라이언트 코드에 집중하지 마세요.

귀하의 최고 점수 시스템은 Flash 응용 프로그램이 네트워크를 통해 암호화되지 않은/서명되지 않은 최고 점수 데이터를 전송한다는 사실을 기반으로 할 때마다 해당 데이터가 가로채어 조작/재생될 수 있습니다.그 대답은 다음과 같습니다.최고 점수 데이터를 암호화(적당하게!)하거나 암호화 방식으로 서명합니다.이것은 적어도 사람들이 SWF 파일에서 비밀 키를 추출해야 하기 때문에 최고 점수 시스템을 해독하는 것을 더 어렵게 만듭니다.아마 많은 사람들이 바로 포기할 것입니다.반면에 키를 추출하여 어딘가에 게시하는 데 필요한 것은 한 사람뿐입니다.

실제 솔루션에는 Flash 응용 프로그램과 최고 점수 데이터베이스 간의 더 많은 통신이 필요하므로 후자는 주어진 점수가 어느 정도 현실적인지 확인할 수 있습니다.이것은 아마도 어떤 종류의 게임을 가지고 있는지에 따라 복잡할 것입니다.

SWF를 디컴파일하는 것은 쉽고 숙련된 개발자 해커가 코드를 추적하여 사용할 수 있는 암호화된 시스템을 우회하는 방법을 알아낼 수 있으므로 완전히 해킹할 수 없게 만드는 방법은 없습니다.

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

당신은 "클라이언트 신뢰" 문제에 대해 이야기하고 있습니다.클라이언트(브라우저에서 실행되는 SWF)가 원래 설계된 작업을 수행하고 있기 때문입니다.높은 점수를 저장하세요.

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

단점은 사용자가 플래시 영화 로드당 하나의 높은 점수만 제출할 수 있다는 것입니다. 새로운 점수를 위해 다시 재생할 수 있으려면 SWF를 새로 고치거나 다시 로드해야 합니다.

나는 보통 최고 점수 항목과 함께 게임 세션의 "고스트 데이터"를 포함합니다.따라서 레이싱 게임을 만드는 경우 리플레이 데이터를 포함합니다.리플레이 기능이나 고스트 레이싱 기능(마지막 레이스를 상대로 플레이하거나 리더보드에서 #14 친구의 고스트를 상대로 플레이)을 위한 리플레이 데이터가 이미 있는 경우가 많습니다.

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

아무도 볼 필요 없이 최고 점수 목록을 시간이 끝날 때까지 온라인에 유지하는 것이 목표라면 별 효과가 없을 것입니다.

새로운 인기 아케이드 모드가 수행하는 방식은 플래시에서 PHP로, 다시 플래시로(또는 다시 로드) 데이터를 보낸 다음 다시 PHP로 보내는 것입니다.이를 통해 데이터를 비교하고 사후 데이터/암호 해독 해킹 등을 우회하고 싶은 모든 작업을 수행할 수 있습니다.이를 수행하는 한 가지 방법은 PHP에서 플래시로 2개의 무작위 값을 할당하고(실시간 플래시 데이터 그래버를 실행하더라도 가져오거나 볼 수 없음) 수학 공식을 사용하여 무작위 값으로 점수를 추가한 다음 다음을 사용하여 확인하는 것입니다. 마지막에 PHP로 갈 때 점수가 일치하는지 확인하기 위해 동일한 공식을 사용합니다.이러한 무작위 값은 결코 표시되지 않으며 거래가 발생하는 시간도 표시하며, 몇 초 이상이면 부정행위로 플래그를 지정합니다. 왜냐하면 무작위 값을 알아내거나 실행하기 위해 전송을 중지했다고 가정하기 때문입니다. 점수 값과 비교할 수 있는 임의의 값을 반환하기 위해 일부 유형의 암호를 통해 숫자를 반환합니다.

제게 물어보면 꽤 좋은 해결책인 것 같습니다. 이 방법을 사용하는 데 문제가 있다고 생각하는 사람이 있나요?아니면 가능한 방법이 있나요?

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

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

원하는 것을 달성하는 것은 실제로 불가능합니다.Flash 앱의 내부는 항상 부분적으로 액세스할 수 있습니다. 특히 다음과 같은 기능을 사용하는 방법을 알고 있는 경우에는 더욱 그렇습니다. 치트 엔진, 즉, 웹사이트와 브라우저<->서버 통신이 아무리 안전하더라도 극복하기가 상대적으로 간단하다는 의미입니다.

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

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top