Domanda

Sto cercando di codificare un exe packer / protector come un modo di imparare di più su assembler, C ++, e come PE file funzionano. Ho attualmente ottenuto che funziona in modo che la sezione contenente il PE è XORed con una chiave e una nuova sezione si crea che contiene il mio codice di decrittazione. Tutto funziona alla grande tranne quando provo e JMP al PE originale dopo la decrittografia.

In pratica faccio questo:

DWORD originalEntryPoint = optionalHeader->AddressOfEntryPoint;
// -- snip -- //
    crypted.put(0xE9);
 crypted.write((char*)&orginalEntryPoint, sizeof(DWORD)); 

Ma invece di esso saltare al punto di ingresso, OllyDbg dimostra che questo codice smonta a:

00404030   .-E9 00100000    JMP 00405035 ; should be 00401000 =[

e quando provo a cambiare manualmente in Olly il nuovo codice operativo presenta come

00404030    -E9 CBCFFFFF    JMP crypted.00401000

Da dove 0xCBCFFFFF viene? Come faccio a generare quella dal lato C ++?

È stato utile?

Soluzione

Credo che E9 è un codice operativo per un salto relativo:. Suo operando specifica una distanza relativa per essere saltato, più o meno dall'inizio della prossima istruzione

Se si vuole l'operando per specificare un indirizzo assoluto, si avrebbe bisogno di un codice operativo diverso.

Altri suggerimenti

è possibile utilizzare:

mov eax,DESTINATION_VA
jmp eax                ; pick any register the destination doesn't care about

o

push DESTINATION_VA
ret                    ; not recommended for performance

Questa e le prossime istruzioni ret up-to-16 che risalgono l'albero chiamata superiore a questa profondità si mispredict, a meno che non sono stati spinti dallo stack predittore ritorno l'indirizzo da una profondità di chiamata più profonda. (CPU corrente in genere hanno uno stack predittore 16-entry).


relativa E9 jmp codifica viene utilizzato in questo modo:

CURRENT_RVA: jmp (DESTINATION_RVA - CURRENT_RVA - 5 [sizeof(E9 xx xx xx xx)])

Push + ret è la soluzione più piccola se si dispone di indirizzo VA e l'immagine non viene spostato, ma è ancora 6 byte in modo che sia più grande di un jmp rel32 diretta.

Registrati-indiretta è probabilmente il più efficiente, se non è possibile utilizzare un jmp diretta normale.

codice operativo per il salto indiretto assoluto è FF + 4byte indirizzo. Questo è più spesso utilizzato per jumptables di indirizzi memorizzati nei dati.

indirizzi assoluti richiedono rilocazione quando non caricato all'indirizzo atteso, così indirizzi relativi sono generalmente preferiti. Codice per i salti relative è anche 2 byte più piccolo.

Intel ottimizzazione manuale indica che la CPU aspetta chiamata e ret ad essere utilizzati in coppia, in modo che il ret senza invito suggerito in risposta 2 causerebbe quello che chiamano un "penalizzazione delle prestazioni".

Inoltre, se il codice non è stato caricato per lo stesso indirizzo che il compilatore ha assunto, il ret sarebbe probabilmente in crash il programma. Sarebbe più sicuro per calcolare un indirizzo relativo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top