Domanda

Come posso bloccare le classi Java compilate per impedire la decompilazione?

So che questo argomento deve essere discusso molto bene su Internet, ma non sono riuscito a giungere ad alcuna conclusione dopo averli riferiti.

Molte persone suggeriscono l'offuscatore, ma si limitano a rinominare classi, metodi e campi con sequenze di caratteri difficili da ricordare, ma per quanto riguarda i valori costanti sensibili?

Ad esempio, hai sviluppato il componente di crittografia e decrittografia basato su una tecnica di crittografia basata su password.Ora, in questo caso, qualsiasi persona media Java può utilizzare JAD per decompilare il file di classe e recuperare facilmente il valore della password (definito come costante) nonché sale e a sua volta può decrittografare i dati scrivendo un piccolo programma indipendente!

Oppure tali componenti sensibili dovrebbero essere costruiti in codice nativo (ad esempio, VC++) e chiamarli tramite JNI?

È stato utile?

Soluzione

Alcuni degli offuscatori di bytecode Java più avanzati fanno molto di più che semplicemente alterare i nomi delle classi. Zelix KlassMaster, ad esempio, può anche confondere il flusso del codice in un modo che lo rende davvero difficile da seguire e funziona come un eccellente ottimizzatore di codice...

Inoltre molti offuscatori sono anche in grado di codificare le costanti di stringa e rimuovere il codice inutilizzato.

Un'altra possibile soluzione (non escludendo necessariamente l'offuscamento) è utilizzare file JAR crittografati e un classloader personalizzato che esegue la decrittografia (preferibilmente utilizzando la libreria di runtime nativa).

Il terzo (e forse offrendo la protezione più forte) è utilizzare compilatori nativi in ​​anticipo come CCG O ExcelsiorJET, ad esempio, che compilano il codice Java direttamente in un binario nativo specifico della piattaforma.

In ogni caso bisogna ricordare che come dice il proverbio estone "le serrature sono per gli animali".Ciò significa che ogni bit di codice è disponibile (caricato in memoria) durante il runtime e, con sufficiente abilità, determinazione e motivazione, le persone possono decompilare, decodificare e hackerare il codice...Il tuo compito è semplicemente rendere il processo il più scomodo possibile e continuare a far funzionare la cosa...

Altri suggerimenti

Finché hanno accesso sia ai dati crittografati che al software che li decrittografa, praticamente non c’è modo di renderli completamente sicuri.Il modo in cui questo è stato risolto in precedenza è utilizzare una qualche forma di scatola nera esterna per gestire la crittografia/decrittografia, come dongle, server di autenticazione remota, ecc.Ma anche in questo caso, dato che l'utente ha pieno accesso al proprio sistema, ciò rende le cose solo difficili, non impossibili, a meno che non si possa collegare il prodotto direttamente alla funzionalità memorizzata nella "scatola nera", come, ad esempio, i server di gioco online. .

Disclaimer:Non sono un esperto di sicurezza.

Sembra una cattiva idea:Stai permettendo a qualcuno di crittografare cose con una chiave "nascosta" che gli dai.Non penso che questo possa essere reso sicuro.

Forse i tasti asimmetrici potrebbero funzionare:

  • distribuire una licenza crittografata con una chiave pubblica per decrittografare
  • consenti al cliente di creare una nuova licenza e di inviartela per la crittografia
  • inviare una nuova licenza al client.

Non ne sono sicuro, ma credo che il client possa effettivamente crittografare la chiave di licenza con la chiave pubblica che gli hai fornito.Puoi quindi decrittografarlo con la tua chiave privata e anche crittografarlo nuovamente.

Potresti mantenere una coppia di chiavi pubblica/privata separata per cliente per assicurarti di ricevere effettivamente materiale dal cliente giusto, ora Voi sono responsabili delle chiavi...

Qualunque cosa tu faccia, può essere "decompilato".Cavolo, puoi semplicemente smontarlo.Oppure guarda un dump della memoria per trovare le tue costanti.Vedi, il computer ha bisogno di conoscerli, quindi anche il tuo codice dovrà saperlo.

Cosa fare a riguardo?

Cerca di non spedire la chiave come costante hardcoded nel tuo codice:Mantienilo come impostazione per utente.Rendi l'utente responsabile della custodia di quella chiave.

@jatanp:o meglio ancora, possono decompilare, rimuovere il codice di licenza e ricompilare.Con Java, non penso davvero che esista una soluzione adeguata e a prova di hacker a questo problema.Nemmeno un piccolo dongle malvagio potrebbe impedirlo con Java.

I miei manager aziendali si preoccupano di questo e io penso troppo.Ma ancora una volta, vendiamo la nostra applicazione a grandi aziende che tendono a rispettare le condizioni di licenza, generalmente un ambiente sicuro grazie agli addetti ai lavori e agli avvocati.L'atto stesso di decompilare può essere illegale se la licenza è scritta correttamente.

Quindi devo chiedertelo, vero? Veramente hai bisogno di una protezione rafforzata come quella che stai cercando per la tua applicazione?Com'è la tua base clienti?(Aziende?O le masse di giocatori adolescenti, dove questo sarebbe più un problema?)

Se stai cercando una soluzione di licenza, puoi consultare il file API TrueLicense.Si basa sull'uso di chiavi asimmetriche.Tuttavia, ciò non significa che la tua applicazione non possa essere violata.Ogni applicazione può essere craccata con sufficiente sforzo.Ciò che è veramente importante è, come rispose Stu, per capire quanto forte sia la protezione di cui hai bisogno.

Non credo che esista un metodo antipirateria offline efficace.L'industria dei videogiochi ha provato a scoprirlo molte volte e i loro programmi sono sempre stati violati.L'unica soluzione è che il programma debba essere eseguito online connesso ai vostri server, in modo da poter verificare la chiave di licenza, e che ci sia una sola connessione attiva alla volta da parte del licenziatario.Questo è come Mondo di Warcraft O Diablo lavori.Anche se ci sono server privati ​​sviluppati per aggirare la sicurezza.

Detto questo, non credo che le aziende medio-grandi utilizzino software copiato illegalmente, perché il costo della licenza per loro è minimo (forse, non so quanto ti farai pagare per il tuo programma) rispetto a il costo di una versione di prova.

Puoi utilizzare la crittografia byte-code senza timore.

Il fatto è che il documento sopra citato “Cracking Java byte-code Encryption” contiene un errore logico.L'affermazione principale del documento è prima di essere eseguite tutte le classi devono essere decifrate e passate al file ClassLoader.defineClass(...) metodo.Ma questo non è vero.

Il presupposto mancato qui è a condizione che vengano eseguiti in un ambiente runtime Java autentico o standard.Niente può obbligare l'app Java protetta non solo a lanciare queste classi, ma anche a decrittografarle e trasmetterle ClassLoader.In altre parole, se sei in JRE standard non puoi intercettare defineClass(...) metodo perché Java standard non ha API per questo scopo e se usi JRE modificato con patched ClassLoader o qualsiasi altro “trucco da hacker” non puoi farlo perché l'app Java protetta non funzionerà affatto, e quindi non avrai nulla da intercettare.E non importa assolutamente quale "ricerca patch" viene utilizzato o quale trucco viene utilizzato dagli hacker.Questi dettagli tecnici sono una storia completamente diversa.

Q:Se crittografo i miei file .class e utilizzo un classloader personalizzato per caricarli e decrittografarli al volo, ciò impedirà la decompilazione?

UN:Il problema di impedire la decompilazione del bytecode Java è vecchio quasi quanto il linguaggio stesso.Nonostante la gamma di strumenti di offuscamento disponibili sul mercato, i programmatori Java alle prime armi continuano a pensare a modi nuovi e intelligenti per proteggere la propria proprietà intellettuale.In questa puntata di domande e risposte su Java, dissipo alcuni miti attorno a un'idea spesso riproposta nei forum di discussione.

L'estrema facilità con cui i file Java .class possono essere ricostruiti in sorgenti Java che somigliano molto agli originali ha molto a che fare con gli obiettivi e i compromessi di progettazione del codice byte Java.Tra le altre cose, il codice byte Java è stato progettato per la compattezza, l'indipendenza dalla piattaforma, la mobilità della rete e la facilità di analisi da parte degli interpreti del codice byte e dei compilatori dinamici JIT (just-in-time)/HotSpot.Probabilmente, i file .class compilati esprimono l'intento del programmatore in modo così chiaro che potrebbero essere più facili da analizzare rispetto al codice sorgente originale.

Si possono fare diverse cose, se non per impedire completamente la decompilazione, almeno per renderla più difficile.Ad esempio, come passaggio post-compilazione potresti massaggiare i dati .class per rendere il codice byte più difficile da leggere quando decompilato o più difficile da decompilare in codice Java valido (o entrambi).Tecniche come l'esecuzione di un sovraccarico estremo dei nomi dei metodi funzionano bene per il primo, mentre la manipolazione del flusso di controllo per creare strutture di controllo che non è possibile rappresentare tramite la sintassi Java funziona bene per il secondo.Gli offuscatori commerciali di maggior successo utilizzano un mix di queste e altre tecniche.

Sfortunatamente, entrambi gli approcci devono effettivamente modificare il codice che verrà eseguito dalla JVM e molti utenti temono (giustamente) che questa trasformazione possa aggiungere nuovi bug alle loro applicazioni.Inoltre, la ridenominazione di metodi e campi può causare l'interruzione del funzionamento delle chiamate di riflessione.La modifica dei nomi effettivi delle classi e dei pacchetti può danneggiare diverse altre API Java (JNDI (Java Naming and Directory Interface), provider URL, ecc.).Oltre ai nomi modificati, se viene modificata l'associazione tra gli offset del codice byte di classe e i numeri di riga di origine, il recupero delle tracce dello stack delle eccezioni originali potrebbe diventare difficile.

Poi c'è la possibilità di offuscare il codice sorgente Java originale.Ma fondamentalmente questo causa una serie di problemi simili.Crittografare, non offuscare?

Forse quanto sopra ti ha fatto pensare: "Bene, e se invece di manipolare il codice byte crittografassi tutte le mie classi dopo la compilazione e le decrittografassi al volo all'interno della JVM (cosa che può essere fatta con un classloader personalizzato)?Quindi la JVM esegue il mio codice byte originale e tuttavia non c'è nulla da decompilare o decodificare, giusto?"

Sfortunatamente sbaglieresti, sia nel pensare di essere stato il primo ad avere questa idea, sia nel pensare che funzioni davvero.E il motivo non ha nulla a che fare con la forza del tuo sistema di crittografia.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top