Lo que está preguntando es factible, pero no es muy fácil.
Una forma de hacerlo es compensar el movimiento del código en sus instrucciones. Necesita encontrar todas las instrucciones que usan el direccionamiento relativo de RIP (tienen el byte ModRM
de 05h, 0dh, 15h, 1dh, 25h, 2dh, 35h o 3dh) y ajustar su campo disp32
por la cantidad de movimiento (el movimiento por lo tanto, está limitado a +/- 2GB en el espacio de direcciones virtuales, lo que puede no estar garantizado dado que el espacio de direcciones de 64 bits es más grande que 4 GB).
También puede reemplazar esas instrucciones con sus equivalentes, más probable es que la sustitución de cada instrucción original con más de uno, por ejemplo:
; These replace the original instruction and occupy exactly as many bytes as the original instruction:
JMP Equivalent1
NOP
NOP
Equivalent1End:
; This is the code equivalent to the original instruction:
Equivalent1:
Equivalent subinstruction 1
Equivalent subinstruction 2
...
JMP Equivalent1End
Ambos métodos requieren por lo menos algunas rutinas x86 desmontaje rudimentarios.
El primero puede requerir el uso de VirtualAlloc()
en Windows (o algún equivalente en Linux) para garantizar que la memoria que contiene la copia parcheada del código original está dentro de +/- 2GB de ese código original. Y la asignación en direcciones específicas todavía puede fallar.
Este último requerirá algo más que el simple desarme primitivo, pero también la descodificación y generación de instrucciones completas.
Puede haber otros caprichos para solucionarlos.
límites instrucción también se pueden encontrar estableciendo el indicador TF
en el Registro RFLAGS
para que la CPU genera la interrupción de depuración single-step
al final de la ejecución de cada instrucción. Un controlador de excepción de depuración tendrá que detectarlos y registrar el valor de RIP de la siguiente instrucción. Creo que esto se puede hacer usando Structured Exception Handling (SEH)
en Windows (nunca lo intenté con las interrupciones de depuración), no estoy seguro acerca de Linux. Para que esto funcione, tendrás que hacer que todo el código se ejecute, cada instrucción.
Por cierto, hay direccionamiento absoluto en el modo de 64 bits, véase, por ejemplo, el MOV a/de instrucciones acumulador con códigos de operación de 0A0h través 0A3h.
el -mcmodel = large debería ser la solución. Tengo que investigar por qué el compilador de gcc osx no lo admite – nux
Tal vez es demasiado viejo. Los modelos pequeños (estándar) y de código medio se agregaron temprano, el modelo grande vino más tarde. – hirschhornsalz
muchas gracias, esto se ve muy bien y definitivamente resuelve el problema de direccionamiento absoluto – nux