Создание функции в памяти и вызов ее

1

У меня есть простая "функция", если вы даже можете назвать ее так, что это только "NOP", хранящийся в памяти:

byte[] func = new byte[] {0x90}; // NOP

Затем я выделяю фрагмент памяти, который будет удерживать его, и установите содержимое:

Memory mem = new Memory(func.length);
mem.write(0, code, 0, code.length); // Write all bytes from code, starting at mem + 0

Теперь я хочу "вызвать" эту небольшую функцию, которую я только что создал. Попробуем:

Function function = Function.getFunction(mem, Function.C_CONVENTION);
function.invokeVoid(null); // I have tried other types of invokeXX too.

Но это не работает, но вместо этого выдает исключение:

Exception in thread "main" java.lang.Error: Invalid memory access at com.sun.jna.Native.invokeVoid(Native Method) at com.sun.jna.Function.invoke(Function.java:367) at com.sun.jna.Function.invoke(Function.java:315) at com.sun.jna.Function.invoke(Function.java:268) at com.sun.jna.Function.invokeVoid(Function.java:727) at [my line calling invokeVoid]

Я не ожидал получить эту ошибку, потому что она, безусловно, должна быть там. Я понятия не имею, что может пойти не так.

Есть ли что-то, чего я здесь не вижу или (очевидно, но что?) Делает неправильно?

NB: Я использую JNA 4.1.0.

  • 2
    В настоящее время на большинстве процессоров код (только для чтения) и данные (для записи) находятся на отдельных страницах. Я не думаю, что вы можете запустить код на страницах данных таким образом. Кстати, использование сгенерированного байтового кода, скорее всего, будет работать, и может быть быстрее.
  • 0
    Ну, я тоже не знал, но в соответствии с приведенными здесь примерами, было бы неплохо создавать функции на лету и вызывать их. Это то, что я тоже пытался. :)
Показать ещё 2 комментария
Теги:
jni
jna

2 ответа

1

Оказалось, что, как предложил Питер Лори, страница действительно была защищена от казни. Решение было довольно простым.

Мне пришлось сопоставить VirtualProtectEx с Win32 API и вызвать это со значением 0x40, чтобы разрешить выполнение. После этого все получилось!

1

Я думаю, что использование объекта памяти - не очень хорошая идея. Если вы посмотрите на метод finalize, вы заметите, что он вызывает функцию free free(), а адрес, который не управляется jvm, может вызвать ошибку сегментации. Очевидно, проблема здесь возникает раньше. Попробуйте предоставить объект указателя функции Function.getFunction, но не память. Вы можете просто попробовать следующее:

Pointer ptr = Pointer.createConstant(0x90);
Function f = Function.getFunction(ptr, Function.C_CONVENTION);

Ещё вопросы

Сообщество Overcoder
Наверх
Меню