none
寫入記憶體出現記憶體保護的問題? RRS feed

  • 問題

  • 大大請教一下以下是 GetWindowThreadProcessId

     Dim q As Long

    getwin = FindWindow(vbNullString, "Form1")
            GetWindowThreadProcessId(getwin, q)

    為什上面的寫法出現錯誤訊息告訴我:

    嘗試讀取或寫入受保護的記憶體。這通常表示其他記憶體已損毀

    請問這是甚麼情形

    我使用的是vs2015的vb請問要用哪一種型別才部會出現上述的記憶體被保護的問題

    煩請回覆謝謝!

    2015年9月17日 上午 03:53

解答

所有回覆

  • findwindow (user32)

    getwindowthreadprocessid (user32)

            Dim q As Integer
            Dim getwin As IntPtr


    • 已編輯 Joe Hung 2015年9月17日 上午 04:12
    • 已標示為解答 璉璉Moderator 2015年9月26日 上午 02:57
    2015年9月17日 上午 04:11
  • 大大不好意思照你寫的用法改了

    結果發生錯誤訊息:

    數學運算導致溢位

    請問大大這又是甚麼情形啊

    我的作業系統是win8.1 64位元跟作業系統有關係嗎?

    宣告如下:

     Private Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
        Private Declare Function GetWindowThreadProcessId Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal lpdwProcessId As Long) As Long

    大大請問有沒有專門介紹api的書籍啊!有的話可以跟我說哪一本書嗎 ?

    煩請回復感恩!


    • 已編輯 daybule 2015年9月17日 上午 07:49
    2015年9月17日 上午 07:13
  •     <DllImport("user32.dll", SetLastError:=True)> _
        Private Shared Function GetWindowThreadProcessId(ByVal hwnd As IntPtr, _
                              ByRef lpdwProcessId As Integer) As Integer
        End Function
        <DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
        Private Shared Function FindWindow( _
         ByVal lpClassName As String, _
         ByVal lpWindowName As String) As IntPtr
        End Function
    網頁的內容,請點進去看範例...
    2015年9月17日 上午 08:07
  • 你的宣告適用VB6,在VB.net下,Long要改成Integer。

    另外,之前問的 ReadProcessMemory,宣告要改成

    Public Declare  Function ReadProcessMemory Lib "kernel32" Alias "ReadProcessMemory" (ByVal hProcess As IntPtr, ByVal lpBaseAddress As IntPtr, ByVal lpBuffer As Byte(), ByVal dwSize As Integer, ByVal lpNumberOfBytesRead As Integer) As Boolean

    OpenProcess可以改成

     Private Declare Function OpenProcess Lib "kernel32" Alias "OpenProcess" (ByVal dwDesiredAccess As Integer, ByVal bInheritHandle As Boolean, ByVal dwProcessId As Integer) As Integer

    在讀取記憶體資料時,只要你確定要讀取的程序已經開啟,就不必使用FindWindow這個API

    也不必使用GetWindowThreadProcessId這個API

    整個程序的範例如下

      Private Declare Function OpenProcess Lib "kernel32" Alias "OpenProcess" (ByVal dwDesiredAccess As Integer, ByVal bInheritHandle As Boolean, ByVal dwProcessId As Integer) As Integer

        Public Declare  Function ReadProcessMemory Lib "kernel32" Alias "ReadProcessMemory" (ByVal hProcess As IntPtr, ByVal lpBaseAddress As IntPtr, ByVal lpBuffer As Byte(), ByVal dwSize As Integer, ByVal lpNumberOfBytesRead As Integer) As Boolean

        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

            Dim pro As Process() = Process.GetProcessesByName("notepad")  取得筆記本的執行程序陣列

            Dim processHandle As Integer = OpenProcess(&H10, False, pro(0).Id)  取得開啟程序的識別碼

                   Dim bytesRead As Integer = 0

            Dim buffer(29) As Byte 

          

               Dim b1 As Boolean = ReadProcessMemory(processHandle, 123456, buffer, buffer.Length, bytesRead)

               註:123456為目標資料的記憶體起始位址,buffer儲存讀取的資料

               

    2015年9月17日 上午 09:11
  • 感謝大大解答

    我再努力研究一下

    2015年9月17日 上午 10:18
  • 謝謝大大

    我再努力研究一下

    感恩

    2015年9月17日 上午 10:19
  • 大大們不好意思我使用了你們的方法結果如以下圖檔:

    請問這要如何解決呢?                                                                   

    在請教一下哪裡有可以抓可以抓取程式記憶體位址的軟體呢?

    煩請回復感恩!


    • 已編輯 daybule 2015年9月17日 下午 01:18
    2015年9月17日 下午 01:16
  •         Dim prochack As Process() = Process.GetProcessesByName("WindowsApplication8.vshost")  '取得筆記本的執行程序陣列
            If prochack.GetLength(0) > 0 Then
                Dim mporss As Integer = OpenProcess(&H1F0FFF, False, prochack(0).Id)  '取得開啟程序的識別碼
                Debug.Print(mporss)
            End If
    請檢查在工作管理員的名稱是什麼?程式要檢查確實有找到,再進行後面程式。與開發程式無關的問題,請至其它論壇發問...

    2015年9月17日 下午 02:14
  •         Dim prochack As Process() = Process.GetProcessesByName("WindowsApplication8.vshost")  '取得筆記本的執行程序陣列
            If prochack.GetLength(0) > 0 Then
                Dim mporss As Integer = OpenProcess(&H1F0FFF, False, prochack(0).Id)  '取得開啟程序的識別碼
                Debug.Print(mporss)
            End If
    請檢查在工作管理員的名稱是什麼?程式要檢查確實有找到,再進行後面程式。與開發程式無關的問題,請至其它論壇發問...


    感謝大大!知道了
    2015年9月17日 下午 02:18
  • 各位大大不好意思又要發問了

    為什麼寫入記憶體的資料在記憶體的位址沒有東西呢?

    請問寫入應該要如何寫.還有讀取記憶體資料要如何讀再轉字串呢?

    還有dim d as byte()跟dim d() as byte有何差別呢?

    如以下程式碼:

      Private Declare Function WriteProcessMemory Lib "kernel32.dll" (ByVal hProcess As Integer, ByVal lpBaseAddress As Integer, ByRef lpBuffer As String, ByVal nSize As Integer, ByRef lpNumberOfBytesWritten As Integer) As Integer

     Public Declare Function ReadProcessMemory Lib "kernel32.dll" (ByVal hProcess As IntPtr, ByVal lpBaseAddress As IntPtr, ByVal lpBuffer() As Byte, ByVal nSize As Integer, ByRef lpNumberOfBytesWritten As Integer) As Integer

     Dim d(2048) As Byte
            Dim en As System.Text.Encoding = System.Text.Encoding.Unicode
            Dim qwe As String = TextBox1.Text
            Dim prochack As Process() = Process.GetProcessesByName("WindowsApplication8.vshost") '("vshost32.exe")
            getwin = FindWindow(vbNullString, "Form1")
            GetWindowThreadProcessId(getwin, MineID)
            If prochack.GetLength(0) > 0 Then
                mporss = OpenProcess(&H1F0FFF, False, prochack(0).Id)  '取得開啟程序的識別碼
                Debug.Print(mporss)
            End If
            ' Dim mporss As Integer = OpenProcess(PROCESS_ALL_ACCESS, False, prochack(0).Id)
            ' Dim mporss As Integer = OpenProcess(&H10, False, prochack(0).Id)
            i = Val(TextBox1.Text)

            WriteProcessMemory(mporss, &H00001854, i, qwe.Length, 0)
            TextBox2.Text = &H00001854
            ReadProcessMemory(mporss, &H00001854, d, d.Length, 0)
            TextBox2.Text = d.ToString
            'For f As Integer = 0 To d.Length
            'hqq = en.GetString(d)
            'TextBox2.Text = hqq
            'If (qwe.Length > d.Length) Then Exit For
            'f = f + 1
            ' Next

    以上程式哪裡有問題呢?

    煩請回覆感恩!!

    2015年9月17日 下午 03:40
  • 你不懂 API 就不要用了。

    剪貼 API 前,你要先摸熟不跨程序的 API 。


    不精確的問法,就會得到隨便猜的答案;自己都不肯花時間好好描述問題,又何必期望網友會認真回答?

    2015年9月17日 下午 04:01
  • 大大不好意思我剛剛又測試一下為什麼會讀步道筆記本的資料呢?

    如一下程式:

     Dim d As Byte() = New Byte(0) {}
            Dim en As System.Text.Encoding = System.Text.Encoding.Unicode
            Dim qwe As String = TextBox1.Text
            Dim prochack As Process() = Process.GetProcessesByName("notepad") '("WindowsApplication8.vshost") '("vshost32.exe")
            getwin = FindWindow(vbNullString, "qwe.txt")
            Debug.Print(getwin)
            GetWindowThreadProcessId(getwin, MineID)
            Debug.Print(MineID)
            If prochack.GetLength(0) > 0 Then
                mporss = OpenProcess(&H1F0FFF, True, prochack(0).Id)  '取得開啟程序的識別碼
                Debug.Print(mporss)
            End If
            ReadProcessMemory(mporss, &H00001854, d, d.Length, 0)
            Debug.Print(CStr(d.ToString))

    煩請回覆感恩!!

    2015年9月17日 下午 05:26
  • 你不懂 API 就不要用了。

    剪貼 API 前,你要先摸熟不跨程序的 API 。


    不精確的問法,就會得到隨便猜的答案;自己都不肯花時間好好描述問題,又何必期望網友會認真回答?

    哎呀大大不要這樣嗎?

    學習嗎?不要生氣嗎 ?

    心靜自然涼...

    2015年9月17日 下午 07:42
  • 大大請教一下.我會讀步道notepad的資料是不是我抓錯notepad的記憶體位址啊

    如果是的話請問有哪一套軟體還可以用來抓記憶體位址啊

    我是使用ce抓的.因為在windows的notepad的記憶體位址是動態的

    每次關掉notepad在打開就還要再抓一次.如下:

    在ce抓到的記憶體位址是00003470..那我再在前面加上&H

    這樣是對的嗎 ?

    不然我怎麼會讀不到NOTEPAD的資料呢?

    在 ReadProcessMemory(mporss, &H00003470, d, 2048, 0)

    底下的d應該是緩衝區為何 Debug下測是會是System.Byte[]

    請問System.Byte[]是不是裡面沒資料呢?

    煩請回覆謝謝!!


    • 已編輯 daybule 2015年9月18日 上午 06:34
    2015年9月18日 上午 06:25
  • Windows 每個記憶體本來就是獨立的一個 x86 去跑,所以不能直接跨程序存取記憶體。

    此外,參考型別本身記憶體就是動態配置。

    所以才說,你不懂 API 就先別摸跨程序了。

    你連不跨程序的記憶體配置都搞不清楚,跨程序只是破壞系統穩定而已。


    不精確的問法,就會得到隨便猜的答案;自己都不肯花時間好好描述問題,又何必期望網友會認真回答?

    2015年9月18日 下午 04:54
  • Windows 每個記憶體本來就是獨立的一個 x86 去跑,所以不能直接跨程序存取記憶體。

    此外,參考型別本身記憶體就是動態配置。

    所以才說,你不懂 API 就先別摸跨程序了。

    你連不跨程序的記憶體配置都搞不清楚,跨程序只是破壞系統穩定而已。


    不精確的問法,就會得到隨便猜的答案;自己都不肯花時間好好描述問題,又何必期望網友會認真回答?

    大大你心情不好喔.我去買一瓶仙草茶給你好了!

    謝謝你回覆感恩!!

    2015年9月18日 下午 06:21
  • 各位大大不好意思我都改成這樣了為什麼資料還是讀不出來

    請教一下問題出在哪啊?

    如以下程式碼:

     Dim d As Byte() = New Byte(512) {}
            Dim en As System.Text.Encoding = System.Text.Encoding.Unicode
            Dim qwe As String = TextBox2.Text
            Dim prochack As Process() = Process.GetProcessesByName("WindowsApplication8.vshost")
            getwin = FindWindow(vbNullString, "Form1.TextBox2.Text")
            Debug.Print(getwin)
            GetWindowThreadProcessId(getwin, prochack(0).Id)
            Debug.Print(prochack(0).Id)
            mporss = OpenProcess(PROCESS_ALL_ACCESS, False, prochack(0).Id)  '取得開啟程序的識別碼
            Debug.Print(mporss)
            ' End If
            WriteProcessMemory(mporss, &H00000B60, i, qwe, 0)
            ReadProcessMemory(mporss, &H00000B60, d, d.Length, byteread)
            If (d.Length < 0) Then
                Debug.Print("無資料")
            End If
            Debug.Print(en.GetString(d))
            TextBox1.Text = en.GetString(d)

    還是我的邏輯有問題呢?

    煩請回覆感恩!


    • 已編輯 daybule 2015年9月18日 下午 08:48
    2015年9月18日 下午 08:48
  • ...

    你是不是分不清楚簽名檔跟回應差在哪?


    不精確的問法,就會得到隨便猜的答案;自己都不肯花時間好好描述問題,又何必期望網友會認真回答?

    2015年9月19日 上午 02:34
  • ...

    你是不是分不清楚簽名檔跟回應差在哪?


    不精確的問法,就會得到隨便猜的答案;自己都不肯花時間好好描述問題,又何必期望網友會認真回答?

    大大恩對啊

    到底差在哪

    緩衝區測試過了有資料啊 .但是就是用編碼的方式去讀還是讀不出來啊.奇怪了


    • 已編輯 daybule 2015年9月19日 上午 06:15
    2015年9月19日 上午 06:14
  • 大大在請教一下記憶體的資料是不是不能取出轉成字串輸出呢?

    煩請回覆感恩!!

    2015年9月19日 下午 01:52
  • 根據這行

        WriteProcessMemory(mporss, &H00000B60, i, qwe, 0)

    你的資料應該沒有寫入記憶體。

    這個API有回傳值,你可以測試看看

    Dim b2 as Boolean= WriteProcessMemory(mporss, &H00000B60, i, qwe, 0)

    TextBox1.Text=b2

    我猜b2應該等於False。

    不論這個API宣告是否正確,你在引用時,內部的資料就錯誤了。

    i的位置應該是個byte()資料,不能是字串

    qwe的位置應該是這個byte()的長度,是個Integer資料

    另外,記憶體取出的資料當然可以轉成字串,但是要取出的資料是可以轉成字串的byte()。

    2015年9月19日 下午 03:58
  • 根據這行

        WriteProcessMemory(mporss, &H00000B60, i, qwe, 0)

    你的資料應該沒有寫入記憶體。

    這個API有回傳值,你可以測試看看

    Dim b2 as Boolean= WriteProcessMemory(mporss, &H00000B60, i, qwe, 0)

    TextBox1.Text=b2

    我猜b2應該等於False。

    不論這個API宣告是否正確,你在引用時,內部的資料就錯誤了。

    i的位置應該是個byte()資料,不能是字串

    qwe的位置應該是這個byte()的長度,是個Integer資料

    另外,記憶體取出的資料當然可以轉成字串,但是要取出的資料是可以轉成字串的byte()。

    大大你說的沒錯果然是false

    那請問一下上面的記憶體位址是對的嗎 ?

    2015年9月20日 上午 06:24
  • 只要你的WriteProcessMemory使用方法正確,不管記憶體位址是多少,大多會寫入,只是可能引起當機的問題。

    同時,目標資料的位址是變動的,所以記憶體位址是要自己找的。

    可以參考這個網頁的範例,找到筆記本編輯區的起始位址。

    http://blog.xuite.net/k0033a/vb2008/344154511

    (以OpenProcess、ReadProcessMemory讀出筆記本編輯區的文字 )

    2015年9月20日 上午 11:47