我有一个简单的'功能',如果你甚至可以称之为,那只是存储在内存中的'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]
我没想到会收到这个错误,因为它当然应该存在。我不知道什么可能出错。
我在这里缺少什么或(显然,但是什么?)做错了?
注意:我使用的是JNA 4.1.0。
答案 0 :(得分:1)
我认为使用Memory对象并不是一个好主意。如果查看finalize方法,您会注意到它调用了本机free()函数,并且提供不受jvm管理的地址可能会导致分段错误。显然这里的问题出现得更早了。尝试向Function.getFunction提供Pointer对象,但不提供Memory。 你可以试试这个:
Pointer ptr = Pointer.createConstant(0x90);
Function f = Function.getFunction(ptr, Function.C_CONVENTION);
答案 1 :(得分:1)
事实证明,正如Peter Lawrey所建议的那样,页面确实受到了保护而无法执行。解决方案相当简单。
我必须从Win32 API映射VirtualProtectEx并使用值0x40调用它以允许执行。在那之后,它工作了!