2010-03-25 67 views
4

我正試圖讓程序讀取某個地址處的值。 我有這個:在地址處讀取值

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    int *address; 
    address = (int*)0x00000021; 
    cout << *address; 
    return 0; 
} 

但是,這給出了讀取違規錯誤。我究竟做錯了什麼? 謝謝

+0

爲什麼在這個世界上你想要這樣做? – 2010-03-25 21:30:38

+0

你從哪裏得到地址?你是否以虛擬模式運行(我懷疑...)?程序是否以內核模式鏈接(大概不是......)? – 2010-03-25 21:31:39

+0

因爲我想了解更多關於電腦如何工作的信息 – jmasterx 2010-03-25 21:31:48

回答

2

您只能使用指向實際對象的指針。

如果您沒有地址0x00000021的對象,則此操作無效。

如果你想創建的自由存儲區(堆)的對象,你需要做的所以使用new

int* address = new int; 
*address = 42; 
cout << *address; 
delete address; 
+0

那麼我怎樣才能獲得內存中的值,因爲OlyDbg可以告訴我這個地址是什麼... – jmasterx 2010-03-25 21:30:36

+2

@ user146780:調試器通常使用特定於操作系統和特定於環境的掛鉤來從進程的虛擬地址空間或物理內存中的給定地址讀取數據。 – 2010-03-25 21:33:35

5

讀取的過程中自己的空間範圍內的地址的值。如果要讀取另一個進程的空間或物理內存,則需要使用其他方法。

0

您不能只從內存中的任意地址讀取數據。

1

當您的程序在提供虛擬內存的操作系統上運行時(Windows,* nix,OS X)並非所有地址都由內存支持。支持虛擬內存的CPU使用稱爲Page Tables的東西來控制指向內存的地址。單個頁面的大小通常是4096個字節,但是確實有所不同,未來可能會更大。

用於查詢頁表的API不是標準C/C++運行時的一部分,因此您需要使用操作系統特定的功能來了解哪些地址可以讀取,哪些會導致您過錯。在Windows上,您可以使用VirtualQuery來確定給定的地址是可以讀取,寫入,執行還是以上任何一項。

3

對於OlyDbg向您展示的內容,有些問題是可以接受的。 32位(和64位)Windows使用虛擬內存,這意味着您在程序中使用的地址是而不是,與實際通過總線發送到內存芯片的地址相同。相反,Windows(我應該補充說其他操作系統,比如Linux,MacOS,* bsd等,大致相同)建立了一些表格,說明(實質上)何時該程序使用這個範圍內的地址,使用範圍的物理地址。

該映射是逐頁完成的(每個頁面通常爲4K字節,儘管其他大小也是可能的)。在該表中,它也可以將頁面標記爲「不存在」 - 這是支持將內存分頁到磁盤的內容。當您嘗試讀取標記爲不存在的頁面時,CPU會生成一個異常。然後,OS通過從磁盤讀取數據到一塊內存來處理該異常,並更新表格以表示數據存在於物理地址X處。除非存在,表格還支持其他一些值,例如只讀,所以你可以通過不寫一些地址來閱讀。

Windows(與其他操作系統一樣)爲地址空間的第一部分設置表,但不會將任何內存與它們關聯。從用戶程序的角度來看,這些地址不應該被使用。

這讓我們回想起OlyDbg在你要求從地址0x21讀取時給你的東西的不確定性。該地址根本不涉及任何真實的數據 - 永遠不會有,也永遠不會。

什麼其他人所說的是事實,以及:一個調試器通常會使用一些OS功能(例如ReadProcessMemoryWriteProcessMemory等等Windows下),以獲得訪問的東西,你不能直接讀寫。這些將允許您在另一個進程中讀寫內存,這是不能由普通指針直接訪問的。儘管這兩個地址都不會幫助嘗試讀取地址0x21 - 該地址並不涉及任何進程中的任何實際內存。