Bagaimana saya bisa sepenuhnya menyembunyikan dan melindungi string dari pemain di Unity?

47

Saya telah menggunakan Unity untuk membuat game 2D yang akan sepenuhnya offline (yang merupakan masalah), permainan-permainannya mengharuskan Anda memasukkan string tertentu pada level tertentu dan Unity mengkompilasi ke DLL, yang dapat dengan mudah direkayasa balik, demikian juga ada cara untuk melindungi string-string itu (game sedang offline jadi saya tidak bisa mengambil dari sumber lain)?

Permainan ini sangat bergantung pada string-string itu, dan ya saya sadar Kebingungan tetapi saya menginginkan sesuatu yang lebih kuat. Dan saya tahu bahwa jalan keluar yang mudah adalah melakukan segala sesuatu secara online dari sumber data, tetapi saya bertanya-tanya apakah itu mungkin.

Itu dapat didekompilasi seperti ini: masukkan deskripsi gambar di sini

TheBinaryGuy
sumber
10
Meskipun saya setuju ini adalah pertarungan yang tidak dapat Anda menangkan, Anda pasti dapat membuatnya lebih sulit dengan sedikit usaha. obfuscar.codeplex.com
Jacob Persi
46
@Gabriele Hah? Mengurai kode C # yang tidak membingungkan adalah semudah yang didapat. Anda mendapatkan kode yang cukup mudah dibaca dengan cara itu, bandingkan dengan apa yang dihasilkan IDA untuk kode C atau C ++ yang dioptimalkan. Yang mengatakan dengan upaya yang cukup kode asli bisa sama banyak dipahami, tetapi urutan besarnya lebih sulit. Tidak tahu seberapa baik kebingungan bekerja - jika itu membuat dekompiler biasa (DotPeek, ILSpy, sesuatu yang lain?) Muntah pada kode IL yang seharusnya memperkenalkan penghalang untuk menjaga orang biasa menjauh dari itu.
Voo
15
@GabrieleVierti, menarik teks dari DLL adalah sepele: di Linux atau Cygwin, Anda dapat melakukannya hanya dengan mengarahkan stringsprogram ke sana.
Markus
31
Apa sebenarnya yang kamu coba lakukan di sini? Ini terdengar seperti kasus XY yang agak parah. meta.stackexchange.com/questions/66377/what-is-the-xy-problem Apa pun yang Anda coba capai (dari perspektif gameplay, bukan perspektif teknis) hampir pasti bukan yang terbaik dilayani dengan mencoba menyembunyikan dan mengenkripsi string ini. .
GrandOpener
36
Saya bertanya-tanya apakah menyembunyikan string benar-benar bermanfaat: Setelah beberapa pemain menyelesaikannya, mereka kemungkinan besar akan menyebar dalam wiki atau sejenisnya, sehingga siapa pun yang ingin mengenal mereka akan dengan mudah dapat mencari mereka. Ya, dengan mengaburkan mereka, pemain tidak bisa hanya membuka dll dalam editor teks dan mencari string, tetapi sebagian besar akan berkonsultasi dengan google (atau mesin pencari pilihan mereka) terlebih dahulu ...
hoffmale

Jawaban:

159

Jangan simpan string-string itu, simpan hash (kriptografis) dari mereka.

Fungsi hash (kriptografi), seperti enkripsi, adalah cara untuk mengubah string menjadi "omong kosong" (disebut hash), tetapi tidak seperti enkripsi, Anda tidak bisa mendapatkan string asli dari hash ini (kecuali jika Anda dapat dengan paksa memaksakannya atau hash fungsi rusak). Sebagian besar (jika tidak semua) fungsi hash mengambil string dengan panjang sewenang-wenang dan mengembalikan string dengan panjang konstan (tergantung pada fungsinya).

Bagaimana Anda memeriksa bahwa string yang dimasukkan pengguna adalah yang benar? Karena Anda tidak bisa mendapatkan string yang valid dari hash, satu-satunya hal yang dapat Anda lakukan adalah dengan hash tebakan pengguna dan membandingkannya dengan hash yang benar.

Peringatan (oleh Eric Lippert): JANGAN GUNAKAN fungsi bawaan GetHashCodesebagai fungsi - hasilnya dapat berbeda antara versi .NET dan platform yang berbeda, membuat kode Anda hanya berfungsi pada versi dan platform kerangka kerja .NET tertentu.

pengguna49822
sumber
81
Ini memang jawaban terbaik. Tapi ingat bahwa Anda benar-benar positif tidak boleh menggunakan algoritma hash bawaan pada string . itu dirancang untuk melakukan satu hal dan satu hal saja dan itu adalah untuk menyeimbangkan tabel hash. Anda tidak dapat menyimpan hash string dan menggunakannya sebagai autentikator dari rahasia bersama karena .NET runtime author berhak untuk mengubah algoritma hashing string kapan saja dengan alasan apa pun dan bahkan mereka telah melakukannya di masa lalu . Gunakan hash standar crypto-strength, atau terapkan hash sederhana Anda sendiri.
Eric Lippert
4
Ini. Persis. Jika Anda menggunakan algoritma seperti sha256 (ada banyak perpustakaan yang mengimplementasikan ini sehingga Anda tidak perlu menulis sendiri) maka Anda akan memiliki sesuatu yang tidak dapat dipecahkan dengan mudah dan sangat dapat diandalkan.
Micheal Johnson
12
@Michael Johnson menggunakan garam akan membuatnya lebih sulit untuk menggunakan tabel pelangi, dan menggunakan kata sandi hash seperti bcrypt akan membuatnya lebih lambat dan karenanya lebih sulit untuk dipatahkan. Tetapi pada akhirnya di akhir hari ini sepertinya terlalu banyak upaya untuk dilakukan; pengguna telah membeli permainan jika mereka ingin menipu itu adalah pilihan mereka sendiri
Melkor
2
@MichealJohnson: Peregangan kunci bisa membuat serangan brute force sedikit lebih sulit (katakanlah, dengan faktor satu miliar atau lebih). Tetapi masalah sebenarnya dengan jawaban ini adalah bahwa, mungkin, pada suatu titik permainan harus bisa memberi tahu pemain mana string yang mereka harus masukkan. Kecuali jika string-string itu sebenarnya adalah solusi untuk beberapa jenis teka-teki yang perlu dipecahkan oleh pemain, saya kira. Atau kecuali string disediakan secara online, meskipun gim ini offline, semacam kunci lisensi gaya lama.
Ilmari Karonen
5
@Sentinel Itu artinya gameplay mungkin berbeda untuk pemain yang berbeda. Kita benar-benar perlu tahu jenis string apa yang kita bicarakan, jika mereka terkandung dalam buku / tanda / dialog dalam game, jika mereka solusi untuk teka-teki di mana jawaban sebenarnya tidak diberikan kepada pemain secara langsung, atau jika itu dihasilkan secara acak. Dan jika itu kata-kata, kalimat, atau karakter acak.
Micheal Johnson
106

Apa yang Anda coba lakukan itu sia-sia dan sia-sia.

Itu sia-sia karena tidak ada cara untuk menyembunyikan informasi yang ada di mesin pengguna. Siapa pun yang cukup berdedikasi akan menemukannya. Anda bisa membuatnya lebih sulit, tetapi Anda tidak pernah bisa mencegahnya. Jika Anda mengenkripsi itu, maka Anda perlu menyimpan kunci dan algoritma enkripsi di suatu tempat. Tidak peduli berapa banyak lapisan enkripsi yang Anda tambahkan, lapisan terluar akan selalu perlu dienkripsi agar permainan Anda dapat berjalan.

Ini juga tidak ada gunanya, karena kita hidup di era internet. Ketika game Anda menjadi sangat populer, maka kode sandi itu akan diposting di seluruh web.

Yang bisa Anda lakukan adalah mempercayai pemain untuk tidak merusak pengalaman gim mereka sendiri dengan mencari informasi yang seharusnya tidak diceritakan oleh gim itu kepada mereka. Sebagian besar pemain tidak akan memulai rekayasa ulang permainan Anda. Dan jika beberapa yang memiliki keterampilan yang diperlukan melakukan ini, maka itu adalah kesalahan mereka sendiri.

Philipp
sumber
38
Reverse engineering adalah permainannya sendiri! Ini adalah satu-satunya jawaban yang benar - orang tidak boleh menyembunyikan informasi dalam permainan pemain tunggal saat ini, pemain akan mengaksesnya jika mereka mau.
Mephy
27
@TheBinaryGuy Safety dari apa? Pengguna Anda memainkan game offline . Ancaman apa yang memunculkan kode? Pemain pada akhirnya seharusnya menemukannya untuk tetap dapat memainkan game! Aturan keamanan yang penting adalah bahwa Anda harus mengidentifikasi perlakuan yang melindungi Anda; ini disebut sebagai "model ancaman."
jpmc26
7
@TheBinaryGuy Selain poin-poin lainnya, saya akan mempertanyakan kepekaan menggunakan kode akses "tetap" - bahkan tanpa melihat kode secara online / melalui rekayasa balik, hanya dengan memainkan game untuk kedua kalinya sudah akan memungkinkan pemain untuk langsung melewati bagian dari permainan (karena mereka sudah tahu kodenya). Jika Anda benar-benar ingin "memaksa" pemain untuk mendapatkan kode-kode ini, Anda perlu membuatnya berubah pada setiap permainan (mis: memiliki beberapa bentuk pengacakan)
UnholySheep
6
Jawaban ini memiliki beberapa poin bagus tetapi paragraf kedua salah. Anda tidak perlu mengenkripsi string. Anda dapat hash itu. Jika seorang pemain dapat memecahkan hash, maka ia akan merampok rekening bank, akan disewa oleh FBI, atau sesuatu seperti itu. Poin lainnya valid.
Pedro A
5
@Hamster Saya kira jawabannya mengasumsikan Anda membutuhkan string yang sebenarnya untuk disimpan, misalnya untuk menunjukkannya kepada pemain di beberapa titik, yang berarti hashing tidak akan berhasil.
Frank Hopkins
4

Jika hal seperti itu benar-benar diinginkan, maka alih-alih hashing, Anda dapat mempertimbangkan membangun string dari nilai input numerik saat runtime.

Keuntungannya adalah seperti yang ditunjukkan oleh @Philipp, agak tidak ada gunanya untuk mencoba dan menyembunyikan kode yang dapat dieksekusi jika Anda dapat mengharapkannya diposting di internet. Hash atau tidak, kata yang sama ditemukan di internet dan dimasukkan ke dalam permainan akan memberikan hash yang sama dan akan bekerja dengan cara baik.

Kecuali ... kecuali jika kode orang lain tidak bekerja untuk Anda. Yang bisa Anda lakukan sepele - bukan 100% anti-perusakan tetapi cukup sulit untuk dikerjakan untuk pengguna biasa. Apa pun yang sesederhana "Generator nama Elven Online" akan dilakukan (bisa semena-mena sederhana, benar-benar tidak memerlukan banyak mesin gen teks markov, menarik 4-5 suku kata dari daftar acak cukup baik).

Hanya menghasilkan angka yang agak spesifik untuk pengguna atau mesin, itu bahkan tidak harus benar-benar unik atau sangat tahan-rusak. Sesuatu yang mungkin berbeda bagi kebanyakan orang, dan tidak mungkin berubah secara teratur, misalnya nama jaringan komputer, alamat MAC, atau GUID dari drive disk sistem, apa pun (nomor seri GPU mungkin sangat buruk)ide karena pengguna cenderung untuk meningkatkan GPU). Tambahkan ke kode numerik yang ditunjuk oleh kode buka kunci, dan masukkan itu ke dalam generator kata Anda. Tetapi bersiaplah untuk menjawab pertanyaan dukungan ketika pemain menggunakan dua komputer atau mengganti kartu jaringan mereka (yang tidak biasa, tetapi bukan tidak mungkin). Mungkin rencana yang bagus untuk hanya menghasilkan ID acak satu kali, dan menyimpannya dengan pengaturan game. Dengan begitu, setidaknya itu tidak merusak instalasi yang ada pada mesin yang sama jika ada perubahan.

Atau, Anda mungkin hanya menggunakan nomor seri gim yang unik dan akan berfungsi jika pengguna mengubah perangkat keras (ironisnya, bagaimanapun, ini dapat mempromosikan pembajakan karena kode buka bersama yang digunakan berfungsi untuk serial bajakan tetapi tidak untuk pelanggan yang sah!).

Perhatikan bahwa mencegah pengguna dari kecurangan tidak selalu merupakan hal yang baik. Dalam permainan offline (yaitu game yang tidak bersaing) biasanya tidak ada masalah jika pengguna menipu dan mendapatkan kode dari suatu tempat daripada dari bermain. Dia hanya menipu dirinya sendiri. Siapa peduli.
Di sisi lain, terlalu banyak menghalangi mereka jika mereka benar-benar ingin menipu adalah peluang besar untuk benar - benar mengecewakan pelanggan yang membayar.

Jadi ... sebelum Anda melakukan sesuatu seperti itu, pikirkan dengan seksama apakah Anda benar-benar menginginkan itu, dan apa yang Anda inginkan. Sangat mungkin, memiliki string yang dapat dibaca manusia (atau secara sepele membuat "tidak dapat dibaca" dengan xor) cukup baik dan memang lebih disukai.

Damon
sumber
Proses apa yang Anda bayangkan? Jika program menghasilkan nilai hash setelah diunduh, maka harus memiliki string yang tidak rusak saat diunduh. Jadi apakah server akan meminta klien untuk mengidentifikasi informasi dan kemudian menghasilkan sisi server hash?
Akumulasi
@Akumulasi: Server apa? Q mengatakan "sepenuhnya offline". Yang mungkin berarti program pada DVD (atau mungkin unduhan) plus nomor seri. Jadi, Anda memiliki acara 1,2,3,4 di mana kode sandi harus ada. Misalnya Anda menghitung untuk hash(serial + 1)mendapatkan nomor yang sesuai dengan kode pertama. Kemudian masukkan itu ke dalam generator kata Anda, yang menarik, katakanlah, satu suku kata dari daftar 16 untuk setiap 4 bit input. Ini dia, "kata-kata" individual untuk setiap pengguna.
Damon
Jika itu unduhan, maka itu sedang diunduh dari server. Jika program menghitung hash(serial+1) setelah diunduh, apa yang membuat pengguna berhenti menghitung hash(serial+1)? Setelah program diunduh, pengguna memiliki akses ke semua yang dilakukan oleh program.
Akumulasi
@Accumulation: Tidak ada yang mencegah pengguna dari pertama mendekompilasi program dan kemudian menghitung hash(serial + 1). Terus? Ini bukan masalah. Dengar, jika seseorang berinvestasi satu hingga dua jam (mungkin 6-8 jam untuk "pengguna" yang khas tanpa latar belakang pengembang perangkat lunak) hanya untuk menipu dirinya sendiri, yah ... biarkan dia. Masalahnya, ini bekerja untuk satu orang, tetapi tidak untuk semua orang, dan itu tidak kompetitif ... jadi, tidak masalah.
Damon
3

Jika Anda tidak perlu menunjukkan string, maka ide hashing mungkin adalah cara yang harus dilakukan. Jika, di sisi lain, Anda perlu menunjukkannya kepada pengguna, ada beberapa cara lain untuk menghindarinya agar tidak langsung muncul di DLL Anda.

Salah satu cara untuk mengatasinya selain mengenkripsi atau mengaburkan string adalah dengan memecahnya. Mungkin hanya memiliki kamus yang diurutkan berdasarkan abjad dari semua kata yang mungkin dari semua string dalam permainan. Kemudian miliki array di suatu tempat yang memungkinkan Anda untuk menyatukan kata-kata ke dalam string yang Anda butuhkan dengan mengindeks ke dalam array kata-kata. Dengan cara ini Anda tidak memiliki string lengkap di mana pun dalam permainan. Tidak diperlukan kunci utama untuk mendekripsi string. Dan data yang memberi tahu urutannya bisa di seluruh sumber Anda, jika, misalnya, setiap fungsi yang menggunakan string hanya memiliki array indeks lokal ke fungsi. Saya tidak yakin seberapa praktis itu dalam kasus spesifik Anda, tapi itu salah satu cara untuk melakukannya.

Anda bahkan mungkin memiliki string yang terdiri dari beberapa kata, tetapi kata-kata tersebut akhirnya dimasukkan dalam urutan berbeda. Misalnya, Anda mungkin memerlukan 2 string berikut:

  1. Seekor beruang berjalan melewati rumah saya
  2. Rumah saya melindungi saya dari beruang

Daftar frasa Anda akan berisi "beruang" dan "rumah saya", tetapi Anda akan memiliki daftar besar frasa lain yang dapat dimasukkan di antara mereka, jadi mencari tahu mana yang akan sama sulitnya dengan benar-benar mencari tahu teka-teki dalam game (atau apa pun). Misalnya, frasa tindakan dapat "berjalan melalui", "dibakar", "didorong", "melindungi saya dari", "memisahkan saya dari", "diproduksi secara ajaib", dll.

Anda bisa mengerjakan ini dalam gim Anda dengan membuat indeks berdasarkan pada sesuatu yang telah dikumpulkan atau dilakukan pemain. Jadi tidak akan ada daftar utama indeks di mana pun di dalam permainan. Mereka akan dihasilkan oleh pemain yang memainkan game.

pengguna1118321
sumber
4
Jadi alih-alih menemukan fungsi yang mereferensikan string tertentu, Anda menemukan fungsi yang mereferensikan array dengan indeks dan kemudian membuat ulang string. Itu tampaknya tidak lebih dari perlindungan 30 detik tambahan. Apa yang dilindunginya adalah seseorang hanya menggunakan stringsterhadap dieksekusi sekalipun.
Voo
Seperti yang saya katakan, jika array yang mereferensikan string didistribusikan ke semua fungsi yang membutuhkannya, maka itu sedikit lebih sulit daripada hanya menemukan satu array dalam satu fungsi. Bukan tidak mungkin, tetapi mencakup area yang lebih luas tanpa banyak pekerjaan ekstra.
user1118321
Bukankah ini hanya bentuk enkripsi yang lebih rendah?
Arturo Torres Sánchez
2
Tunggu, bahkan enkripsi. Hanya penyandian.
Arturo Torres Sánchez
2
Saya sudah memperbarui jawabannya agar lebih jelas. Pada dasarnya, jika indeks didasarkan pada sesuatu yang telah dilakukan pemain, maka mereka sebenarnya tidak disimpan dalam permainan. Sekali lagi, itu mungkin bukan bukti bodoh, atau sempurna, tapi saya menempatkannya di sini sebagai pilihan yang mungkin ingin dijelajahi orang.
user1118321