Domanda:
Qual è lo scopo di "mov edi, edi"?
Mellowcandle
2013-03-25 14:56:00 UTC
view on stackexchange narkive permalink

Vedo questa istruzione all'inizio di diversi programmi Windows: sta copiando un registro su se stesso, quindi fondamentalmente agisce come un nop . Qual è lo scopo di questa istruzione?

The Essence: è un NOP a due byte. Quindi puoi correggere due byte atomicamente senza che il processore carichi un'istruzione incompleta / errata quando cerca di eseguire questa parte del codice mentre lo stai cambiando.
In x86-64 `mov edi, edi` non è un NOP. In x86-64 azzera i primi 32 bit di "rdi". Nel codice a 32 bit `mov edi, edi` può essere usato come NOP.
Tre risposte:
#1
+68
QAZ
2013-03-25 15:03:13 UTC
view on stackexchange narkive permalink

Raymond Chen (Microsoft) ha un post sul blog che ne discute in dettaglio:

https://devblogs.microsoft.com/oldnewthing/20110921-00/?p=9583

In breve, è un'aggiunta in fase di compilazione applicata per supportare hot patch in fase di esecuzione, quindi la funzione può avere i primi due byte sovrascritti con un'istruzione JMP per reindirizzare l'esecuzione a un'altra parte di codice. / p>

Probabilmente dovresti aggiungere una nota sui 5 byte vuoti che precedono l'istruzione `mov edi, edi`.
Perché non un vero NOP a 2 byte come "66 90"? Sarebbe più efficiente: nessun uop back-end necessario, nessuna latenza aggiuntiva per EDI (nel caso sia importante), nessun registro fisico necessario per rinominare l'output. Forse dovrebbe essere una "firma" che gli strumenti possono riconoscere come non presente in natura se non nel codice hotpatch?
@PeterCordes: Raymond Chen discute che anche https://devblogs.microsoft.com/oldnewthing/20130102-00/?p=5663 "la decisione di usare MOV EDI, EDI come istruzione NOP a due byte è arrivata dopo aver consultato i produttori di CPU per il loro consigli per il miglior NOP a due byte "
@BenSchwehn: Huh, probabilmente quella decisione risale ai giorni del P5 Pentium, dove un prefisso "66" faceva sì che l'istruzione richiedesse un ciclo extra per la decodifica. È un peccato per le CPU successive dal P6 in poi. È anche un peccato che debba essere un NOP, piuttosto che essere facoltativamente un'istruzione utile come una codifica a 2 byte di `push ebp` per le funzioni che usano un puntatore di frame. (Usando il form `push r / m32` con un byte modrm, non la forma abbreviata da 1 byte.) Ma è un po 'meno semplice da gestire e necessita di un'alternativa per non pessimizzare le funzioni che non vogliono inviare nulla.
#2
+19
peter ferrie
2013-03-30 03:59:49 UTC
view on stackexchange narkive permalink

È destinato a passare a una posizione specifica , 5 byte prima dell'istruzione mov. Da lì, hai 5 byte che devono essere modificati per un salto in lungo da qualche altra parte nello spazio di memoria a 32 bit. Si noti che durante l'hot-patch, è necessario posizionare prima il salto di 5 byte, quindi è possibile sostituire il mov. Andando dall'altra parte, rischi che il mov-jmp sostituito venga eseguito per primo e salti ai 5 byte di qualunque cosa accada (è tutto nops per impostazione predefinita, ma non si sa mai).

[aggiunta segue ]

Per quanto riguarda la scrittura del salto di 5 byte, c'è anche il problema che c'è solo un'istruzione che ti permetterà di scrivere più di 4 byte atomicamente - cmpxchg8b, e non è un'istruzione ideale per lo scopo. Se scrivi prima 0xe9 e poi una dword, allora hai una condizione di competizione se 0xe9 viene eseguito prima di posizionare la dword. Ancora un altro motivo per scrivere prima il salto in lungo.

In genere sono NOP o INT3.
Giusto, ma nel caso degli INT3, sicuramente non vuoi eseguirlo per sbaglio.
E nel caso in cui la funzione sia * già * deviata, scrivere prima l'indirizzo di destinazione del salto a 4 byte sostituirà atomicamente qualsiasi cosa `rel32` avesse il precedente` jmp`. (Supponendo che la dword sia allineata a 4 byte, che sarà se le funzioni sono allineate a 8 o 16 byte. Termina all'inizio di una funzione.)
#3
+8
rebel87
2015-10-03 12:54:27 UTC
view on stackexchange narkive permalink

presentazione di cortesia Hotpatching and the Rise ofThird-Party Patches al BlackHat USA 2006 di Alexander Sotirov

Cos'è l'hotpatching? Hotpatching è un metodo per modificare il comportamento di un'applicazione modificando il suo codice binario in fase di esecuzione. È una tecnica comune con molti usi:

• debug (punti di interruzione del software)

• strumentazione runtime

• aggancio delle funzioni API di Windows

• modifica dell'esecuzione o aggiunta di nuove funzionalità alle applicazioni di origine chiusa

• distribuzione di aggiornamenti software senza riavviare

• correzione delle vulnerabilità di sicurezza

Hotpatch sono generati da uno strumento automatizzato che confronta i file binari originali e quelli corretti. Le funzioni che sono state modificate sono incluse in un file con estensione .hp.dll. Quando la DLL hotpatch viene caricata in un processo in esecuzione, la prima istruzione della funzione vulnerabile viene sostituita con un salto all'hotpatch.

L'opzione del compilatore / hotpatch garantisce che la prima istruzione di ogni funzione sia un'istruzione mov edi, edi che può essere sovrascritta in modo sicuro dall'hotpatch. Le versioni precedenti di Windows non sono compilate con questa opzione e non possono essere aggiornate a caldo.



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...