2011-05-14 37 views
1

你好 我使用vb 2008這裏是我的代碼部分:VB 2008 WriteProcessMemory的()返回0

Private Declare Function WriteProcessMemory Lib "kernel32" Alias "WriteProcessMemory" (_ 
     ByVal hProcess As Integer, _ 
     ByVal lpBaseAddress As Integer, _ 
     ByVal lpBuffer As Integer, _ 
     ByVal nSize As Integer, _ 
     ByVal lpNumberOfBytesWritten As Integer _ 
    ) As Integer 

    Dim proc() As Process = Process.GetProcessesByName("process") 
    If proc.Length = 0 Then Console.WriteLine("Process Not Found") : Exit Sub 
    Dim p = proc(0) 
    Dim pH As Integer = OpenProcess(PROCESS_ALL_ACCESS, 0, p.Id) 
    Dim address As Integer 
    address = &H98544 
    Dim memory As IntPtr 
    Call ReadProcessMemory(pH, address, memory, 4, 0) 
    Console.WriteLine(memory.ToString) 
    Dim data As Integer = 2000 
    Call WriteProcessMemory(pH, address, data, Len(data), 0&) 

但是,在WriteProcessMemory的()返回0,和值不改變

SOLUTION:

<DllImport("kernel32", CharSet:=CharSet.Auto, SetLastError:=True)> _ 
Private Shared Function WriteProcessMemory(_ 
             ByVal hProcess As IntPtr, _ 
             ByVal lpBaseAddress As IntPtr, _ 
             ByVal lpBuffer As Byte(), _ 
             ByVal nSize As UInt32, _ 
             ByRef lpNumberOfBytesWritten As UInt32 _ 
            ) As Boolean 
End Function 

     Dim proc() As Process = Process.GetProcessesByName("process") 
     If proc.Length = 0 Then Console.WriteLine("Process Not Found") : Exit Sub 
     Dim p = proc(0) 
     Dim pH As Integer = OpenProcess(PROCESS_ALL_ACCESS, 0, p.Id) 
     Dim address As Integer 
     address = &H98544 
     Dim memory As IntPtr 
     Call ReadProcessMemory(pH, address, memory, 4, 0) 
     Console.WriteLine(memory.ToString) 
     Dim data() As Byte = BitConverter.GetBytes(2000) 
     Call WriteProcessMemory(pH, address, data, 4, 0&) 

回答

2

當您調用Windows API函數時,您必須自己實現錯誤檢查代碼。當標準.NET Framework函數出現問題時,它們不會拋出異常。

所需的具體錯誤檢查因功能而異。 (像這樣的不一致就是.NET使用異常的原因。)檢查文檔是必不可少的。

WriteProcessMemory工作方式是相當常見。返回值是BOOL(Win32庫視爲布爾值的整數,其中0 = FALSE且1 = TRUE)。如果函數失敗,則返回值爲0(FALSE)。如果成功,則返回值爲1(TRUE):

如果函數成功,則返回值爲非零值。

如果函數失敗,返回值爲0(零)。要獲得更多的錯誤信息,請致電GetLastError。如果請求的寫入操作進入不可訪問的進程區域,則該函數失敗。

有趣的地方在那裏,當然,是我們被告知,我們必須調用GetLastError功能,以確定爲什麼函數失敗。其中一部分是事實。 You only call GetLastError when you're writing unmanaged C++ code。在.NET中,你需要做別的事情。有兩個步驟:

  1. 標記的P/Invoke簽名與SetLastError = True,這會導致CLR自動調用GetLastError,並保存其價值。
  2. 致電Marshal.GetLastWin32Error檢索該值。

所以,調試它,你就需要重新編寫代碼,像這樣的(使用標準的P/Invoke的語法,而不是更有限Declare關鍵字所獨有的VB.NET):

<DllImport("kernel32", CharSet:=CharSet.Auto, SetLastError:=True)> 
Private Shared Function WriteProcessMemory(
              ByVal hProcess As Integer, _ 
              ByVal lpBaseAddress As Integer, _ 
              ByVal lpBuffer As Integer, _ 
              ByVal nSize As Integer, _ 
              ByVal lpNumberOfBytesWritten As Integer _ 
             ) As Integer 
End Function 

Dim proc() As Process = Process.GetProcessesByName("process") 
If proc.Length = 0 Then Console.WriteLine("Process Not Found") : Exit Sub 
Dim p = proc(0) 
Dim pH As Integer = OpenProcess(PROCESS_ALL_ACCESS, 0, p.Id) 
Dim address As Integer 
address = &H98544 
Dim memory As IntPtr 
Call ReadProcessMemory(pH, address, memory, 4, 0) 
Console.WriteLine(memory.ToString) 
Dim data As Integer = 2000 
If WriteProcessMemory(pH, address, data, Len(data), 0&) = 0 Then 
    ' The function failed, so find out what the error was 
    MessageBox.Show("WriteProcessMemory failed with error " & Marshal.GetLastWin32Error) 
End If 

一旦你知道了錯誤代碼,你可以看看它在list of System Error Codes,看看這是什麼意思。


原來的錯誤是299號,ERROR_PARTIAL_COPY,該文件說,只是表示:

一個ReadProcessMemory或WriteProcessMemory的請求只有部分已經完成。

嗯,不是很有幫助...我希望你能找到更好的東西。 C'est la vie

你將不得不有一點額外的知識來解決這個問題。文件中再次提供了一個提示。任何時候它說一個參數是一個「指針」(用C++語法用星號*表示),這意味着在VB.NET中,它需要作爲參考而不是作爲值傳遞。要指定將某些內容作爲參考傳遞,請使用ByRef關鍵字。當然,要通過值傳遞,您需要指定默認的ByVal關鍵字。

此外,請注意,當文件說的東西是手柄地址,你應該在VB.NET其聲明爲IntPtr type,而不是作爲一個整數。 IntPtr是特殊的,因爲它的大小會發生變化,具體取決於底層操作系統是32位還是64位(與固定大小的整數不同,無論您在哪個平臺上運行)。儘管這不會造成您的直接問題,但在編譯64位代碼時,將導致兼容性問題

所以事實證明,你的聲明其實是錯誤的。再次聲明它是這樣的:

<DllImport("kernel32", CharSet:=CharSet.Auto, SetLastError:=True)> 
Private Shared Function WriteProcessMemory(
              ByVal hProcess As IntPtr, _ 
              ByVal lpBaseAddress As IntPtr, _ 
              ByVal lpBuffer As Integer, _ 
              ByVal nSize As Integer, _ 
              ByRef lpNumberOfBytesWritten As Integer _ 
             ) As Integer 
End Function 

你也可以考慮的是,第三個參數(lpBuffer)應該是字節(Byte())的陣列,因爲它指定的數據被寫入到地址空間。

+0

它顯示「299」錯誤(系統錯誤代碼(0-499)),但仍然無法理解問題出在哪裏。 – John 2011-05-14 11:26:40

+0

@John:299是'ERROR_PARTIAL_COPY':只有部分ReadProcessMemory或WriteProcessMemory請求已完成。原來這不是很有幫助。我認爲它會告訴你更好的東西。讓我修改我的答案。 – 2011-05-14 11:31:27

+0

我用解決方案更新了我的問題,感謝您的幫助 – John 2011-05-14 11:46:32

1

documentation狀態:

如果該功能失敗,返回 值爲0(零)。要獲得擴展的 錯誤信息,請調用GetLastError。 如果請求的 寫入操作跨入不可訪問的進程的區域 ,則該功能失敗。

我建議您按照說明的方式找出失敗的原因。

說完這一點之後,看起來可能是失敗的原因是您嘗試寫入的地址2000在該進程中不是有效地址。

lpBuffer參數是一個指針,並且您將傳遞整數值2000作爲該參數。因此這被解釋並且是一個內存地址。我懷疑你實際上打算通過data的地址。

+0

嗯,我看你已經發布了我的答案的「執行摘要」... – 2011-05-14 11:17:24