То, о чем вы спрашиваете, выполнимо, но не очень просто.
Один из способов сделать это - компенсировать перемещение кода в его инструкциях.Вам нужно найти все инструкции, которые используют относительную RIP-адресацию (они имеют байт ModRM
05h, 0dh, 15h, 1dh, 25h, 2dh, 35h или 3dh) и откорректировать их поле disp32
на величинуmove (поэтому перемещение ограничено до +/- 2 ГБ в виртуальном адресном пространстве, что не может быть гарантировано, если 64-разрядное адресное пространство превышает 4 ГБ).
Вы также можете заменить эти инструкции ихэквиваленты, скорее всего, заменяя каждую исходную инструкцию более чем одной, например:
; 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
Оба метода потребуют как минимум несколько элементарных процедур разборки x86.
В первом случае может потребоваться использованиеVirtualAlloc()
в Windows (или некотором аналоге в Linux), чтобы гарантировать, что память, содержащая исправленную копию исходного кода, находится в пределах +/- 2 ГБ этого исходного кода.И выделение по определенным адресам все еще может потерпеть неудачу.
Последнее потребует не только примитивной разборки, но также полного декодирования и генерации команд.
Могут существовать и другие причуды, которые можно обойти.
Границы команд также можно найти, установив флаг TF
в регистре RFLAGS
, чтобы ЦП генерировал прерывание отладки single-step
в конце выполнения каждой инструкции.Обработчик исключений отладки должен будет перехватить их и записать значение RIP следующей инструкции.Я полагаю, что это можно сделать с помощью Structured Exception Handling (SEH)
в Windows (никогда не пробовал с прерываниями отладки), не уверен насчет Linux.Чтобы это работало, вам нужно будет выполнить весь код, каждую инструкцию.
Кстати, в 64-битном режиме есть абсолютная адресация, см., Например, инструкции MOV к / от аккумулятора с кодами операций изС 0A0h по 0A3h.