Tip 22 Java: Lindungi bytecode Anda dari rekayasa balik / dekompilasi

Jika Anda menulis kelas Java dan mendistribusikannya melalui Internet, Anda harus tahu bahwa orang dapat merekayasa balik, membongkar, atau mendekompilasi kelas Anda ke dalam kode sumber Java. Dekompiler yang paling banyak digunakan (setidaknya untuk umum) adalah Mocha. Mocha membaca satu atau lebih file bytecode (kelas) dan mengubahnya kembali ke kode sumber Java. Meskipun kode yang dihasilkan oleh Mocha tidak persis sama dengan kode sumber aslinya, kode tersebut cukup dekat untuk dipahami dan dimodifikasi oleh seseorang. Jika Anda tertarik untuk mengembangkan kelas Java dan mendistribusikannya melalui Internet - dan Anda ingin melindunginya agar tidak diuraikan - baca terus.

Mocha: contoh

Sebelum memperkenalkan Crema, kita akan melihat contoh menggunakan Mocha. Program sederhana berikut menampilkan string "Halo" di layar:

uji kelas {public static void main (String argv []) {System.out.println ("Halo"); }}

Jika empat baris di atas disimpan dalam sebuah file, test.javamaka kompilasi test.javaakan menghasilkan file baru test.class,, yang berisi bytecode Java yang mewakili kode sumber Java tersebut. Sekarang mari kita jalankan Mocha pada file kelas dan lihat keluaran Mocha:

% java mocha.Decompiler test.class //% adalah prompt shell C saya di UNIX. 

Perintah di atas menghasilkan file bernama test.mocha, yang berisi kode sumber Java yang dihasilkan oleh Mocha:

% more test.mocha / * Diurai oleh Mocha dari test.class * / / * Awalnya dikompilasi dari test.java * / import java.io.PrintStream; uji kelas {public static void main (String astring []) {System.out.println ("Hi there"); } uji() { } }

Seperti yang Anda lihat dari contoh di atas, Mocha telah memberi kami kode sumber Java yang mudah dibaca dan dipahami. Jika Anda menyalin file ini ke test.java, mengkompilasi lagi, dan menjalankannya, itu akan mengkompilasi dan berjalan dengan baik.

Crema untuk menyelamatkan!

Jadi bagaimana Anda bisa melindungi kelas Anda dari dekompilasi? Salah satu jawabannya adalah Crema. Crema mengacak informasi simbolis dalam .classfile Anda sehingga tidak terlalu rentan terhadap dekompilasi. Informasi simbolis yang diacak Crema mencakup nama kelas, superkelasnya, antarmuka, nama variabel, metode, dan sebagainya. Nama simbolis ini diperlukan oleh mesin virtual Java (JVM) untuk menautkan kelas Anda dengan paket perpustakaan. Crema mengacak nama simbolis ini dan membuat referensi ke sana dengan cara yang sama sehingga JVM masih dapat mencapai penautan yang benar antara kelas dan paket.

Jadi, bagaimana cara kerja Crema? Pada dasarnya, sebelum mendistribusikan file kelas Anda di Internet, jalankan Crema di atasnya. Crema akan mengacak informasi simbolis yang terkandung di dalamnya, dan akan menempatkan setiap kelas baru dalam file tersebut 1.crema. Tugas Anda kemudian adalah mengubah nama 1.cremamenjadi sesuatu seperti filename.classsebelum mendistribusikannya di Internet.

Mari kita jalankan Crema pada test.classcontoh kita yang ditunjukkan di atas, dan kemudian coba dekompilasinya dengan Mocha:

% java Crema -v test.class // -v adalah opsi untuk mengaktifkan mode verbose //. Ada lebih banyak pilihan. CREMA - The Java Obfuscator - VERSI EVALUASI Hak Cipta (c) 1996 Hanpeter van Vliet Loading test.class Obfuscating test Menyimpan tes sebagai 1. crema CATATAN: Kelas yang diproses dengan versi evaluasi Crema hanya dapat digunakan secara lokal, karena sebagian besar browser akan menolak untuk memuat mereka. Untuk versi lengkap Crema, arahkan browser Anda ke: //www.inter.nl.net/users/HPvan.Vliet/crema.html (lihat Sumberdaya)

Perintah di atas telah menghasilkan file baru 1.crema, yang berisi bytecode dengan informasi simbolik yang diacak. Perhatikan bahwa Crema memiliki banyak parameter opsi baris perintah yang dapat Anda gunakan; untuk informasi lebih lanjut tentang Crema, lihat bagian Sumber.

Sekarang mari kita pindahkan file itu ke dalam test.classlagi dan mendekompilasi menggunakan Mocha:

% mv 1.crema test.class% java mocha.Decompiler test.class java.lang.NullPointerException SIGSEGV 11 * pelanggaran segmentasi si_signo [11]: SIGSEGV 11 * pelanggaran segmentasi si_errno [0]: Error 0 si_code [1]: SEGV_ACCERR [ addr: 0x0] stackbase = EFFFF35C, stackpointer = EFFFF040 Pembuangan utas lengkap: "Utas finalizer" (TID: 0xee3003b0, sys_thread_t: 0xef490de0) prio = 1 "Async Garbage Collector" (TID: 0xee300368, sys_thread_t = 1 "Idefle4) thread "(TID: 0xee300320, sys_thread_t: 0xef4f0de0) prio = 0" clock handler "(TID: 0xee3001f8, sys_thread_t: 0xef5b0de0) prio = 11" main "(TID: 0xee3000a0, sys_thread_t: current 0x835a0, sys_thread_t: current 0x835 .lang.Throwable.printStackTrace (Throwable.java) java.lang.ThreadGroup.uncaughtException (ThreadGroup.java) java.lang.ThreadGroup.uncaughtException (ThreadGroup.java) Monitor Cache Dump: Registered Monitor Dump: Selesaikan saya kunci antrian: tidak berpemilik Kunci antrian thread: tidak berpemilik Kunci kelas: kunci tumpukan Java tidak berpemilik: Kunci penulisan ulang kode: kunci Heap tidak berpemilik: tidak berpemilik Memiliki kunci antrian finalisasi: Kunci IO monitor tidak berpemilik: tidak dimiliki Monitor kematian anak: monitor kejadian tidak berpemilik: Monitor I / O tak berpemilik: Monitor alarm tak berpemilik: tak berpemilik Menunggu untuk diberi tahu: "penangan jam" Kunci Sbrk: Kunci cache monitor tak berpemilik: Monitor registry tak berpemilik: pemilik monitor: "utama" Thread Alarm Q: Batalkan (inti dibuang)Monitor alarm tidak berpemilik: tidak berpemilik Menunggu untuk diberi tahu: "penangan jam" Kunci Sbrk: Kunci cache monitor tidak berpemilik: Registri monitor tidak berpemilik: pemilik monitor: "main" Thread Alarm T: Batalkan (core dumped)Monitor alarm tidak berpemilik: tidak berpemilik Menunggu untuk diberi tahu: "penangan jam" Kunci Sbrk: Kunci cache monitor tidak berpemilik: Tidak dimiliki Monitor registry: pemilik monitor: "main" Thread Alarm Q: Batalkan (core dumped)

Seperti yang Anda lihat pada kode di atas, hal pertama yang dikeluhkan Mocha adalah NullPointerExceptionkarena bingung tentang informasi simbolik. Oleh karena itu, tujuan kami untuk mempersulit penguraian kode kami tercapai.

Perlu dicatat bahwa penulis Mocha, Hanpeter van Vliet, juga penulis Crema! Mocha didistribusikan tanpa biaya. Salinan evaluasi Crema tersedia tanpa biaya, tetapi versi lengkapnya adalah produk komersial.

Saat mendistribusikan kelas Java melalui Internet, Anda dapat melindungi bytecode Java Anda dari risiko rekayasa-terbalik. Contoh kode di atas menunjukkan bagaimana Mocha digunakan untuk mempengaruhi dekompilasi dan bagaimana Crema dapat menyelamatkan dengan mencegah aktivitas tersebut.

Qusay H. Mahmoud adalah mahasiswa pascasarjana dalam ilmu komputer di The University of New Brunswick, kampus Saint John, Kanada.

Pelajari lebih lanjut tentang topik ini

  • Catatan Editor Sejak kematian Mr. van Vliet (karena kanker), situs yang dia dirikan untuk distribusi Mocha dan Crema tidak ada lagi.
  • Situs distribusi Mocha Eric Smith //www.brouhaha.com/~eric/computers/mocha.html
  • Crema di situs CERN //java.cern.ch:80/CremaE1/DOC/quickstart.html

Artikel ini, "Tip 22 Java: Lindungi bytecode Anda dari rekayasa balik / dekompilasi", awalnya diterbitkan oleh JavaWorld.