In che modo C / C ++ è più difficile da decompilare rispetto a C #?

4

Vedi la risposta migliore qui: Offuscamento a livello di codice sorgente più efficace degli offuscatori? , in particolare "Codificalo in una lingua non facile da decompilare come C / C ++"

Sto cercando di scrivere una nuova applicazione che verrà venduta a $ 500 per licenza, quindi vorrei impedire i decompilatori.

Il C # dovrebbe essere evitato, o sta usando un offuscatore sufficiente per prevenire questo genere di cose?

    
posta Michael 01.02.2013 - 22:16
fonte

3 risposte

13

Gli assembly C # contengono metadati che gli assembly c ++ no, che possono aiutare nella decompilazione. C # compila anche in un linguaggio intermedio che mappa molto meglio il codice sorgente originale di quanto non faccia l'output del codice macchina di C ++. Gli Obfuscator possono aiutarti, ma non puoi prevenire reverse-engineering; puoi solo renderlo più difficile.

In pratica, nessuno vuole il tuo codice gratuitamente comunque. Le aziende vogliono essere legittimamente autorizzate; non vogliono andare nei guai (o nell'esposizione legale) di hackerare il tuo codice per ottenere una licenza gratuita. A $ 500 per licenza, è improbabile che tu stia prendendo di mira i consumatori ordinari, quindi gli unici che saranno interessati a hackerare il tuo software saranno comunque quelli che non sono nel tuo mercato di destinazione.

Quindi prendi delle precauzioni sensate, come avere uno schema di licenza, installare codici, telefonare a casa, o qualunque altra cosa sia per proteggere il tuo software, e concentrare i tuoi sforzi sull'aggiunta di nuove funzionalità per rendere il tuo software migliore e più attraente, scegliendo il linguaggio che ti offre la migliore produttività possibile.

NB: se non ti vengono fregati di tanto in tanto dagli hacker, il tuo software non è abbastanza importante. A quel punto, puoi probabilmente assumere qualcuno per emettere avvisi di rimozione e lavorare su soluzioni tecnologiche migliori.

    
risposta data 01.02.2013 - 22:31
fonte
6

Fondamentalmente, qualsiasi programma eseguibile può essere smontato e controllato. La facilità con cui un tecnico inverso può ricreare il codice sorgente originale dipende da quante informazioni o metadati sul codice sorgente originale esistono all'interno dell'eseguibile. Il reverse engineer può scoprire i nomi delle variabili originali, le funzioni, le strutture dati, ecc.? Un compilatore essenzialmente "comprime" il codice sorgente, trasformandolo in un formato che è più suscettibile all'esecuzione della macchina, come il codice macchina nativo o il codice byte elaborato da un runtime intermedio. Ma in generale, la compressione è in perdita, il che significa che molte informazioni sul codice sorgente originale semplicemente non sono lì. Tuttavia, alcuni output del compilatore sono più dannosi di altri.

C e C ++ generalmente compilano direttamente al codice macchina nativo. Ma né lo standard C né C ++ descrive il layout di un eseguibile binario creato dal compilatore. Un compilatore C ++ ottimizzante, ad esempio, è libero di fare molte cose per aumentare le prestazioni, tra cui l'ottimizzazione di alcune dichiarazioni di variabili o la rimozione di intere funzioni e classi. Pochissime informazioni sul codice C ++ originale devono necessariamente esistere nell'eseguibile binario. Un tecnico inverso sarebbe ancora in grado di smontarlo, ma spigolare qualsiasi codice C o C ++ dall'assemblea sarebbe un atto di supposizione e interpretazione.

C #, tuttavia, compila in CIL (Common Intermediate Language). In genere, molte più informazioni sul codice sorgente originale, come concetti orientati agli oggetti inclusa la struttura di classi, possono essere dedotte dalla lettura del CIL piuttosto che dalla lettura, diciamo, del codice macchina x86 altamente ottimizzato prodotto da un compilatore C ++.

    
risposta data 01.02.2013 - 22:39
fonte
2

C # non dovrebbe essere necessariamente evitato. Lavoro per PreEmptive Solutions nel loro team Dotfuscator , sebbene questa sia una risposta imparziale. (senza una singola spina :))

C # è intrinsecamente più facile da decompilare nel codice sorgente perché contiene metadati e la maggior parte del codice C # deve rispettare un insieme di regole chiamate "codice verificabile". I decompilatori sfruttano l'aderenza a queste regole insieme ai metadati allegati per rendere la decompilazione molto migliore degli equivalenti decompilatori C ++. È difficile entrare in una conoscenza approfondita dell'IL, ma in pratica ogni classe del tuo codice finirà con l'avere i metadati. È come .Net ti impedisce di spedire i file di intestazione o di simboli affinché qualcuno usi un assembly / API che scrivi. E per il bit di codice verificabile, in pratica significa che è possibile utilizzare solo il codice che il runtime .Net può verificare è "sicuro". Il runtime è limitato nelle sue capacità di analisi statica, quindi c'è un sacco di codice che può essere verificato sia "sicuro e corretto", ma non sarà verificabile dal runtime. I decompilatori approfittano di questo insieme di regole.

Se stai spedendo un prodotto in C # e hai IP che vuoi proteggere, in pratica devi usare un prodotto di offuscamento. È lo stesso in linguaggi / runtime simili come Java. I prodotti di offuscamento per .Net fanno una varietà di cose:

  • Obfuscate il flusso di controllo (trasformate le istruzioni in cicli con goto e riordinate tutto)
  • Inietta le istruzioni inutili per la spazzatura per "nascondere" il codice reale
  • Rinominare i metadati, quindi non è di grande aiuto. (trasformando i nomi delle classi come FooBar in a )
  • Cambia il modo in cui le classi sono strutturate (spostando 5 metodi in un unico metodo prendendo tutti gli argomenti dai 5 metodi)
  • Inietti codice o metadati non verificabili (anche se questo di solito è facilmente sconfitto dagli deobfuscator)
  • Cripta le stringhe in modo che non siano solo testo
  • Cifra risorse come file di configurazione allegati, pagine XAML, ecc.
  • Aggiungi protezione antisabotaggio (rilevamento che l'applicazione è stata modificata)

A seconda di quale offuscatore usi, questi metodi possono renderlo tale per tutti gli effetti e il codice è un'enorme "scatola nera" senza immergersi nell'IL e defondellarlo (molto tempo)

C ++ ha il vantaggio che l'offuscamento non è altrettanto importante. Non ci sono metadati quindi i decompilatori hanno un tempo molto più difficile. Tuttavia, ci sono ancora una grande quantità di hacker in grado di leggere l'assembly x86. E le applicazioni C ++ molto spesso vengono violate. (buono) Gli offuscatori C ++ sono anche molto più difficili da trovare. Questo perché sono tanto difficili da offuscare quanto da decompilare. .Net ha una serie di regole che gli offuscatori usano sia per leggere il tuo codice, sia per offuscarlo. C ++ non ha queste regole.

Quindi, in sintesi

  • C # richiede fondamentalmente l'offuscamento
  • C ++ è molto più difficile da decompilare, ma manca il supporto per l'offuscamento
  • Indipendentemente da quale scegli, è sempre possibile crack . Tutto quello che puoi fare è rallentarlo o renderlo indesiderabile da rompere a causa della quantità di tempo richiesta

Inoltre, come una nota in più. Gli obfuscator di C # che producono codice verificabile forniscono fondamentalmente un'applicazione che verrà eseguita ovunque, purché disponga di una versione abbastanza nuova di .Net. Gli offuscatori C # che non producono codice verificabile di solito funzionano ovunque, ma non sono garantiti . È possibile che Microsoft esca con qualche ottimizzazione JIT nella prossima versione di .Net che infrangerà il tuo codice non verificabile e offuscato. Il codice C ++ di solito non viene eseguito "ovunque", ma di solito lo fa. Il codice C ++ offuscato funzionerà probabilmente ovunque tu intenda farlo, ma non è garantito. Scrivere un C ++ corretto e sicuro per i thread è abbastanza difficile, e molto meno preoccupante per un obfuscator che lo infastidisce.

    
risposta data 02.02.2013 - 06:01
fonte

Leggi altre domande sui tag