Cercando di proteggere un codice

-2

Sto cercando di rendere difficile un codice da modificare. La sicurezza è la mia preoccupazione.

Ok, so cosa dirai della pirateria, bla bla bla. Lascialo da questa discussione.

Sto cercando di raccogliere idee per fare le cose in modo diverso nel codice.

Cose come questa ad esempio:

int delta = value1 - value2;

if (delta > 0) {
   // code is fine
} else {
   // code is tampered
}

può essere facilmente corretto in binario semplicemente sostituendo l'equivalente binario a ">" questa sarebbe l'istruzione JG (salta se maggiore) con JLE (salta se minore o uguale) o anche sostituendo la sottrazione con l'aggiunta.

In questo caso specificamente quali tecniche posso usare invece?

Quali trucchi, ragazzi, sapete per rendere le cose semplici difficili per i cracker?

    
posta SpaceDog 27.04.2014 - 11:56
fonte

4 risposte

5

In definitiva, qualsiasi codice verrà ridotto a codice macchina / codice operativo. Il risultato è lo stesso, ma consente di discutere sia il codice sorgente di distribuzione sia il codice macchina compilato:

Se stai usando qualcosa come PHP dove hai il codice sorgente, puoi aggiungere più loop e costrutti, ma qualcuno può semplicemente caricare un debugger e tracciare comunque il codice per rimuovere l'accesso. Se si dispone di un obbligo contrattuale o di un obbligo di licenza per fornire codice sorgente questo non renderà felici i clienti. Se vuoi aggiungere confusione a livello di livello superiore, questo renderà il codice difficile da gestire. Aggiungendo in offuscamenti l'utilizzo di uno script in seguito, di nuovo si può semplicemente spogliarlo. Quando JavaScript e CSS sono minimizzati, è fastidioso risalire ma non impossibile. Per PHP e simili, puoi compilare opcode (ad es. ioncube ) e aggiungere l'offuscamento, ma non impedisce a qualcuno di tracciare .

Per codice compilato: i costrutti del linguaggio di livello superiore saranno ridotti a istruzioni più semplici. Il tuo compilatore fa un sacco di cose sotto il cofano che possono ridurre tutto questo sforzo che stai facendo al livello più alto. Ancora una volta, possono sempre passare attraverso il codice con un debugger. L'offuscamento sta aggiungendo complessità e confusione, ma è necessario un percorso di esecuzione per le istruzioni corrette. Faresti meglio a eseguire l'offuscamento al momento della compilazione o eseguendo l'offuscamento sul codice compilato, cercando quindi di complicare il codice sorgente. Vedi queste domande di overflow SO:

Se non si sta utilizzando un algoritmo speciale, se le persone possono osservare il flusso, lo duplicheranno con la vista e la funzione invece di perdere tempo per ottenere la fonte. Alla fine, possono comunque copiare la tua funzionalità indipendentemente dalla tua offuscazione.

L'altra domanda che potresti chiederti sta rilevando se il tuo file sorgente è stato modificato prima / durante l'esecuzione. Ad esempio, questo non è più il mio codice legittimo, quindi non correrò? Puoi farlo a livello di file system usando monitoraggio dell'integrità dei file , come TripWire . Puoi anche utilizzare DRM . Cose come DEP aiutano anche a prevenire questo.  Se qualcuno ha una patch o hack contro il tuo codice, è probabile che sia in grado di eludere eventuali protezioni in-app quando inseriscono anche il loro codice dannoso.

    
risposta data 27.04.2014 - 18:19
fonte
1

Quello che stai cercando è l'offuscamento. E per il tuo specifico esempio di controllo del flusso di offuscamento.

Ad esempio, potresti aggiungere ifs e istruzioni goto inutili:

if (!this_is_always_true_and_defined_somewhere_else) {
    goto some_label;
} else {
    if (delta > 0) {
       // code is fine
    } else {
       // code is tampered
    }
}

Puoi anche rendere la query if più complicata:

if (!this_is_always_true_and_defined_somewhere_else) {
    goto some_label;
} else {
    if (delta > 0 && complicated_expression_that_is_always_true) {
       // code is fine
    } else {
       // code is tampered
    }
}

E ovviamente puoi fare lo stesso per la sottrazione:

int delta = (value1 - value2) + (value3 - 4 * value4);

dove value3 e value4 sono definiti altrove e value3 = 4 * value4

Per ulteriori risorse sull'offuscamento, consulta qui , qui e qui

Ci sono molti offuscatori là fuori, e userei uno di essi invece di rendere il tuo codice più difficile da leggere. Ma in generale, penso che l'offuscamento non risolva davvero nulla. Ecco perché DRM esiste ancora:)

Modifica dal commento di @ TeunVink - Se utilizzi un compilatore per generare una versione binaria del tuo programma, assicurati di sapere come funziona. Molti compilatori eseguono analisi del codice morto, che rimuove tutte le parti non raggiungibili del codice. Questo sconfigge molti di questi esempi poiché il compilatore (pre) sostituirà o rimuoverà la complessità aggiunta.

    
risposta data 27.04.2014 - 14:32
fonte
0

I link pubblicati da altri qui su offuscamento valgono una lettura. Come noti te stesso, un singolo punto di test può essere facilmente corretto per testare i risultati. Ci possono essere chilometri di utilizzo di effetti collaterali che causano l'interruzione del codice non correlato a meno che il codice importante non sia stato eseguito e lasciato valori particolari in giro, e anche che il codice si interrompa se tali valori indicano che un test importante come un controllo della licenza ha fallito. Lo scopo sarebbe quello di richiedere a un tecnico inverso di ottenere una comprensione più approfondita del codice rispetto alla semplice identificazione di un codice "se (license_check_check_valid)" e di determinare quale stato avrebbero bisogno di simulare tramite patching per abilitare il codice da bypassare o non funziona come previsto e tuttavia lascia il programma operativo.

Gli ottimizzatori sono in grado di annullare semplici offuscamenti del flusso di controllo. In linguaggi come C / C ++, tecniche come l'utilizzo di puntatori di funzione per le chiamate e l'esplosione di questi nei loro byte costitutivi in posizioni discrete in modo che non vengano mai memorizzate insieme e solo riassemblate per effettuare una chiamata possono complicare l'analisi.

    
risposta data 01.05.2014 - 15:46
fonte
0

Dipende dal linguaggio e dall'ambiente, ho avuto successo con la crittografia del codice eseguibile e la decrittografia al volo. Cambiare la chiave tra le versioni minori rallenta notevolmente le crepe, Come fa il confronto di codice in RAM vs controlli di codice crittografati in fase di esecuzione.

Afferrando il puntatore a una funzione auth, calcolando il suo checksum e confrontandolo con qualcosa che è noto in qualche posto non correlato nel codice e causando quindi "errori minori" nel software (ad esempio per un gioco che perde la frequenza dei fotogrammi o che introduce glitch per un'applicazione scientifica che lanciano statistiche leggermente al punto in cui un cracker potrebbe non accorgersene ma un utente sarebbe molto consapevole)

Anche i timer sono fantastici, puoi sembrare innocentemente come se avessi qualche codice di debug / profilatura avanzato quando stai guardando un'applicazione che è in fase di debug. Lo stesso vale per la sorveglianza per vedere se i tavoli di interruzione sono in disordine o vengono lanciati i nmi.

Un altro trucco personale che mi piace usare è prendere parti della chiave di registrazione e usarle come costanti altrove nel codice in luoghi non correlati, ancora una volta la chiave non sta facendo il crack iniziale per far funzionare il software facilmente, ma più difficile fare il il software si comporta in modo non corretto in modo subdolo quando è rotto.

    
risposta data 09.02.2015 - 17:49
fonte

Leggi altre domande sui tag