Як я можу повністю заховати і захистити струни від програвача в Unity?


47

Я використовував Unity для створення 2D-гри, яка буде повністю в автономному режимі (це проблема). Ігрові ігри потребують, щоб ви ввели певні рядки на певних рівнях, а Unity компілював у DLL-файли, які можна легко інженерно розробити, так це є спосіб захистити ці рядки (гра в автономному режимі, тому я не можу отримати інше джерело)?

Гра в значній мірі покладається на ці рядки, і так, я знаю, що затупляється, але мені хочеться чогось більш міцного. І я знаю, що найпростішим виходом було б робити все в Інтернеті з джерела даних, але мені було цікаво, чи можливо це.

Його можна декомпілювати так: введіть тут опис зображення


10
Хоча я згоден, що це битва, яку ви ніколи не можете по-справжньому виграти, ви, безумовно, можете зробити її складнішою з невеликими зусиллями. obfuscar.codeplex.com
Яків Персі

46
@Gabriele Так? Декомпіляція кодового коду C # настільки ж просто, як це стає. Таким чином ви отримуєте майже ідеально читабельний код, порівняйте його з тим, що генерується IDA для оптимізованого коду C або C ++. Це сказане з достатньо зусиль рідного коду можна зрозуміти так само багато, але це порядки складніше. Не маю уявлення, наскільки добре працює обфускація - якщо вона робить звичайні декомпілятори (DotPeek, ILSpy, щось інше?) Barf на 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 та платформі.


81
Це справді найкраща відповідь. Але пам’ятайте, що ви абсолютно позитивно не повинні використовувати вбудований хеш-алгоритм на рядках . він створений для того, щоб робити одне і лише одне, а це збалансувати хеш-таблицю. Ви не можете зберігати хеші рядків і використовувати їх як автентифікатори спільної таємниці, тому що автори виконання .NET залишають за собою право змінювати алгоритм хешування рядків будь-коли з будь-якої причини і фактично вони це робили раніше . Використовуйте стандартний хеш-криптовалюту або реалізуйте власний простий хеш.
Ерік Ліпперт

4
Це. Саме так. Якщо ви використовуєте такий алгоритм, як sha256 (є багато бібліотек, які реалізують це, тому вам не потрібно писати власні), у вас вийде щось, що неможливо легко зламати і дуже надійне.
Мішель Джонсон

12
@Michael Johnson за допомогою солі значно ускладнить використання таблиць веселки, а використання хеша пароля, як bcrypt, зробить його набагато повільніше і, отже, важче зламати. Але врешті-решт, це здається занадто великим зусиллям, щоб докласти його; Користувач придбав гру, якщо хоче обдурити, що це їхній власний вибір
Мелькор

2
@MichealJohnson: Ключове розтягнення може зробити такі грубі напади дещо складнішими (скажімо, в мільярд разів). Але справжня проблема з цією відповіддю полягає в тому, що, мабуть, в якийсь момент грі потрібно мати можливість сказати гравцеві, який рядок їм потрібно ввести. Якщо ці рядки насправді не є вирішенням якоїсь загадки, яку гравцеві потрібно вирішити, я думаю. Або якщо рядки не надаються в Інтернеті, навіть якщо гра в автономному режимі, як ліцензійні ключі старого стилю.
Ілмарі Каронен

5
@Sentinel Це означає, що геймплей може бути різним для різних гравців. Нам дійсно потрібно знати, про які рядки ми говоримо, якщо вони містяться в книгах / знаках / діалогах у грі, якщо вони вирішують головоломки, де фактична відповідь не дається гравцеві безпосередньо, або якщо вони генеруються випадковим чином. І якщо це слова, речення чи випадкові символи.
Мікель Джонсон

106

Те, що ви намагаєтеся зробити, є і марним, і безглуздим.

Це марно, оскільки немає можливості правильно приховати інформацію, яка знаходиться на машині користувача. Той, хто достатньо відданий, знайде його. Ви можете зробити це важче, але ніколи не зможете запобігти цьому. Якщо ви шифруєте його, то вам потрібно десь зберігати ключ і алгоритм шифрування. Незалежно від того, скільки шарів шифрування ви додали, найзавершений шар завжди повинен бути незашифрованим для того, щоб ваша гра працювала.

Це також безглуздо, адже ми живемо в епоху Інтернету. Коли ваша гра стане просто віддаленою популярністю, ці коди будуть розміщені по всій мережі Інтернет.

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


38
Зворотна інженерія - це власна гра! Це єдина правильна відповідь - сьогодні не слід приховувати інформацію в одиночних іграх, гравці отримають доступ до неї, якщо хочуть.
Мефі

27
@TheBinaryGuy Безпека від чого? Ваші користувачі грають в офлайн-гру . Яку загрозу наражає викриття коду? Гравець, зрештою, повинен виявити це все одно, щоб мати можливість грати в гру! Важливим правилом безпеки є те, що ви повинні визначити трактування, від якої ви захищаєте; це називається "моделлю загрози".
jpmc26

7
@TheBinaryGuy Окрім інших моментів, я б поставив під сумнів чутливість використання "фіксованих" кодів паролів - навіть не шукаючи коди в Інтернеті / через зворотну інженерію, просто грати в гру вдруге вже дозволить гравцям просто пропустити через розділи гри (як вони вже знають коди). Якщо ви дійсно хочете "змусити" гравців заробляти ці коди, вам потрібно змусити їх змінюватись на кожному
ігровому етапі

6
Ця відповідь має хороші моменти, але другий абзац невірний. Не потрібно шифрувати рядок. Ви можете розім’яти його. Якщо гравець може зламати хеш, то натомість він буде грабувати банківські рахунки, найме ФБР чи щось подібне. Інші пункти дійсні, хоча.
Педро А

5
@Hamsterrific Я думаю, що відповідь передбачає, що вам потрібні фактичні рядки для зберігання, наприклад, щоб показати їх гравцеві в якийсь момент, а це означає, що хеширование не буде робити.
Френк Хопкінс

4

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

Перевага полягає в тому, що, як вказував @Philipp, намагатися приховати коди у виконуваному файлі дещо безглуздо, якщо ви можете очікувати їх розміщення в Інтернеті. Перемішане чи ні, те саме слово, знайдене в Інтернеті та введене в гру, дасть той же хеш і буде працювати в будь-якому випадку.

За винятком ... за винятком випадків, якщо чийсь код не працює для вас. Що ви можете банально зробити - не на 100% захищених від несанкціонованих дій, але досить важко обійтися середньому користувачеві. Все настільки просто, як "Онлайн-генератор імен ельфійців" зробить (може бути довільно простим, насправді не потрібно багато маркованого двигуна тексту маркова, достатньо добре витягнути 4-5 складів із випадкового списку).

Просто генеруйте дещо конкретне або певне для користувача число, воно навіть не повинно бути абсолютно унікальним або дуже стійким до фальсифікації. Щось, що, мабуть, відрізняється для більшості людей і навряд чи регулярно змінюватиметься, наприклад, мережеве ім’я комп'ютера, MAC-адреса або GUID системного дискового диска, як би там не було (серійний номер GPU може бути дуже поганимідея, оскільки користувачі, ймовірно, оновлять графічні процесори). Додайте до цього числовий код, на який посилається код розблокування, і введіть його у свій генератор слів. Але будьте готові відповідати на запити підтримки, коли гравці використовують два комп’ютери або змінюють свою мережеву карту (що незвично, але не неможливо). Це може бути гарним планом генерувати випадковий ідентифікатор лише один раз і зберігати його з налаштуваннями гри. Таким чином, принаймні він не порушує існуючі установки на одній машині, якщо щось зміниться.

Або ви можете просто скористатись серійним номером гри, який є унікальним, і він працюватиме, якщо користувач змінить апаратне забезпечення (правда, це може сприяти піратству, оскільки спільні коди розблокування працюють для піратських серіалів, але не для законних клієнтів!).

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

Отже ... перш ніж робити щось таким чином, подумайте дуже ретельно, чи дійсно ви цього хочете, і чого ви хочете. Цілком можливо, наявність людських читабельних рядків (або тривіально зроблених "нечитабельних" за допомогою xor) є достатньо хорошою і справді бажаною.


Який процес ви передбачаєте? Якщо програма генерує хеш-значення після завантаження, то при завантаженні вона повинна мати незбиту рядок. Тож чи буде сервер запитувати клієнта для виявлення інформації, а потім генерувати хеш-сервер?
Накопичення

@ Накопичення: Який сервер? 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. Мій будинок захистив мене від ведмедя

Ваш перелік фраз містив би і "ведмедя", і "мій дім", але ви мали б великий перелік інших фраз, які можна було б помістити між ними, так що з'ясувати, яка з них буде такою ж важкою, як насправді з'ясувати головоломка в грі (чи що завгодно). Наприклад, фразові дії можуть бути "пройденими", "згорілими", "штовханими", "захищеними від мене", "відокремленими від мене", "магічно виробленими" тощо.

Ви можете це зробити у своїй грі, зробивши індекси засновані на тому, що гравець зібрав чи зробив. Так що ніде в грі не буде головного списку індексів. Вони будуть генеровані гравцем, який грає в гру.


4
Отже, замість того, щоб знайти функцію, на яку посилається певна рядок, ви знайдете функцію, яка посилається на масив з індексами, а потім відтворить рядок. Це не більше 30 секунд захисту. Що він захищає, це те, що хтось просто використовує stringsпроти виконавчого файлу.
Voo

Як я вже говорив, якщо масиви, на які посилаються рядки, розподіляються на всі функції, які їм потрібні, то це трохи складніше, ніж просто знайти один масив в одній функції. Не неможливо, але охоплює більшу площу без зайвих робіт.
користувач1118321

Це не просто менша форма шифрування?
Артуро Торрес Санчес

2
Зачекайте, навіть не шифрування. Просто кодування.
Артуро Торрес Санчес

2
Я оновив відповідь, щоб бути більш зрозумілою. В основному, якщо індекси базуються на тому, що зробив гравець, вони насправді не зберігаються в грі. Знову ж, це може бути не дурним, або ідеальним, але я ставлю це тут як варіант, який люди можуть хотіти вивчити.
користувач1118321
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.