Code:
'Option Strict On
Imports System.Runtime.InteropServices
Imports System.Text
Module MemoryModule
' API
<DllImport("kernel32.dll")> _
Private Function OpenProcess(ByVal dwDesiredAccess As UInteger, <MarshalAs(UnmanagedType.Bool)> ByVal bInheritHandle As Boolean, ByVal dwProcessId As Integer) As IntPtr
End Function
<DllImport("kernel32.dll", SetLastError:=True)> _
Private Function WriteProcessMemory(ByVal hProcess As IntPtr, ByVal lpBaseAddress As IntPtr, ByVal lpBuffer As Byte(), ByVal nSize As IntPtr, <Out()> ByRef lpNumberOfBytesWritten As IntPtr) As Boolean
End Function
<DllImport("kernel32.dll", SetLastError:=True)> _
Private Function ReadProcessMemory(ByVal hProcess As IntPtr, ByVal lpBaseAddress As IntPtr, <Out()> ByVal lpBuffer() As Byte, ByVal dwSize As IntPtr, ByRef lpNumberOfBytesRead As IntPtr) As Boolean
End Function
<DllImport("kernel32.dll", SetLastError:=True)>
Private Function CloseHandle(ByVal hObject As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
Private Declare Function VirtualProtectEx Lib "kernel32.dll" (ByVal hProcess As IntPtr, ByVal lpAddress As IntPtr, ByVal lpSize As IntPtr, ByVal dwNewProtect As UInt32, ByRef dwOldProtect As UInt32) As Boolean
Declare Function VirtualAllocEx Lib "kernel32.dll" (ByVal hProcess As IntPtr, ByVal lpAddress As IntPtr, ByVal dwSize As IntPtr, ByVal flAllocationType As Integer, ByVal flProtect As Integer) As IntPtr
Private Const PROCESS_VM_WRITE As UInteger = &H20
Private Const PROCESS_VM_READ As UInteger = &H10
Private Const PROCESS_VM_OPERATION As UInteger = &H8
Private TargetProcess As String = "S4Client"
Private ProcessHandle As IntPtr = IntPtr.Zero
Private LastKnownPID As Integer = -1
' Function Process Id Exists: pID as Integer
Private Function ProcessIDExists(ByVal pID As Integer) As Boolean
For Each p As Process In Process.GetProcessesByName(TargetProcess)
If p.Id = pID Then Return True
Next
Return False
End Function
' Function Set Process Name: ProcessName as String
Public Sub SetProcessName(ByVal processName As String)
TargetProcess = processName
If ProcessHandle <> IntPtr.Zero Then CloseHandle(ProcessHandle)
LastKnownPID = -1
ProcessHandle = IntPtr.Zero
End Sub
' Function Get Current Process Name, as String
Public Function GetCurrentProcessName() As String
Return TargetProcess
End Function
' Function Update Process Handle, as Boolean
Public Function UpdateProcessHandle() As Boolean
If LastKnownPID = -1 OrElse Not ProcessIDExists(LastKnownPID) Then
If ProcessHandle <> IntPtr.Zero Then CloseHandle(ProcessHandle)
Dim p() As Process = Process.GetProcessesByName(TargetProcess)
If p.Length = 0 Then Return False
LastKnownPID = p(0).Id
ProcessHandle = OpenProcess(PROCESS_VM_READ Or PROCESS_VM_WRITE Or PROCESS_VM_OPERATION, False, p(0).Id)
If ProcessHandle = IntPtr.Zero Then Return False
End If
Return True
End Function
' Function Read Memory: Address as Object
Public Function ReadMemory(Of T)(ByVal address As Object) As T
Return ReadMemory(Of T)(CLng(address))
End Function
' Function Read Memory: Address as Integer
Public Function ReadMemory(Of T)(ByVal address As Integer) As T
Return ReadMemory(Of T)(New IntPtr(address), 0, False)
End Function
' Function Read Memory: Address as Long
Public Function ReadMemory(Of T)(ByVal address As Long) As T
Return ReadMemory(Of T)(New IntPtr(address), 0, False)
End Function
' Function Read Memory: Address as IntPtr
Public Function ReadMemory(Of T)(ByVal address As IntPtr) As T
Return ReadMemory(Of T)(address, 0, False)
End Function
' Function Read Memory: Address as IntPtr, Length as Integer
Public Function ReadMemory(ByVal address As IntPtr, ByVal length As Integer) As Byte()
Return ReadMemory(Of Byte())(address, length, False)
End Function
' Function Read Memory: Address as Integer, Length as Integer
Public Function ReadMemory(ByVal address As Integer, ByVal length As Integer) As Byte()
Return ReadMemory(Of Byte())(New IntPtr(address), length, False)
End Function
' Function Read Memory: Address as Long, Length as Integer
Public Function ReadMemory(ByVal address As Long, ByVal length As Integer) As Byte()
Return ReadMemory(Of Byte())(New IntPtr(address), length, False)
End Function
' Function Read Memory: Address as IntPtr, Length as Integer, UnicodeString as Boolean
Public Function ReadMemory(Of T)(ByVal address As IntPtr, ByVal length As Integer, ByVal unicodeString As Boolean) As T
Dim buffer() As Byte
If GetType(T) Is GetType(String) Then
If unicodeString Then buffer = New Byte(length * 2 - 1) {} Else buffer = New Byte(length - 1) {}
ElseIf GetType(T) Is GetType(Byte()) Then
buffer = New Byte(length - 1) {}
Else
buffer = New Byte(Marshal.SizeOf(GetType(T)) - 1) {}
End If
If Not UpdateProcessHandle() Then Return Nothing
Dim success As Boolean = ReadProcessMemory(ProcessHandle, address, buffer, New IntPtr(buffer.Length), IntPtr.Zero)
If Not success Then Return Nothing
If GetType(T) Is GetType(Byte()) Then Return CType(CType(buffer, Object), T)
If GetType(T) Is GetType(String) Then
If unicodeString Then Return CType(CType(Encoding.Unicode.GetString(buffer), Object), T)
Return CType(CType(Encoding.ASCII.GetString(buffer), Object), T)
End If
Dim gcHandle As GCHandle = gcHandle.Alloc(buffer, GCHandleType.Pinned)
Dim returnObject As T = CType(Marshal.PtrToStructure(gcHandle.AddrOfPinnedObject, GetType(T)), T)
gcHandle.Free()
Return returnObject
End Function
' Function Get Object Bytes
Private Function GetObjectBytes(ByVal value As Object) As Byte()
If value.GetType() Is GetType(Byte()) Then Return CType(value, Byte())
Dim buffer(Marshal.SizeOf(value) - 1) As Byte
Dim ptr As IntPtr = Marshal.AllocHGlobal(buffer.Length)
Marshal.StructureToPtr(value, ptr, True)
Marshal.Copy(ptr, buffer, 0, buffer.Length)
Marshal.FreeHGlobal(ptr)
Return buffer
End Function
' Function Write Memory: Addres as Object, Value as T
Public Function WriteMemory(Of T)(ByVal address As Object, ByVal value As T) As Boolean
Return WriteMemory(CLng(address), value)
End Function
' Function Write Memory: Address as Object, Value as Object
Public Function WriteMemory(Of T)(ByVal address As Object, ByVal value As Object) As Boolean
Return WriteMemory(CLng(address), CType(value, T))
End Function
' Function Write Memory: Address as Integer, Value as T
Public Function WriteMemory(Of T)(ByVal address As Integer, ByVal value As T) As Boolean
Return WriteMemory(New IntPtr(address), value)
End Function
' Function Write Memory: Address as Integer, Value as Object
Public Function WriteMemory(Of T)(ByVal address As Integer, ByVal value As Object) As Boolean
Return WriteMemory(address, CType(value, T))
End Function
' Function Write Memory: Address as Long, Value as T
Public Function WriteMemory(Of T)(ByVal address As Long, ByVal value As T) As Boolean
Return WriteMemory(New IntPtr(address), value)
End Function
' Function Write Memory: Address as Long, Value as Object
Public Function WriteMemory(Of T)(ByVal address As Long, ByVal value As Object) As Boolean
Return WriteMemory(address, CType(value, T))
End Function
' Function Write Memory: Address as IntPtr, Value as T
Public Function WriteMemory(Of T)(ByVal address As IntPtr, ByVal value As T) As Boolean
Return WriteMemory(address, value, False)
End Function
' Function Write Memory: Address as IntPtr, Value as Object
Public Function WriteMemory(Of T)(ByVal address As IntPtr, ByVal value As Object) As Boolean
Return WriteMemory(address, CType(value, T), False)
End Function
' Function Write Memory: Address as Object, Value as T, Unicode as Boolean
Public Function WriteMemory(Of T)(ByVal address As Object, ByVal value As T, ByVal unicode As Boolean) As Boolean
Return WriteMemory(CLng(address), value, unicode)
End Function
' Function Write Memory: Address as Integer, Value as T, Unicode as Boolean
Public Function WriteMemory(Of T)(ByVal address As Integer, ByVal value As T, ByVal unicode As Boolean) As Boolean
Return WriteMemory(New IntPtr(address), value, unicode)
End Function
' Function Write Memory: Address as Long, Value as T, Unicode as Boolean
Public Function WriteMemory(Of T)(ByVal address As Long, ByVal value As T, ByVal unicode As Boolean) As Boolean
Return WriteMemory(New IntPtr(address), value, unicode)
End Function
' Function Write Memory: Address as IntPtr, Value as T, Unicode as Boolean
Public Function WriteMemory(Of T)(ByVal address As IntPtr, ByVal value As T, ByVal unicode As Boolean) As Boolean
If Not UpdateProcessHandle() Then Return False
Dim buffer() As Byte
If TypeOf value Is String Then
If unicode Then buffer = Encoding.Unicode.GetBytes(value.ToString()) Else buffer = Encoding.ASCII.GetBytes(value.ToString())
Else
buffer = GetObjectBytes(value)
End If
Dim result As Boolean = WriteProcessMemory(ProcessHandle, address, buffer, New IntPtr(buffer.Length), IntPtr.Zero)
Return result
End Function
Private Function EXECUTE_READ() As Boolean
Throw New NotImplementedException
End Function
Sub RemoveProtection(ByVal ProcessName As String, ByVal AddressOfStart As Integer, ByVal SizeToRemoveProtectionInBytes As Integer)
For Each p As Process In Process.GetProcessesByName(ProcessName)
Const PAGE_EXECUTE_READWRITE As Integer = &H40
Dim oldProtect As Integer
If Not VirtualProtectEx(p.Handle, New IntPtr(AddressOfStart), New IntPtr(SizeToRemoveProtectionInBytes), PAGE_EXECUTE_READWRITE, oldProtect) Then Throw New Exception
p.Dispose()
Next
End Sub
Sub RemoveProtection(ByVal ProcessName As String, ByVal AddressOfStart As Integer, ByVal SizeToRemoveProtectionInBytes As Long)
For Each p As Process In Process.GetProcessesByName(ProcessName)
Const PAGE_EXECUTE_READWRITE As Integer = &H40
Dim oldProtect As Integer
If Not VirtualProtectEx(p.Handle, New IntPtr(AddressOfStart), New IntPtr(SizeToRemoveProtectionInBytes), PAGE_EXECUTE_READWRITE, oldProtect) Then Throw New Exception
p.Dispose()
Next
End Sub
Sub AllocMem(ByVal ProcessName As String, ByVal AddressOfStart As Integer, ByVal SizeOfAllocationInBytes As Integer)
For Each p As Process In Process.GetProcessesByName(ProcessName)
Const MEM_COMMIT As Integer = &H1000
Const PAGE_EXECUTE_READWRITE As Integer = &H40
Dim pBlob As IntPtr = VirtualAllocEx(p.Handle, New IntPtr(AddressOfStart), New IntPtr(SizeOfAllocationInBytes), MEM_COMMIT, PAGE_EXECUTE_READWRITE)
If pBlob = IntPtr.Zero Then Throw New Exception
p.Dispose()
Next
End Sub
End Module