Declare Function ReadProcessMemory Lib "kernel32" Alias "ReadProcessMemory" (ByVal hProcess As Integer, ByVal lpBaseAddress As Integer, ByRef lpBuffer As Integer, ByVal nSize As Integer, ByRef lpNumberOfBytesWritten As Integer) As IntPtr
Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
Private Sub btnCurrentXP_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCurrentXP.Click
Dim var As Integer
Dim windowhandle As IntPtr
Dim buffer(7) As Byte
Dim bytesWritten As Integer
windowhandle = FindWindow(vbNullString, "My window")
var = ReadProcessMemory(windowhandle, &H80B910, buffer(0), 8, bytesWritten)
MsgBox(var)
End Sub
Last edited by rhijaen; Feb 14th, 2008 at 03:43 AM.
You really don't need FindHandle if yo know the process you are trying to read. You can use the MainWindowHandle method of the process object to get the handle. I attached my memory and API classes that I use to read and write to process memory
There are a couple functions in the memory class you will not need as they are for reading specific structures from memory but this can give you an idea about how to do it easily.
Boooya
Visual Studio 2008 Professional
Don't forget to use [CODE]your code here[/CODE] when posting code
Don't forget to rate helpful posts!
If you're question was answered please mark your thread [Resolved]
Oops just had to Imports System.Runtime.InteropServices
EDIT:
Using
Code:
Imports System.Runtime.InteropServices
Public Class Form1
Declare Function ReadProcessMemory Lib "kernel32" Alias "ReadProcessMemory" (ByVal hProcess As Integer, ByVal lpBaseAddress As Integer, ByRef lpBuffer As Integer, ByVal nSize As Integer, ByRef lpNumberOfBytesWritten As Integer) As IntPtr
Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
Private Sub btnCurrentXP_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCurrentXP.Click
Dim var As Integer
Dim windowhandle As IntPtr
Dim buffer As IntPtr = marshal.AllocHGlobal(marshal.SizeOf(GetType(Integer)))
Dim bytesWritten As Integer
windowhandle = FindWindow(vbNullString, "The 4th Coming")
MsgBox(windowhandle)
var = ReadProcessMemory(windowhandle, &H80B910, buffer, 8, bytesWritten)
MsgBox(var)
End Sub
End Class
The ReadProcessMemory won't like a simple window handle, it is after the process handle. Bmahler's code should help a lot (I think I read his explanations from the code bank back then to finally get this working).
Imports System.Runtime.InteropServices
Public Class Form1
Declare Function ReadProcessMemory Lib "kernel32" Alias "ReadProcessMemory" (ByVal hProcess As Integer, ByVal lpBaseAddress As Integer, ByRef lpBuffer As Integer, ByVal nSize As Integer, ByRef lpNumberOfBytesWritten As Integer) As IntPtr
Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hWnd As Long, ByVal lpdwProcessId As Long) As IntPtr
Private Sub btnCurrentXP_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCurrentXP.Click
Dim var As Integer
Dim buffer As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(GetType(Integer)))
Dim bytesWritten As Integer
Dim t4cp As IntPtr
Dim prList() As Process
prList = Process.GetProcessesByName("T4C")
For Each pr As Process In prList
If pr.MainWindowHandle <> 0 Then
t4cp = pr.MainWindowHandle
' Has a GUI interface
End If
Next
var = ReadProcessMemory(t4cp, 8435984, buffer, 8, bytesWritten)
MsgBox(var)
End Sub
End Class
You're still passing a window handle. Half specifically said that you need to pass a process handle, not a window handle. Get the Handle of the Process, NOT its MainWindowHandle.
You need to allocate unmanaged memory if you are sending data to the other application or asking it to give you data. In your case neither is true - you simpy use an api call to copy some bytes over. So instead of marshalling you use a simple byte array as a storage container.
It is not a good idea to force bytes into an integer. It would only work(properly) if the returned data encodes an integer. I prefer to use strings since any byte array can convert to a string without a problem. Then you can extract your number or anything else. These assumptions have worked for me so far.
Code:
'API declaration
Private Declare Function ReadProcessMemory Lib "kernel32" ( _
ByVal hProcess As IntPtr, _
ByVal lpBaseAddress As Integer, _
ByVal lpBuffer() As Byte, _
ByVal nSize As Integer, _
ByRef lpNumberOfBytesWritten As Integer) As Integer
'function getting the job done, returns a string that containing the read bytes
Function MoviePath(ByVal MainWndTitle As String, ByVal StartingAddress As Integer, _
ByVal NumberOfBytesToRead As Integer) As String
'create a byte array to accomodate the read bytes
Dim MemoryValues(NumberOfBytesToRead - 1) As Byte
'Check if the process in question is running and get its handle
For Each proc As Process In Process.GetProcesses
If proc.MainWindowTitle = MainWndTitle Then
'the parameters explained
'1-native handle (of the process, not of the main window), 2-starting address in memory,
'3-storage variable (buffer), 4-how many bytes to read,
'5-the number of bytes transferred; If NULL is specified, the parameter is ignored.
If ReadProcessMemory(proc.Handle, StartingAddress, MemoryValues, NumberOfBytesToRead, 0) = 1 Then
'using an intermediate variable for clarity
'convert the byte array to string
Dim strData As String = System.Text.Encoding.Default.GetString(MemoryValues)
Return strData
Else
Return "Can't read memory."
End If
End If
Next
Return "Process not running."
End Function
In this example I use it to read the movie path in BSPlayer, the passed parameters can be adjusted as needed.
Code:
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
'read 256 bytes from the process' memory from address 1385277 on
MessageBox.Show(MoviePath("BSplayer", 1385277, 256))
End Sub
So you are trying to return a 32 bit integer from an address right. Well if you use my class you can easily do this.
I have attached an example project using my classes to easily read another processes memory.
Last edited by bmahler; Feb 13th, 2008 at 11:57 AM.
Boooya
Visual Studio 2008 Professional
Don't forget to use [CODE]your code here[/CODE] when posting code
Don't forget to rate helpful posts!
If you're question was answered please mark your thread [Resolved]
Messageboxes and textboxes truncate strings when they contain a char above the 128th ASCII symbol. One way to circumvent this for displaying purposes is to add the characters to a lisbox one at the time. Try to read a 100 bytes starting from Address 8435984 and see what that gives you:
Code:
Private Sub Button4_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button4.Click
Dim MemoryValues(99) As Byte
For Each proc As Process In Process.GetProcesses
If proc.MainWindowTitle = "BSplayer" Then
ReadProcessMemory(proc.Handle, 1385280, MemoryValues, 100, 0)
'convert each byte to its corresponding char and add it in the listbox
For Each b As Byte In MemoryValues
ListBox1.Items.Add(Chr(b))
Next
End If
Next
End Sub
Since you expect a number and not some chars above 127 ASCII I guess there is something else to the determining of the start address. Can you post a screenshot of the actual bytes in hex that represent the number please. I guess your memory scanner can do this.
Imports System.Runtime.InteropServices
Public Class Form1
<DllImport("kernel32.dll")> _
Public Shared Function ReadProcessMemory(ByVal hProcess As IntPtr, ByVal lpBaseAddress As IntPtr, <Out()> ByVal lpBuffer As Byte(), ByVal nSize As UIntPtr, ByVal lpNumberOfBytesRead As IntPtr) As Boolean
End Function
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
MsgBox(GetIntegerValue("BSPlayer", 1385280).ToString)
End Sub
Private Function GetIntegerValue(ByVal ProcessName As String, ByVal Address As Integer) As Integer
Dim proc As Process() = Process.GetProcessesByName(ProcessName)
Dim targetProc As Process
If proc.Length > 0 Then
targetProc = proc(0)
Dim value As Byte() = New Byte(3) {}
ReadProcessMemory(targetProc.Handle, New IntPtr(Address), value, _
New UIntPtr(CType(value.Length, UInt32)), New IntPtr(0))
Return BitConverter.ToInt32(value, 0)
Else
Return 0
End If
End Function
End Class
Boooya
Visual Studio 2008 Professional
Don't forget to use [CODE]your code here[/CODE] when posting code
Don't forget to rate helpful posts!
If you're question was answered please mark your thread [Resolved]
Imports System.Runtime.InteropServices
Public Class Form1
<DllImport("kernel32.dll")> _
Public Shared Function ReadProcessMemory(ByVal hProcess As IntPtr, ByVal lpBaseAddress As IntPtr, <Out()> ByVal lpBuffer As Byte(), ByVal nSize As UIntPtr, ByVal lpNumberOfBytesRead As IntPtr) As Boolean
End Function
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
MsgBox(GetIntegerValue("BSPlayer", 1385280).ToString)
End Sub
Private Function GetIntegerValue(ByVal ProcessName As String, ByVal Address As Integer) As Integer
Dim proc As Process() = Process.GetProcessesByName(ProcessName)
Dim targetProc As Process
If proc.Length > 0 Then
targetProc = proc(0)
Dim value As Byte() = New Byte(3) {}
ReadProcessMemory(targetProc.Handle, New IntPtr(Address), value, _
New UIntPtr(CType(value.Length, UInt32)), New IntPtr(0))
Return BitConverter.ToInt32(value, 0)
Else
Return 0
End If
End Function
End Class
That works perfectly, thanks everyone for putting up with my probably stupid questions.
Re: [RERESOLVED] [2008] Help with ReadProcessMemory
well the vb equivalent would be something along the lines of &HDBBCDC
so just add that as the address you want to read from ie: New IntPtr(&HDBBCDC) in the ReadProcessMemory api call.
~ if a post is resolved, please mark it as [Resolved] protected string get_Signature(){return Censored;} [vbcode][php] please use code tags when posting any code [/php][/vbcode]
Re: [RERESOLVED] [2008] Help with ReadProcessMemory
just remove the IntPtr part. should be
Code:
MsgBox(GetIntegerValue("World of Warcraft", &HDBBCDC))
Adding the &h befor it signifies that it is a hexidecimal value. The GetIntegerValue function will accept this because it is merely an integer value written in hex format.
Boooya
Visual Studio 2008 Professional
Don't forget to use [CODE]your code here[/CODE] when posting code
Don't forget to rate helpful posts!
If you're question was answered please mark your thread [Resolved]
Re: [RERESOLVED] [2008] Help with ReadProcessMemory
No matter What i put in i still get 0 as a value. Even though i know for a fact that is not the correct Value.
vb Code:
Imports System.Runtime.InteropServices
Public Class Form1
<DllImport("kernel32.dll")> _
Public Shared Function ReadProcessMemory(ByVal hProcess As IntPtr, ByVal lpBaseAddress As IntPtr, <Out()> ByVal lpBuffer As Byte(), ByVal nSize As UIntPtr, ByVal lpNumberOfBytesRead As IntPtr) As Boolean
End Function
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
MsgBox(GetIntegerValue("World of Warcraft", &HC47A28))
End Sub
Private Function GetIntegerValue(ByVal ProcessName As String, ByVal Address As Integer) As Integer
Dim proc As Process() = Process.GetProcessesByName(ProcessName)
Dim targetProc As Process
If proc.Length > 0 Then
targetProc = proc(0)
Dim value As Byte() = New Byte(3) {}
ReadProcessMemory(targetProc.Handle, New IntPtr(Address), value, _
New UIntPtr(CType(value.Length, UInt32)), New IntPtr(0))
Return BitConverter.ToInt32(value, 0)
Else
Return 0
End If
End Function
End Class
I am trying to read the value of &HC47A28 in the application World of Warcraft. I believe i am doing this wrong.
Re: [RERESOLVED] [2008] Help with ReadProcessMemory
What value are you trying to read from that game? are you sure there is a value there? Most games today use a method called code shifting that loads information in a different place each time. The location is relevant to the base address of the dll that loads it. For example in FFXI a game taht I have written many programs for, they use this method and in order to find the location to read you must first find the pointer to that location. I am not sure about WoW or how they handle memory, but I can tell you that this type of activity is against the WoW TOS and can result in you losing your account. Also WoW uses GameGuard to prevent this sort of thing.
Anothoner thing I noticed is that you are passing the processname as World of Warcraft is that what it is listed as in your process list? Step through your function I would guess that is not the actual process name and the function is returning 0 because the process is not found. I am pretty sure the World of Warcraft process name is wow. Good luck and I hope you don't lose your account,
Boooya
Visual Studio 2008 Professional
Don't forget to use [CODE]your code here[/CODE] when posting code
Don't forget to rate helpful posts!
If you're question was answered please mark your thread [Resolved]
Re: [RERESOLVED] [2008] Help with ReadProcessMemory
I am pretty sure i have made some progress, now it takes about 10 seconds to load then gives me the error message "Access is Denied" and highlights the following lines of code.
vb Code:
ReadProcessMemory(targetProc.Handle, New IntPtr(Address), value, _
New UIntPtr(CType(value.Length, UInt32)), New IntPtr(0))
Any idea what could be the problem? not sure if its the games built in security but hex editors like Cheat Engine can read and write the memory no problem. I have found some sample source code that reads memory from wow and they have these lines of code.
Code:
OpenProcess(PROCESS_ALL_ACCESS, 0, execID)
Where exeID is the window title. I cant find the code it is refering to though. All i can find is
Code:
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Integer, ByVal bInheritHandle As Integer, ByVal dwProcessId As Integer) As Integer
Re: [RERESOLVED] [2008] Help with ReadProcessMemory
you should not get any read errors with the code i posted. I use this in about 10 applications that I wrote for Final Fantasy XI. Just make sure the process name is correct and it shouldn't error, but if it still does then you would need to use the OpenProcess function with the PROCESS_ALL_ACCESS flag to prevent them, but like I said, I have yet to ever have to do that and I read and write to memory in all of my applications using the classes I posted earlier.
Boooya
Visual Studio 2008 Professional
Don't forget to use [CODE]your code here[/CODE] when posting code
Don't forget to rate helpful posts!
If you're question was answered please mark your thread [Resolved]