我在学着使用进程操作的API,下面是部分代码:Private Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Long, ByVal lpBaseAddress As Any, ByVal lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
Dim pid&, pHandle&     '进程ID和进程句柄
Dim address&           '地址
Dim content&           '内容
Dim res As Long
res = ReadProcessMemory(pHandle, address, content, 4, 0&)
MsgBox "内容为:" & content在这个程序中我能够得到窗口句柄,然后找到进程ID,成功打开进程(OpenProcess返回不为0)。我先用金山游侠随便查找一个不为0的值,然后将找到的地址赋给address,结果运行到ReadProcessMemory的时候msgbox弹出来的内容是0。我不知道这是为什么,还请高手指教!

解决方案 »

  1.   

    res = ReadProcessMemory(pHandle, byval address, content, 4, 0&)
    注意是按值传递。
      

  2.   

    我是按8位16进制数的形式赋给address的,应该没什么问题吧?
      

  3.   

    对于VB调用win32的api,处理字符串参数一律使用byval ,因为vb中的字符串是BSTR类型,它本身保存就是字符串的地址,你可以用strptr读入字符串变量真正的内容,而valptr可以读出存储这个字符串变量地址,所以字符串变量其实就是指针。
    你这个例子可以这样试试
    res = ReadProcessMemory(pHandle, strptr(address)..
    或者
    res = ReadProcessMemory(pHandle, byval address...
    一个例子:
    Private Const PROCESS_ALL_ACCESS As Long = &H1F0FFF
    Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hWnd As Long, lpdwProcessId As Long) As Long
    Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
    Private Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Long, ByVal lpBaseAddress As Any, lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
    Private Declare Function WriteString Lib "kernel32" Alias "WriteProcessMemory" (ByVal hProcess As Long, ByVal lpBaseAddress As Any, ByVal lpBuffer As Any, ByVal nSize As Long, ByVal lpNumberOfBytesWritten As Long) As Long
    Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As LongPrivate Sub Command1_Click()
        Dim str As String, MyString As String
        MyString = "HELLO"
        'in this case I read the memory of my own process
        MsgBox "MyString= " & MyString
        
        str = ReadMemory(Me.hWnd, StrPtr(MyString), LenB(MyString), "BYE!!")
        
        MsgBox "Now, MyString=" & MyString & vbCr & "Old Value= " & str
        
    End Sub
    Private Function ReadMemory(hWnd As Long, Address As Long, Bytes As Long, Optional strReplaceWith As String) As String
        'Runs For Not Unicode Strings (VB-Strings)
        On Error Resume Next
        Dim pId As Long        ' Used to hold the Process Id
        Dim pHandle As Long    ' Holds the Process Handle
        Dim bytValue As Long   'Stores the value of a byte in the memory
        Dim i As Long
        Dim Text As String
        
        ' Get the ProcId of the Window
        GetWindowThreadProcessId hWnd, pId    ' use the pId to get a handle
        pHandle = OpenProcess(PROCESS_ALL_ACCESS, False, pId)
        
        If (pHandle = 0) Then
             'MsgBox "Unable to open process!"
             Exit Function
        End If
        If Address = 0 Then Exit Function
        
        For i = 1 To Bytes Step 2
           ' Read Byte to Byte
           ReadProcessMemory pHandle, Address + i - 1, bytValue, 1, 0&
           'value now contains the long value of the byte located in [Address + i - 1] pos.
           'ReadMemory is a string...
           
           ReadMemory = ReadMemory & Chr$(bytValue)
        Next
        'to write numeric values you can ..(Must) use WriteValue API
        If LenB(strReplaceWith) <> 0 Then
            'No Unicode!!
            WriteString pHandle, Address, StrPtr(strReplaceWith), LenB(strReplaceWith), 0&
        End If
        'Close the Handle
        CloseHandle pHandle
    End Function
      

  4.   

    虽然懂得了什么是按值传递,但是我在函数声明的时候已经将该参数声明为byval了(见代码)。我照你的意思在调用函数的时候加上byval,但还是不对。
      

  5.   

    我将as any都改成了as long, 还是不对。
      

  6.   

    我现在把代码改成这样,想找一个内容为非0的地址出来,依然无效:
    Private Sub Timer1_Timer()
        If address < &HFFFFFF Then
            address = address + 4
            ReadProcessMemory pHandle, address, content, 4, 0&
            lblContent.Caption = "地址:H" & Hex(address) & "   值:" & content
            If content <> 0 Then
                Timer1.Enabled = False
                Exit Sub
            End If
        End If
    End Sub
      

  7.   

    楼上都已经指明要传值,为什么不改呢
    Private Sub Timer1_Timer()
        If address < &HFFFFFF Then
            address = address + 4
    ''''''''''''''''''''''''''''''''''''''''''''''''
            ReadProcessMemory pHandle, byval address, content, 4, 0&
    '''''''''''''''''''''''''''''''''''''''''''''''''
            lblContent.Caption = "地址:H" & Hex(address) & "   值:" & content
            If content <> 0 Then
                Timer1.Enabled = False
                Exit Sub
            End If
        End If
    End Sub
      

  8.   

    对不起我抄错了,我已经改为 byval adress了,但还是不行。
      

  9.   

    这是我以前写的一个程序,有调用ReadProcessMemory 的地方,你可以参考,因为我声明的时候
    就是byval ,所以调用的时候就不再byval了
    Attribute VB_Name = "Module1"
    Option ExplicitPublic Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
    'Public Declare Function CreateProcess Lib "kernel32" Alias "CreateProcessA" (ByVal lpApplicationName As String, ByVal lpCommandLine As String, lpProcessAttributes As SECURITY_ATTRIBUTES, lpThreadAttributes As SECURITY_ATTRIBUTES, ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, lpEnvironment As Any, ByVal lpCurrentDriectory As String, lpStartupInfo As STARTUPINFO, lpProcessInformation As PROCESS_INFORMATION) As Long
    'Public Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Long, lpBaseAddress As Any, lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
    Public Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Long, ByVal lpBaseAddress As Long, lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As LongPublic Declare Function WriteProcessMemory Lib "kernel32" (ByVal hProcess As Long, lpBaseAddress As Any, lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
    Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
    Public Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
    Public Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
    Public Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As LongPublic Const PROCESS_VM_READ = &H10
    Public Const PROCESS_VM_WRITE = &H20Const strCaption = "Unregistered Version"Sub main()
        Open "d:\s2h\test6.exe" For Binary As #1
        Open "d:\s2h\test.exe" For Binary As #2
        Open "d:\s2h\socks2http.exe" For Binary As #3
        Dim b() As Byte
        ReDim b(FileLen("d:\s2h\socks2http.exe") - 1)
        Get #3, 1, b
        Put #1, , b
        
        ReDim b(&H798200 - &H49200 - 1)
        Put #1, , b
        
        
        ReDim b(FileLen("d:\s2h\test.exe") - 1)
        Get #2, 1, b
        Put #1, , b
        
        Close #1
        Close #2
        Close #3
        
        
        
    End SubSub main1()
        Dim ret As Long
        Dim hWin As Long
        Dim hProcess As Long
        Dim hThread As Long
        Dim PID As Long
        Dim TID As Long
        Dim b() As Byte
        Dim nSize As Long  'bytes to write or read  wanted
        Dim aSize As Long  'bytes to write or read  actually
        Dim baseAddr As Long
        Dim endAddr As Long
        
        On Error GoTo errHandle
        hWin = FindWindow(vbNullString, strCaption)
        If hWin = 0 Then
            MsgBox "Get window handle fail!", vbInformation, "tip"
            Exit Sub
        End If
        
        TID = GetWindowThreadProcessId(hWin, PID)
        If PID = 0 Then
            MsgBox "Get process id fail!", vbInformation, "tip"
            Exit Sub
        End If
        
    '    Dim d As Double
    '    d = Shell("d:\s2h\socks2http.exe", vbHide) 'return process id
    '    hProcess = OpenProcess(PROCESS_VM_READ Or PROCESS_VM_WRITE, 0, CLng(d))
        
        hProcess = OpenProcess(PROCESS_VM_READ Or PROCESS_VM_WRITE, 0, PID)
        If hProcess = 0 Then
            MsgBox "Get process handle fail!", vbInformation, "tip"
            Exit Sub
        End If
        
        Open "d:\s2h\test.exe" For Binary As #1
        
        baseAddr = &HC21000
        endAddr = &HC32FFF
        nSize = endAddr - baseAddr + 1
        ReDim b(nSize - 1)
      
        
        ret = ReadProcessMemory(hProcess, baseAddr, b(0), nSize, aSize)
        If ret = 0 Then
            MsgBox "read process memory errror!", vbInformation, "tip"
            If hProcess Then CloseHandle hProcess
            Close #1
            Exit Sub
        End If
        Put #1, , b
        
        baseAddr = &HC33000
        endAddr = &HC33FFF
        nSize = endAddr - baseAddr + 1
        ReDim b(nSize - 1)
        
        ret = ReadProcessMemory(hProcess, baseAddr, b(0), nSize, aSize)
        If ret = 0 Then
            MsgBox "read process memory errror!", vbInformation, "tip"
            If hProcess Then CloseHandle hProcess
            Close #1
            Exit Sub
        End If
        Put #1, , b
        
        baseAddr = &HC34000
        endAddr = &HC37FFF
        nSize = endAddr - baseAddr + 1
        ReDim b(nSize - 1)
        
        ret = ReadProcessMemory(hProcess, baseAddr, b(0), nSize, aSize)
        If ret = 0 Then
            MsgBox "read process memory errror!", vbInformation, "tip"
            If hProcess Then CloseHandle hProcess
            Close #1
            Exit Sub
        End If
        Put #1, , b
        Close #1
        CloseHandle hProcess
        MsgBox "ok", vbInformation, "tip"
            
        Exit Sub
    errHandle:
        Reset
        MsgBox Err.Description, vbInformation, "tip"End Sub
      

  10.   

    可以参考
    http://expert.csdn.net/Expert/topic/2647/2647305.xml?temp=.1548426
      

  11.   

    先看看asize(读取的)是不是对的,还有就是读取后的值是字节型的,转换成long,integer注意在内存中的顺序,intel的cpu是低位在前的,&H4030201在内存中的是1(addr)2(addr+2)3(addr+3)4(addr+4)。
      

  12.   

    试一试使用IsBadReadPtr 来断言
    Private Declare Function IsBadReadPtr Lib "kernel32" (ByVal lp As Long, ByVal ucb As Long) As Long    Dim lpYourData As Long, cbSize As Long
        lpYourData = address
        cbSize = 1
        Debug.Assert IsBadReadPtr(lpYourData, cbSize) = 0
      

  13.   

    楼主遇到的问题应该可以这样解决: ReadProcessMemory pHandle, byval address, Varptr(content), 4, 0&