2014-01-17 48 views
1

我試圖做一個自我修改的代碼庫,我已經scowered遍,我有後續代碼:Android的自修改代碼 - NDK

typedef int (*FUNC) (void); 
int test(); 

JNIEXPORT int Java_com_example_untitled_MyActivity_decrypt(JNIEnv* env, jobject thiz) 
{ 
    void *code = mmap(NULL, 4, PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 

    if (code != MAP_FAILED) { 
     memcpy(code, test, 4); 

     return ((FUNC)code)(); 
    } 

    return 0; 
} 

int test() 
{ 
    return 100; 
} 

請幫助...我用Native self-modifying code on Android爲我的出發點,他們說了一些關於編譯與「-marm」和拇指位...

我遇到的問題是,它只是崩潰。我試過使用cacheflush函數,似乎沒有幫助。我很茫然。

+0

你有什麼問題?代碼的預期行爲和觀察行爲是什麼? (例如,你爲什麼認爲測試的長度正好是4字節?) – addaon

+0

因爲我對ARM進行了反向工程,知道mov r0,100是2個字節,而BX LR是2個字節... :)也驗證了它沒有使用4字節的mov指令。 – Thomas

+0

ARM指令長度爲4個字節... – addaon

回答

0

在ARM上,您需要刷新CPU高速緩存以確保剛纔複製的指令在執行之前對CPU可見。一個簡單的方法是:

#include <unistd.h> // for cacheflush() 

... 

// Copy the instructions to the destination address. 
memcpy(dest, original_intructions, size_of_instructions); 

// Clear the CPU cache 
cacheflush((uintptr_t)dest, (uintptr_t)dest + size_of_instructions, 0); 

// Run them. 
return ((FUNC)dest)(); 
+0

這不是直接問題。這個問題是隨着addaon說的。也許你可以回答我這個問題,但是,我可以編譯一個函數,拿到ARM,刪除函數,仍然使用ARM並將參數傳遞給它?或者ARM使用會導致問題的內存地址? – Thomas

+0

這取決於函數的編譯方式。您需要首先使用-fPIC來生成與位置無關的代碼。其次,您需要確保函數永遠不會嘗試訪問全局變量或另一個函數(都會引入重定位,從而阻止您做出您想要的)。 – Digit

+1

我最終只是使用mprotect修改了應用程序的內存,所以代碼只是在ida中使用AES和多級混淆進行了模糊處理。 – Thomas