Imports System.Runtime.InteropServices Imports System.Reflection '------------------ 'Creator: aeonhack 'Site: elitevs.net 'Created: 11/9/2011 'Changed: 3/17/2012 'Version: 1.2.0 '------------------ Class Scanner Public ProgressChangeEvent As ProgressChangeDG Delegate Sub ProgressChangeDG(ByVal value As Integer) Sub New(progressChange As ProgressChangeDG) ProgressChangeEvent = progressChange End Sub #Region " Properties " Property Handle() As IntPtr Private _Pages As New List(Of PAGE) ReadOnly Property Pages() As PAGE() Get Return _Pages.ToArray End Get End Property Private _Results As New List(Of Integer) Property Results As Integer() Get Return _Results.ToArray End Get Set(value As Integer()) _Results = New List(Of Integer)(value) End Set End Property #End Region #Region " Process " Private PID As Integer Public Sub OpenProcess(ByVal processId As Integer) PID = processId _Handle = OpenProcess(1080, False, processId) If _Handle = IntPtr.Zero Then Dim Win32Error As Integer = Marshal.GetLastWin32Error If Win32Error = 5 Then 'Requires elevation. End If Throw New Exception(CStr(Win32Error)) End If End Sub Public Sub CloseProcess() CloseHandle(_Handle) _Handle = IntPtr.Zero _Pages.Clear() _Results.Clear() _Mask = Nothing _Data = Nothing _Search = Nothing End Sub #End Region #Region " Scanning " Public Sub ScanPages() If _Handle = IntPtr.Zero Then Throw New InvalidOperationException _Pages.Clear() Dim Current As Integer While True Dim T As New INFORMATION If QueryEx(_Handle, Current, T, 28) = 0 Then Exit While If T.State = 4096 AndAlso T.Protect = 4 AndAlso Not T.RegionSize = 0 Then _Pages.Add(New PAGE(T.BaseAddress, T.RegionSize)) End If If (CUInt(T.BaseAddress.ToInt32) + CUInt(T.RegionSize)) > Integer.MaxValue Then Exit While Current = T.BaseAddress.ToInt32 + T.RegionSize End While End Sub Public Sub FirstScan(ByVal search As Byte(), Optional ByVal index As Integer = 0, Optional ByVal [step] As Integer = 4, Optional ByVal mask As Byte() = Nothing) CheckParameters(search, mask) If [step] = 0 Then Throw New ArgumentOutOfRangeException _Results.Clear() ProgressChangeEvent(0) Dim Count As Integer Dim Size As Integer Dim Base As Integer For I As Integer = 0 To Pages.Length - 1 Size = Pages(I).Size If Size >= (search.Length + index) Then Base = Pages(I).Base.ToInt32 _Data = New Byte(Size - 1) {} If ReadMem(_Handle, Base, _Data, _Data.Length, Count) Then For O As Integer = index To Count - search.Length Step [step] If ScanData(O) Then _Results.Add(Base + O) Next End If End If ProgressChangeEvent(CInt(((I + 1) / Pages.Length) * 100)) Next ProgressChangeEvent(100) End Sub Public Sub NextScan(ByVal search As Byte(), Optional ByVal mask As Byte() = Nothing) CheckParameters(search, mask) If _Results.Count = 0 Then Throw New ArgumentOutOfRangeException ProgressChangeEvent(0) Dim Clean As Boolean Dim Count As Integer Dim Index As Integer Dim Current As Integer Dim Maximum As Integer = _Results.Count _Data = New Byte(search.Length - 1) {} Do Until Clean OrElse _Results.Count = 0 Clean = True For R As Integer = Index To _Results.Count - 1 Index = R Current += 1 If ReadMem(_Handle, _Results(R), _Data, _Data.Length, Count) Then Clean = ScanData(0) Else Clean = False End If If Not Clean Then _Results.RemoveAt(R) Exit For End If ProgressChangeEvent(CInt((Current / Maximum) * 100)) Next Loop ProgressChangeEvent(100) End Sub Private _Mask As Byte() Private _Data As Byte() Private _Search As Byte() Private HandleMask As Boolean Private MaskIndex As Integer Private Function ScanData(ByVal offset As Integer) As Boolean If HandleMask Then For I As Integer = MaskIndex To _Search.Length - 1 If _Mask(I) = 255 AndAlso Not _Data(offset + I) = _Search(I) Then Return False Next Else For I As Integer = 0 To _Search.Length - 1 If Not _Data(offset + I) = _Search(I) Then Return False Next End If Return True End Function #End Region #Region " Validation " Private Sub CheckParameters(ByVal search As Byte(), ByVal mask As Byte()) _Search = search _Mask = mask If _Handle = IntPtr.Zero Then Throw New InvalidOperationException If search.Length = 0 Then Throw New ArgumentOutOfRangeException If mask IsNot Nothing Then If Not search.Length = mask.Length Then Throw New ArgumentOutOfRangeException If Not CheckMask(mask) Then Throw New FormatException HandleMask = True Else HandleMask = False End If End Sub Private Function CheckMask(ByVal mask As Byte()) As Boolean For I As Integer = 0 To mask.Length - 1 If mask(I) = 255 Then MaskIndex = I Return True End If Next Return False End Function #End Region #Region " Read / Write " Public Function ReadMemory(ByVal address As Integer, ByVal length As Integer) As Byte() If _Handle = IntPtr.Zero Then Throw New InvalidOperationException If address < 0 Then Throw New ArgumentOutOfRangeException If length < 1 Then Throw New ArgumentOutOfRangeException Dim Count As Integer Dim Data(length - 1) As Byte If Not ReadMem(_Handle, address, Data, Data.Length, Count) Then Throw New Exception(CStr(Marshal.GetLastWin32Error)) Return Data End Function Public Sub WriteMemory(ByVal address As Integer, ByVal data As Byte()) If _Handle = IntPtr.Zero Then Throw New InvalidOperationException If address < 0 Then Throw New ArgumentOutOfRangeException If data.Length = 0 Then Throw New ArgumentOutOfRangeException Dim Count As Integer If Not WriteMem(_Handle, address, data, data.Length, Count) Then Throw New Exception(CStr(Marshal.GetLastWin32Error)) End Sub #End Region #Region " Alloc / Free " Public Function Alloc(ByVal length As Integer) As Integer If _Handle = IntPtr.Zero Then Throw New InvalidOperationException If length < 1 Then Throw New ArgumentOutOfRangeException Dim T As Integer = AllocEx(_Handle, 0, length, 12288, 4).ToInt32 If T = 0 Then Throw New Exception(CStr(Marshal.GetLastWin32Error)) Return T End Function Public Sub Free(ByVal address As Integer) If _Handle = IntPtr.Zero Then Throw New InvalidOperationException If address < 0 Then Throw New ArgumentOutOfRangeException If Not FreeEx(_Handle, address, 0, 32768) Then Throw New Exception(CStr(Marshal.GetLastWin32Error)) End Sub #End Region #Region " Suspend / Resume " Public Sub Suspend() If _Handle = IntPtr.Zero Then Throw New InvalidOperationException Dim Handle As IntPtr Dim P As Process = Process.GetProcessById(PID) For Each T As ProcessThread In P.Threads Handle = OpenThread(2, False, T.Id) If Not Handle = IntPtr.Zero Then SuspendThread(Handle) End If Next End Sub Public Sub [Resume]() If _Handle = IntPtr.Zero Then Throw New InvalidOperationException Dim Handle As IntPtr Dim P As Process = Process.GetProcessById(PID) For Each T As ProcessThread In P.Threads Handle = OpenThread(2, False, T.Id) If Not Handle = IntPtr.Zero Then ResumeThread(Handle) End If Next End Sub #End Region #Region " Win32 Calls " _ Private Shared Function OpenProcess( _ ByVal access As UInteger, _ ByVal inherit As Boolean, _ ByVal process As Integer) As IntPtr End Function _ Private Shared Function OpenThread( _ ByVal access As UInteger, _ ByVal inherit As Boolean, _ ByVal thread As Integer) As IntPtr End Function _ Private Shared Function SuspendThread( _ ByVal handle As IntPtr) As Integer End Function _ Private Shared Function ResumeThread( _ ByVal handle As IntPtr) As Integer End Function _ Private Shared Function QueryEx( _ ByVal handle As IntPtr, _ ByVal base As Integer, _ ByRef information As INFORMATION, _ ByVal length As Integer) As Integer End Function _ Private Shared Function AllocEx( _ ByVal handle As IntPtr, _ ByVal address As Integer, _ ByVal length As Integer, _ ByVal type As Integer, _ ByVal protect As Integer) As IntPtr End Function _ Private Shared Function FreeEx( _ ByVal handle As IntPtr, _ ByVal address As Integer, _ ByVal length As Integer, _ ByVal type As Integer) As Boolean End Function _ Shared Function ReadMem( _ ByVal handle As IntPtr, _ ByVal base As Integer, _ ByVal data As Byte(), _ ByVal dataLength As Integer, _ ByRef length As Integer) As Boolean End Function _ Shared Function WriteMem( _ ByVal handle As IntPtr, _ ByVal base As Integer, _ ByVal data As Byte(), _ ByVal dataLength As Integer, _ ByRef length As Integer) As Boolean End Function _ Private Shared Function CloseHandle( _ ByVal handle As IntPtr) As Boolean End Function #End Region #Region " Structures " Structure PAGE Private _Base As IntPtr ReadOnly Property Base() As IntPtr Get Return _Base End Get End Property Private _Size As Integer ReadOnly Property Size() As Integer Get Return _Size End Get End Property Sub New(ByVal base As IntPtr, ByVal size As Integer) _Base = base _Size = size End Sub End Structure _ Private Structure INFORMATION Public BaseAddress As IntPtr Public AllocationBase As IntPtr Public AllocationProtect As UInteger Public RegionSize As Integer Public State As UInteger Public Protect As UInteger Public Type As UInteger End Structure #End Region End Class