Con la proliferazione dei polymorphic engine (TPE, MTE, DAME, DSCE, VIP, etc.) nasce l'esigenza di descrivere per sommi capi cosa fa in pratica questo codice. Un motore non è nient'altro che un generatore di codice macchina. La scrittura di tali motori richiede una conoscenza approfondita dell'instruction set del 80x86, di come manipolare gli opcode a livello di bit in modo che con delle opportune operazioni si trasforma un valore senza significato in un certo opcode valido per il processore. In effetti, l'idea è quella di avere una routine di decifrazione che a prima vista non lasci capire ciò che effettivamente fa.
I virus polimorfici codificano ogni copia del virus con una routine di decodifica differente. Poiché (teoricamente) in ogni routine di decodifica generata nessun byte rimane costante, è difficile per gli antivirus rilevare questo codice con tecniche di semplice pattern matching. Infatti, gli antivirus sono costretti ad usare delle routine di rilevamento (che variano da virus a virus) che spesso provocano dei ``falsi allarmi'' segnalando la presenza di virus che effettivamente non esistono (in quel sistema). In più, se un antivirus fallisce nel rilevare una singola istanza del virus, allora quella singola istanza rimarrà irrilevata e produrrà a sua volta molte altre ``generazioni'' di quel virus. Diciamo generazioni e non ``copie'' perché la mutazione che ha oltrepassato il rilevamento antivirale può divenire una caratteristica ereditaria, cioè come succede in biologia si può avere una selezione naturale della specie (cfr. C.Darwin). Come succede anche in natura, l'obiettivo principale del virus è la sopravvivenza.
L'approccio più banale tratta la routine di decodifica come una semplice sequenza di byte; un approccio concettualmente più evoluto tratta la routine di decodifica come un algoritmo astratto, cioè come una sequenza di passi:
mov bx, offset startencrypt ; BX e` il pointer register mov cx, viruslength / 2 ; CX e` il count register decrypt_loop: xor word ptr [bx], 12h ; decifra una word alla volta inc bx ; aggiorna il pointer register inc bx ; per puntare alla prossima word loop decrypt_loop ; aggiorna il count register e cicla ; finche' e` maggiore di zero
start: mov bx, viruslength ; BX e` il count register mov bp, offset start ; BP e` il pointer register decrypt_loop: add byte ptr [bp+0Ch], 33h ; decifra un byte alla volta inc bp ; aggiorna il pointer register dec bx ; aggiorna il count register jnz decrypt_loop ; e cicla finche' e` maggiore di zero
Chiaramente i motori, per ogni istanza del virus, possono generare una routine di decodifica diversa nel codice ma uguale nell'algoritmo. Per aumentare la difficoltà di analisi, le routine di decodifica vengono alterate inserendo al loro interno del loro codice del codice fittizio chiamato do-nothing che praticamente non altera l'algoritmo di decifratura. Per esempio, supponiamo di voler inizializzare il count register (posto nel registro AX) con il valore 0808h. Invece di inserire l'istruzione
mov ax,0808h
il motore inserisce le istruzioni seguenti:
mov ax, 0303h ; ax = 0303h mov bx, 0101h ; bx = 0101h add ax, bx ; ax = 0404h mov cl, 1 ; cx = 0001h shl ax, cl ; ax = 0808h
I motori polimorfici fanno questo tipo di operazioni non solo per la fase di inizializzazione ma per tutte le istruzioni ``effettive'' della routine di decifratura.
I motori effettivamente utilizzati dai virus-maker si comportano in modo analogo a quanto descritto, accentuando chiaramente la complessità delle operazioni coinvolte.