2016-07-12 23 views
1

我試圖修改一個名爲函數的第一個指令,但在下面的代碼片段上了第二條語句段故障如何修改流程中的指令? Linux和ARMv7的

int a = *(int*)g; 
*(int*)g=0; // segment fault! 
*(int*)g=a; 

了這部分的故障是由於NO-在我想要修改的指令所在頁面的頁表項中寫入權限?

我這樣做是因爲我想看看我是否能修補函數的一些錯誤,並保持過程的運行,像這樣:

1)功能運行,並且的工藝g已被發現有一些錯誤。因此,編寫一個名爲patch_g的新函數,它沒有錯誤。

2)編譯新功能到patch.so

3)的dlopen & 對dlsym的.so文件。獲取地址patch_g

4)暫停正在運行的進程

5)使用一些代碼(有點類似於上面代碼段的第二語句)改變所述第一指令到jump patch_g

回答

1

好吧,讓我們來做一個實驗。 下面是代碼:

#include <stdio.h> 

int (*functionPtr)(int,int); 

int addInt(int n, int m) { 
     return n+m; 
} 


int main() 
{ 
    functionPtr = &addInt; 
    printf("%p\n", functionPtr); 
    while(1){}; 
    *(int *) functionPtr = 0x0; 
    return 0; 
} 

編譯

$ gcc -o ./main.c main 

啓動這個程序,在第一個控制檯。

$ ./main 
0x40052d 

在第二個控制檯

$ cat /proc/`pidof main`/maps 
00400000-00401000 r-xp 00000000 08:01 6345711       /tmp/main 
00600000-00601000 r--p 00000000 08:01 6345711       /tmp/main 
00601000-00602000 rw-p 00001000 08:01 6345711       /tmp/main 

...

R-XP意味着,當內核加載此二進制文件,它已經映射的文字部分爲民營虛擬映射具有讀取和執行權限,但沒有寫入權限。我認爲這是出於安全原因而完成的。

因此,內核中的vma_area被標記爲不可寫,導致未處理的用戶空間頁錯誤,即發生段錯誤。

現在let'us mprotect的調用添加到適當的地方

17   if (mprotect((void *)0x00400000, 4096, PROT_READ | PROT_WRITE | PROT_EXEC)) { 
18     printf("error\n"); 
19     return -1; 
20   } 

你會發現,這將有助於你與你的運行時修補的想法。

00400000-00401000 rwxp 00000000 08:01 6345711       /tmp/main 
00600000-00601000 r--p 00000000 08:01 6345711       /tmp/main 
00601000-00602000 rw-p 00001000 08:01 6345711       /tmp/main 
+0

非常感謝你,Alex。有用的/ proc/pid/maps和mprotect。 – xiaokaoy