Bagaimana cara mengunci kelas Java yang dikompilasi untuk mencegah dekompilasi?
Saya tahu ini pasti topik yang didiskusikan dengan sangat baik di Internet, tetapi saya tidak dapat mengambil kesimpulan apa pun setelah merujuk mereka.
Banyak orang menyarankan obfuscator, tetapi mereka hanya mengganti nama kelas, metode, dan bidang dengan urutan karakter yang sulit diingat, tetapi bagaimana dengan nilai konstanta sensitif?
Misalnya, Anda telah mengembangkan komponen enkripsi dan dekripsi berdasarkan teknik enkripsi berbasis kata sandi. Sekarang dalam kasus ini, setiap orang Java rata-rata dapat menggunakan JAD untuk mendekompilasi file kelas dan dengan mudah mengambil nilai kata sandi (didefinisikan sebagai konstan) serta garam dan pada gilirannya dapat mendekripsi data dengan menulis program independen kecil!
Atau haruskah komponen sensitif semacam itu dibangun dalam kode native (misalnya, VC ++) dan memanggilnya melalui JNI ?
sumber
Jawaban:
Beberapa pembuat obfuscode bytecode Java yang lebih canggih melakukan lebih dari sekadar mangling nama kelas. Zelix KlassMaster , misalnya, juga dapat mengacak aliran kode Anda dengan cara yang membuatnya sangat sulit untuk diikuti dan berfungsi sebagai pengoptimal kode yang sangat baik ...
Juga banyak obfuscator yang juga dapat mengacak konstanta string Anda dan menghapus kode yang tidak digunakan.
Solusi lain yang mungkin (tidak harus mengecualikan obfuscation) adalah dengan menggunakan file JAR terenkripsi dan classloader kustom yang melakukan dekripsi (sebaiknya menggunakan library runtime native).
Ketiga (dan mungkin menawarkan perlindungan terkuat) adalah menggunakan kompiler asli sebelumnya seperti GCC atau Excelsior JET , misalnya, yang mengompilasi kode Java Anda langsung ke biner asli khusus platform.
Bagaimanapun Anda harus ingat bahwa seperti kata pepatah dalam bahasa Estonia "Kunci untuk binatang". Artinya bahwa setiap bit kode tersedia (dimuat ke dalam memori) selama runtime dan diberi keterampilan, tekad, dan motivasi yang cukup, orang dapat dan akan mendekompilasi, menguraikan, dan meretas kode Anda ... Tugas Anda hanyalah membuat prosesnya tidak nyaman seperti Anda dapat dan tetap menjalankannya ...
sumber
Selama mereka memiliki akses ke data terenkripsi dan perangkat lunak yang mendekripsinya, pada dasarnya tidak ada cara Anda dapat membuat ini sepenuhnya aman. Cara memecahkan masalah ini sebelumnya adalah dengan menggunakan beberapa bentuk kotak hitam eksternal untuk menangani enkripsi / dekripsi, seperti dongle, server otentikasi jarak jauh, dll. Namun meskipun demikian, mengingat bahwa pengguna memiliki akses penuh ke sistem mereka sendiri, ini hanya membuat sesuatu sulit, bukan tidak mungkin -kecuali Anda dapat mengikat produk Anda secara langsung ke fungsionalitas yang disimpan dalam "kotak hitam", seperti, katakanlah, server game online.
sumber
Penafian: Saya bukan ahli keamanan.
Ini terdengar seperti ide yang buruk: Anda membiarkan seseorang mengenkripsi barang dengan kunci 'tersembunyi' yang Anda berikan padanya. Saya tidak berpikir ini bisa dibuat aman.
Mungkin kunci asimetris bisa berfungsi:
Saya tidak yakin, tapi saya yakin klien benar-benar dapat mengenkripsi kunci lisensi dengan kunci publik yang Anda berikan padanya. Anda kemudian dapat mendekripsikannya dengan kunci pribadi Anda dan juga mengenkripsi ulang.
Anda dapat menyimpan pasangan kunci publik / pribadi yang terpisah per pelanggan untuk memastikan Anda benar-benar mendapatkan barang dari pelanggan yang tepat - sekarang Anda bertanggung jawab atas kuncinya ...
sumber
Tidak peduli apa yang Anda lakukan, itu bisa 'diuraikan'. Heck, Anda bisa membongkar saja. Atau lihat dump memori untuk menemukan konstanta Anda. Soalnya, komputer perlu mengetahuinya, jadi kode Anda juga perlu.
Apa yang harus dilakukan tentang ini?
Cobalah untuk tidak mengirimkan kunci sebagai konstanta hardcode dalam kode Anda: Simpan sebagai pengaturan per pengguna. Buat pengguna bertanggung jawab untuk menjaga kunci itu.
sumber
@jatanp: atau lebih baik lagi, mereka dapat mendekompilasi, menghapus kode lisensi, dan mengkompilasi ulang. Dengan Java, saya rasa tidak ada solusi yang tepat dan anti retas untuk masalah ini. Bahkan dongle kecil yang jahat tidak bisa mencegah ini dengan Java.
Manajer bisnis saya sendiri mengkhawatirkan hal ini, dan saya terlalu banyak berpikir. Tapi sekali lagi, kami menjual aplikasi kami ke perusahaan besar yang cenderung mematuhi ketentuan perizinan - umumnya lingkungan yang aman berkat penghitung kacang dan pengacara. Tindakan mendekompilasi itu sendiri bisa ilegal jika lisensi Anda ditulis dengan benar.
Jadi, saya harus bertanya, apakah Anda benar - benar membutuhkan perlindungan yang diperkuat seperti Anda mencari aplikasi Anda? Seperti apa basis pelanggan Anda? (Korporasi? Atau massa gamer remaja, di mana ini akan lebih menjadi masalah?)
sumber
Jika Anda mencari solusi lisensi, Anda dapat melihat API TrueLicense . Ini didasarkan pada penggunaan kunci asimetris. Namun, bukan berarti aplikasi Anda tidak bisa di-crack. Setiap aplikasi dapat diretas dengan usaha yang cukup. Yang paling penting adalah, seperti jawab Stu , mencari tahu seberapa kuat perlindungan yang Anda butuhkan.
sumber
Saya rasa tidak ada metode antipiracy offline yang efektif. Industri videogame telah mencoba untuk menemukannya berkali-kali dan program mereka selalu retak. Satu-satunya solusi adalah program harus dijalankan secara online yang terhubung dengan server Anda, sehingga Anda dapat memverifikasi kunci lincense, dan hanya ada satu koneksi aktif oleh pemegang lisensi pada satu waktu. Beginilah cara kerja World of Warcraft atau Diablo . Bahkan sulit ada server pribadi yang dikembangkan untuk melewati keamanan.
Karena itu, saya tidak percaya bahwa perusahaan menengah / besar menggunakan perangkat lunak yang disalin secara ilegal, karena biaya lisensi untuk mereka minimal (mungkin, saya tidak tahu berapa banyak biaya yang harus Anda kenakan untuk program Anda) dibandingkan dengan biaya versi percobaan.
sumber
Anda dapat menggunakan enkripsi kode byte tanpa rasa takut.
Faktanya adalah bahwa makalah yang dikutip di atas "Mengacak enkripsi kode byte Java" berisi kesalahan logika. Klaim utama kertas sebelum menjalankan semua kelas harus didekripsi dan diteruskan ke
ClassLoader.defineClass(...)
metode . Tapi ini tidak benar.Asumsi yang terlewat di sini asalkan mereka berjalan dalam lingkungan run-time java yang otentik, atau standar . Tidak ada yang dapat mewajibkan aplikasi java yang dilindungi tidak hanya untuk meluncurkan kelas-kelas ini tetapi bahkan mendekripsi dan meneruskannya
ClassLoader
. Dengan kata lain, jika Anda menggunakan JRE standar, Anda tidak dapat mencegatdefineClass(...)
metode karena java standar tidak memiliki API untuk tujuan ini, dan jika Anda menggunakan JRE yang dimodifikasi dengan patchedClassLoader
atau "trik peretas" lainnya, Anda tidak dapat melakukannya karena dilindungi Aplikasi java tidak akan berfungsi sama sekali, dan oleh karena itu Anda tidak perlu melakukan apa pun. Dan sama sekali tidak masalah "pencari patch" mana yang digunakan atau trik mana yang digunakan oleh peretas. Detail teknis ini adalah cerita yang sangat berbeda.sumber
T: Jika saya mengenkripsi file .class saya dan menggunakan classloader khusus untuk memuat dan mendekripsinya dengan cepat, apakah ini akan mencegah dekompilasi?
J: Masalah dalam mencegah dekompilasi kode byte Java hampir sama tuanya dengan bahasanya itu sendiri. Meskipun berbagai alat kebingungan tersedia di pasaran, programmer Java pemula terus memikirkan cara baru dan cerdas untuk melindungi kekayaan intelektual mereka. Dalam angsuran Tanya Jawab Java ini, saya menghilangkan beberapa mitos seputar ide yang sering diulang di forum diskusi.
Sangat mudahnya file .class Java dapat direkonstruksi menjadi sumber Java yang sangat mirip dengan aslinya sangat berkaitan dengan tujuan dan trade-off desain kode byte Java. Antara lain, kode byte Java dirancang untuk kekompakan, kemandirian platform, mobilitas jaringan, dan kemudahan analisis oleh juru bahasa kode-byte dan kompiler dinamis JIT (just-in-time) / HotSpot. Bisa dibilang, file .class yang dikompilasi mengekspresikan maksud pemrogram dengan sangat jelas sehingga lebih mudah dianalisis daripada kode sumber aslinya.
Beberapa hal bisa dilakukan, jika tidak untuk mencegah pembusukan sepenuhnya, setidaknya membuatnya lebih sulit. Misalnya, sebagai langkah pasca-kompilasi, Anda dapat memijat data .class untuk membuat kode byte lebih sulit dibaca saat didekompilasi atau lebih sulit untuk didekompilasi menjadi kode Java yang valid (atau keduanya). Teknik seperti melakukan overloading nama metode ekstrim bekerja dengan baik untuk yang pertama, dan memanipulasi aliran kontrol untuk membuat struktur kontrol yang tidak mungkin untuk direpresentasikan melalui sintaks Java bekerja dengan baik untuk yang terakhir. Obfuscator komersial yang lebih sukses menggunakan campuran teknik ini dan lainnya.
Sayangnya, kedua pendekatan tersebut harus benar-benar mengubah kode yang akan dijalankan JVM, dan banyak pengguna takut (memang seharusnya demikian) bahwa transformasi ini dapat menambahkan bug baru ke aplikasi mereka. Selanjutnya, metode dan penggantian nama bidang dapat menyebabkan panggilan refleksi berhenti bekerja. Mengubah nama kelas dan paket sebenarnya dapat merusak beberapa Java API lainnya (JNDI (Penamaan Java dan Antarmuka Direktori), penyedia URL, dll.). Selain nama yang diubah, jika asosiasi antara offset kode byte kelas dan nomor baris sumber diubah, memulihkan jejak tumpukan pengecualian asli bisa menjadi sulit.
Lalu ada opsi untuk mengaburkan kode sumber Java asli. Tetapi pada dasarnya hal ini menyebabkan serangkaian masalah serupa. Enkripsi, bukan obfuscate?
Mungkin hal di atas telah membuat Anda berpikir, "Bagaimana jika alih-alih memanipulasi kode byte saya mengenkripsi semua kelas saya setelah kompilasi dan mendekripsinya dengan cepat di dalam JVM (yang dapat dilakukan dengan classloader khusus)? Kemudian JVM menjalankan kode byte asli dan tidak ada yang perlu didekompilasi atau direkayasa balik, bukan? "
Sayangnya, Anda salah, baik dalam berpikir bahwa Anda adalah orang pertama yang mengemukakan ide ini dan berpikir bahwa ide itu benar-benar berhasil. Dan alasannya tidak ada hubungannya dengan kekuatan skema enkripsi Anda.
sumber