2014-09-02 96 views
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]

我以爲不會收到錯誤,因爲它肯定應該有。我不知道可能會出現什麼問題。

有什麼我在這裏失蹤或(顯然,但是什麼?)做錯了?

注意:我正在使用JNA 4.1.0。

+2

在大多數CPU上,代碼(只讀)和數據(可寫)在不同的頁面上。我不認爲你可以用這種方式在數據頁面上運行代碼。順便說一句,使用生成的字節碼更有可能工作,並且可能會更快。 – 2014-09-02 17:24:25

+0

那麼,我也不知道,但根據[這裏]的示例(https://github.com/kobalicek/asmjit),建議在動態生成函數並調用這些函數時都很好。這正是我正在嘗試的。 :) – 2014-09-02 17:26:43

+2

你確定它不只是執行你的NOP,然後繼續進行一些未定義的內存?您可能只需要一個調用返回操作碼。 – darron 2014-09-02 17:28:55

回答

1

我認爲使用Memory對象不是一個好主意。如果你看看finalize方法,你會注意到它調用了本地的free()函數,並且提供不被jvm管理的地址可能導致分段錯誤。顯然這裏問題出現得更早。嘗試將一個指針對象提供給Function.getFunction而不是Memory。 你可以簡單地嘗試這個辦法:

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

橫空出世,作爲彼得Lawrey所建議的,該網頁確實是從執行保護。解決方案相當簡單。

我必須從Win32 API映射VirtualProtectEx並使用值0x40調用它以允許執行。完成後,它就起作用了!