2013-06-05 40 views
0

所以我一直在通過問題與外部進程內存讀取(讀取進程的內存我不能訪問。)我已經改變了,但有一件事我只是我無法理解我的頭腦。內存在Windows中如何工作?

的Win32API函數ReadProcessMemory()接受幾個參數,如下所示:

public static extern Int32 ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, 
     [In, Out] byte[] buffer, UInt32 size, out IntPtr lpNumberOfBytesRead); 

我傳遞這些參數是這樣的:

public byte[] ReadBytes(IntPtr Handle, Int64 Address, uint BytesToRead) 
    { 
     IntPtr ptrBytesRead; 
     byte[] buffer = new byte[BytesToRead]; 
     ReadProcessMemory(Handle, new IntPtr(Address), buffer, BytesToRead, out ptrBytesRead); 
     return buffer; 
    } 

那是,直到最近,我的理解是這裏列出的地址對於閱讀內存來說是唯一非常重要的事情,這就是我在內存中找到的正確值。不幸的是,這似乎是一個託什的負擔,而且看起來實際上這個句柄控制着我與之交互的那個窗口。例如:

我正在運行「Notepad.exe」進程的2個版本。

過程的每個實例有一個整數,第一個包含數字12345,第二個是包含54321

我期待讀取整數,並讓我們說(雖然我還沒有證實了這一點,所以它可能是不真實的)該程序內存空間內存地址是0x1000。

如果我例如運行:

ReadProcessMemory(NP.Handle, NP.MainModule.BaseAddress + 0x1000, buffer, 32, bread); 

這將與手柄閱讀的過程中,在該基地的地址添加到該偏移。然而這段代碼將讀取完全相同的值:

ReadProcessMemory(NP.Handle, NP2.MainModule.BaseAddress + 0x1000, buffer, 32, bread); 

注意NP2應該是第二個記事本窗口,NP是第一。在上述的頂部,這將讀出的不同的值(儘管我們正在閱讀是相同的與第一示例中的地址的):

ReadProcessMemory(NP2.Handle, NP.MainModule.BaseAddress + 0x1000, buffer, 32, bread); 

當然這意味着該把手控制,其中存儲器是閱讀,而不是地址,而且事實上這個地址與我實際上想要做的事情完全不相關?任何人都可以向我解釋爲什麼會是這種情況?

道歉,如果這個問題過於具體,但這個問題一直困擾着我的腦子很長一段時間了,雖然我每天都和很多程序員說話,但他們都沒有能夠(或者更多他們不願意)幫助我。

我完全意識到這隻適用於同一個exe的2個運行實例,所以如果你要閱讀Firefox和記事本(我認爲),它將不起作用。我只是想知道爲什麼它是這個改變的句柄,而不是地址。

感謝

+2

由於您僅從基址讀取4k,我懷疑您正在讀取內存的可執行部分,這對於'notepad.exe'進程都是相同的。你有沒有嘗試過讀兩個不同的程序?兩個過程的價值在這個位置是完全可行的。 – Steve

+0

「完全相同的價值」是什麼意思?同樣的答案,當它不應該? –

+0

@Steve - 我明白你的意思,實際上我沒有使用記事本,但另一個程序,我懷疑這裏會有人,記事本只是作爲一個例子。我實際讀取的偏移量是一個結構數組的一部分(在我注意到這個「問題」的情況下),並且距基數的偏移量爲0x553008)。 (還是)感謝你的建議。 – XtrmJosh

回答

2

那是,直到最近,我的理解是,這裏所列出的地址是讀取存儲真正重要的唯一的事情,那是什麼找到了我記憶中正確的值。不幸的是,這似乎是一個託什的負擔,而且看起來實際上這個句柄控制着我與之交互的那個窗口。

在這一段裏有很多關於你在做什麼的錯誤理解,我不確定從哪裏開始。

但在這裏不用(假設這是不完整):

閱讀我沒有訪問進程的內存

你不能。

如果您沒有足夠的權限訪問目標進程,Windows安全將阻止您獲得具有必要權限的進程的句柄。 (如果情況並非如此,則不存在安全性。)

但是,我們將假設讀取過程使用調試或具有足夠訪問權限的同等權限運行(這就是爲什麼,這部分被稱爲「上帝特權「允許持有者繞過安全)。

哪個窗口

你需要一個過程手柄,而不是一個窗口句柄手柄控制:他們是完全不同的事情。使用OpenProcess從進程ID獲取進程句柄,讀取內存請求的訪問權限包括PROCESS_VM_READ

他們你需要利用Windows進程的(虛擬)內存佈局知識來確定你需要讀取哪些地址。請記住,ASLR和32與64位進程將改變該內存佈局。另外分配的地址空間不太可能是連續的,所以你不能僅僅依次讀取內存。

這是一個高級主題。最後幾乎總是有一個更好的方法(適當的API,使用SendMessage來請求控件的內容,...),而不是直接讀取進程內存(記住對一個DLL的小改動 - 例如來自安全補丁 - 將轉移事物)。

摘要:找到另一種更好的方法。

編輯:一些資源來了解內存在Windows中:

  1. Mysteries of Memory Management Revealed,with Mark Russinovich (Part 1 of 2)
  2. Mysteries of Memory Management Revealed,with Mark Russinovich (Part 2 of 2)

    的兩個部分談話(第1部分:虛擬內存,第2部分:物理),也即會引入一些 非常有用的工具來查看內存以及它是如何組織的。

  3. 閱讀Windows Internals,Mark Russinovich et al。 (並非所有的都是相關的,但你也需要了解Win32的安全性)。

  4. 閱讀高級視窗,Jeffrey Richter。我認爲這已經絕版了(我的第三版涵蓋了Win95/NT4),但它是對於讀取進程內存並解釋結果所需知道的唯一嚴重信息。

+0

高度讚賞你的迴應,但找到另一種更好的方式並不可行。如上所述,我沒有直接訪問該程序,並且我也不太瞭解開發人員要求他們做出任何更改。 ReadProcessMemory函數幾乎是完美的,因爲我希望儘可能少地與程序交互,主要替代方法可能是注入或像素解釋,注入對於此目的有點過分,並且像素讀取會需要一些強烈的算法,計算單詞和什麼不... – XtrmJosh

+0

@XtrmJosh:我已經添加了一些資源,你可以用作你需要的基本知識(一個[SO]答案只能在這裏表面劃傷)。還有關於編寫Win32調試器的任何內容都可能會有所幫助(但是從內存管理的基礎知識開始:例如理解物理和進程內存幾乎完全不相關的原因)。瞭解其他開發人員*會更容易*(他們可能很樂意提供幫助)。 – Richard

相關問題