2015-06-18 15 views
5

Ho un'istruzione di traccia e voglio estrarre chiamate di funzione e restituisce.Differenze tra chiamata, push + ret e push + jump in assembly

ho scoperto che, tranne call istruzioni, push + jmp e push + ret può essere utilizzato per chiamata di funzione? All'inizio voglio essere sicuro sia corretto? e se sì quali sono le differenze tra loro?

Anche se push + ret è un tipo di chiamata, quindi quale sarebbe la fine o il ritorno di una funzione? Vedendo solo ret senza l'istruzione push prima di esso?

risposta

4

In termini semplificati:

chiamata indirizzo

Questo spingerà il program counter aggiornato (che indica l'istruzione successiva call) nello stack poi passa alla indirizzo indicato (possono essere applicate le modalità di indirizzamento).

ret

Questa istruzione apre internamente e l'indirizzo dallo stack e salta ad esso. Questo è ben adattato con call in modo che possa tornare alle istruzioni dopo il precedente call.

JMP indirizzo

Questo salta semplicemente alla data indirizzo (possono essere modalità di indirizzamento). Non fa assolutamente nulla con lo stack.


Così, si può anche fare questo:

push address 
ret 

Quale pop e saltare al indirizzo che è stato inserito nello stack come descritto sopra. È un modo intelligente per eseguire un salto indiretto in un microprocessore che non supporta le modalità di indirizzamento indiretto nelle istruzioni di salto.

La sequenza:

push address 
jmp someplace 

Sarà salta semplicemente a qualche parte e non influisce sulla pila o utilizzare l'indirizzo che è stato inserito nello stack. Se l'indirizzo è l'istruzione successiva allo jmp, è equivalente a call someplace.

Per set di istruzioni che non supportano un salto indirizzamento indiretto, Ho visto questo bel po 'di lavoro-around:

push address 
ret 

Quale salterà a qualunque address è.

+0

Inusuali variazioni di questi sono spesso utilizzati quando l'autore vuole oscurare la vera funzionalità del codice (ad es. Malware e software commerciale "protetto da copia"). –

+0

Non 'ret' essenzialmente' pop e salta indirettamente all'indirizzo popped'? –

+0

@JohnHascall si, è ... "duh" da parte mia. : p Stavo pensando "no" call', no "ret". :) – lurker

6

Sì, sei corretto.

Quando viene emesso uno call, l'indirizzo di ritorno inserito nello stack è l'indirizzo successivo in cui l'esecuzione deve continuare (l'indirizzo immediatamente successivo all'istruzione corrente). In sostanza si tratta di un atomico push seguito da un jmp.

Ciò significa che se si manualmente push e poi jmp, la funzione che si salta in possibile in seguito ret e, purché tutti gli accessi pila nella funzione è equilibrato tornerà all'indirizzo che spinto in precedenza.

Analogamente, è possibile push e quindi ret per simulare un ritorno di chiamata, ma questo non consente di tornare in seguito. Questo tipo di comportamento è più comunemente usato per eliminare i disassemblatori, rendendo più difficile determinare con quale indirizzo il codice si sta dirigendo con un semplice disassemblatore.

+0

"Questo tipo di comportamento è più comunemente usato per eliminare i disassemblatori" sai se IDA Pro ha qualche funzionalità per interpretare correttamente queste tattiche come chiamate/resi? Da una prospettiva generale, in quale direzione suggeriresti di andare a smontare il codice che impiega questa tattica offuscante? modifica: un po 'più di ricerca ha prodotto questa discussione che fa riferimento alla tua risposta e risponde alla mia domanda: http://reverseengineering.stackexchange.com/questions/10911/automatically-decode-pushret-call-into-jmp – SullX

Problemi correlati