2009-02-21 16 views
25

Al mio precedente datore di lavoro abbiamo utilizzato un componente di terze parti che fondamentalmente era solo una DLL e un file di intestazione. Quel particolare modulo gestiva la stampa in Win32. Tuttavia, la società che ha creato il componente è andata in bancarotta, quindi non ho potuto segnalare un bug che avevo trovato.Qual è il tuo trucco anti-debug preferito?

Quindi ho deciso di correggere il bug e ho lanciato il debugger. Sono stato sorpreso di trovare il codice anti-debugging quasi ovunque, il solito IsDebuggerPresent, ma la cosa che ha attirato la mia attenzione è stata questa:

; some twiddling with xor 
    ; and data, result in eax 
    jmp eax 
    mov eax, 0x310fac09 
    ; rest of code here 

A prima vista ho appena fatto un passo sopra la routine che è stato chiamato due volte, poi le cose Sono appena andato banane. Dopo un po 'mi sono reso conto che il risultato del bit twiddling era sempre lo stesso, cioè il jmp eax era sempre saltato a destra nell'istruzione mov eax, 0x310fac09. Ho sezionato i byte ed è stato, 0f31, l'istruzione rdtsc che è stata utilizzata per misurare il tempo trascorso tra alcune chiamate nella DLL.

Quindi la mia domanda su SO è: Qual è il tuo trucco anti-debug preferito?

+10

È mia opinione che davvero non voglio che il codice in esecuzione sul mio sistema abbia fatto qualcosa per prevenire il debug. Mostra che l'autore del codice non può essere considerato attendibile. – bruceatk

+1

Sono d'accordo con bruceatk, specialmente per DLL e altri componenti che uso per creare la mia applicazione. Sono meno interessato alle applicazioni complete che uso. Non mi sorprende che la società sia andata in bancarotta :) - sarebbe meglio spendere tempo a produrre un buon codice che a proteggerlo. – Michael

+0

@bruceatk in modo da non eseguire Windows? Il sistema operativo stesso contiene alcuni trucchi anti-debugger per aiutare a nascondere alcuni dei suoi meccanismi di protezione più interessanti. – mrduclaw

risposta

27

Il mio trucco preferito è scrivere un semplice emulatore di istruzioni per un microprocessore oscuro.

La protezione da copia e alcune delle funzionalità di base verranno quindi compilate per il microprocessore (GCC è di grande aiuto qui) e collegate al programma come un blob binario.

L'idea alla base di questo è che la protezione della copia non esiste nel comune codice x86 e come tale non può essere smontata.Non è possibile rimuovere l'intero emulatore perché ciò eliminerebbe la funzionalità principale dal programma.

L'unica possibilità di hackerare il programma è di decodificare ciò che fa l'emulatore del microprocessore.

Ho usato MIPS32 per l'emulazione perché era così facile da emulare (ci sono volute solo 500 linee di semplice codice C). Per rendere le cose ancora più oscure non ho usato gli opcode MIPS32 non elaborati. Invece, ogni codice operativo era xo'ed con il proprio indirizzo.

Il file binario della protezione della copia sembrava immondizia.

Altamente raccomandato! Ci sono voluti più di 6 mesi prima che venisse fuori un crack (era per un progetto di gioco).

+0

Quindi, in pratica, hai passato tutto quel lavoro sapendo che alla fine avresti fallito? – fow

+0

Sei mesi sono lunghi quando stiamo parlando di crackare un'applicazione. – Irwin

+3

Direi che ci sono voluti 6 mesi prima che qualcuno ci provasse. Non ne vale la pena. Sono sicuro che qualsiasi cosa tu abbia fatto è stata aggirata facilmente da qualcosa a cui non hai mai pensato. – bruceatk

0

L'utilizzo di nop per rimuovere l'assembly tramite il debugger è un trucco utile. Certo, rimettere il codice è molto più difficile !!!

+1

A seconda del debugger dovrebbe esserci una funzione 'annulla'. OllyDbg ne ha uno, basta selezionare i byte modificati e premere ALT + BACKSPACE. – Irwin

6

Sono stato membro di molte comunità RCE e ho avuto la mia giusta quota di hacking & cracking. Dalla mia epoca mi sono reso conto che trucchi così inconsistenti di solito sono volatili e piuttosto futili. La maggior parte dei trucchi anti-debugging generici sono specifici del sistema operativo e non sono affatto "portatili".

Nell'esempio sopra riportato, si presume che si utilizzi l'assemblaggio inline e una funzione naked__declspec, che non sono supportate da MSVC durante la compilazione sull'architettura x64. Naturalmente ci sono ancora modi per implementare il trucco sopra menzionato, ma chiunque sia stato in retromarcia per un periodo abbastanza lungo sarà in grado di individuare e sconfiggere quel trucco in pochi minuti.

Quindi, in generale, suggerirei di non utilizzare trucchi anti-debug al di fuori dell'utilizzo dell'API IsDebuggerPresent per il rilevamento. Invece, ti suggerirei di codificare uno stub e/o una macchina virtuale. Ho codificato la mia macchina virtuale e ci sto migliorando da molti anni e posso dire onestamente che è stata di gran lunga la decisione migliore che ho fatto per quanto riguarda la protezione del mio codice finora.

2

I secondo il suggerimento della macchina virtuale. Ho implementato un simulatore MIPS I che (ora) può eseguire binari generati con mipsel-elf-gcc. Aggiungi a quel codice/capacità di crittografia dei dati (AES o con qualsiasi altro algoritmo di tua scelta), la capacità di auto-simulazione (in modo da poter avere simulatori nidificati) e hai un buon codice offuscatore.

La bella funzionalità di scegliere MIPS I è che 1) è facile da implementare, 2) Posso scrivere codice in C, eseguirne il debug sul desktop e semplicemente compilarlo per MIPS quando è fatto. Non è necessario eseguire il debug di codici opzionali personalizzati o scrivere manualmente il codice per una VM personalizzata.

+0

Wtf - usi anche MIPS? Pensavo di essere l'unico a farlo in questo modo. –

+0

Beh, per prima cosa ho voluto progettare un set di istruzioni personalizzato, ma mi è subito venuto in mente che mi sarei dovuto condannare manualmente alla scrittura e al debug del codice per esso. Quindi sono andato a cercare una semplice CPU supportata da gcc :-) – zvrba

3

Il metodo di offuscamento più moderno sembra essere la macchina virtuale.

Prendi in pratica una parte del codice oggetto e lo converti nel tuo formato bytecode. Quindi aggiungi una piccola macchina virtuale per eseguire questo codice. L'unico modo per eseguire correttamente il debug di questo codice sarà quello di codificare un emulatore o un disassemblatore per il formato di istruzioni della VM. Certo, devi anche pensare alle prestazioni. Troppo bytecode renderà il tuo programma più lento del codice nativo.

La maggior parte dei vecchi trucchi sono inutili ora:

  • Isdebuggerpresent: molto zoppo e facile per rattoppare
  • altro debugger/rilevamenti breakpoint
  • roba Ring0: gli utenti non piace per installare i driver, si potrebbe effettivamente rompere qualcosa sul loro sistema ecc.
  • Altre cose banali che tutti conoscono o che rendono il software instabile. ricorda che anche se un crack rende instabile il tuo programma ma funziona ancora, questa instabilità verrà attribuita a te.

Se si desidera codificare autonomamente la soluzione VM (esistono buoni programmi in vendita), non utilizzare un solo formato di istruzioni. Rendilo polimorfico, in modo che tu possa avere diverse parti del codice in formato diverso. In questo modo non è possibile interrompere tutto il codice scrivendo solo un emulatore/disassemblatore. Ad esempio, la soluzione MIPS di alcune persone offerte sembra essere facilmente interrotta perché il formato delle istruzioni MIPS è ben documentato e gli strumenti di analisi come IDA possono già smontare il codice.

List of instruction formats supported by IDA pro disassembler

1

Calcolato salti nel bel mezzo di un legittimo cercando, ma in realtà si nasconde una vera e propria istruzione istruzioni sono i miei preferiti. Sono comunque abbastanza facili da rilevare per gli umani, ma spesso gli strumenti automatici lo incasinano.

Anche la sostituzione di un indirizzo di ritorno sullo stack fa un buon spreco di tempo.

3

Preferirei che le persone scrivano software solido, affidabile e che faccia ciò che è pubblicizzato. Che lo vendono anche a un prezzo ragionevole con una licenza ragionevole.

So che ho sprecato troppo tempo a gestire i fornitori con complicati schemi di licenza che causano solo problemi ai clienti e ai fornitori. È sempre mia raccomandazione evitare quei venditori. Lavorando in una centrale nucleare, siamo costretti a utilizzare determinati prodotti dei fornitori e quindi siamo costretti a dover gestire i loro piani di licenza.Mi piacerebbe che ci fosse un modo per tornare indietro nel tempo che personalmente ho sprecato a gestire i loro falliti tentativi di darci un prodotto funzionante con licenza. Sembra una piccola cosa da chiedere, ma sembra essere una cosa difficile per le persone che diventano troppo ingannevoli per il loro bene.

+0

Offensivo? Mi piacerebbe chi ha deciso di etichettare questa offensiva per contattarmi e spiegare cosa è offensivo al riguardo. [email protected] – bruceatk

+0

+1 Per contrastare la "offensiva". +1 punto virtuale per i problemi di energia nucleare. –

+1

Non ti ho segnalato come offensivo, ma ti ho valutato come il tuo post è davvero fuori tema. – rhinovirus

6

Spin off un processo figlio che si collega a padre come debugger & modifica le variabili chiave. Punti bonus per mantenere il processo figlio residente e utilizzare le operazioni di memoria del debugger come una sorta di IPC per determinate operazioni chiave.

Sul mio sistema, non è possibile collegare due debugger allo stesso processo.

La cosa bella di questo è che a meno che non provino a manomettere le cose, niente si rompe.

2

mio preferito era su Amiga, dove v'è un coprocessore (la Blitter) facendo grandi quantità di dati trasferimenti indipendenti dal processore; questo chip verrà istruito per cancellare tutta la memoria e resettare da un IRQ del timer.

Quando si è collegata una cartuccia Action Replay, l'arresto della CPU implica che Blitter continuerà a cancellare la memoria.

Problemi correlati