Packer (informatica)

modi di comprimere un file eseguibile che preservano trasparentemente la sua eseguibilità

Un packer è uno strumento che permette di rendere difficile l'analisi di un file eseguibile o, semplicemente, di ridurre la sua dimensione. I packer vengono solente usati nelle versioni limitate di prodotti commerciali per impedire, o perlomeno scoraggiare, la creazione di crack. Essi usano delle tecniche anti-debug e anti-disassembly sempre più avanzate che, se non sono interpretate nella maniera giusta dai più comuni debugger/disassembler, fanno perdere molto tempo al cracker (o al reverser in generale).

Struttura

Un packer, una volta elaborato un file eseguibile, produrrà un nuovo eseguibile (comunemente detto "packato") la cui struttura consta di un "loader" polimorfico (perlomeno nei packer di recente concezione) affiancato ad una versione modificata, per esempio mediante algoritmi crittografici, del codice originale. Il loader, una volta eseguito, eseguirà quindi le operazioni necessarie a ripristinare il codice originale e gli cederà il controllo.

Tecniche anti-disasm

Le tecniche anti-disassembly sono molteplici e, perlomeno quelle più conosciute, vengono rilevate e gestite corrrettamente dai più comuni disassembler.

Junk Code

Il junk code è una tecnica che consiste nel mischiare dati e codice insieme. Questa tecnica ha lo scopo di far perdere l'allineamento al disassembler che tenterà di decodificare dei dati (e quindi non delle istruzioni). La tecnica usata dai disassembler più avanzati è quella di considerare "dati" tutto quello che, nel corso del programma, non verrà mai eseguito. Il junk code è facilmente identificabile anche da un essere umano, perché la sua decodifica di solito produce:

  • errore, il codice non corrisponde a nessun opcode. In questo caso la presenza di junk code è palese.
  • istruzioni privilegiate, davvero insolito per un programma funzionante a livello utente.
  • salti a porzioni di codice visibilmente fuori dal programma. Questo avviene se il codice del junk code corrisponde ad un istruzione di salto (condizionato o no).

Il junk code può essere usato anche per altri scopi. Ad esempio, si consideri questa porzione di codice:

     call func1
     DB ...
     jmp somewhere
  
  ...
  
  func1:
     pop ebx
     inc ebx
     push ebx
     ret

In questa porzione di codice viene chiamata la funzione func1 che incrementa l'indirizzo di ritorno di func1 per fare in modo che "DB ..." non venga eseguito. Nell'analisi di questa porzione di codice con un debugger, è facile accorgersi che lo step-over della funzione "func1" non ha l'effetto sperato: l'esecuzione continua fino al termine del programma. Questo è dovuto al fatto che i più comuni strumenti di debugging, nell'eseguire lo step-over, impostano un breakpoint subito dopo la chiamata della funzione. Di conseguenza per un debugger una funzione non è terminata fin quando l'istruction pointer non punta all'istruzione successiva alla CALL.

Collegamenti esterni