2017-07-25 106 views
0
返回值

有這個程序的功能,目前返回我更希望它返回一個0如何更改的功能

從此我推斷:我們可以添加偏移量,程序計數器,uregs[R_PC]+arg0,找到返回值的地址。我已經分配了一個32位的「0」,並且我嘗試將2個字節寫入返回值所在的地址(我們的函數期望返回一個BOOL16,所以我們只需要2個字節的0) :

sudo dtrace -p "$(getpid)" -w -n ' 
int *zero; 
BEGIN { zero=alloca(4); *zero=0; } 
pid$target::TextOutA:return { 
    copyout(zero, uregs[R_PC]+arg0, 2); 
}' 

當然,我得到:

的DTrace:無效的地址(0x41f21c)中:上啓用探頭ID 2(:pid60498:gdi32.dll.so:TextOutA:返回ID 320426)錯誤在DIF偏移60的動作#1

uregs[R_PC]可能是一個用戶空間地址。可能copyout()想要一個內核地址。

如何將用戶空間地址uregs[R_PC]轉換爲內核空間?我知道用copyin()我們可以將存儲在用戶空間地址的數據讀入內核空間。但是這並沒有給我們該內存的內核地址。

或者:是否有其他方法可以使用DTrace更改返回值?

+0

我看不到'arg0 + u_regs [R_PC];'得到你返回值的地址。那是兩個地址。添加它們似乎沒有意義。你怎麼知道返回值的地址?它很可能通過寄存器傳遞。實際的返回值*在'arg1'中。請參閱http://docs.oracle.com/cd/E19253-01/817-6223/chp-pid/index.html –

+0

我從文檔中瞭解到'u_regs [R_PC]'是程序計數器,而' arg0'是程序counter_的一個_offset。所以,'u_regs [R_PC]'將是一個_absolute_地址,'arg0'是一個_relative_offset_,你可以添加到該絕對地址,以獲得不同的絕對地址。對於'arg1', – Birchlabs

+0

:當然這是_value_,但我的意圖是在函數返回it_之前修改該值。我們在DTrace中修改數據的唯一工具('copyout()')要求我們知道數據的地址。 – Birchlabs

回答

1

DTrace不是這方面的正確工具。您應該改用像dbx,mdb或gdb這樣的調試器。

與此同時,我會嘗試澄清一些您提到的概念。

首先,您可能會在源代碼中看到一個簡單的函數,即有一個返回值。編譯結果(即函數的機器特定實現)也很可能只包含一個單一的退出點。然而,通常情況下,實現可能包含多個退出點,並且開發人員可能會知道返回的函數來自哪個特定的退出點。正是這種信息被描述爲從函數開始的偏移量,它由返回探測器的arg0給出。然後,你的D腳本正試圖更新程序或庫本身的一部分;儘管arg0的添加使得目標地址有些隨機,但結果很可能仍然在只讀的文本部分內。其次,在一般情況下,函數的實現通過將其存儲在特定的寄存器中來返回值;例如在amd64上的%rax。因此,覆蓋返回值將會覆蓋寄存器值。這是不可能的,因爲DTrace對用戶地址寄存器的訪問是隻讀的。

函數有可能以這樣的方式實現,當它返回時,它會在將特定的內存位置寫入適當的寄存器之前從特定的內存位置恢復返回值。如果是這種情況,那麼確實可以在訪問存儲器之前修改其值(given its location)。但是,這隻適用於一部分情況:返回值可能同樣包含在另一個寄存器中,或者在程序文本本身中簡單表示爲常量。在任何情況下,如果存在更合適的調試工具,這將比其值得多得多。

+0

輝煌!感謝您的詳細解釋。鏈接的答案也很有用。好吧,所以'arg0'指向一個_instruction_(即「這個函數中的一個返回指令」),而不是數據 - 所以即使我有它的內核空間地址,它不是我所尋找的。是的,這可能是一個不同工具的工作。 – Birchlabs