Offuscamento del codice basato su hash

0

Il codice seguente

if(str1 == "abc") {}

può essere convertito in

if(hash(str1) == 0x8732e) {} // assume hash("abc") == 0x8732e

per offuscare il codice.

Ma non sono equivalenti quando si verifica una collisione di hash; ad es., str1 = il valore hash di "xyz" è lo stesso di "abc".

Questo è vero in teoria. Ma è un problema nella vita reale quando il metodo sopra è usato per offuscare il codice? È un metodo di offuscamento ben accettato?

    
posta Infinite 05.08.2016 - 17:20
fonte

2 risposte

3

Il digest di hash di esempio che hai dato è troppo corto (20 bit o circa un milione di possibilità), quindi potresti ottenere collisioni troppo spesso e, peggio, chiunque decompilasse il tuo programma potrebbe produrre banalmente le stringhe corrette (o , almeno, stringhe accettabili a causa di collisioni hash) solo forzando brutemente il probabile spazio di input.

"Questa è una stupida obiezione, è solo un esempio ..." si potrebbe dire, ma in realtà non lo è. Ho trovato e sfruttato questo esatto tipo di debolezza prima. Ad esempio, c'era un'app mobile che utilizzava una funzione hash a 32 bit sugli input dell'utente per cercare di nascondere quali input avrebbero prodotto gli output. Ci è voluta meno di un'ora per scrivere ed eseguire un programma che costringeva brutalmente lo spazio di ricerca e ha trovato input mappati su ogni hash digest che l'app stava cercando.

In pratica, è come cercare di memorizzare le password in modo sicuro. Ci sono sicuramente delle differenze - le password raramente sono molto lunghe, mentre le stringhe con hardcoded in un programma possono essere, e se si esegue spesso il test di uguaglianza delle stringhe allora non ci si può permettere che sia lento come una buona funzione di verifica della password essere - ma molti degli stessi paralleli hanno. Usa una strong funzione di hash, non solo elastico per le collisioni e l'inversione, ma anche idealmente uno che non è così veloce che è possibile forzare l'intero spazio di ricerca. Per le stringhe brevi, usa un valore in modo che le persone non possano semplicemente cercare il valore in una tabella arcobaleno.

Ora, per quanto riguarda l'effettiva offuscazione: questa tecnica è una (di molte) che può essere utilizzata dall'offuscamento. Di solito non è molto efficace, specialmente se implementato debolmente (vedi il mio secondo paragrafo), e ha un impatto sulle prestazioni sufficiente che non viene solitamente utilizzato se non in modo selettivo in luoghi in cui il rallentamento non è un grosso problema. L'offuscamento in generale è una non soluzione; nel migliore dei casi rallenta il reverse engineering abbastanza che al momento in cui il RE è completo, il codebase è abbastanza vecchio, a cui nessuno importa, senza causare indebite prestazioni o bug di logica del programma nel frattempo. In pratica, però, di solito non è così bello.

    
risposta data 05.08.2016 - 22:04
fonte
1

Non è utile

Questo non fa davvero un buon lavoro a offuscare. Se si controllano stringhe specifiche, tali stringhe probabilmente si verificheranno nella RAM ad un certo punto (anche durante il normale utilizzo). Un utente malintenzionato può semplicemente eseguire l'hash delle stringhe che trova nella RAM del programma, trovare una collisione e sostituire le parti corrispondenti del codice con la stringa trovata.

È stupido

Inoltre, praticamente tutte le ragioni per offuscare il codice sono stupide, ma questo va oltre il punto.

Non farlo

Quello che dovresti vedere è che c'è il rischio di fallimento. Vale a dire quando si verifica una collisione di hash. A causa del modo in cui le funzioni di hash sono progettate, per i calcoli probabilistici possiamo assumere che l'output della funzione di hash sia casuale per ogni input che non abbiamo ancora provato.

Se sono presenti diversi valori hash confrontati con l'hash di una stringa variabile, è possibile calcolare il tasso di errore per quel confronto utilizzando la formula approssimativa del paradosso dei compleanni link dove link è la dimensione del codominio del La funzione hash e il collegamento sono il numero di valori diversi che la stringa variabile avrà.

Una volta ottenuta questa probabilità per ogni confronto tra stringhe nel tuo programma, moltiplicale e chiama il numero che ottieni link . La probabilità che il programma fallisca è link . Se il programma verrà eseguito link in questo modo, la probabilità che fallisca è link .

Se apprezzi la piccola quantità di offuscamento più di quanto teme le conseguenze del tuo programma fallendo con la probabilità di link , fallo. Altrimenti no.

    
risposta data 05.08.2016 - 22:38
fonte

Leggi altre domande sui tag