Domanda:
Come si chiama questo metodo di offuscamento?
PSS
2013-06-25 22:01:58 UTC
view on stackexchange narkive permalink

Di recente ho visto il seguente metodo di offuscamento del codice:

  ... jump loc_1234; --------------------- ---- Un mucchio di spazzatura; ------------------------- loc_1234: codice continuato ...  

La logica alla base del meccanismo di offuscamento sembra piuttosto semplice. Un mucchio di spazzatura viene inserito nel codice con istruzioni di salto per saltarci sopra. Immagino che lo scopo sia confondere i disassemblatori di sweep lineari e offuscare i file in generale. Mi piacerebbe saperne di più. Qualcuno sa come si chiama? Quanto è efficace questo metodo contro i moderni software antivirus?

Io la chiamo "distruzione della località sequenziale per istruzioni relative al tempo".
Lo chiamerei "* inserimento codice morto *". Per me, questa è una tecnica per eludere lo sweep lineare e l'attraversamento ricorsivo. Ma, una volta seguita la semantica delle istruzioni durante lo smontaggio, questo offuscamento è totalmente inutile.
@perror non è morto se viene eseguito da qualche altra parte.
@cb88: Pensavo fosse un * mucchio di spazzatura * ...
@perror Penso che non dovrebbe confondere l'attraversamento ricorsivo, poiché segue alberi binari e seguirà solo i salti. Ho ragione?
@PSS: Dipende da come si definisce questo algoritmo. A seconda di chi lo definisce, l'attraversamento ricorsivo si comporterà come uno sweep lineare tranne quando incontra l'istruzione "call" o "ret" (e quindi ignora le istruzioni "jmp"). Oppure, seguirà tutti i possibili target quando incontra "jmp", "call" ("ret" avrà un solo target che ritorna all'ultimo "call"). Ad esempio, questo [documento] (http://www.reddit.com/r/ReverseEngineering/comments/1gq2mh/obfuscation_of_executable_code_to_improve/) accetta la seconda opzione. Ma, originariamente, * l'attraversamento ricorsivo * implica una ricerca approfondita.
Il numero di lettere consentite per i commenti non mi ha permesso di elaborare ... Scusate. Ma, in effetti, questa è sicuramente una buona domanda PSS.
@perror penserò a un modo per porre una nuova domanda. Grazie mille per il tuo contributo.
Tre risposte:
ekse
2013-06-25 22:28:09 UTC
view on stackexchange narkive permalink

Questa tecnica anti-disassemblaggio è descritta come istruzione Jump con una condizione costante nel libro Practical Malware Analysis (Capitolo 16, pagina 336 della prima edizione). L'idea, come hai descritto, è di avere una condizione tale che il salto sia sempre eseguito e aggiungere il codice dopo il salto che genererà uno smontaggio sbagliato nel punto del salto. Poiché il disassemblatore presume che entrambi i rami siano coerenti, ne disassembla solo uno.

Per quanto riguarda l'efficacia contro il software antivirus, la maggior parte di loro utilizza emulatori. Poiché la condizione viene sempre rispettata, l'emulatore continuerà lì e vedrà le giuste istruzioni.

debray
2013-06-26 17:02:54 UTC
view on stackexchange narkive permalink

Una variazione su questo è l'uso di una "funzione di ramo". L'idea di base è la seguente:

  • un'istruzione di salto "jmp L" viene convertita in "call branch_fn" e N byte di spazzatura vengono inseriti dopo l'istruzione di chiamata;
  • il chiamato, branch_fn, aggiunge N al suo indirizzo di ritorno e poi ritorna.

Questo schema di base può essere elaborato in vari modi, ad esempio:

  • Salti multipli possono utilizzare la stessa funzione di ramo e possono avere valori diversi di N (la quantità di aggiustamento necessaria per l'indirizzo di ritorno). La funzione branch utilizza l'indirizzo di ritorno per identificare il sito di chiamata e quindi la particolare istruzione di salto in esame, dalla quale può determinare la quantità di aggiustamento N necessaria (ad esempio, utilizzando una tabella di ricerca basata sull'indirizzo di ritorno).
  • La quantità di rettifica N applicata all'indirizzo del mittente non deve essere memorizzata "in chiaro", ma può essere calcolata dinamicamente tramite la valutazione di un'espressione. Ad esempio, l'utilizzo di funzioni hash perfette per mappare gli indirizzi di ritorno a un valore di regolazione N può produrre codice piuttosto imperscrutabile.
  • Una funzione di ramo non deve regolare il proprio indirizzo di ritorno, poiché è relativamente facile da individuare . Invece, può utilizzare una sequenza di chiamate branch_fn0 -> branch_fn1 -> ... -> branch_fnK dove l'ultima nella sequenza "raggiunge" lo stack di chiamate per eseguire la regolazione dell'indirizzo di ritorno.

Ma, come accennato in precedenza, questo è fondamentalmente finalizzato a eliminare il disassemblaggio statico; non fa molto contro l'analisi dinamica.

David Hoelzer
2013-07-14 03:04:14 UTC
view on stackexchange narkive permalink

Una risposta alternativa è che stai guardando un assembly codificato a mano e in realtà non c'è alcuno sforzo per ingannare il disassemblatore.

Quando consegno l'assembly del codice, indipendentemente da quale sia la buona pratica, se si tratta di un piccolo bit di codice Molto spesso imposterò il selettore di dati in modo che corrisponda al selettore di codice e inserirò semplicemente i miei dati all'interno del segmento di codice. Lo faccio soprattutto se sto scrivendo un boot loader in modalità reale, ad esempio, o qualche altro pezzo di codice di breve durata.

Un altro posto in cui lo farei e ancora non cerco di offuscare le cose è in un pezzo di codice di exploit. Questo mi permette di avere variabili a cui posso fare riferimento in modo affidabile e di avere ancora un pezzo di codice shell molto stretto.



Questa domanda e risposta è stata tradotta automaticamente dalla lingua inglese. Il contenuto originale è disponibile su stackexchange, che ringraziamo per la licenza cc by-sa 3.0 con cui è distribuito.
Loading...