Pregunta

Estoy tratando de codificar un exe empacador / protector como una manera de aprender más sobre ensamblador, C ++, y cómo funcionan los archivos PE. He actualmente tengo trabajo por lo que la sección que contiene el EP se hace un XOR con una clave y una nueva sección se crea que contiene el código de descifrado. Todo funciona de maravilla, excepto cuando intento y JMP al PE original después de descifrado.

Básicamente hago esto:

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

Pero en lugar de ello saltar al punto de entrada, OllyDbg muestra que este código se desarma a:

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

y cuando trato de cambiar manualmente en Olly el nuevo código de operación se muestra como

00404030    -E9 CBCFFFFF    JMP crypted.00401000

¿De dónde 0xCBCFFFFF viene? ¿Cómo iba a generar que desde el lado C ++?

¿Fue útil?

Solución

Creo que E9 es un código de operación para un salto relativo:. Su operando especifica una distancia relativa que ser saltado, más o menos desde el principio de la siguiente instrucción

Si desea que el operando para especificar una dirección absoluta, que se necesita un código de operación diferente.

Otros consejos

puede usar:

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

o

push DESTINATION_VA
ret                    ; not recommended for performance

Esta y las siguientes instrucciones ret arriba-a-16 que se remontan hasta el árbol de llamadas superiores a esta profundidad se mispredict, a menos que fueran empujados fuera de la pila predictor de retorno de dirección por una profundidad más profunda llamada. (CPU actual tienen típicamente una pila predictor de 16 entrada).


E9 relativa jmp codificación se utiliza como esto:

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

+ ret empuje es la solución más pequeña si tiene dirección de VA y la imagen no se reubica, pero aún así es de 6 bytes por lo que es más grande que un jmp rel32 directa.

Registrar-indirecta es probablemente el más eficiente si no se puede utilizar un jmp directa normal.

opcode para absoluta salto indirecto es FF + 4byte dirección. Esta es la más utilizada para jumptables de direcciones almacenadas en los datos.

direcciones absolutas requieren reubicación cuando no cargado a la dirección esperada, por lo general, se prefieren direcciones relativas. Código de saltos relativos es también 2 bytes más pequeño.

Intel optimización manual indica que la CPU espera de llamada y ret a ser utilizados en pares, por lo que el ret sin convocatoria sugeridas en respuesta 2 causaría lo que llaman una "penalización en el rendimiento".

Además, si el código no se cargó a la misma dirección que el compilador asume, la ret probablemente fallar el programa. Sería más seguro para calcular una dirección relativa.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top