Unityでプレイヤーから文字列を完全に非表示にして保護するにはどうすればよいですか?


47

私はUnityを使用して完全にオフラインになる2Dゲームを作成しました(これが問題です)、ゲームプレイでは特定のレベルで特定の文字列を入力する必要があり、UnityはDLLにコンパイルされます。これは簡単にリバースエンジニアリングできますそれらの文字列を保護する方法はありますか(ゲームはオフラインなので、他のソースから取得できません)?

ゲームはこれらの文字列に大きく依存しており、はい、私は難読化に気付いていますが、もっと堅牢なものが欲しいです。そして、私は簡単な方法はデータソースからすべてをオンラインで行うことであることを知っていますが、それが可能かどうか疑問に思っていました。

次のように逆コンパイルできます。 ここに画像の説明を入力してください


10
私はそれがあなたが本当に勝つことができない戦いであることに同意しますが、あなたはわずかな努力で間違いなくそれをより難しくすることができます。obfuscar.codeplex.com
ジェイコブペルシ

46
@Gabrieleえ?難読化されていないC#コードの逆コンパイルは、取得と同じくらい簡単です。そのようにして、完全に読み取り可能なコードを取得できます。これを、最適化されたCまたはC ++コード用にIDAが生成するものと比較してください。とはいえ、十分な労力でネイティブコードを理解することはできますが、桁違いに難しくなります。難読化がどれほどうまく機能するかはわかりません-通常のデコンパイラー(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

それらの文字列を保存せず、それらの(暗号化)ハッシュを保存します。

暗号化のような(暗号化)ハッシュ関数は、文字列を「ギブリッシュ」(ハッシュと呼ばれる)に変換する方法ですが、暗号化とは異なり、このハッシュから元の文字列を取得することはできません(ブルートフォースまたはハッシュ機能が壊れています)。ほとんどの(すべてではないにしても)ハッシュ関数は、任意の長さの文字列を受け取り、一定の長さの文字列を返します(関数によって異なります)。

ユーザーが入力した文字列が正しいことをどのように確認しますか?ハッシュから有効な文字列を取得できないため、できることはユーザーの推測をハッシュし、正しいハッシュと比較することだけです。

警告(Eric Lippert作):組み込み関数GetHashCodeをそのような関数として使用しないでください。その結果は.NETバージョンとプラットフォームによって異なる可能性があり、コードは特定の.NETフレームワークバージョンとプラットフォームでのみ動作します。


81
これは確かに最良の答えです。ただし、文字列に組み込みのハッシュアルゴリズム絶対に使用しないでください。1つのことと1つのことだけを行うように設計されており、それはハッシュテーブルのバランスを取ることです。.NETランタイムの作成者は、理由を問わずいつでも文字列ハッシュアルゴリズムを変更する権利を留保しているため、実際には過去にそうしているため、文字列のハッシュを保存して共有秘密の認証子として使用することはできません。暗号強度の標準ハッシュを使用するか、独自の単純なハッシュを実装します。
エリックリッパー

4
この。まさに。sha256などのアルゴリズムを使用する場合(これを実装するライブラリが多数あるため、独自のライブラリを作成する必要はありません)、簡単に壊れることがなく、非常に信頼性の高いものが得られます。
マイケルジョンソン

12
@Michael Johnsonはソルトを使用すると、レインボーテーブルを使用するのがはるかに難しくなり、bcryptのようなパスワードハッシュを使用すると、はるかに遅くなり、解読が難しくなります。しかし、結局のところ、これは最終的にはあまりにも多くの労力を費やしているように思えます。彼らは自分の選択であることカンニングしたい場合は、ユーザーがゲームを買った
Melkor

2
@MichealJohnson:キーストレッチにより、このようなブルー​​トフォース攻撃が少し難しくなる可能性があります(たとえば、10億倍程度)。しかし、この答えの本当の問題は、おそらく、ある時点で、どの文字列を入力する必要があるかをゲームがプレイヤーに伝える必要があることです。これらの文字列が実際にプレイヤーが解決する必要のある種のパズルの解決策でない限り、私は推測します。または、ゲームがオフラインであっても、文字列がオンラインで提供されない限り、古いスタイルのライセンスキーのようなものです。
イルマリカロネン

5
@Sentinelこれは、プレイヤーによってゲームプレイが異なる可能性があることを意味します。ゲーム内の本/サイン/ダイアログに含まれている場合、実際の答えがプレイヤーに直接与えられないパズルの解決策である場合、話している文字列の種類を本当に知る必要があります。または、それらがランダムに生成される場合。単語、文章、またはランダムな文字の場合。
マイケルジョンソン

106

あなたがやろうとしていることは無駄で無意味です。

ユーザーのマシン上にある情報を適切に隠す方法がないため、無駄です。十分に熱心な人なら誰でも見つけるでしょう。難しくすることはできますが、決して防ぐことはできません。暗号化する場合は、暗号化キーとアルゴリズムをどこかに保存する必要があります。追加する暗号化の層の数に関係なく、ゲームを実行するには、常に一番外側の層の暗号化を解除する必要があります。

私たちはインターネット時代に生きているので、それも無意味です。あなたのゲームがリモートで人気を博すと、それらのパスコードはウェブ全体に投稿されます。

できるのは、ゲームがまだ伝えてはならない情報を調べることで、プレイヤーが自分のゲーム体験を台無しにしないことを信頼することだけです。とにかく、大半のプレイヤーはゲームのリバースエンジニアリングを開始しません。そして、必要なスキルを持っている少数がこれをするならば、それは彼ら自身の責任です。


38
リバースエンジニアリングは独自のゲームです!これが唯一の正しい答えです。最近のシングルプレイヤーゲームでは情報を非表示にしないでください。プレイヤーは必要に応じて情報にアクセスします。
Mephy

27
@TheBinaryGuy安全性は何ですか?ユーザーはオフラインゲームをプレイしています。コードを公開する脅威は何ですか?プレーヤーは、ゲームをプレイできるようになるためにとにかくそれを発見することになっています!セキュリティの重要なルールは、保護元の御treat走を特定する必要があることです。これは「脅威モデル」と呼ばれます。
jpmc26

7
@TheBinaryGuy他のポイントに加えて、「固定」パスコードを使用することの感性に疑問を呈します。コードをオンライン/リバースエンジニアリングで検索しなくても、ゲームを2回プレイするだけでプレーヤーはすぐにスキップできますゲームのセクション(既にコードを知っているため)。これらのコードを獲得するためにプレーヤーを「強制」したい場合は、プレイスルーごとに変更する必要があります(例:何らかの形式のランダム化が必要)
UnholySheep

6
この答えにはいくつかの良い点がありますが、2番目の段落は間違っています。文字列を暗号化する必要はありません。ハッシュできます。プレイヤーがハッシュを破ることができる場合、代わりに彼は銀行口座を強奪し、FBI、またはそのようなものに雇われます。ただし、他のポイントは有効です。
ペドロA

5
@Hamsterrific答えは、実際の文字列を保存する必要があることを前提としています。たとえば、ある時点でプレーヤーに表示するため、ハッシュは実行されません。
フランクホプキンス

4

そのようなことが本当に必要な場合は、ハッシュする代わりに、実行時に数値入力値から文字列を構築することを検討できます。

利点は、@ Philippが指摘しているように、とにかくインターネット上に投稿されることが予想される場合、実行可能ファイル内のコードを隠そうとすることは無意味です。ハッシュされているかどうかにかかわらず、インターネット上で見つかってゲームに入力された同じ単語は同じハッシュを与え、どちらの方法でも機能します。

ただし、他の誰かのコードが機能しない場合を除きます。簡単にできること-100%の改ざん防止ではありませんが、平均的なユーザーにとっては回避するのはかなり難しいです。「オンラインエルフ名ジェネレータ」と同じくらい簡単なこと(任意に簡単にでき、実際には多くのマルコフテキスト生成エンジンを必要とせず、ランダムリストから4-5音節を引き出すだけで十分です)。

多少ユーザー固有またはマシン固有の番号を生成するだけで、完全に一意である必要も、改ざん防止する必要もありません。コンピュータのネットワーク名、MACアドレス、システムディスクドライブのGUIDなど、ほとんどの人にとってはおそらく異なるものであり、定期的に変更される可能性の低いもの(GPUシリアル番号は非常に悪いかもしれません)ユーザーがGPUをアップグレードする可能性が高いためです。それにロック解除コードが参照する数値コードを追加し、それをワードジェネレーターにフィードします。ただし、プレーヤーが2台のコンピューターを使用する場合や、ネットワークカードを変更する場合(これは珍しいことではありませんが、不可能ではありません)、サポートクエリに答える準備をしてください。ランダムIDを1回だけ生成し、ゲームの設定で保存するのは良い計画かもしれません。そうすれば、少なくとも何かが変わっても同じマシン上の既存のインストールが壊れることはありません。

または、一意のゲームのシリアル番号を使用するだけで、ユーザーがハードウェアを変更した場合に機能します(ただし、皮肉なことに、共有ロック解除コードは海賊版のシリアルでは機能しますが、正当な顧客では機能しないため、海賊行為を促進する可能性があります!)

ユーザーの不正行為を防ぐことは必ずしも良いことではないことに注意してください。オフライン(非競合ゲーム)では、ユーザーがプレイからではなく、どこかからコードをごまかして取得しても、通常は問題ありません。彼はごまかしているだけです。誰も気にしない。
一方で、彼らが本当に不正をしたい場合に邪魔になりすぎることは、有料の顧客を完全に怒らせる絶好の機会です。

だから...あなたがそのように何かをする前に、あなたが本当にそれを望むかどうか、そしてあなたが望むものを非常に徹底的に考えてください。おそらく、人間が読める文字列(またはxorを使用して「読めない」ようにする)で十分であり、実際に望ましいものです。


どのようなプロセスを想定していますか?プログラムがダウンロード後にハッシュ値を生成する場合、ダウンロード時にハッシュされていない文字列が必要です。サーバーはクライアントに識別情報を照会し、ハッシュサーバー側を生成しますか?
蓄積

@Acccumulation:どのサーバーですか?Qは「完全にオフライン」と言います。これはおそらく、DVD上のプログラム(またはダウンロード)とシリアル番号を意味します。したがって、パスコードが存在する必要があるイベント1、2、3、4があります。たとえばhash(serial + 1)、最初のコードに対応する番号を取得するために計算します。次に、それをワードジェネレータに入力します。ワードジェネレータは、入力の4ビットごとに16のリストから1つの音節を取り出します。すべてのユーザーの個別の「単語」が表示されます。
デイモン

ダウンロードの場合は、サーバーからダウンロードされています。ダウンロードhash(serial+1) にプログラムが計算する場合、ユーザーの計算を停止するにはどうすればよいhash(serial+1)ですか?プログラムがダウンロードされると、ユーザーはプログラムが実行するすべてにアクセスできます。
累積

@Acccumulation:ユーザーが最初にプログラム逆コンパイルしてから計算することを妨げるものはありませんhash(serial + 1)。だから何?これは問題ではありません。誰かが1〜2時間(ソフトウェア開発者のバックグラウンドを持たない典型的な「ユーザー」の場合はおそらく6〜8時間)を投資して、ごまかしているなら... 問題は、これは1人で機能しますが、すべての人で機能するわけではなく、競争力がないということです。したがって、問題はありません。
デイモン

3

文字列を表示する必要がない場合は、ハッシュ化のアイデアがおそらく道です。一方、ユーザーにそれらを表示する必要がある場合は、DLLに直接表示されないようにする他の方法があります。

文字列を暗号化または難読化する以外にこれに対処する1つの方法は、文字列を分割することです。たぶん、ゲーム内のすべての文字列から考えられるすべての単語のアルファベット順にソートされた辞書があるだけかもしれません。次に、単語の配列にインデックスを付けて、必要な文字列に単語をつなげることができる配列をどこかに作成します。この方法では、ゲームのどこにも完全な文字列がありません。文字列を復号化するために必要なマスターキーはありません。また、たとえば、文字列を使用する各関数に、その関数に対してローカルなインデックスの配列がある場合、順序を示すデータはソース全体に存在する可能性があります。それがあなたの特定のケースでどれほど実用的かは分かりませんが、それはそれを行う一つの方法です。

いくつかの単語で構成された文字列を使用することもできますが、それらは最終的に異なる順序で配置されます。たとえば、次の2つの文字列が必要になる場合があります。

  1. 熊が私の家を歩いた
  2. 私の家はクマから私を守った

フレーズのリストには「クマ」と「私の家」の両方が含まれますが、それらの間に入れることができる他のフレーズの大きなリストがあるので、実際に把握するのと同じくらい難しいものを把握してくださいゲーム内のパズル(または何でも)。たとえば、アクションフレーズは「ウォークスルー」、「バーンダウン」、「プッシュオーバー」、「保護された」、「分離された」、「魔法のプロデュース」などです。

プレイヤーが収集または実行したものに基づいてインデックスを作成することで、これをゲームに組み込むことができます。そのため、ゲーム内のどこにもインデックスのマスターリストはありません。それらは、ゲームをプレイするプレイヤーによって生成されます。


4
そのため、特定の文字列を参照する関数を見つける代わりに、インデックス付きの配列を参照する関数を見つけて、文字列を再作成します。それは、余分な30秒の保護以上のものではないようです。それに対して保護するのはstrings、実行可能ファイルに対して誰かが使用しているだけです。
Voo

先ほど言ったように、文字列を参照する配列がそれらを必要とするすべての関数に分散している場合、単一の関数で単一の配列を見つけるよりも少し難しくなります。不可能ではありませんが、多くの余分な作業をせずに広い領域をカバーします。
user1118321

これは単なる暗号化の形式ではありませんか?
アルトゥーロトーレスサンチェス

2
暗号化すらしないでください。エンコードのみ。
アルトゥーロトーレスサンチェス

2
答えをより明確にするために更新しました。基本的に、インデックスがプレイヤーが行ったことに基づいている場合、実際にはゲームに保存されません。繰り返しになりますが、それは絶対確実なものでも完璧でもないかもしれませんが、私はここで人々が探検したいと思うかもしれないオプションとしてそれを置いています。
user1118321
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.