Я говорю об игре действия без верхнего предела оценки и ни в коем случае не проверять счет на сервере, переигрывая ходы и т. Д.
Мне действительно нужно самое сильное шифрование, возможное во Flash / PHP, и способ предотвратить людей, вызывающих страницу PHP, кроме моего файла Flash. В прошлом я пробовал некоторые простые методы, позволяющие делать множественные вызовы для одного балла и завершения последовательности контрольной суммы / фибоначчи и т. Д., А также обфускацию SWF с помощью шифрования Amayeta 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 работает на компьютере пользователя. Ты СОЛ. Нет ничего, что вы могли бы сделать, чтобы не дать злоумышленнику подделывать высокие баллы:
Flash еще проще перестроить, чем вы думаете, так как байт-коды хорошо документированы и описывают язык высокого уровня (ActionScript). Когда вы публикуете флеш-игру, вы публикуете исходный код, независимо от того, используете ли вы знаете это или нет.
Атакующие управляют памятью времени выполнения интерпретатора Flash, так что любой, кто знает, как использовать программируемый отладчик, может в любой момент изменить любую переменную (включая текущую оценку) или изменить сама программа.
Простейшей возможной атакой на вашу систему является запуск HTTP-трафика для игры через прокси-сервер, улавливание сбережений по максимуму и повторное воспроизведение с более высокой оценкой.
Вы можете попытаться заблокировать эту атаку, привязав каждый высокий балл к одному экземпляру игры, например, отправив зашифрованный токен клиенту при запуске игры, который может выглядеть так:
hex-encoding( AES(secret-key-stored-only-on-server, timestamp, user-id, random-number))
(Вы также можете использовать cookie сеанса с тем же эффектом).
Код игры повторяет этот токен на сервере с сохранением наивысшего балла. Но злоумышленник все еще может снова запустить игру, получить токен, а затем сразу же вставить этот токен в повторное сохранение с высоким счетом.
Таким образом, вы будете кормить не только токеном или сеансом cookie, но и ключ сеанса с высоким уровнем шифрования. Это будет 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 высокого балла (если вы пропустите этот шаг , дешифрование будет просто производить случайные, вероятно очень высокие, высокие баллы).
Итак, теперь злоумышленник декомпилирует ваш Flash-код и быстро находит код AES, который торчит как больной палец, хотя даже если бы он его не выследил за 15 минут с поиском памяти и индикатором («Я знаю мой счет для этой игры составляет 666, поэтому давайте найдем 666 в памяти, а затем поймаем любую операцию, которая затрагивает это значение — о, посмотрите, код шифрования с высоким коэффициентом! »). С помощью ключа сеанса злоумышленнику даже не нужно запускать Flash-код; она захватывает токен запуска игры и ключ сеанса и может отправить обратно произвольный высокий балл.
Вы сейчас в точке, где большинство разработчиков просто сдаются – дайте или возьмите пару месяцев возиться с нападающими:
Скремблирование ключей AES с помощью операций XOR
Замена основных байтовых массивов функциями, которые вычисляют ключ
Рассеяние фальшивых ключевых шифров и высокие записи баллов по всему двоичному.
Это в основном пустая трата времени. Само собой разумеется, SSL не поможет вам; SSL не может защитить вас, когда одна из двух конечных точек SSL зла.
Вот некоторые вещи, которые могут фактически уменьшить высокий балл мошенничества:
Требовать вход в систему для игры, ввести логин в сессионный файл cookie и не допускать нескольких выдающихся запусков игр в одном сеансе или нескольких одновременных сеансов для одного и того же пользователя.
Отклонить высокие оценки от игровых сессий, которые в прошлом меньше, чем самые короткие реальные игры, которые когда-либо исполнялись (для более сложного подхода, попробуйте «карантинировать» высокие баллы для игровых сессий, которые имеют менее 2 стандартных отклонений ниже средней продолжительности игры). Убедитесь, что вы отслеживаете продолжительность игровых серверов.
Отказывать или карантинировать высокие баллы от логинов, которые только играли в игру один или два раза, так что злоумышленники должны создать «бумажный след» разумного поиска игры для каждого входа, который они создают.
«Heartbeat» забивает во время игры, так что ваш сервер видит рост очков за всю игру в одной игре. Отклоните высокие баллы, которые не соответствуют разумным кривым оценки (например, прыгают с 0 до 999999).
Статус игры «Снимок» во время игры (например, количество боеприпасов, позиция на уровне и т. Д.), Которые вы можете позже согласовать с зарегистрированными промежуточными оценками. У вас даже не должно быть способа обнаружить аномалии в этих данных для начала; вам просто нужно собрать его, а затем вы можете вернуться и проанализировать его, если все будет выглядеть подозрительно.
Отключите учетную запись любого пользователя, который не выполнил одну из проверок безопасности (например, когда-либо отправлял зашифрованный высокий балл, который не прошел проверку).
Помните, хотя вы только сдерживаете мошенничество с высокими баллами здесь. Вы ничего не можете сделать, чтобы предотвратить это. Если на вашей игре есть деньги, кто-то победит любую систему, которую вы придумали. Цель состоит не в том, чтобы остановить эту атаку; это сделать атаку более дорогостоящей, чем просто очень хорошо играть в игру и избивать ее.
Возможно, вы задаете неправильный вопрос. Вы, похоже, сосредоточены на методах, которые люди используют для игры в своем списке вверх по списку высоких баллов, но блокировка определенных методов только доходит до сих пор. У меня нет опыта работы с TamperData, поэтому я не могу с этим поговорить.
Вопрос, который вы должны задать, заключается в следующем: «Как я могу проверить, что представленные баллы действительны и аутентичны?» Конкретный способ сделать это зависит от игры. Для очень простых головоломок вы можете отправить по счету вместе со специфическим начальным состоянием и последовательностью ходов, которые привели к состоянию конца, а затем повторно запустить игру на стороне сервера, используя те же ходы. Подтвердите, что заявленная оценка совпадает с вычисленным счетом и принимает только партитуру, если они совпадают.
Простым способом сделать это будет предоставление криптографического хэша вашей высокой стоимости наряду с оценкой его. Например, при отправке результатов через HTTP GET: http://example.com/highscores.php?score=500&checksum=0a16df3dc0301a36a34f9065c3ff8095
При расчете этой контрольной суммы следует использовать общий секрет; этот секрет никогда не должен передаваться по сети, но должен быть жестко закодирован как в бэкэнде PHP, так и во флэш-интерфейсе. Контрольная сумма выше была создана путем добавления строки « secret » к счету « 500 » и запуска ее через md5sum.
Хотя эта система не позволяет пользователю публиковать произвольные баллы, она не предотвращает «повторную атаку», когда пользователь перечитывает ранее рассчитанную оценку и хеш-комбинацию. В приведенном выше примере оценка 500 всегда будет содержать одну и ту же строку хэша. Некоторые из этих рисков могут быть смягчены путем включения в строку, которая должна быть хеширована, больше информации (например, имя пользователя, временная метка или IP-адрес). Хотя это не помешает воспроизведению данных, оно гарантирует, что набор данных действителен только для одного пользователя за один раз.
Чтобы предотвратить появление каких-либо повторных атак, необходимо создать некоторую систему запроса-ответа, такую как:
Имейте в виду, что безопасность любого из вышеперечисленных методов скомпрометирована, если общий секрет всегда доступен пользователю
В качестве альтернативы можно избежать некоторых из этих проблем, заставляя клиента общаться с сервером через HTTPS и гарантируя, что клиент предварительно настроен, чтобы доверять только сертификатам, подписанным определенным центром сертификации, доступ к которому у вас один ,
Мне нравится то, что сказал tpqf, но вместо того, чтобы отключать учетную запись при обнаружении обмана, реализуйте honeypot, поэтому всякий раз, когда они входят в систему, они видят свои взломанные баллы и никогда не подозревают, что они были отмечены как тролль. Google для «phpBB MOD Troll», и вы увидите изобретательный подход.
В принятом ответе tqbf упоминает, что вы можете просто выполнить поиск по памяти для переменной оценки («Мой счет 666, поэтому я ищу номер 666 в памяти»).
Есть способ обойти это. У меня есть класс здесь: http://divillysausages.com/blog/safenumber_and_safeint
В принципе, у вас есть объект для хранения вашей оценки. В сеттере он умножает значение, которое вы передаете ему со случайным числом (+ и -), а в получателе вы делите сохраненное значение на случайный мультипликатор, чтобы вернуть оригинал. Это просто, но помогает остановить поиск в памяти.
Кроме того, ознакомьтесь с видео от некоторых из парней, стоящих за движком PushButton, которые рассказывают о различных способах борьбы с взломом: http://zaa.tv/2010/12/the-art-of-hacking-flash- игры / . Они были вдохновением для класса.
Шифрование с использованием известного (частного) обратимого ключа будет самым простым методом. Я не все в AS, поэтому я не уверен, какие существуют поставщики шифрования.
Но вы можете включить такие переменные, как длина игры (зашифрована, снова) и количество кликов.
Все такие вещи могут быть обратно спроектированы, поэтому подумайте о том, чтобы бросить кучу ненужных данных, чтобы выбросить людей из запаха.
Редактировать: Возможно, стоит попробовать и на некоторых сеансах PHP. Начните сеанс, когда они нажмут на игру, и (как отмечается в комментарии к этому сообщению) запишите время. Когда они отправляют счет, вы можете проверить, что на самом деле у них открытая игра, и они не слишком рано или слишком велики.
Возможно, стоит разработать скаляр, чтобы увидеть, какой максимальный балл за секунду / минуту игры.
Ни одна из этих вещей не является необратимой, но это поможет иметь некоторую логику не в Flash, где люди могут ее видеть.
По моему опыту, это лучше всего подходит как проблема социальной инженерии, а не проблема программирования. Вместо того, чтобы сосредоточиться на том, чтобы сделать невозможным обмануть, сосредоточьтесь на том, чтобы сделать его скучным, удалив стимулы для обмана. Например, если основным стимулом являются общедоступные высокие оценки, просто задержка при показе высоких баллов может значительно уменьшить обман, удалив положительный цикл обратной связи для читеров.
Всякий раз, когда ваша рекордная система основана на том факте, что приложение Flash отправляет незарегистрированные / неподписанные данные о рекорде через сеть, которые могут быть перехвачены и обработаны / воспроизведены. Ответ следует из этого: шифровать (порядочно!) Или криптографически подписывать рекорды. Это, по крайней мере, затрудняет людям взломать вашу рекордерную систему, потому что им нужно будет извлечь секретный ключ из вашего SWF-файла. Многие люди, вероятно, откажутся отсюда. С другой стороны, все, что требуется, – это отдельный человек, чтобы извлечь ключ и отправить его где-нибудь.
Реальные решения включают большую связь между приложением Flash и базой данных, чтобы последний мог проверить, что данный балл несколько реалистичен. Это, вероятно, сложно в зависимости от того, какую игру у вас есть.
Невозможно сделать его полностью недоступным, так как легко декомпилировать SWF-файлы, и квалифицированный разработчик-хакер может проследить ваш код и выяснить, как обойти любую зашифрованную систему, которую вы могли бы использовать.
Если вы просто хотите, чтобы дети обманывали с помощью простых инструментов, таких как TamperData, тогда вы могли бы сгенерировать ключ шифрования, который вы передадите SWF при запуске. Затем используйте что-то вроде http://code.google.com/p/as3crypto/, чтобы зашифровать высокий балл, прежде чем передавать его обратно в PHP-код. Затем расшифруйте его на сервере, прежде чем хранить его в базе данных.
Вы говорите о том, что называется проблемой «доверия клиентов». Поскольку клиент (в этих денежных средствах, SWF, работающий в браузере) делает то, что он предназначен. Сохраните высокий балл.
Проблема в том, что вы хотите убедиться, что запросы «сохранить счет» поступают из вашего флеш-ролика, а не какой-то произвольный HTTP-запрос. Возможным решением для этого является кодирование маркера, сгенерированного сервером, в SWF во время запроса (с использованием flasm ), который должен сопровождать запрос, чтобы сохранить высокий балл. Как только сервер сохраняет этот балл, токен истек и больше не может использоваться для запросов.
Недостатком этого является то, что пользователь сможет подавать только один высокий балл за загрузку флеш-ролика – вам нужно заставить их обновить / перезагрузить SWF, прежде чем они смогут снова сыграть для новой оценки.
Обычно я включаю «данные о призрак» игрового сеанса с записью рекорда. Поэтому, если я участвую в гоночной игре, я включаю данные повтора. У вас часто есть данные повторного воспроизведения уже для функциональности воспроизведения или функциональности призрачных гонок (игра против вашей последней гонки или игра против призрака чувака №14 в таблице лидеров).
Проверка их – это очень ручной труд, но если цель состоит в том, чтобы проверить, являются ли 10 лучших записей в конкурсе законными, это может быть полезным дополнением к арсеналу мер безопасности, о которых другие уже указали.
Если цель состоит в том, чтобы вести список рекордов онлайн до конца времени, и никто не должен смотреть на них, это не принесет вам многого.
Способ, которым пользуется новый популярный аркадный мод, заключается в том, что он отправляет данные со вспышки на php, обратно на флэш (или перезагружает его), а затем обратно на php. Это позволяет вам делать все, что вы хотите сравнить с данными, а также обходить почтовые данные / расшифровать хаки и тому подобное. Один из способов, которым это делается, – назначить 2 рандомизированных значения из php во флеш (которые вы не можете захватить или увидеть, даже если запускаете захват данных в реальном времени), используя математическую формулу для добавления оценки со случайными значениями, затем проверяя ее, используя ту же формулу, чтобы отменить ее, чтобы увидеть, соответствует ли оценка, когда она, наконец, переходит к php в конце. Эти случайные значения никогда не видны, а также время совершения транзакции, и если это не более чем на пару секунд, тогда это также означает, что он обманывает, поскольку предполагает, что вы остановили отправку, чтобы попытаться определить рандомизированные значения или выполнить номера через некоторый тип шифрования, чтобы возвращать возможные случайные значения для сравнения со значением оценки.
Это кажется довольно хорошим решением, если вы спросите меня, не видят ли какие-либо проблемы с использованием этого метода? Или возможные пути вокруг него?
Я думаю, что самым простым способом было бы вызвать вызовы функции типа RegisterScore (оценка) каждый раз, когда игра регистрирует счет, который будет добавлен, а затем закодировать его, упаковать и отправить в скрипт php в виде строки. PHP-скрипт знал бы, как правильно его декодировать. Это остановит любые вызовы прямо на php-скрипт, так как любые попытки заставить счет привести к ошибке декомпрессии.
Это возможно только при сохранении всей игровой логики на стороне сервера, которая также хранит оценку внутренне без знания пользователя. По экономическим и научным причинам человечество не может применять эту теорию ко всем типам игр, исключая пошаговые инструкции. Например, сохранение физики на стороне сервера является дорогостоящим вычислительным процессом и трудно реагировать как скорость руки. Даже возможно, играя в шахматы, любой может сравниться с игровым процессом в шахматы AI противнику. Поэтому лучшие многопользовательские игры должны также содержать творческий потенциал по требованию.
Вы не можете доверять никаким данным, возвращаемым клиентом. Проверка должна выполняться на стороне сервера. Я не разработчик игр, но я делаю программное обеспечение для бизнеса. В обоих случаях могут быть задействованы деньги, и люди будут нарушать методы обфускации на стороне клиента.
Может периодически отправлять данные на сервер и выполнять некоторую проверку. Не сосредотачивайтесь на клиентском коде, даже если это место, где живет ваше приложение.
Я сделал какое-то обходное решение … Я дал, где количество очков увеличилось (вы всегда получаете +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 }
Затем я отправляю переменную среди других фальшивых варов, и она просто теряется в пути … Много работы для небольшой флеш-игры, но там, где привлекают призы, некоторые люди просто жадничают. Если вам нужна помощь, напишите мне.
Привет, Ико
Невозможно достичь того, чего вы хотите. Внутренности приложения Flash всегда доступны частично, особенно если вы знаете, как использовать такие вещи, как CheatEngine , что означает независимо от того, насколько безопасен ваш веб-сайт и серверная связь браузера <->, но по-прежнему будет относительно легко преодолеть.
Возможно, неплохо было бы связаться с бэкэнд через AMFPHP . Это должно препятствовать, по крайней мере, ленивым попыткам проталкивать результаты через консоль браузера.