Results 1 to 12 of 12
  1. #1
    abuckau907's Avatar
    Join Date
    Dec 2012
    Gender
    male
    Location
    other side of the wire
    Posts
    1,342
    Reputation
    162
    Thanks
    239
    My Mood
    Cold

    vb.net ReadProcessMemory part2

    (same thing as part 1: re-posting from another forum I go to, incase anyone needs it. Some info may be wrong/incorrect, I'm not an expert)

    The goal
    To be able to scan all the memory being used by a process. Eventually being able to read all of the data and comparing it to some value. That is, to be able to find the specific location of a known value in a process's memory! ie. Scan(), and eventually FindPattern()

    Basic Assumptions
    You read part 1.
    Probably not 64 bit compatible

    If you remember from the last tutorial, each address in a process's ram has access rights associated with it. But that's not quite right. Actually the ram
    (0-0xFFFFFFFF) is divided up into many chunks of many different sizes. Each chunk has specific access rights, and all addresses in that chunk have the same rights.
    For example

    10000 - 20000 READ_ONLY 0x10000, 0x10001, 0x1**** are all READ_ONLY
    20000 - 30000 READ_ONLY
    30000 - 60000 EXECUTE_READ are all EXECUTE_READWRITE (ie.can't call WriteProcessMemory on these addr)
    60000 - 80000 READ_ONLY (ie.can't call WriteProcessMemory on these addr)
    80000 - 10000 EXECUTE_READWRITE
    10000 - FFFFF READ_WRITE are all READ_WRITE

    That is totally made up. But you can see there are chunks (start address to end address) which each have access rights.Also note that each chunk, or 'region', has more properties than just Protection. Windows has a nice structure for us called MEMORY_BASIC_INFORMATION.
    Basically it represents a chunk/region and has useful properties like Size. So how do we fill this nice structure with info? Another API of course, coming soon.

    The MEMORY_BASIC_INFORMATION structure
    Code:
     Private Structure MEMORY_BASIC_INFORMATION
            Dim BaseAddress As IntPtr          Pretty obvious. The lowest address of the page
            Dim AllocationBase As IntPtr
            Dim AllocationProtect As UInt32   Same as protect. When the region was first created 
            Dim RegionSize As IntPtr
            Dim State As UInt32                    COMMIT is the only one we care about
            Dim Protect As UInt32                  Access rights. EXECUTE_READWRITE, READONLY etc.
            Dim zType As UInt32                    IMAGE, MAPPED, PRIVATE.
     End Structure
    And now to use our new struture. But how do we fill it with useful data? That api. VirtualQueryEx().
    Code:
    Private Declare Function VirtualQueryEx Lib "kernel32.dll" (ByVal hProcess As IntPtr, ByVal lpAddress As IntPtr, ByRef lpBuffer As MEMORY_BASIC_INFORMATION, ByVal dwLength As UInt32) As Int32
    hProcess Valid process handle from OpenProcess(). In my code, _targetProcessHandle
    lpAddress The address we want info on. (it automatically figures out
    which region that address is in,and returns the rights for that region, via lpBuffer)
    lpBuffer An object of our MEMORY_BASIC_MEMORY structure. Passed BYREF.
    dwLength The size of our MEMORY_BASIC_MEMORY structure in bytes

    dwLength is slightly tricky. We could count all the variables in the structure, and because we know what type they are, and how big each type is in bytes, it's easy to figure out the overall size of the structure. There is also a .Net function to do this for us. In the Marshal class.
    Code:
         Dim _mbi As MEMORY_BASIC_INFORMATION
         Dim _mbiSize as Int32 = System.Runtime.InteropServices.Marshal.SizeOf(_mbi)
              'or Marshal.SizeOf(New MEMORY_BASIC_INFO) and u don't need to have _mbi declared.
         
         'which we will use as
         
         VirtualQueryEx(_targetProcessHandle, _addr, _mbi, _mbiSize) 'Now _mbi's properties are filled with data.
         MsgBox("Region BaseAddress: 0x" & _mbi.BaseAddress.ToString("X") & ", size: " & _mbi.RegionSize.ToString("X"))
    We will use Marshal.SizeOf(mbi) several times. This size shouldn't change so we can calculate then store it to avoid unnecessary function calls.
    It's not _mbi = VirtualQuery(etc) because _mbi (lpBuffer) is passed ByRef. I hope you understand ByRef.

    Ok, great. Now we can know the access rights of any address (and therefore it's region). Let's take this a step further and find out the access rights for every region. This involves looping over the entire memory range and figuring out where each region is, but how do we do that? Actually it's pretty simple. The trick is, when you add Region.Base + Region.Size you get the next Region's .Base. Seems obvious. It wasn't 2 seconds ago Here is the code to do just that.
    Code:
    Public Sub xxx
    Dim _addr As IntPtr = IntPtr.Zero
      Do
          VirtualQueryEx(_targetProcessHandle, _addr, _mbi, _mbiSize)
           ''increment _addr to next region
           _addr = _mbi.BaseAddress + _mbi.RegionSize
      Loop While _addr.ToInt32 < 0xFFFFFFFF
    End Sub
    Admittedly, it doesn't actually do anything. Here is a loop that does *something*.
    Code:
    Public Sub yyy
    'Don't actually run this loop. LOTS of message boxes.
    Dim _addr As IntPtr = IntPtr.Zero
          Do
              VirtualQueryEx(_targetProcessHandle, _addr, _mbi, _mbiSize)
              MsgBox("Region  BaseAddress: " & _mbi.BaseAddress & " , size: " & _mbi.RegionSize)
               ''increment _addr to next region
              _addr = _mbi.BaseAddress + _mbi.RegionSize
          Loop While _addr.ToInt32 < 0xFFFFFFFF
    End Sub
       
    
    	note. Instead of using 0 and 0xFFFFFFFF for our start and stop addresses, I 
                  recomend using SystemInfo.lpMinAddress and .lpMaxAddress.
                  Just like MEMORY_BASIC_INFO and VirtualQueryEx, we create a structure
                  called SYTEM_INFO and fill it with the api GetSystemInfo(), that has 
                  useful properties like # of processors. See below.
    Some notes
    If mbi.State isn't COMMITTED, the target app ISN'T using it. You probably don't care about reading it.
    mbi.Type IMAGE, SYSTEM, MAPPED. I don't know. Depending on what you need you may ignore,or focus, on some types.
    Generally you can read all 3 without problems? Specific cases of not being able to??

    Here is a loop that will "Analyze" every region of a process's ram.
    Code:
    Public Sub AnalyzeRam
    Dim _addr As IntPtr = IntPtr.Zero 
    Dim _mbi as MEMORY_BASIC_INFORMATION
    Dim _mbiSize As Int32 = System.Runtime.InteropServices.Marshal.SizeOf(_mbi)
    Dim _sysInfo As SYSTEM_INFORMATION
    Dim _outputString as String = ""
            GetSystemInfo(_sysInfo)
    	_addr = _sysInfo.lpMinimumApplicationAddress 
     Do
      VirtualQueryEx(_targetProcessHandle, _addr, _mbi, _mbiSize)
      If _mbi.State = MemoryAllocationState.Commit Then
       'This region actively being used by process
       _outputString += "Base: 0x" & _mbi.BaseAddress.ToString("X") & Environment.NewLine
       _outputString += "Size: " & _mbi.BaseAddress.ToString("X") & Environment.NewLine 'Also in hex!
       If _mbi.zType = MemoryAllocationType.MEM_PRIVATE Then
       _outputString += "[private]" & Environment.NewLine
       ElseIf _mbi.zType = MemoryAllocationType.MEM_IMAGE
       _outputString += "[image]" & Environment.NewLine
       Else
       _outputString += "[mapped]" & Environment.NewLine
       End If
       If _mbi.Protect And MemoryAllocationType.PAGE_GUARD Then
    	'guard-ed. Reading will result in exception by OS.
       _outputString += "---GUARDED---"
       End If
      End If   
      'MessageBox.Show(_outputString)
      _addr = _mbi.BaseAddress + _mbi.RegionSize ''point _addr to next region
      Loop While _addr.ToInt32 < _sysInfo.lpMaximumApplicationAddress
    End Sub
    note. MBI.Type has been renamed to mbi.zType because of keyword name collision.
    I assume you added this function to the MemoryManager class from part 1,
    and that you've already called OpenProcess() successfully.

    You also need these...
    Code:
    Private Declare Sub GetSystemInfo Lib "kernel32.dll" (ByRef lpSystemInfo As SYSTEM_INFO)
    Code:
    Private Structure SYSTEM_INFO
            Dim wrocessorArchitecture As Int16
            Dim wReserved As Int16
            Dim dwPageSize As Int32			 'Useful
            Dim lpMinimumApplicationAddress As Int32 'Useful
            Dim lpMaximumApplicationAddress As Int32 'Useful
            Dim dwActiveProcessorMask As Int32
            Dim dwNumberOfProcessors As Int32
            Dim dwProcessorType As Int32
            Dim dwAllocationGranularity As Int32
            Dim wProcessorLevel As Int16
            Dim wProcessorRevision As Int16
        End Structure
    Code:
    Private Enum MemoryAllocationProtectionType As UInt32
            PAGE_NOACCESS = &H1
            PAGE_READONLY = &H2
            PAGE_READWRITE = &H4
            PAGE_WRITECOPY = &H8
            PAGE_EXECUTE = &H10
            PAGE_EXECUTE_READ = &H20
            PAGE_EXECUTE_READWRITE = &H40
            PAGE_EXECUTE_WRITECOPY = &H80
            PAGE_GUARD = &H100
            PAGE_NOCACHE = &H200
            PAGE_WRITECOMBINE = &H400
            PAGE_CANREAD = PAGE_READONLY Or PAGE_READWRITE Or PAGE_EXECUTE_READ Or PAGE_EXECUTE_READWRITE
            PAGE_CANEXECUTE = PAGE_EXECUTE Or PAGE_EXECUTE_READ Or PAGE_EXECUTE_READWRITE 'Or PAGE_WRITECOPY?
            PAGE_CANWRITE = PAGE_READWRITE Or PAGE_EXECUTE_READWRITE OR PAGE_WRITECOMBINE
        End Enum
        Private Enum MemoryAllocationType As UInt32
            MEM_IMAGE = &H1000000
            MEM_MAPPED = &H40000
            MEM_PRIVATE = &H20000
        End Enum
        Private Enum MemoryAllocationState As UInt32
            Commit = &H1000
            Reserve = &H2000
            Decommit = &H4000
            Release = &H8000
            Reset = &H80000
            Physical = &H400000
            TopDown = &H100000
            WriteWatch = &H200000
            LargePages = &H20000000
        End Enum
    Actually reading out all of the data (or as much as possible)
    Now that we have a framework which well let us loop over each memory region, we need to actually read the data from the regions. If you remember, ReadProcessMemory() takes a Size parameter. Reading from 0-0xffffffff only Int32 or Int64 at a time would take LOTS and lots of calles to ReadProcessMemory() and that can't be efficient. If we increase the read size, then we can call it a lot less times and improve performance. How big can you make ReadProcessMemory() go? Well, I'm not sure(Look into it), but the SYSTEM_INFO structure has a property called PageSize. On my 32 bit Windows Xp with only 2g of ram, this is 4096. So apparently ReadProcessMemory() can read upto/more than 4096 bytes at a time. This kind of seems like a lot! But really it isn't. I assume this is most efficient?
    My strategy is this
    Code:
    if mbi.RegionSize <= pageSize then
    bytes = ReadProcessMemory(entire_region)
    else
    bytes = SecondFunctionToGetLargerPages()
    end if
    I'm not going to fully explain the code that copies the regions. Now that we can use ReadProcessMemory and have MemoryManager.GetBytes(), it's
    just a matter of creating the correct byte arrays and how to pass them back and forth. For now we can only read regions that are marked readable (EXECUTE_READ, READWRITE, etc). Obviously. There is actually another API to change the permissions, we'll cover that later. Notice the If _mbi.Protect AND MemoryAllocation.PAGE_CANREAD? The .Protect property is actually a bit mask, so it can store several values simultaneously. I use bitmasking to check if certain values are set: readable, writable, executable.
    I'm not going to explain it too much further, you have what you need.
    Code:
    Private Sub AnalyzeAndReadAll
         Dim _mbi As MEMORY_BASIC_INFORMATION, _sysInfo As SYSTEM_INFO
            Dim _mbiSize As Int32 = System.Runtime.InteropServices.Marshal.SizeOf(_mbi)
            GetSystemInfo(_sysInfo)
            Dim _addr As IntPtr = IntPtr.Zero
            Dim _readBuff(_sysInfo.dwPageSize - 1) As Byte 'read small pages
            Dim _bigBuff(0) As Byte 'read big pages
            Dim _actualBytesRead As Int32 = 0 'actual length of bytes copied during ReadProcessMemory()
    
    Do
           VirtualQueryEx(_targetProcessHandle, _addr, _mbi, _mbiSize)
           If _mbi.State = MemoryAllocationState.Commit Then
               'this region of ram actively being used by process (commited at least..)
               If (_mbi.Protect And MemoryAllocationProtectionType.PAGE_CANREAD) And Not (_mbi.Protect And MemoryAllocationProtectionType.PAGE_GUARD)) Then 'bitmask (checks for any readable type)
    		''READable and not GUARDed
                    ''Read the data.
                    If _mbi.RegionSize.ToInt32 <= _sysInfo.dwPageSize Then
                        'small page. Read entire page into buffer.
                        If ReadProcessMemory(_targetProcessHandle, _mbi.BaseAddress, _readBuff, _mbi.RegionSize, _actualBytesRead) Then
                            If _actualBytesRead <> _mbi.RegionSize  Then
                                'not able to read all data, handle gracefully. do nothing :)
                                'MsgBox("ScanForBytes() RPM->ActualBytesRead too low!" & _addr.ToString("X"))
                            Else
                                'do something with the data
                                'ie. compare to another byte arrar for equality ;)
                            End If
    
                        Else
                            'MsgBox("ScanForBytes::RPM FAIL 0x" & _mbi.BaseAddress.ToString("X"))
                        End If
                    Else  'large page. Read page in chunks
                        _bigBuff = ReadLargeRamChunk(_addr, IntPtr.Add(_addr, _mbi.RegionSize.ToInt32))
                         'do something with the data
                         'ie. compare to another byte arrar for equality ;)
                    End If ''//page size		
    	   End If 
    	_addr = _mbi.BaseAddress + _mbi.RegionSize ''increment _addr to next region
            Loop While _addr.ToInt32 < _systemInfo.lpMaximumApplicationAddress
    End Sub
    
     Private Function ReadLargeRamRegion(ByVal aStart As IntPtr, ByVal aStop As IntPtr) As Byte()
         Dim _rtnBuffSize As Int32 = aStop.ToInt32 - aStart.ToInt32 'theoretical max size: may be smaller due to Read failures
         Dim _sizeRemaining As Int32 = _rtnBuffSize 
         Dim _byteBuff(_rtnBuffSize - 1) As Byte
         Dim _byteBuffCurrIndex As Int32 = 0 'actual size of data to be returned
         Dim _curAddr As IntPtr = aStart
         Dim _readBuff(_systemInfo.dwPageSize -1) As Byte
         Dim _actualBytesRead As Int32 = 0 '' Actual count of bytes read by ReadProcessMemory()
         'start reading
         Do
    
             If _sizeRemaining >= _systemInfo.dwPageSize Then
                 If ReadProcessMemory(_targetProcessHandle, _curAddr, _readBuff, _systemInfo.dwPageSize, _actualBytesRead) Then
                     If _actualBytesRead <> _systemInfo.dwPageSize Then
                         'didn't read all data?! Don't append _readBuff to byteBuff. or do..
                         'MsgBox("ReadLargeRamChunk() RPM->ActualBytesRead too low! 0x" & _curAddr.ToString("X"))
                     Else
                         Array.Copy(_readBuff, 0, _byteBuff, _byteBuffCurrIndex, _actualBytesRead)
                         _byteBuffCurrIndex += _systemInfo.dwPageSize
                     End If
                 Else
                     'MsgBox("ReadLargeRamChunk() RPM->FAIL! 0x" & _curAddr.ToString("X"))
                 End If
                 _curAddr += _systemInfo.dwPageSize
                 _sizeRemaining -= _systemInfo.dwPageSize
                 If _sizeRemaining = 0 Then Exit Do
             Else
                 'almost at end of mem scan. 1 small piece left
                  If ReadProcessMemory(_targetProcessHandle, _curAddr, _readBuff, _sizeRemaining, _actualBytesRead) Then
                     If (_actualBytesRead <> _sizeRemaining)  Then
                         'not able to read entire area
                         'MsgBox("ReadLargeRamChunk() RPM->ActualBytesRead too low! (final chunk) 0x" & _curAddr.ToString("X"))
                     Else
                         Array.Copy(_readBuff, 0, _byteBuff, _byteBuffCurrIndex, _actualBytesRead)
                         'success
                         Exit Do
                     End If
    
                 Else
                     'MsgBox("ReadLargeRamChunk() RPM->FAIL! (final chunk) 0x" & _curAddr.ToString("X"))
                 End If
             End If
         Loop
         If _byteBuffCurrIndex < _rtnBuffSize Then
           'not all data read. _byteBuff is too large. chop off extra, unused byte.
         Redim Preserve _byteBuff(_byteBuffCurrIndex + 1) 'efficiency? only occurs if read fails occur.
         Return _byteBuff
     End Function
    You're now reading all the readable data from the process! Big stuff.
    Notice the PAGE_CANREAD. You don't actually have to make that check, but depending on the access type of the memory region, rpm may fail. If you check CANREAD, it should* succeed.


    Also, the second choice..you can call OpenProcess() every time! you want to read, or you can 'attach' once, and keep track of the handle. Obviously I chose to keep track of it, so none of my Read() functions call OpenProcess(), they used a local variable _targetProcessHandle.



    The goal
    To be able to scan all the memory being used by a process. Even those not marked as readable

    It's actually really easy. There is yet another windows api that will change the access rights of a memory region. VirtualProtectEx().
    VirtualProtectEx is just like VirtualQueryEx except that instead of reading the access rights, we're settings them! Simple, right?

    Code:
        Private Declare Function VirtualProtectEx Lib "kernel32.dll" (ByVal hProcess As IntPtr, ByVal lpAddress As IntPtr, ByVal dwSize As IntPtr, ByVal flNewProtect As UInt32, ByRef lpfoldProtect As UInt32) As Boolean
    hProcess Same as all the others
    lpAddress
    dwSize
    fwNewProtect New protection rights
    fwOldProtect Old protection rights (byref. for restoring when finished)

    Code:
    'assuming _mbi has been set
    Dim _oldProtects as Uint32 = 0 'BYREF. Save so we can restore rights later.
    VirtualProtectEx(_targetProcessHandle, _mbi.BaseAddress, _mbi.RegionSize,MemoryAllocationProtectionType.EXECUTE_READWRITE, _oldProtect)
    One thing to note: you need to be careful of the new Protect value. If the region was marked as EXECUTEable, you better make the new protection be
    executable or the program will crash when it tries to run it's code there. Same situation with WRITEable. If the region was writeable, and you change
    it to read_only, the program will crash when it tries to write to it. Seems pretty obvious, but I didn't think about it my first time.

    That's really all there is to it. Now inside our scan, if the memory region isn't readable, we can make it readable. One last word of advice. Remember how MBI.Protect uses bitmasks to store several values. This means it can be PAGE_READ and PAGE_GUARD at the same time. I think PAGE_GUARD is like an anti-cheat mechanism. It will flag the OS if there is an attempt to Read() if GUARD is set to true. (not necessarily anti-cheat, but can be used this way)


    ---------- Post added at 02:49 AM ---------- Previous post was at 02:11 AM ----------

    edit: I posted that tutorial a while ago, there were quite a few (obvious) bugs, and I've since change some code. Hopefully you can spot the differences / bugs / improvements.
    Scan
    Code:
    #Region "Scan"
        ''' <summary>
        ''' Scans a process's entire memory range for the specified hex string.
        ''' <param name="hexString">Standard search/mask technique. (** denotes a masked byte.)</param>
        ''' <param name="returnOnFirstOccurance">End scan early if value found?</param>
        ''' </summary>
        Public Function FindPattern(ByVal hexString As String, Optional ByVal returnOnFirstOccurance As Boolean = True) As IntPtr()
            ''format example: 64 8b 15 ** ** ** ** 8b 34 ** 8b 0d ** ** ** ** 89 81
            Dim _hexStringChunks() As String = hexString.Split(" ")
            Dim _hexStringAsBytes(_hexStringChunks.Length - 1) As Byte
            Dim _mask(_hexStringChunks.Length - 1) As Byte
    
            For xx As Int32 = 0 To _hexStringChunks.Length - 1
                If _hexStringChunks(xx) = "**" Then
                    _hexStringAsBytes(xx) = &H0
                    _mask(xx) = &H0 'unimportant
                Else
                    _hexStringAsBytes(xx) = Byte.Parse(_hexStringChunks(xx), Globalization.NumberStyles.HexNumber)
                    _mask(xx) = &H1 'important
                End If
            Next
            Dim _results() As IntPtr = ScanForByteMask(_hexStringAsBytes, _mask, returnOnFirstOccurance)
            Return _results
        End Function
        ''' <summary>
        ''' Scan a process's entire memory range for the specified array of bytes. Function always return an array(). (may specify to return when first occurance is found. If returnOnFirstOccurance=true, array.length will be 1)
        ''' </summary>
        Private Function ScanForBytes(ByVal byteBuff() As Byte, Optional ByVal returnOnFirstOccurance As Boolean = False) As IntPtr()
            If IsAttachedToProcess() = False Then
                Return New IntPtr() {IntPtr.Zero} 'user fail
            End If
            Dim _rtns As New List(Of IntPtr) 'locations (memory addresses) where the buff() was found at
            If Not returnOnFirstOccurance Then _rtns.Capacity = 1000 'could be larger. depends how many results you expect..
            Dim _mbi As MEMORY_BASIC_INFORMATION, _sysInfo As SYSTEM_INFO
            Dim _mbiSize As Int32 = Marshal.SizeOf(_mbi) ' size of mbi struct, in bytes.
            GetSystemInfo(_sysInfo)
            Dim _addr As IntPtr = IntPtr.Zero 'counter/loop control.
            Dim _readBuff(_sysInfo.dwPageSize - 1) As Byte 'small buffer to read small mem regions
            Dim _bigBuff(0) As Byte 'large buffer to read large mem regions
            Dim _actualBytesRead As Int32 = 0 ''actual length of bytes copied during ReadProcessMemory()
            Dim _origPageProtection As UInt32 = 0 ''To preserve/restore original protection values
            Dim _hasAlreadyFoundOnce As Boolean = False 'possibly end the scan early when first result found
            Dim _oldProtects As String = "" 'displayed after errorrs. as string of '0' padded bits.
    
            Do
                VirtualQueryEx(_targetProcessHandle, _addr, _mbi, _mbiSize)
                _oldProtects = ConvertMBIProtectToBinaryString(_mbi.Protect)
                If _mbi.State = MemoryAllocationState.Commit Then
                    If _mbi.Protect And MemoryAllocationProtectionType.PAGE_CANREAD Then 'bitmask check for any readable type
                        ''EASY READ
                        If _mbi.Protect And MemoryAllocationProtectionType.PAGE_GUARD Then
                            DoOutput("avoided the guard at 0x" & _addr.ToString("X"))
                            GoTo badLabelSkipThisMemRegion 'BUT ITS GUARDED
                        End If
                    Else
                        ''CANT READ YET
                        If _mbi.Protect And MemoryAllocationProtectionType.PAGE_COPYFORWARD Then
                            ''CANT READ AT ALL (ignore non-readable copyforward unless you really* know what you're doing. usually fails anyway)
                            DoOutput("avoided OS managed file (dll?) at 0x" & _addr.ToString("X"))
                            GoTo badLabelSkipThisMemRegion
                        Else
                            ''Enable Read
                            If _mbi.Protect And MemoryAllocationProtectionType.PAGE_CANEXECUTE Then
                                'it should remain executable! 
                                If VirtualProtectEx(_targetProcessHandle, _mbi.BaseAddress, _mbi.RegionSize, MemoryAllocationProtectionType.PAGE_EXECUTE_READWRITE, _origPageProtection) Then
                                    'DoOutput("execPatching OK 0x" & _addr.ToString("X"))
                                Else
                                    DoOutput("SFB() execPatching FAIL 0x" & _addr.ToString("X"))
                                    DoOutput("protect: " & _oldProtects)
                                    Threading.Thread.Sleep(2500)
                                    GoTo badLabelSkipThisMemRegion
                                End If
                            Else
                                If VirtualProtectEx(_targetProcessHandle, _mbi.BaseAddress, _mbi.RegionSize, MemoryAllocationProtectionType.PAGE_READWRITE, _origPageProtection) Then
                                    'DoOutput("readPatching OK 0x" & _mbi.BaseAddress.ToString("X"))
                                Else
                                    DoOutput("SFB() readPatching FAIL 0x" & _mbi.BaseAddress.ToString("X"))
                                    DoOutput("protect: " & _oldProtects)
                                    Threading.Thread.Sleep(2500)
                                    GoTo badLabelSkipThisMemRegion
                                End If
                            End If
                        End If
                    End If
                    ''READ THE DATA
                    If _mbi.RegionSize.ToInt32 <= _sysInfo.dwPageSize Then '4096 bytes. 4kb. see windows memory management for info.
                        ''READ THE DATA. small region
                        If ReadProcessMemory(_targetProcessHandle, _mbi.BaseAddress, _readBuff, _mbi.RegionSize, _actualBytesRead) Then
                            If (_actualBytesRead <> _mbi.RegionSize) Then
                                'not able to read all data, handle gracefully. do nothing :)
                                modPublic.DoOutput("SFB() RPM->ActualBytesRead too low! 0x" & _mbi.BaseAddress.ToString("X"))
                            Else
                                ''COMPARE VALUE                                      
                                For xx As Int32 = 0 To _mbi.RegionSize.ToInt32 - byteBuff.Length 'todo:  align4?
                                    For yy As Int32 = 0 To byteBuff.Length - 1
                                        If byteBuff(yy) <> _readBuff(xx + yy) Then
                                            GoTo badLabelNoSuccess
                                        End If
                                    Next
                                    _rtns.Add(_addr.ToInt32 + xx)  'found it
                                    If returnOnFirstOccurance Then
                                        _hasAlreadyFoundOnce = True
                                        Exit For
                                    End If
    badLabelNoSuccess:
                                Next
                            End If
                        Else
                            modPublic.DoOutput("SFB() RPM FAIL 0x" & _mbi.BaseAddress.ToString("X"))
                        End If
                    Else
                        ' large region                                     
                        _bigBuff = ReadLargeRamPage(_addr, _addr.ToInt32 + _mbi.RegionSize.ToInt32)
                        For xx As Int32 = 0 To _bigBuff.Length - byteBuff.Length 'todo:  align4?
                            ''COMPARE VALUE 
                            For yy As Int32 = 0 To byteBuff.Length - 1
                                If byteBuff(yy) <> _bigBuff(xx + yy) Then
                                    GoTo badLabelNoMoreSuccess
                                End If
                            Next
                            _rtns.Add(_addr.ToInt32 + xx) 'found it
                            If returnOnFirstOccurance Then
                                _hasAlreadyFoundOnce = True
                                Exit For
                            End If
    badLabelNoMoreSuccess:
                        Next
                    End If ''end region size
                    '' RESTORE PROTECTION
                    If _origPageProtection Then
                        VirtualProtectEx(_targetProcessHandle, _mbi.BaseAddress, _mbi.RegionSize, _origPageProtection, _origPageProtection)
                        _origPageProtection = 0
                    End If
                    If _hasAlreadyFoundOnce AndAlso returnOnFirstOccurance Then Exit Do
                End If ''//state=committed
    badLabelSkipThisMemRegion:
                _addr = _mbi.BaseAddress.ToInt32 + _mbi.RegionSize.ToInt32 ''increment _addr to next region
            Loop While _addr.ToInt32 < _sysInfo.lpMaximumApplicationAddress
    
            If _rtns.Count = 0 Then _rtns.Add(IntPtr.Zero) 'pattern not found!
            Return _rtns.ToArray
        End Function
        Private Function ScanForByteMask(ByVal buff() As Byte, ByVal mask() As Byte, Optional ByVal returnOnFirstOccurance As Boolean = False) As IntPtr()
            If IsAttachedToProcess() = False Or mask.Length <> buff.Length Then
                Return New IntPtr() {IntPtr.Zero} 'user fail
            End If
            Dim _rtns As New List(Of IntPtr) 'locations (memory addresses) where the buff() was found at
            If Not returnOnFirstOccurance Then _rtns.Capacity = 1000 'could be larger. depends how many results you expect..
            Dim _mbi As MEMORY_BASIC_INFORMATION, _sysInfo As SYSTEM_INFO
            Dim _mbiSize As Int32 = Marshal.SizeOf(_mbi) ''size of memory_basic_region struct in bytes.
            GetSystemInfo(_sysInfo)
            Dim _addr As IntPtr = IntPtr.Zero 'counter/loop control.
            Dim _readBuff(_sysInfo.dwPageSize - 1) As Byte 'small buffer to read small mem regions
            Dim _bigBuff(0) As Byte 'large buffer to read large mem regions
            Dim _actualBytesRead As Int32 = 0 ''actual length of bytes copied during ReadProcessMemory()
            Dim _origPageProtection As UInt32 = 0 ''To preserve/restore original protection values
            Dim _hasAlreadyFoundOnce As Boolean = False
            Dim _oldProtects As String = "" 'displayed after errorrs. as string of bits.
            Do
                VirtualQueryEx(_targetProcessHandle, _addr, _mbi, _mbiSize)
                _oldProtects = ConvertMBIProtectToBinaryString(_mbi.Protect)
                If _mbi.State = MemoryAllocationState.Commit Then
                    If _mbi.Protect And MemoryAllocationProtectionType.PAGE_CANREAD Then 'bitmask check for any readable type
                        ''EASY READ
                        If _mbi.Protect And MemoryAllocationProtectionType.PAGE_GUARD Then
                            'DoOutput("avoided the guard at 0x" & _addr.ToString("X"))
                            GoTo badLabelSkipThisMemRegion 'BUT ITS GUARDED
                        End If
                    Else
                        ''CANT READ YET
                        If _mbi.Protect And MemoryAllocationProtectionType.PAGE_COPYFORWARD Then
                            ''CANT READ AT ALL (ignore non-readable copyforward unless you really* know what you're doing. usually fails anyway)
                            DoOutput("avoided OS managed file (dll?) at 0x" & _addr.ToString("X"))
                            GoTo badLabelSkipThisMemRegion
                        Else
                            ''Enable Read
                            If _mbi.Protect And MemoryAllocationProtectionType.PAGE_CANEXECUTE Then
                                'it should remain executable! 
                                If VirtualProtectEx(_targetProcessHandle, _mbi.BaseAddress, _mbi.RegionSize, MemoryAllocationProtectionType.PAGE_EXECUTE_READWRITE, _origPageProtection) Then
                                    'DoOutput("execPatching OK 0x" & _addr.ToString("X"))
                                Else
                                    DoOutput("SFBM() execPatching FAIL 0x" & _addr.ToString("X"))
                                    DoOutput("protect: " & _oldProtects)
                                    Threading.Thread.Sleep(2500)
                                    GoTo badLabelSkipThisMemRegion
                                End If
                            Else
                                If VirtualProtectEx(_targetProcessHandle, _mbi.BaseAddress, _mbi.RegionSize, MemoryAllocationProtectionType.PAGE_READWRITE, _origPageProtection) Then
                                    'DoOutput("readPatching OK 0x" & _mbi.BaseAddress.ToString("X"))
                                Else
                                    DoOutput("SFBM() readPatching FAIL 0x" & _mbi.BaseAddress.ToString("X"))
                                    DoOutput("protect: " & _oldProtects)
                                    Threading.Thread.Sleep(2500)
                                    GoTo badLabelSkipThisMemRegion
                                End If
                            End If
                        End If
                    End If
                    ''READ THE DATA
                    If _mbi.RegionSize.ToInt32 <= _sysInfo.dwPageSize Then '4096 bytes. 4kb. see windows memory management for info.
                        ''READ THE DATA. small region
                        If ReadProcessMemory(_targetProcessHandle, _mbi.BaseAddress, _readBuff, _mbi.RegionSize, _actualBytesRead) Then
                            If (_actualBytesRead <> _mbi.RegionSize) Then
                                'not able to read all data, handle gracefully. do nothing :)
                                modPublic.DoOutput("SFBM() RPM->ActualBytesRead too low! 0x" & _mbi.BaseAddress.ToString("X"))
                            Else
                                ''COMPARE VALUE                                      
                                For xx As Int32 = 0 To _mbi.RegionSize.ToInt32 - buff.Length 'todo:  align4?
                                    For yy As Int32 = 0 To buff.Length - 1
                                        If mask(yy) <> 0 Then
                                            If buff(yy) <> _readBuff(xx + yy) Then
                                                GoTo badLabelNoSuccess
                                            End If
                                        End If
                                    Next
                                    _rtns.Add(_addr.ToInt32 + xx)  'found it
                                    If returnOnFirstOccurance Then
                                        _hasAlreadyFoundOnce = True
                                        Exit For
                                    End If
    badLabelNoSuccess:
                                Next
                            End If
                        Else
                            modPublic.DoOutput("SFBM() RPM FAIL 0x" & _mbi.BaseAddress.ToString("X"))
                        End If
                    Else
                        ' large region                                     
                        _bigBuff = ReadLargeRamPage(_addr, _addr.ToInt32 + _mbi.RegionSize.ToInt32)
                        For xx As Int32 = 0 To _bigBuff.Length - buff.Length 'todo:  align4?
                            ''COMPARE VALUE 
                            For yy As Int32 = 0 To buff.Length - 1
                                If mask(yy) <> 0 Then
                                    If buff(yy) <> _bigBuff(xx + yy) Then
                                        GoTo badLabelNoMoreSuccess
                                    End If
                                End If
                            Next
                            _rtns.Add(_addr.ToInt32 + xx) 'found it
                            If returnOnFirstOccurance Then
                                _hasAlreadyFoundOnce = True
                                Exit For
                            End If
    badLabelNoMoreSuccess:
                        Next
                    End If ''end region size
                    '' RESTORE PROTECTION
                    If _origPageProtection Then
                        VirtualProtectEx(_targetProcessHandle, _mbi.BaseAddress, _mbi.RegionSize, _origPageProtection, _origPageProtection)
                        _origPageProtection = 0
                    End If
                    If _hasAlreadyFoundOnce AndAlso returnOnFirstOccurance Then Exit Do
                End If ''//state=committed
    badLabelSkipThisMemRegion:
                _addr = _mbi.BaseAddress.ToInt32 + _mbi.RegionSize.ToInt32 ''increment _addr to next region
            Loop While _addr.ToInt32 < _sysInfo.lpMaximumApplicationAddress
    
            If _rtns.Count = 0 Then _rtns.Add(IntPtr.Zero) 'pattern not found!
            Return _rtns.ToArray
        End Function
        ''' <summary>
        ''' Reads a region of ram (startAddress to stopAddress). CALLING code is responsible for checking memory_allocation_protection_type before calling this function.
        ''' </summary>
        ''' <param name="aStart">Beginning of scan range. (usually a memory_basic_information.BaseAddress, doesn't have to be).</param>
        ''' <param name="aStop">End of scan range. (usually memory_basic_information.BaseAddress + iSize, doesn't have to be) </param>
        ''' <returns></returns>
        ''' <remarks>Can span multiple regions, but caller should verity access rights first!</remarks>
        Private Function ReadLargeRamPage(ByVal aStart As IntPtr, ByVal aStop As IntPtr) As Byte()
            Dim _rtnBuffSize As Int32 = aStop.ToInt32 - aStart.ToInt32 'theoretical max size: may be smaller due to read failure
            Dim _returnByteBuff(_rtnBuffSize - 1) As Byte ' return results
            Dim _byteBuffCurrIndex As Int32 = 0 'counter
            Dim _readBuff(_systemInfo.dwPageSize - 1) As Byte 'temporary storage for ReadProcessMemory()
            Dim _actualBytesRead As Int32 = 0 '' actual length of bytes returned by ReadProcessMemory()
            Dim _curAddr As IntPtr = aStart
            Dim _sizeRemaining As Int32 = _rtnBuffSize '
            'start reading
            Do
                If _sizeRemaining >= _systemInfo.dwPageSize Then
                    If ReadProcessMemory(_targetProcessHandle, _curAddr, _readBuff, _systemInfo.dwPageSize, _actualBytesRead) Then
                        If (_actualBytesRead <> _systemInfo.dwPageSize) Then
                            ''not able to read entire area
                            If _actualBytesRead > 0 Then 'append what little data we did read
                                Array.Copy(_readBuff, 0, _returnByteBuff, _byteBuffCurrIndex, _actualBytesRead)
                                _byteBuffCurrIndex += _actualBytesRead
                            End If
                            modPublic.DoOutput("ReadLargeRamChunk() RPM->ActualBytesRead too low! 0x" & _curAddr.ToString("X"))
                        Else
                            Array.Copy(_readBuff, 0, _returnByteBuff, _byteBuffCurrIndex, _systemInfo.dwPageSize)
                            _byteBuffCurrIndex += _systemInfo.dwPageSize
                        End If
                    Else
                        modPublic.DoOutput("ReadLargeRamChunk() RPM->FAIL! 0x" & _curAddr.ToString("X"))
                    End If
                    _sizeRemaining -= _systemInfo.dwPageSize ' 
                Else
                    'almost at end of mem scan. 1 small piece left
                    If ReadProcessMemory(_targetProcessHandle, _curAddr, _readBuff, _sizeRemaining, _actualBytesRead) Then
                        If (_actualBytesRead <> _sizeRemaining) Then
                            'not able to read entire area
                            If _actualBytesRead > 0 Then 'append what little data we did read
                                Array.Copy(_readBuff, 0, _returnByteBuff, _byteBuffCurrIndex, _actualBytesRead)
                                _byteBuffCurrIndex += _actualBytesRead
                            End If
                            modPublic.DoOutput("ReadLargeRamChunk() RPM->ActualBytesRead too low! (final chunk) 0x" & _curAddr.ToString("X"))
                        Else
                            Array.Copy(_readBuff, 0, _returnByteBuff, _byteBuffCurrIndex, _sizeRemaining)
                            _byteBuffCurrIndex += _sizeRemaining
                        End If
                    Else
                        modPublic.DoOutput("ReadLargeRamChunk() RPM->FAIL! (final chunk!) 0x" & _curAddr.ToString("X"))
                    End If
                    _sizeRemaining = 0
                End If
                If _sizeRemaining = 0 Then Exit Do
                _curAddr = _curAddr.ToInt32 + _systemInfo.dwPageSize
            Loop
            If _byteBuffCurrIndex < _rtnBuffSize Then ' ie. actual_read_length < expected_read_length
                '_returnBuff was declared too large. Shrink it.
                ReDim Preserve _returnByteBuff(_byteBuffCurrIndex - 1) ' only occurs on read failures
            End If
            Return _returnByteBuff
        End Function
        ''' <summary>
        ''' Will return a string of 0's and 1's representing a uint32 value.
        ''' </summary>
        ''' <param name="mbiProtect">Protect value of MEMORY_BASIC_INFORMATION.</param>
        ''' <returns>Return string will be left-padded with 0's so that the final length of the string is a multiple of 8</returns>
        Private Function ConvertMBIProtectToBinaryString(ByVal mbiProtect As UInt32) As String
            ''only used for user output. easier to read if they're all 8-padded
            Dim _rtnStr As String = Convert.ToString(mbiProtect, 2) 'binary string
            Dim _padNeeded As Int32 = _rtnStr.Length Mod 8 'add padding if needed
            If _padNeeded <> 0 Then
                _padNeeded = 8 - _padNeeded
                _rtnStr = New String("0", _padNeeded) & _rtnStr '' .net has a string function .Pad(). o well, already made the code.
            End If
            Return _rtnStr
        End Function
    #End Region
    struct/enums maybe have posted in part 1. sry. descriptions taken from msdn.com
    Code:
    #Region "Structs/Enum"
        Private Structure SYSTEM_INFO
            Dim wrocessorArchitecture As Int16
            Dim wReserved As Int16
            Dim dwPageSize As Int32
            Dim lpMinimumApplicationAddress As Int32
            Dim lpMaximumApplicationAddress As Int32
            Dim dwActiveProcessorMask As Int32
            Dim dwNumberOfProcessors As Int32
            Dim dwProcessorType As Int32
            Dim dwAllocationGranularity As Int32
            Dim wProcessorLevel As Int16
            Dim wProcessorRevision As Int16
        End Structure
        Private Structure MEMORY_BASIC_INFORMATION
            Dim BaseAddress As IntPtr
            Dim AllocationBase As IntPtr
            Dim AllocationProtect As UInt32
            Dim RegionSize As IntPtr
            Dim State As UInt32
            ''' <summary>
            ''' See the MemoryAllocationProtectionType enum. for values
            ''' </summary>
            ''' <remarks>no remarks anywhere.</remarks>
            Dim Protect As UInt32
            Dim zType As UInt32
        End Structure
        Public Enum MemoryAllocationProtectionType As UInt32
            ''' <summary>
            ''' Disables all access to the committed region of pages. An attempt to read from, write to, or execute the committed region results in an access violation.
            ''' </summary>
            PAGE_NOACCESS = &H1             'ALWAYS LEAVE ALONE
            ''' <summary>
            ''' Enables read-only access to the committed region of pages. An attempt to write to the committed region results in an access violation.
            ''' </summary>
            PAGE_READONLY = &H2             'HACKRW
            ''' <summary>
            ''' Enables read-only or read/write access to the committed region of pages.
            ''' </summary>
            PAGE_READWRITE = &H4            'HACKRW
            ''' <summary>
            ''' Enables read-only or copy-on-write access to a mapped view of a file mapping object. An attempt to write to a committed copy-on-write page results in a private copy of the page being made for the process. 
            ''' </summary>
            PAGE_WRITECOPY = &H8            'DONT  phux with writeoncopy
            ''' <summary>
            ''' Enables execute access to the committed region of pages. An attempt to read from or write to the committed region results in an access violation. -microsof*****m
            ''' </summary>
            PAGE_EXECUTE = &H10             'HACKRW
            ''' <summary>
            ''' Enables execute or read-only access to the committed region of pages. An attempt to write to the committed region results in an access violation.
            ''' </summary>
            PAGE_EXECUTE_READ = &H20        'HACKRW 
            ''' <summary>
            ''' Enables execute, read-only, or read/write access to the committed region of pages.
            ''' </summary>
            PAGE_EXECUTE_READWRITE = &H40   'HACKRW
            ''' <summary>
            ''' Enables execute, read-only, or copy-on-write access to a mapped view of a file mapping object. An attempt to write to a committed copy-on-write page results in a private copy of the page being made for the process.
            ''' </summary>
            PAGE_EXECUTE_WRITECOPY = &H80   'DONT phux with writeoncopy
            ''' <summary>
            ''' Pages in the region become guard pages. Any attempt to access a guard page causes the system to raise a STATUS_GUARD_PAGE_VIOLATION exception and turn off the guard page status. Guard pages thus act as a one-time access alarm.
            ''' </summary>
            ''' 
            PAGE_GUARD = &H100              'HACKRW
            ''' <summary>
            ''' Sets all pages to be non-cachable. Applications should not use this attribute except when explicitly required for a device.
            ''' </summary>
            PAGE_NOCACHE = &H200
            ''' <summary>
            ''' Sets all pages to be write-combined.Applications should not use this attribute except when explicitly required for a device.
            ''' </summary>
            PAGE_WRITECOMBINE = &H400
            ''' <summary>
            ''' Allowed to call ReadProcessMemory() without needing VirtualProtectEx().
            ''' </summary>
            PAGE_CANREAD = PAGE_READONLY Or PAGE_READWRITE Or PAGE_WRITECOPY Or PAGE_EXECUTE_READ Or PAGE_EXECUTE_READWRITE Or PAGE_EXECUTE_WRITECOPY
            PAGE_CANEXECUTE = PAGE_EXECUTE Or PAGE_EXECUTE_READ Or PAGE_EXECUTE_READWRITE Or PAGE_EXECUTE_WRITECOPY
            PAGE_CANWRITE = PAGE_READWRITE Or PAGE_EXECUTE_READWRITE 'excludes 'copy on write' regions.
            ''' <summary>
            ''' Generally we should leave copy-forward memory alone, except maybe for reading. But only if it is originally marked as readable! Careful with VirtualProtectEx...it can/will fail, and/or cause misc. (memory related) bugs.
            ''' </summary>
            PAGE_COPYFORWARD = PAGE_WRITECOPY Or PAGE_EXECUTE_WRITECOPY Or PAGE_WRITECOMBINE
        End Enum
        Private Enum MemoryAllocationType As UInt32
            MEM_IMAGE = &H1000000
            MEM_MAPPED = &H40000
            MEM_PRIVATE = &H20000
        End Enum
        Private Enum MemoryAllocationState As UInt32
            Commit = &H1000
            Reserve = &H2000
            Decommit = &H4000
            Release = &H8000
            Reset = &H80000
            Physical = &H400000
            TopDown = &H100000
            WriteWatch = &H200000
            LargePages = &H20000000
        End Enum
        Private Enum ProcessAccessProtectionType As UInt32
            ''' <summary>
            ''' Required to terminate a process using TerminateProcess.
            ''' </summary>
            PROCESS_TERMINATE = &H1
            ''' <summary>
            ''' Required to create a thread.
            ''' </summary>
            ''' <remarks></remarks>
            PROCESS_CREATE_THREAD = &H2
            ''' <summary>
            ''' Required to perform an operation on the address space of a process (see VirtualProtectEx and WriteProcessMemory).
            ''' </summary>
            PROCESS_VM_OPERATION = &H8
            ''' <summary>
            ''' Required to read memory in a process using ReadProcessMemory.
            ''' </summary>
            PROCESS_VM_READ = &H10
            ''' <summary>
            ''' Required to read memory in a process using ReadProcessMemory.
            ''' </summary>
            PROCESS_VM_WRITE = &H20
            ''' <summary>
            ''' Required to duplicate a handle using DuplicateHandle.
            ''' </summary>
            PROCESS_DUP_HANDLE = &H40
            ''' <summary>
            ''' Required to create a process.
            ''' </summary>
            PROCESS_CREATE_PROCESS = &H80
            ''' <summary>
            ''' Required to set memory limits using SetProcessWorkingSetSize.
            ''' </summary>
            PROCESS_SET_QUOTA = &H100
            ''' <summary>
            ''' Required to set certain information about a process, such as its priority class (see SetPriorityClass).
            ''' </summary>
            PROCESS_SET_INFORMATION = &H200
            ''' <summary>
            ''' Required to retrieve certain information about a process, such as its token, exit code, and priority class (see OpenProcessToken).
            ''' </summary>
            PROCESS_QUERY_INFORMATION = &H400
            ''' <summary>
            ''' Required to suspend or resume a process.
            ''' </summary>
            PROCESS_SUSPEND_RESUME = &H800
            ''' <summary>
            ''' 	Required to retrieve certain information about a process (see GetExitCodeProcess, GetPriorityClass, IsProcessInJob, QueryFullProcessImageName). A handle that has the PROCESS_QUERY_INFORMATION access right is automatically granted PROCESS_QUERY_LIMITED_INFORMATION.
            ''' </summary>
            PROCESS_QUERY_LIMITED_INFORMATION = &H1000
            ''' <summary>
            ''' Required to wait for the process to terminate using the wait functions.
            ''' </summary>
            PROCESS_SYNCHRONIZE = &H100000
            ''' <summary>
            ''' Enables read/write to most of the process. Exclueds copyforward, non-readable regions. 
            ''' </summary>
            ''' <remarks></remarks>
            PROCESS_ALLACCESS = &H1F0FFF
        End Enum
    and of course the
    write functions
    Code:
        Public Function WriteByte(ByVal addr As IntPtr, ByVal aByte As Byte) As Boolean
            Return WriteProcessMemory(_targetProcessHandle, addr, New Byte() {aByte}, 1, vbNull) 'awk array decl :/
        End Function
        Public Function WriteInt16(ByVal addr As IntPtr, ByVal data As Int16) As Boolean
            Return WriteProcessMemory(_targetProcessHandle, addr, BitConverter.GetBytes(data), 2, vbNull)
        End Function
        Public Function WriteInt32(ByVal addr As IntPtr, ByVal data As Int32) As Boolean
            Return WriteProcessMemory(_targetProcessHandle, addr, BitConverter.GetBytes(data), 4, vbNull)
        End Function
        Public Function WriteInt64(ByVal addr As IntPtr, ByVal data As Int64) As Boolean
            Return WriteProcessMemory(_targetProcessHandle, addr, BitConverter.GetBytes(data), 8, vbNull)
        End Function
        Public Function WriteUInt16(ByVal addr As IntPtr, ByVal data As UInt16) As Boolean
            Return WriteProcessMemory(_targetProcessHandle, addr, BitConverter.GetBytes(data), 2, vbNull)
        End Function
        Public Function WriteUInt32(ByVal addr As IntPtr, ByVal data As UInt32) As Boolean
            Return WriteProcessMemory(_targetProcessHandle, addr, BitConverter.GetBytes(data), 4, vbNull)
        End Function
        Public Function WriteUInt64(ByVal addr As IntPtr, ByVal data As UInt64) As Boolean
            Return WriteProcessMemory(_targetProcessHandle, addr, BitConverter.GetBytes(data), 8, vbNull)
        End Function
        Public Function WriteFloat(ByVal addr As IntPtr, ByVal data As Single) As Boolean
            Return WriteProcessMemory(_targetProcessHandle, addr, BitConverter.GetBytes(data), 4, vbNull)
        End Function
        Public Function WriteDouble(ByVal addr As IntPtr, ByVal data As Double) As String
            Return WriteProcessMemory(_targetProcessHandle, addr, BitConverter.GetBytes(data), 8, vbNull)
        End Function
        Public Function WriteIntPtr(ByVal addr As IntPtr, ByVal ptr As IntPtr) As Boolean
            Dim _bytes(IntPtr.Size - 1) As Byte
    
            If IntPtr.Size = 4 Then
                _bytes = BitConverter.GetBytes(Convert.ToUInt32(ptr))
                Return WriteProcessMemory(_targetProcessHandle, addr, _bytes, 4, vbNull)
            Else
                _bytes = BitConverter.GetBytes(Convert.ToUInt64(ptr))
                Return WriteProcessMemory(_targetProcessHandle, addr, _bytes, 8, vbNull)
            End If
        End Function
        Public Function WriteUnicodeString(ByVal addr As IntPtr, ByVal str As String) As Boolean
            Dim _bytes() As Byte = System.Text.Encoding.Unicode.GetBytes(str)
            Return WriteProcessMemory(_targetProcessHandle, addr, _bytes, _bytes.Length, vbNull)
        End Function
        Public Function WriteAsciiString(ByVal addr As IntPtr, ByVal str As String) As Boolean
            Dim _bytes() As Byte = System.Text.Encoding.ASCII.GetBytes(str)
            Return WriteProcessMemory(_targetProcessHandle, addr, _bytes, _bytes.Length, vbNull)
        End Function
        Public Function WriteBytes(ByVal addr As IntPtr, ByVal bytes() As Byte) As Boolean
            Dim _writeLength As Int32 = 0
            If WriteProcessMemory(_targetProcessHandle, addr, bytes, bytes.Length, _writeLength) Then
                If _writeLength = bytes.Length Then
                    Return True
                Else
                    DoOutput("MemoryManager::WriteBytes() writeLength < buff.size")
                    Return False
                End If
            Else
                Return False 'wpm failed!
            End If
        End Function
    DoOutput() is just a public Sub. Just adds the (msg) to a multi-line text box. Debugging output basically, which I highly recomend for stuff like this.
    Code:
        Public Sub DoOutput(ByVal msg As String, Optional ByVal printTime As Boolean = True)
            If frmMain.txtOutput.TextLength > 5000 Then '' change 50k to something lower to consume less ram. 
                Dim _bracLoc As Int32 = frmMain.txtOutput.Text.IndexOf("[", 2500)
                'remove (about) the first 1/2 of the text, keeping the most recent messages.
                frmMain.txtOutput.Text = "******************" & Environment.NewLine & Mid(frmMain.txtOutput.Text, _bracLoc) ''append old msgs
            End If
            If printTime Then
                frmMain.txtOutput.AppendText("[" & Date.Now.ToString("h-m-s") & "]" & msg & Environment.NewLine)
            Else
                frmMain.txtOutput.AppendText(msg & Environment.NewLine)
            End If
    
            Application.DoEvents()
        End Sub
    'set displayTime = false for exact formatting (when seconds goes from 60 to 0, a jagged effect happens)
    'Don't credit me in your apps, I don't want to be associated with your 'hacks'. Including my name in the source
    'would be nice, but, as I found 1/2 of this info on google and made the other half up..all to the good.
    'I did work hard on ScanForBytes and FindPattern tho.

    If you have any (relevant) questions/comments, feel free.
    Last edited by abuckau907; 01-02-2013 at 02:49 AM.

  2. The Following 3 Users Say Thank You to abuckau907 For This Useful Post:

    DawgiiStylz (01-08-2013),elimabiru (08-11-2013),Paul (04-25-2013)

  3. #2
    Ell0ll's Avatar
    Join Date
    Dec 2012
    Gender
    male
    Posts
    62
    Reputation
    10
    Thanks
    4
    @abuckau907
    can you please write down an example
    how to use the scan method to scan full memory (of game) by value and list all addresses in a list box
    thanks
    Last edited by Ell0ll; 04-15-2013 at 04:16 PM.

  4. #3
    Ell0ll's Avatar
    Join Date
    Dec 2012
    Gender
    male
    Posts
    62
    Reputation
    10
    Thanks
    4
    Is there any one can answer my question ???

  5. #4
    abuckau907's Avatar
    Join Date
    Dec 2012
    Gender
    male
    Location
    other side of the wire
    Posts
    1,342
    Reputation
    162
    Thanks
    239
    My Mood
    Cold
    No. So stop asking. The code is right up there...

    Private Function ScanForBytes(ByVal byteBuff() As Byte, Optional ByVal returnOnFirstOccurance As Boolean = False) As IntPtr()

    [whybother]
    Code:
    Dim _rtnAddrs() As IntPtr
    
    Dim _myData() As Byte = {0x11, 0x22, 0x33, 0x44 } '' BitConvert class for converting primitive types to a byte array 
    
    _rtnAddrs = ScanForBytes(_myData,false) '' false = find every occurance
    
    ''That's it... to view the results maybe..
    
    For Each fcktrd as IntPtr In _rtnAddrs
    MsgBox("Result found at 0x" & fcktrd.ToString("X"))
    Next
    [/why]
    Last edited by abuckau907; 04-24-2013 at 01:26 AM.
    'Some things that can be counted, don't matter. And some things that matter, can't be counted' - A.E.
    --
     

    My posts have some inaccuracies/are wrong/wrong keyword(s) used.
    They're (maybe) pretty close, and I hope they helped you, not created confusion. Take with grain of salt.

    -if you give rep, please leave a comment, else it means less.

  6. The Following User Says Thank You to abuckau907 For This Useful Post:

    Ell0ll (04-24-2013)

  7. #5
    Ell0ll's Avatar
    Join Date
    Dec 2012
    Gender
    male
    Posts
    62
    Reputation
    10
    Thanks
    4
    Code:
    Private Sub Button9_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button9.Click
    
            Try
    
                Dim GaMe As Process() = Process.GetProcessesByName(TextBox19.Text)
    
                Dim pHandle As IntPtr = GaMe(0).Handle
    
                Dim _memManager As New RAMManager_32
    
                If _memManager.TryAttachToProcess(TextBox19.Text) Then
                    
                    'this is my value i want to scan for it
                    Dim MyInt16 As Integer = TextBox1.Text
    
                    Dim MyBytes As Byte() = BitConverter.GetBytes(MyInt16)
    
                    Dim result() As IntPtr = _memManager.ScanForBytes(MyBytes, False)
    
                    For Each Test As IntPtr In result
                        MsgBox("Result found at 0x" & Test.ToString("X"))
                    Next
                    ' Done using MemoryManager for reading. Close it.
                    _memManager.DetachFromProcess()
                    
                Else
                    MessageBox.Show("MemoryManager unable to attach to 3D Pinball for ram reading")
                End If
    
            Catch ex As Exception
    
            End Try
    
        End Sub
    nothing happened

  8. #6
    abuckau907's Avatar
    Join Date
    Dec 2012
    Gender
    male
    Location
    other side of the wire
    Posts
    1,342
    Reputation
    162
    Thanks
    239
    My Mood
    Cold
    and nothing will happen
    'Some things that can be counted, don't matter. And some things that matter, can't be counted' - A.E.
    --
     

    My posts have some inaccuracies/are wrong/wrong keyword(s) used.
    They're (maybe) pretty close, and I hope they helped you, not created confusion. Take with grain of salt.

    -if you give rep, please leave a comment, else it means less.

  9. #7
    Ell0ll's Avatar
    Join Date
    Dec 2012
    Gender
    male
    Posts
    62
    Reputation
    10
    Thanks
    4
    i knew that it is not working nothing of this class is working np i will try to find another way

  10. The Following User Says Thank You to Ell0ll For This Useful Post:

    abuckau907 (04-24-2013)

  11. #8
    abuckau907's Avatar
    Join Date
    Dec 2012
    Gender
    male
    Location
    other side of the wire
    Posts
    1,342
    Reputation
    162
    Thanks
    239
    My Mood
    Cold
    Catch ex As Exception
    MsgBox("Nothing happened")
    End Try

    maybe ask a specific question, or give a specific problem, not just "nothing happened." -- I thought that was common sense.


    Dim GaMe As Process() = Process.GetProcessesByName(TextBox19.Text)

    Dim pHandle As IntPtr = GaMe(0).Handle

    Game(0).Handle will throw an exception if TextBox19.Text wasn't a valid running process name. Was wondering why you had it in a try block.
    And the MyInt16 As Integer = .Text will be your next problem. GL.
    Last edited by abuckau907; 04-24-2013 at 03:56 AM.

  12. #9
    Ell0ll's Avatar
    Join Date
    Dec 2012
    Gender
    male
    Posts
    62
    Reputation
    10
    Thanks
    4
    Private Sub Button9_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button9.Click

    Dim _memManager As New RAMManager_32

    If _memManager.TryAttachToProcess(TextBox19.Text) Then

    Dim MyBytes As Byte() = BitConverter.GetBytes(1000)

    Dim result() As IntPtr = _memManager.ScanForBytes(MyBytes, False)

    For Each Test As IntPtr In result
    MsgBox("Result found at 0x" & Test.ToString("X"))
    Next
    ' Done using MemoryManager for reading. Close it.
    _memManager.DetachFromProcess()
    'MessageBox.Show("Your current 3D Pinball score is: " & _myScore.ToString())
    Else
    MessageBox.Show("MemoryManager unable to attach to 3D Pinball for ram reading")
    End If

    End Sub


    now this is the problem :

    Mixed mode assembly is built against another version of the runtime and cannot be loaded in the 4.0 runtime without additional configuration information.

  13. #10
    abuckau907's Avatar
    Join Date
    Dec 2012
    Gender
    male
    Location
    other side of the wire
    Posts
    1,342
    Reputation
    162
    Thanks
    239
    My Mood
    Cold
    Problem isn't in the code I posted...you probably added a reference to another memory library....one that uses fasm_managed maybe...

    You can create a new project and make it for .net framework 3.5 to remove the error.
    Last edited by abuckau907; 04-24-2013 at 10:00 PM.
    'Some things that can be counted, don't matter. And some things that matter, can't be counted' - A.E.
    --
     

    My posts have some inaccuracies/are wrong/wrong keyword(s) used.
    They're (maybe) pretty close, and I hope they helped you, not created confusion. Take with grain of salt.

    -if you give rep, please leave a comment, else it means less.

  14. The Following User Says Thank You to abuckau907 For This Useful Post:

    Ell0ll (04-26-2013)

  15. #11
    Ell0ll's Avatar
    Join Date
    Dec 2012
    Gender
    male
    Posts
    62
    Reputation
    10
    Thanks
    4
    Quote Originally Posted by abuckau907 View Post
    Problem isn't in the code I posted...you probably added a reference to another memory library....one that uses fasm_managed maybe...

    You can create a new project and make it for .net framework 3.5 to remove the error.
    Thanks

    it is working good but can you explain why i have to use .net framework 3.5

    and how to make this class work with .net framework 4.0

    or the problem is not in the class

    is the problem because of this dll > fasm_managed > so i need to change it

    or what to do exactly to to make my project work with .net framework 4.0

  16. #12
    abuckau907's Avatar
    Join Date
    Dec 2012
    Gender
    male
    Location
    other side of the wire
    Posts
    1,342
    Reputation
    162
    Thanks
    239
    My Mood
    Cold
    This is a tutorial, not a classroom. If you have questions, create a new post.
    I will not answer any more of your questions in this thread unless it's directly related to the code I posted.

    "is the problem because of this dll > fasm_managed > so i need to change it"
    TRY! Remove the reference to fasm_managed and see if the error goes away...
    Last edited by abuckau907; 04-26-2013 at 05:50 PM. Reason: Forgot a period. Pluralized question.
    'Some things that can be counted, don't matter. And some things that matter, can't be counted' - A.E.
    --
     

    My posts have some inaccuracies/are wrong/wrong keyword(s) used.
    They're (maybe) pretty close, and I hope they helped you, not created confusion. Take with grain of salt.

    -if you give rep, please leave a comment, else it means less.

Similar Threads

  1. [Tutorial] vb.net ReadProcessMemory part1
    By abuckau907 in forum Visual Basic Programming
    Replies: 12
    Last Post: 01-18-2013, 06:26 AM
  2. HackShardGaming.net says Fuck MPGH
    By sf0d in forum General
    Replies: 32
    Last Post: 07-26-2006, 09:05 PM
  3. [Help] Atom API with Visual Basic 6.0 or .NET
    By Bull3t in forum Visual Basic Programming
    Replies: 5
    Last Post: 07-23-2006, 09:21 AM
  4. Me r MAD.. GONNA DDOS WarRock.net :)
    By System79 in forum WarRock - International Hacks
    Replies: 14
    Last Post: 06-19-2006, 05:06 PM
  5. Gangsterhood.net
    By supatanka in forum Hack Requests
    Replies: 0
    Last Post: 01-22-2006, 01:42 PM