Jak mogę całkowicie ukryć i chronić ciągi przed graczem w Unity?

47

Używam Unity do stworzenia gry 2D, która będzie całkowicie offline (co jest problemem), rozgrywka wymaga wprowadzenia pewnych ciągów znaków na określonych poziomach i kompilacji Unity do bibliotek DLL, które można łatwo poddać inżynierii wstecznej, więc jest istnieje sposób na ochronę tych ciągów (gra jest offline, więc nie mogę pobrać z innego źródła)?

Gra w dużej mierze opiera się na tych ciągach i tak, jestem świadomy zaciemniania, ale chcę czegoś bardziej solidnego. I wiem, że najłatwiejszym wyjściem byłoby zrobienie wszystkiego online ze źródła danych, ale zastanawiałem się, czy to możliwe.

Można go tak zdekompilować: wprowadź opis zdjęcia tutaj

TheBinaryGuy
źródło
10
Chociaż zgadzam się, że jest to bitwa, której nigdy tak naprawdę nie można wygrać, zdecydowanie można ją utrudnić przy niewielkim wysiłku. obfuscar.codeplex.com
Jacob Persi
46
@Grriele Huh? Dekompilacja nie zaciemnionego kodu C # jest tak łatwa, jak to możliwe. Otrzymujesz w ten sposób prawie doskonale czytelny kod, porównaj to z tym, co IDA generuje dla zoptymalizowanego kodu C lub C ++. To powiedziawszy przy wystarczającym wysiłku, natywny kod może być równie dobrze zrozumiany, ale jest o rząd wielkości trudniejszy. Nie mam pojęcia, jak dobrze działa zaciemnianie - jeśli powoduje to, że zwykłe dekompilatory (DotPeek, ILSpy, coś jeszcze?) Zawierają kod kreskowy w kodzie IL, który powinien wprowadzić barierę, która powstrzyma przypadkową osobę od niego.
Voo
15
@GabrieleVierti, wyciąganie tekstu z biblioteki DLL jest banalne: w Linuksie lub Cygwinie można to zrobić, wskazując na niego stringsprogram.
Mark
31
Co dokładnie próbujesz tutaj zrobić? To brzmi jak dość poważny przypadek problemu XY. meta.stackexchange.com/questions/66377/what-is-the-xy-problem Cokolwiek próbujesz osiągnąć (z perspektywy gry, a nie perspektywy technicznej) prawie na pewno nie najlepiej obsłużyć, próbując ukryć i zaszyfrować te ciągi .
GrandOpener
36
Zastanawiam się, czy ukrywanie łańcuchów rzeczywiście ma jakiś cel: gdy niektórzy gracze je rozwiążą, najprawdopodobniej będą się rozprzestrzeniać na stronach wiki lub podobnych, więc każdy, kto chce je znać, z łatwością będzie mógł je wyszukać. Tak, zaciemniając je, gracz nie może po prostu otworzyć biblioteki DLL w edytorze tekstu i poszukać ciągów, ale większość najpierw skonsultuje się z Google (lub wybraną przez siebie wyszukiwarką) ...
hoffmale

Odpowiedzi:

159

Nie przechowuj tych ciągów, przechowuj ich (kryptograficzny) skrót.

(Kryptograficzna) funkcja skrótu, taka jak szyfrowanie, jest sposobem na przekształcenie łańcucha w „bełkot” (zwany hashem), ale w przeciwieństwie do szyfrowania, nie można uzyskać oryginalnego łańcucha z tego skrótu (chyba że można użyć siły lub skrótu funkcja jest zepsuta). Większość (jeśli nie wszystkie) funkcji skrótu pobiera ciąg o dowolnej długości i zwraca ciąg o stałej długości (w zależności od funkcji).

Jak sprawdzić, czy ciąg, który wprowadził użytkownik, jest poprawny? Ponieważ nie można uzyskać poprawnego ciągu z skrótu, jedyne, co można zrobić, to skasować przypuszczenie użytkownika i porównać go z poprawnym skrótem.

Ostrzeżenie (autor: Eric Lippert): NIE UŻYWAJ wbudowanej funkcji GetHashCodejako takiej - jej wynik może się różnić w zależności od wersji i platformy .NET, dzięki czemu Twój kod działa tylko na określonych wersjach i platformie .NET.

użytkownik49822
źródło
81
To jest rzeczywiście najlepsza odpowiedź. Pamiętaj jednak, że absolutnie pozytywnie nie wolno używać wbudowanego algorytmu skrótu dla ciągów . jest przeznaczony do robienia jednej rzeczy i tylko jednej rzeczy, a mianowicie do równoważenia tabeli mieszającej. Nie można przechowywać skrótów ciągów i używać ich jako uwierzytelniaczy wspólnego hasła, ponieważ autorzy środowiska wykonawczego .NET zastrzegają sobie prawo do zmiany algorytmu skrótu ciągów w dowolnym momencie z dowolnego powodu, a tak naprawdę robili to w przeszłości . Użyj standardowego skrótu o sile kryptograficznej lub zaimplementuj własny prosty skrót.
Eric Lippert,
4
To. Dokładnie. Jeśli użyjesz algorytmu takiego jak sha256 (istnieje wiele bibliotek, które to implementują, więc nie musisz pisać własnego), będziesz mieć coś, czego nie da się łatwo złamać i jest bardzo niezawodny.
Micheal Johnson
12
@Michael Johnson korzystający z soli znacznie utrudni korzystanie z tęczowych tabel, a użycie skrótu hasła, takiego jak bcrypt, spowoduje, że będzie on znacznie wolniejszy, a zatem trudniejszy do złamania. Ale ostatecznie pod koniec dnia wydaje się to zbyt wielkim wysiłkiem; użytkownik kupił grę, jeśli chce oszukiwać, to jest jej własny wybór
Melkor
2
@MichealJohnson: Rozciąganie klawiszy może nieco utrudnić takie brutalne ataki (powiedzmy około miliarda razy). Ale prawdziwym problemem z tą odpowiedzią jest to, że prawdopodobnie w pewnym momencie gra musi być w stanie powiedzieć graczowi, do którego łańcucha musi wejść. Chyba, że ​​te ciągi są rozwiązaniami jakiejś łamigłówki, którą gracz musi rozwiązać. Lub, jeśli ciągi nie są dostarczane online, nawet jeśli gra jest offline, coś w stylu kluczy licencyjnych w starym stylu.
Ilmari Karonen
5
@Sentinel Oznacza to, że rozgrywka może być różna dla różnych graczy. Naprawdę musimy wiedzieć, o jakich ciągach mówimy, jeśli są zawarte w książkach / znakach / oknie dialogowym w grze, jeśli są rozwiązaniami zagadek, w których rzeczywista odpowiedź nie jest przekazywana bezpośrednio graczowi, lub jeśli są generowane losowo. A jeśli są to słowa, zdania lub losowe znaki.
Micheal Johnson
106

To, co próbujesz zrobić, jest zarówno daremne, jak i bezcelowe.

Jest to daremne, ponieważ nie ma sposobu, aby poprawnie ukryć informacje znajdujące się na komputerze użytkownika. Każdy, kto poświęci wystarczająco dużo czasu, znajdzie to. Możesz to utrudnić, ale nigdy nie możesz temu zapobiec. Jeśli go zaszyfrujesz, musisz gdzieś przechowywać klucz szyfrujący i algorytm. Bez względu na to, ile warstw szyfrowania dodasz, najwyższa warstwa zawsze musi być niezaszyfrowana, aby gra mogła działać.

Jest to również bezcelowe, ponieważ żyjemy w erze Internetu. Kiedy Twoja gra stanie się po prostu popularna, hasła zostaną opublikowane w Internecie.

Wszystko, co możesz zrobić, to zaufać graczowi, że nie zrujnuje własnego doświadczenia w grze, wyszukując informacje, których gra nie powinna mu jeszcze powiedzieć. Zdecydowana większość graczy i tak nie rozpocznie inżynierii wstecznej. A jeśli nieliczni, którzy posiadają niezbędne umiejętności, robią to, to z własnej winy.

Philipp
źródło
38
Odwrotna inżynieria to gra sama w sobie! To jedyna poprawna odpowiedź - obecnie nie należy ukrywać informacji w grach dla jednego gracza, gracze będą mieli do nich dostęp, jeśli chcą.
Mephy
27
@TheBinaryGuy Bezpieczeństwo od czego? Twoi użytkownicy grają w grę offline . Jakie zagrożenie ujawnia kod? Gracz w końcu i tak powinien to odkryć, aby móc zagrać w grę! Ważną zasadą bezpieczeństwa jest to, że musisz określić smakołyk, przed którym się chronisz; jest to określane jako „model zagrożenia”.
jpmc26,
7
@TheBinaryGuy Oprócz innych kwestii, chciałbym zakwestionować sens używania „poprawionych” kodów dostępu - nawet bez sprawdzania kodów online / poprzez inżynierię wsteczną, po prostu zagranie w grę po raz drugi pozwoli już graczom przejść bezpośrednio sekcje gry (ponieważ znają już kody). Jeśli naprawdę chcesz „zmusić” graczy do zdobycia tych kodów, musisz zmienić je przy każdej rozgrywce (np. Mieć jakąś formę randomizacji)
UnholySheep
6
Ta odpowiedź ma kilka dobrych argumentów, ale drugi akapit jest niepoprawny. Nie musisz szyfrować łańcucha. Możesz to mieszać. Jeśli gracz może złamać skrót, zamiast tego będzie rabował konta bankowe, zostanie zatrudniony przez FBI lub coś w tym rodzaju. Pozostałe punkty są jednak ważne.
Pedro A
5
@Hamsterrific Wydaje mi się, że odpowiedź zakłada, że ​​potrzebujesz zapisanych ciągów, np. Aby pokazać je graczowi w pewnym momencie, co oznacza, że ​​haszowanie nie da rady.
Frank Hopkins,
4

Jeśli taka rzecz jest naprawdę pożądana, to zamiast mieszania, możesz rozważyć zbudowanie ciągów z numerycznej wartości wejściowej w czasie wykonywania.

Zaletą jest to, że jak wskazał @Philipp, próba ukrycia kodów w pliku wykonywalnym jest nieco bezcelowa, jeśli można się spodziewać, że zostaną opublikowane w Internecie. Zaszyfrowane czy nie, to samo słowo znalezione w Internecie i wprowadzone do gry da ten sam skrót i będzie działało tak czy inaczej.

Z wyjątkiem ... chyba że kod innej osoby nie działa dla ciebie. Co możesz w prosty sposób zrobić - nie w 100% odporne na manipulacje, ale dość trudne do obejścia dla przeciętnego użytkownika. Wszystko, co jest tak proste, jak „Generator nazw elfów online”, może zrobić (może być dowolnie proste, naprawdę nie wymaga dużo silnika tekstowego genov markov, wystarczy pobrać 4-5 sylab z losowej listy).

Po prostu wygeneruj liczbę specyficzną dla użytkownika lub maszyny, nie musi ona nawet być całkowicie unikalna ani bardzo odporna na manipulacje. Coś, co prawdopodobnie różni się u większości ludzi i jest mało prawdopodobne, aby zmieniało się regularnie, np. Nazwa sieciowa komputera, adres MAC lub identyfikator GUID dysku systemowego, cokolwiek (numer seryjny karty graficznej może być bardzo złypomysł, ponieważ użytkownicy prawdopodobnie uaktualnią procesory graficzne). Dodaj do tego kod numeryczny, do którego odnosi się kod odblokowujący, i wprowadź go do generatora słów. Ale bądź przygotowany na udzielenie odpowiedzi na pytania wsparcia, gdy gracze korzystają z dwóch komputerów lub zmieniają kartę sieciową (co jest niezwykłe, ale nie niemożliwe). Dobrym pomysłem może być wygenerowanie losowego identyfikatora tylko raz i zapisanie go z ustawieniami gry. W ten sposób przynajmniej nie psuje istniejących instalacji na tym samym komputerze, jeśli coś się zmieni.

Możesz też użyć numeru seryjnego gry, który jest unikalny i zadziała, jeśli użytkownik zmieni sprzęt (jak na ironię może to promować piractwo, ponieważ wspólne kody odblokowujące działają w przypadku pirackich seriali, ale nie dla legalnych klientów!).

Pamiętaj, że zapobieganie oszustwom nie musi być dobrą rzeczą. W trybie offline (tj. W grze niekonkurencyjnej) zazwyczaj nie ma problemu, jeśli użytkownik oszukuje i pobiera kody gdzieś, a nie z gry. Oszukuje tylko siebie. Kogo to obchodzi.
Z drugiej strony, zbyt wiele im przeszkadza, jeśli naprawdę chcą oszukiwać, to świetna okazja do pełnego wkurzania płacących klientów.

Więc ... zanim zrobisz coś w ten sposób, zastanów się dokładnie, czy naprawdę tego chcesz i czego chcesz. Całkiem możliwe, że ciągi czytelne dla człowieka (lub w trywialny sposób „nieczytelne” za pomocą xor) są po prostu wystarczająco dobre i rzeczywiście preferowane.

Damon
źródło
Jaki proces przewidujesz? Jeśli program generuje wartość skrótu po pobraniu, to musi mieć niehasowany ciąg znaków po pobraniu. Czy serwer zapyta klienta o informacje, a następnie wygeneruje skrót po stronie serwera?
Accumumulation
@Acccumulation: Jaki serwer? Q mówi „całkowicie offline”. Co prawdopodobnie oznacza program na płycie DVD (lub może plik do pobrania) plus numer seryjny. Masz więc wydarzenia 1,2,3,4, dla których musi istnieć hasło. Obliczasz na przykład, hash(serial + 1)aby uzyskać liczbę odpowiadającą pierwszemu kodowi. Następnie podaj to do generatora słów, który pobiera, powiedzmy, jedną sylabę z listy 16 na każde 4 bity wejściowe. Proszę bardzo, poszczególne „słowa” dla każdego użytkownika.
Damon
Jeśli jest to pobieranie, to jest pobierane z serwera. Jeśli program oblicza hash(serial+1) po pobraniu, co powstrzyma użytkownika przed obliczeniem hash(serial+1)? Po pobraniu programu użytkownik ma dostęp do wszystkiego, co robi program.
Kumulacja
@Acccumulation: Nic nie stoi na przeszkodzie, aby użytkownik najpierw zdekompilował program, a następnie dokonał obliczeń hash(serial + 1). Więc co? To nie jest problem. Spójrz, jeśli ktoś zainwestuje od jednej do dwóch godzin (prawdopodobnie 6-8 godzin dla typowego „użytkownika” bez doświadczenia programisty) tylko po to, aby się oszukiwać, no cóż… pozwól mu. Chodzi o to, że działa to dla jednej osoby, ale nie dla wszystkich i nie jest konkurencyjne ... więc nie ma problemu.
Damon,
3

Jeśli nie musisz pokazywać ciągów, prawdopodobnie masz pomysł na haszowanie. Z drugiej strony, jeśli musisz pokazać je użytkownikowi, istnieje kilka innych sposobów, aby uniknąć ich bezpośredniego wyświetlania w bibliotece DLL.

Jednym ze sposobów radzenia sobie z tym oprócz szyfrowania lub innego zaciemniania łańcuchów jest ich rozbicie. Może po prostu masz posortowany alfabetycznie słownik wszystkich możliwych słów ze wszystkich ciągów w grze. Następnie umieść gdzieś tablicę, która pozwala ci poskładać słowa w potrzebny ciąg przez indeksowanie do tablicy słów. W ten sposób nie masz kompletnych ciągów nigdzie w grze. Do odszyfrowania ciągów nie jest potrzebny klucz główny. Dane określające ich kolejność mogą znajdować się w całym źródle, jeśli na przykład każda funkcja, która użyła łańcucha, ma tablicę indeksów lokalnych dla funkcji. Nie jestem pewien, jak praktyczne jest to w twoim konkretnym przypadku, ale jest to jeden ze sposobów na zrobienie tego.

Być może łańcuch składa się z kilku słów, ale ostatecznie są ułożone w różnych porządkach. Na przykład mogą być potrzebne następujące 2 ciągi:

  1. Niedźwiedź przeszedł przez mój dom
  2. Mój dom chronił mnie przed niedźwiedziem

Twoja lista fraz zawierałaby zarówno „niedźwiedzia”, jak i „mojego domu”, ale miałbyś dużą listę innych fraz, które można by umieścić między nimi, więc zastanawianie się, który z nich byłby tak samo trudny, jak faktyczne puzzle w grze (lub cokolwiek innego). Na przykład, zwroty akcji mogą być „przechodzone”, „spalone”, „przepchnięte”, „chronione przed”, „oddzielone od”, „magicznie wyprodukowane” itp.

Możesz to wykorzystać w swojej grze, ustawiając indeksy na podstawie tego, co gracz zebrał lub zrobił. Dlatego w grze nie będzie głównej listy indeksów. Zostaną one wygenerowane przez gracza grającego w grę.

użytkownik1118321
źródło
4
Zamiast znajdować funkcję, która odwołuje się do określonego ciągu, znajduje się funkcja, która odwołuje się do tablicy z indeksami, a następnie odtwarza ciąg. To nie wydaje się więcej niż dodatkowe 30 sekund ochrony. To, przed czym chroni, to ktoś, kto po prostu korzysta stringsz pliku wykonywalnego.
Voo
Jak powiedziałem, jeśli tablice odwołujące się do łańcuchów są rozdzielane na wszystkie funkcje, które ich potrzebują, to jest to trochę trudniejsze niż znalezienie pojedynczej tablicy w jednej funkcji. Nie niemożliwe, ale obejmuje większy obszar bez dużo dodatkowej pracy.
user1118321,
Czy to nie jest tylko mniejsza forma szyfrowania?
Arturo Torres Sánchez
2
Poczekaj, nawet szyfrowanie. Tylko kodowanie.
Arturo Torres Sánchez
2
Zaktualizowałem odpowiedź, aby była bardziej przejrzysta. Zasadniczo, jeśli indeksy są oparte na czymś, co zrobił gracz, to tak naprawdę nie są przechowywane w grze. Ponownie może nie być głupi lub idealny, ale umieszczam go tutaj jako opcję, którą ludzie mogą chcieć odkryć.
user1118321,