У меня есть простая "функция", если вы даже можете назвать ее так, что это только "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.
Оказалось, что, как предложил Питер Лори, страница действительно была защищена от казни. Решение было довольно простым.
Мне пришлось сопоставить VirtualProtectEx с Win32 API и вызвать это со значением 0x40, чтобы разрешить выполнение. После этого все получилось!
Я думаю, что использование объекта памяти - не очень хорошая идея. Если вы посмотрите на метод finalize, вы заметите, что он вызывает функцию free free(), а адрес, который не управляется jvm, может вызвать ошибку сегментации. Очевидно, проблема здесь возникает раньше. Попробуйте предоставить объект указателя функции Function.getFunction, но не память. Вы можете просто попробовать следующее:
Pointer ptr = Pointer.createConstant(0x90);
Function f = Function.getFunction(ptr, Function.C_CONVENTION);