Как мне полностью скрыть и защитить струны от плеера в Unity?

47

Я использовал Unity для создания 2D-игры, которая будет полностью автономна (что является проблемой), для игры требуется, чтобы вы вводили определенные строки на определенных уровнях, а Unity компилируется в библиотеки DLL, которые можно легко перепроектировать, поэтому Есть ли способ защитить эти строки (игра в автономном режиме, поэтому я не могу получить из другого источника)?

Игра в значительной степени опирается на эти строки, и да, я знаю о Obfuscation, но я хочу что-то более надежное. И я знаю, что самым простым выходом было бы делать все онлайн из источника данных, но мне было интересно, возможно ли это.

Это можно декомпилировать так: введите описание изображения здесь

TheBinaryGuy
источник
10
Хотя я согласен, что это битва, которую вы никогда не сможете по-настоящему выиграть, вы определенно можете сделать ее более сложной, приложив немного усилий. obfuscar.codeplex.com
Джейкоб Перси
46
@ Габриэле А? Декомпиляция не запутанного кода C # так же проста, как и получается. Таким образом, вы получаете довольно хорошо читаемый код, сравнивайте его с тем, что генерирует IDA для оптимизированного кода на C или C ++. Тем не менее, при достаточных усилиях нативный код можно понять так же, но это на несколько порядков сложнее. Понятия не имею, насколько хорошо работает запутывание - если оно заставляет обычные декомпиляторы (DotPeek, ILSpy, что-то еще?) Препятствовать коду IL, что должно создавать барьер, чтобы держать случайного человека подальше от него.
Voo
15
@GabrieleVierti, вытащить текст из DLL - тривиально: под Linux или Cygwin вы можете сделать это, просто указав stringsна нее программу.
Отметить
31
Что именно вы пытаетесь сделать здесь? Это звучит как довольно серьезный случай проблемы XY. meta.stackexchange.com/questions/66377/what-is-the-xy-problem Чего бы вы ни пытались достичь (с точки зрения игрового процесса, а не с технической точки зрения), почти наверняка не лучше всего служить попыткам скрыть и зашифровать эти строки ,
GrandOpener
36
Интересно, действительно ли скрытие строк служит какой-то цели: как только некоторые игроки решат их, они, скорее всего, будут распространяться в вики или подобном, поэтому любой, кто хочет их знать, легко сможет их найти. Да, запутывая их, игрок не может просто открыть dll в текстовом редакторе и искать строки, но большинство сначала обратится к google (или к своей поисковой системе) ...
hoffmale

Ответы:

159

Не храните эти строки, храните их (криптографический) хеш.

(Криптографическая) хеш-функция, такая как шифрование, - это способ превратить строку в «бессмысленный» (называемый хеш-код), но в отличие от шифрования вы не можете получить исходную строку из этого хеш-кода (если вы не можете перебрать ее или перебрать) функция нарушена). Большинство (если не все) хеш-функций принимает строку произвольной длины и возвращает строку постоянной длины (зависит от функции).

Как проверить правильность введенной пользователем строки? Поскольку вы не можете получить действительную строку из хеша, единственное, что вы можете сделать, это хешировать предположение пользователя и сравнивать его с правильным хешем.

Предупреждение (Эрик Липперт): НЕ ИСПОЛЬЗУЙТЕ встроенную функцию GetHashCodeкак такую ​​функцию - ее результат может различаться в разных версиях .NET и платформах, поэтому ваш код работает только на определенных версиях .NET Framework и платформе.

user49822
источник
81
Это действительно лучший ответ. Но помните, что вы абсолютно не должны использовать встроенный алгоритм хеширования для строк . он предназначен для выполнения одной и только одной задачи, а именно для балансировки хеш-таблицы. Вы не можете хранить хеши строк и использовать их как аутентификаторы общего секрета, потому что авторы среды выполнения .NET оставляют за собой право изменить алгоритм хеширования строк в любое время по любой причине, и фактически они делали это в прошлом . Используйте стандартный хеш-код с криптостойкостью или реализуйте свой собственный простой хеш.
Эрик Липперт
4
Этот. Именно так. Если вы используете алгоритм, подобный sha256 (есть много библиотек, которые реализуют его, поэтому вам не нужно писать свой собственный), то у вас будет что-то, что не может быть легко сломано и очень надежно.
Майкл Джонсон
12
@ Майкл Джонсон, использующий соль, усложнит использование радужных таблиц, а использование хэша пароля, такого как bcrypt, сделает его намного медленнее и, следовательно, сложнее взломать. Но в конечном итоге это кажется слишком большим усилием, чтобы пойти к нему; пользователь купил игру , если они хотят обмануть , что это их собственный выбор
Мелькор
2
@MichealJohnson: растяжение ключа может сделать такие атаки грубой силой немного сложнее (скажем, в миллиард или около того). Но реальная проблема с этим ответом состоит в том, что, по-видимому, в какой-то момент игра должна быть в состоянии сказать игроку, в какую строку им нужно войти. Думаю, если эти строки не являются решением какой-то головоломки, которую игрок должен решить. Или, если строки не предоставляются онлайн, хотя игра находится в автономном режиме, что-то вроде лицензионных ключей старого стиля.
Ильмари
5
@Sentinel Это означает, что игровой процесс может отличаться для разных игроков. Нам действительно нужно знать, о каких строках мы говорим, если они содержатся в книгах / знаках / диалогах в игре, являются ли они решениями головоломок, где фактический ответ не дается непосредственно игроку, или если они генерируются случайным образом. И если это слова, предложения или случайные символы.
Майкл Джонсон
106

То, что вы пытаетесь сделать, бесполезно и бессмысленно.

Это бесполезно, потому что нет способа правильно скрыть информацию, которая находится на компьютере пользователя. Любой достаточно преданный найдет это. Вы можете сделать это сложнее, но вы никогда не сможете предотвратить это. Если вы его зашифруете, то вам нужно где-то хранить ключ шифрования и алгоритм. Независимо от того, сколько слоев шифрования вы добавите, для запуска вашей игры самый верхний слой всегда должен быть незашифрован.

Это также бессмысленно, потому что мы живем в эпоху Интернета. Когда ваша игра станет просто удаленно популярной, эти пароли будут размещены по всей сети.

Все, что вы можете сделать, - это доверить игроку, что он не испортит себе игровой опыт, отыскивая информацию, которую игра пока не должна ему сообщать. Подавляющее большинство игроков в любом случае не начнет реверс-инжиниринг вашей игры. И если те, кто обладает необходимыми навыками, делают это по своей вине.

Philipp
источник
38
Обратный инжиниринг - это отдельная игра! Это единственный правильный ответ - в наши дни нельзя скрывать информацию в однопользовательских играх, игроки получат к ней доступ, если захотят.
Мефи
27
@TheBinaryGuy Безопасность от чего? Ваши пользователи играют в автономную игру . Какую угрозу представляет разоблачение кода? Игрок должен в конечном итоге обнаружить это, чтобы иметь возможность играть в игру! Важное правило безопасности заключается в том, что вы должны определить, от чего вы защищаете; это называется «моделью угрозы».
jpmc26
7
@TheBinaryGuy В дополнение к другим пунктам, я бы поставил под сомнение целесообразность использования «фиксированных» паролей - даже без поиска кодов онлайн / с помощью обратного инжиниринга, просто игра в игру во второй раз уже позволит игрокам просто пропустить прямо через разделы игры (так как они уже знают коды). Если вы действительно хотите «заставить» игроков зарабатывать эти коды, вам нужно менять их при каждом прохождении (например, иметь некоторую форму рандомизации)
UnholySheep
6
Этот ответ имеет несколько положительных моментов, но второй абзац неверен. Вам не нужно шифровать строку. Вы можете хешировать это. Если игрок может взломать хеш, то вместо этого он будет грабить банковские счета, будет нанят ФБР или что-то в этом роде. Другие пункты действительны, хотя.
Педро А
5
@Hamsterrific Я полагаю, что в ответе предполагается, что вам нужно сохранить фактические строки, например, чтобы показать их игроку в какой-то момент, что означает, что хеширование не будет работать.
Фрэнк Хопкинс
4

Если такая вещь действительно желательна, то вместо хеширования вы можете рассмотреть возможность построения строк из числового входного значения во время выполнения.

Преимущество состоит в том, что, как указал @Philipp, бессмысленно пытаться скрыть коды в исполняемом файле, если вы все равно можете ожидать их размещения в Интернете. Хешированный или нет, одно и то же слово, найденное в интернете и введенное в игру, даст тот же хеш и будет работать в любом случае.

За исключением ... кроме случаев, когда чужой код не работает для вас. Что вы можете сделать тривиально - не на 100% защищено от несанкционированного доступа, но достаточно сложно обойти для среднего пользователя. Подойдет все, что может сделать «Генератор имён эльфов в Интернете» (может быть сколь угодно простым, на самом деле не нужно много движка генерации текста на языке markov, достаточно выбрать 4-5 слогов из случайного списка).

Просто сгенерируйте какое-нибудь пользовательское или машинное число, оно даже не должно быть совершенно уникальным или очень устойчивым к взлому. Что-то, что, вероятно, отличается для большинства людей и вряд ли будет регулярно меняться, например, сетевое имя компьютера, MAC-адрес или GUID системного диска, что угодно (серийный номер графического процессора может быть очень плохимидея, так как пользователи могут обновить GPU). Добавьте к этому числовой код, к которому относится код разблокировки, и введите его в свой генератор слов. Но будьте готовы ответить на вопросы поддержки, когда игроки используют два компьютера или меняют сетевую карту (что необычно, но не невозможно). Это может быть хорошим планом - генерировать случайный идентификатор только один раз и сохранять его с настройками игры. Таким образом, по крайней мере, это не нарушает существующие установки на той же машине, если что-то меняется.

Или вы можете просто использовать серийный номер игры, который уникален и будет работать, если пользователь меняет оборудование (по иронии судьбы, это может способствовать пиратству, поскольку общие коды разблокировки работают для пиратских сериалов, но не для законных клиентов!).

Обратите внимание, что предотвращение обмана пользователей не обязательно является хорошей вещью. В оффлайн (то есть неконкурентной игре) обычно нет проблем, если пользователь обманывает и получает коды откуда- то, а не из игры. Он обманывает только себя. Какая разница.
С другой стороны, слишком много мешать им, если они действительно хотят обмануть, - отличная возможность полностью разозлить платящих клиентов.

Итак ... прежде чем делать что-то таким образом, очень тщательно подумайте, действительно ли вы этого хотите и чего хотите. Вполне возможно, наличие читаемых человеком строк (или тривиально сделанных «нечитаемых» с помощью xor) просто достаточно хорошо и действительно предпочтительнее.

Damon
источник
Какой процесс вы представляете? Если программа генерирует значение хеша после загрузки, то при загрузке она должна иметь строку без заголовка. Так будет ли сервер запрашивать у клиента информацию для идентификации, а затем генерировать хэш на стороне сервера?
накопление
@ Накопление: какой сервер? Q говорит "полностью в автономном режиме". Что, вероятно, означает программу на DVD (или, возможно, загрузку) плюс серийный номер. Таким образом, у вас есть события 1,2,3,4, для которых должен существовать пароль. Вы вычисляете, например, hash(serial + 1)чтобы получить число, соответствующее первому коду. Затем введите это в свой генератор слов, который, скажем, вытягивает один слог из списка 16 для каждых 4 бит ввода. Вот и все, отдельные «слова» для каждого пользователя.
Деймон
Если это загрузка, то она загружается с сервера. Если программа рассчитывает hash(serial+1) после загрузки, что мешает пользователю рассчитать hash(serial+1)? Как только программа загружена, пользователь получает доступ ко всему, что делает программа.
накопление
@ Аккумуляция: ничто не мешает пользователю сначала декомпилировать программу, а затем вычислить hash(serial + 1). И что? Это не проблема. Послушайте, если кто-то тратит от одного до двух часов (вероятно, 6-8 часов для типичного "пользователя" без опыта разработчика программного обеспечения), просто чтобы обмануть себя, ну ... пусть. Дело в том, что это работает для одного человека, но не для всех, и это неконкурентоспособно ... так что нет проблем.
Деймон
3

Если вам не нужно показывать строки, то идея хеширования - это, вероятно, верный путь. Если, с другой стороны, вам нужно показать их пользователю, есть несколько других способов, которыми вы могли бы избежать их непосредственного отображения в вашей DLL.

Один из способов справиться с этим помимо шифрования или иного обфусцирования строк - это их разбить. Может быть, просто иметь отсортированный по алфавиту словарь всех возможных слов из всех строк в игре. Затем где-нибудь есть массив, который позволяет вам соединять слова в нужную строку путем индексации в массив слов. Таким образом, у вас нет полных строк в игре. Для расшифровки строк не требуется мастер-ключ. И данные, которые сообщают их порядок, могут быть по всему вашему источнику, если, например, каждая функция, которая использовала строку, просто имеет массив индексов, локальных для функции. Я не уверен, насколько это практично в вашем конкретном случае, но это один из способов сделать это.

Вы можете даже иметь строку, состоящую из нескольких слов, но в итоге они будут расположены в разных порядках. Например, вам могут понадобиться следующие 2 строки:

  1. Медведь прошел через мой дом
  2. Мой дом защитил меня от медведя

Ваш список фраз будет содержать как «медведь», так и «мой дом», но у вас будет большой список других фраз, которые могут быть вставлены между ними, так что выясните, какая из них будет столь же трудной, как и сама мысль загадка в игре (или как там). Например, фразы действия можно было «пройти», «сжечь», «толкнуть», «защитить меня от», «отделить меня от», «магически произвести» и т. Д.

Вы можете внести это в свою игру, сделав индексы основанными на том, что игрок собрал или сделал. Так что нигде в игре не было бы основного списка индексов. Они будут генерироваться игроком, играющим в игру.

user1118321
источник
4
Таким образом, вместо того, чтобы найти функцию, которая ссылается на конкретную строку, вы найдете функцию, которая ссылается на массив с индексами, а затем воссоздаете строку. Это не более 30 секунд защиты. От чего он защищает, так это от того, что кто-то просто использует stringsпротив исполняемого.
Во
Как я уже сказал, если массивы, которые ссылаются на строки, распределены по всем функциям, которые в них нуждаются, то это немного сложнее, чем просто найти один массив в одной функции. Не невозможно, но охватывает большую площадь без большой дополнительной работы.
user1118321
Разве это не просто меньшая форма шифрования?
Артуро Торрес Санчес
2
Подождите, даже не шифрование. Просто кодировка.
Артуро Торрес Санчес
2
Я обновил ответ, чтобы быть более понятным. По сути, если индексы основаны на том, что сделал игрок, то они фактически не сохраняются в игре. Опять же, это может быть не безошибочно, или идеально, но я помещаю это здесь как вариант, который люди могли бы исследовать.
user1118321