none
VB.NET - write NOP to Memeory RRS feed

  • Frage

  • Hallo Leute,

    Ich will einen Trainer schreiben in .NET, dazu habe ich auch ein "Reading Writing Memory Snippet"

    Bloß blöd wenn man es nicht ganz versteht was :(.

    Also die Funktion zum schreiben von NOPs sieht so aus:

    Public Sub WriteNOPs(ByVal ProcessName As String, ByVal Address As Long, ByVal NOPNum As Integer)
            Dim C As Integer
            Dim B As Integer
            If ProcessName.EndsWith(".exe") Then
                ProcessName = ProcessName.Replace(".exe", "")
            End If
            Dim MyP As Process() = Process.GetProcessesByName(ProcessName)
            If MyP.Length = 0 Then
                MessageBox.Show(ProcessName & " isn't open!")
                Exit Sub
            End If
            Dim hProcess As IntPtr = OpenProcess(PROCESS_ALL_ACCESS, 0, MyP(0).Id)
            If hProcess = IntPtr.Zero Then
                MessageBox.Show("Failed to open " & ProcessName & "!")
                Exit Sub
            End If
    
            B = 0
            For C = 1 To NOPNum
                Call WriteProcessMemory1(hProcess, Address + B, &H90, 1, 0&)
                B = B + 1
            Next C
        End Sub

    Vielleicht könnt ihr mir ja mal erklären wie ich diese Funktion anwenden muss.

    Wahrscheinlich muss es ja dann irgendwie so aussehen:

    WriteNOPs("Processname", "Adress")

    Wahrscheinlich liegt es daran das ich nicht weis wie die Funktion die Adresse haben will.

    Meine sieht so aus:

    'Process.exe+41FF70 - 66 89 30              - mov [eax],si

    Also müsste ja eigentlich die 41FF70 - 66 89 30 es sein.

    Hoffentlich könnt ihr mir helfen.

    Also schon mal Danke im voraus.




    • Bearbeitet Hans[VB] Freitag, 13. Februar 2015 08:09
    Freitag, 13. Februar 2015 08:07

Antworten

  • Hallo Hans,

    wie man "bescheisst" sollte man schon wissen, wenn man nicht selbst das Opfer werden will ;)

    Anfangen tut es damit, dass man weiß wie eine hexadezimale Zahl aussieht, mit der Visual Basic im übrigen als Konstante (&H41FF70) umgehen kann. Der Windows Taschenrechner kennt eine Programmierer-Ansicht, die eine Umrechnung erlaubt.

    Bevor Du blind überschreibst, solltest Du gucken, ob Du die gesuchten Opcodes an der Stelle vorfindest.

    Der obige (wer-weiss-wo zusammengesuchte und recht schlampige) Code scheint seine Wurzeln Visual Basic Classic Zeiten zu haben und die Declares wie Funktions-Argumente sind durchweg fehlerhaft - in .NET arbeitet man mit IntPtr für Adressen. Er wäre besser weg geworfen und in eine anständige Klasse mit Fehlerbehandlung (anstatt MessageBox) umgewandelt.

    Passende Declares sollten sich bei PInvoke.NET (wie ReadProcessMemory, WriteProcessMemory) finden lassen... Wer etwas sucht, findet komplette Klassen im Netz (die ich jetzt nicht nennen werde) - abseits der noch häufiger zu findenden "schrottigen".

    Ansonsten hatten wir das Thema hier schon ein, zwei Male u. a.:  Bitte nochmal um Hilfe bei ReadProcessMemory und WriteProcessMemory

    und zu den Problemen bei neuerem OS (Vista++) auf externe Prozesse zuzugreifen: In welchem Kontext ist Speicherschutz zu verstehen? Was heutzutage ohne (echte) Administrator-Rechte einen Zugriff recht schwierig (unmöglich) macht.

    Gruß Elmar

    Freitag, 13. Februar 2015 14:16
    Beantworter

Alle Antworten

  • Hallo Hans,

    Also mit den reinen VB.NET mitteln wirst du dieses Problem nicht Lösen können.

    Dazu müsstes du, mittels DLLImport zum Beispiel, eine native API aufrufen, die dir das Schreiben erlaubt. Solch eine API wäre z.B. WriteProcessMemory.

    Was auch wichtig ist, du musst höhere Rechte haben als dein Zielprozess.

    Kleiner Hinweis: Ich persönlich hätte die gesammten Hintergrundfunktionen des Trainers einfach in eine c++ Komponente ausgelagert:

    [ UI / VB.NET ] -> PInvoke -> [c++ Komponente] -> Win32API -> [Zielprozess]

     


    © 2015 Thomas Roskop

    Germany // Deutschland

    Freitag, 13. Februar 2015 09:22
  • Ist mir auch schon klar... wie gesagt ist das ja nur der ausschnitt wo ich nicht so ganz weis, wie ich die Adressen die er mit NOPs überschreiben soll übergeben muss. Ich kann dir ja auch mal das Komplette Snippet mal hier mit Senden. Und das ich dass ganze mit Armenrechten vollführen muss ist ja eigentlich auch klar.

    Jedenfalls hier mal das komplette Snippet.

    Module ReadWritingMemory
        Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Integer, ByVal bInheritHandle As Integer, ByVal dwProcessId As Integer) As Integer
    
        Private Declare Function WriteProcessMemory1 Lib "kernel32" Alias "WriteProcessMemory" (ByVal hProcess As Integer, ByVal lpBaseAddress As Integer, ByRef lpBuffer As Integer, ByVal nSize As Integer, ByRef lpNumberOfBytesWritten As Integer) As Integer
        Private Declare Function WriteProcessMemory2 Lib "kernel32" Alias "WriteProcessMemory" (ByVal hProcess As Integer, ByVal lpBaseAddress As Integer, ByRef lpBuffer As Single, ByVal nSize As Integer, ByRef lpNumberOfBytesWritten As Integer) As Single
        Private Declare Function WriteProcessMemory3 Lib "kernel32" Alias "WriteProcessMemory" (ByVal hProcess As Integer, ByVal lpBaseAddress As Integer, ByRef lpBuffer As Long, ByVal nSize As Integer, ByRef lpNumberOfBytesWritten As Integer) As Long
    
        Private Declare Function ReadProcessMemory1 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 Integer
        Private Declare Function ReadProcessMemory2 Lib "kernel32" Alias "ReadProcessMemory" (ByVal hProcess As Integer, ByVal lpBaseAddress As Integer, ByRef lpBuffer As Single, ByVal nSize As Integer, ByRef lpNumberOfBytesWritten As Integer) As Single
        Private Declare Function ReadProcessMemory3 Lib "kernel32" Alias "ReadProcessMemory" (ByVal hProcess As Integer, ByVal lpBaseAddress As Integer, ByRef lpBuffer As Long, ByVal nSize As Integer, ByRef lpNumberOfBytesWritten As Integer) As Long
    
        Const PROCESS_ALL_ACCESS = &H1F0FF
    
        Public Function WriteDMAInteger(ByVal Process As String, ByVal Address As Integer, ByVal Offsets As Integer(), ByVal Value As Integer, ByVal Level As Integer, Optional ByVal nsize As Integer = 4) As Boolean
            Try
                Dim lvl As Integer = Address
                For i As Integer = 1 To Level
                    lvl = ReadInteger(Process, lvl, nsize) + Offsets(i - 1)
                Next
                WriteInteger(Process, lvl, Value, nsize)
                Return True
            Catch ex As Exception
                Return False
            End Try
        End Function
    
        Public Function ReadDMAInteger(ByVal Process As String, ByVal Address As Integer, ByVal Offsets As Integer(), ByVal Level As Integer, Optional ByVal nsize As Integer = 4) As Integer
            Try
                Dim lvl As Integer = Address
                For i As Integer = 1 To Level
                    lvl = ReadInteger(Process, lvl, nsize) + Offsets(i - 1)
                Next
                Dim vBuffer As Integer
                vBuffer = ReadInteger(Process, lvl, nsize)
                Return vBuffer
            Catch ex As Exception
    
            End Try
        End Function
    
        Public Function WriteDMAFloat(ByVal Process As String, ByVal Address As Integer, ByVal Offsets As Integer(), ByVal Value As Single, ByVal Level As Integer, Optional ByVal nsize As Integer = 4) As Boolean
            Try
                Dim lvl As Integer = Address
                For i As Integer = 1 To Level
                    lvl = ReadFloat(Process, lvl, nsize) + Offsets(i - 1)
                Next
                WriteFloat(Process, lvl, Value, nsize)
                Return True
            Catch ex As Exception
                Return False
            End Try
        End Function
    
        Public Function ReadDMAFloat(ByVal Process As String, ByVal Address As Integer, ByVal Offsets As Integer(), ByVal Level As Integer, Optional ByVal nsize As Integer = 4) As Single
            Try
                Dim lvl As Integer = Address
                For i As Integer = 1 To Level
                    lvl = ReadFloat(Process, lvl, nsize) + Offsets(i - 1)
                Next
                Dim vBuffer As Single
                vBuffer = ReadFloat(Process, lvl, nsize)
                Return vBuffer
            Catch ex As Exception
    
            End Try
        End Function
    
        Public Function WriteDMALong(ByVal Process As String, ByVal Address As Integer, ByVal Offsets As Integer(), ByVal Value As Long, ByVal Level As Integer, Optional ByVal nsize As Integer = 4) As Boolean
            Try
                Dim lvl As Integer = Address
                For i As Integer = 1 To Level
                    lvl = ReadLong(Process, lvl, nsize) + Offsets(i - 1)
                Next
                WriteLong(Process, lvl, Value, nsize)
                Return True
            Catch ex As Exception
                Return False
            End Try
        End Function
    
        Public Function ReadDMALong(ByVal Process As String, ByVal Address As Integer, ByVal Offsets As Integer(), ByVal Level As Integer, Optional ByVal nsize As Integer = 4) As Long
            Try
                Dim lvl As Integer = Address
                For i As Integer = 1 To Level
                    lvl = ReadLong(Process, lvl, nsize) + Offsets(i - 1)
                Next
                Dim vBuffer As Long
                vBuffer = ReadLong(Process, lvl, nsize)
                Return vBuffer
            Catch ex As Exception
    
            End Try
        End Function
    
        Public Sub WriteNOPs(ByVal ProcessName As String, ByVal Address As Long, ByVal NOPNum As Integer)
            Dim C As Integer
            Dim B As Integer
            If ProcessName.EndsWith(".exe") Then
                ProcessName = ProcessName.Replace(".exe", "")
            End If
            Dim MyP As Process() = Process.GetProcessesByName(ProcessName)
            If MyP.Length = 0 Then
                MessageBox.Show(ProcessName & " isn't open!")
                Exit Sub
            End If
            Dim hProcess As IntPtr = OpenProcess(PROCESS_ALL_ACCESS, 0, MyP(0).Id)
            If hProcess = IntPtr.Zero Then
                MessageBox.Show("Failed to open " & ProcessName & "!")
                Exit Sub
            End If
    
            B = 0
            For C = 1 To NOPNum
                Call WriteProcessMemory1(hProcess, Address + B, &H90, 1, 0&)
                B = B + 1
            Next C
        End Sub
    
        Public Sub WriteXBytes(ByVal ProcessName As String, ByVal Address As Long, ByVal Value As String)
            If ProcessName.EndsWith(".exe") Then
                ProcessName = ProcessName.Replace(".exe", "")
            End If
            Dim MyP As Process() = Process.GetProcessesByName(ProcessName)
            If MyP.Length = 0 Then
                MessageBox.Show(ProcessName & " isn't open!")
                Exit Sub
            End If
            Dim hProcess As IntPtr = OpenProcess(PROCESS_ALL_ACCESS, 0, MyP(0).Id)
            If hProcess = IntPtr.Zero Then
                MessageBox.Show("Failed to open " & ProcessName & "!")
                Exit Sub
            End If
    
            Dim C As Integer
            Dim B As Integer
            Dim D As Integer
            Dim V As Byte
    
            B = 0
            D = 1
            For C = 1 To Math.Round((Len(Value) / 2))
                V = Val("&H" & Mid$(Value, D, 2))
                Call WriteProcessMemory1(hProcess, Address + B, V, 1, 0&)
                B = B + 1
                D = D + 2
            Next C
    
        End Sub
    
        Public Sub WriteInteger(ByVal ProcessName As String, ByVal Address As Integer, ByVal Value As Integer, Optional ByVal nsize As Integer = 4)
            If ProcessName.EndsWith(".exe") Then
                ProcessName = ProcessName.Replace(".exe", "")
            End If
            Dim MyP As Process() = Process.GetProcessesByName(ProcessName)
            If MyP.Length = 0 Then
                MessageBox.Show(ProcessName & " isn't open!")
                Exit Sub
            End If
            Dim hProcess As IntPtr = OpenProcess(PROCESS_ALL_ACCESS, 0, MyP(0).Id)
            If hProcess = IntPtr.Zero Then
                MessageBox.Show("Failed to open " & ProcessName & "!")
                Exit Sub
            End If
    
            Dim hAddress, vBuffer As Integer
            hAddress = Address
            vBuffer = Value
            WriteProcessMemory1(hProcess, hAddress, CInt(vBuffer), nsize, 0)
        End Sub
    
        Public Sub WriteFloat(ByVal ProcessName As String, ByVal Address As Integer, ByVal Value As Single, Optional ByVal nsize As Integer = 4)
            If ProcessName.EndsWith(".exe") Then
                ProcessName = ProcessName.Replace(".exe", "")
            End If
            Dim MyP As Process() = Process.GetProcessesByName(ProcessName)
            If MyP.Length = 0 Then
                MessageBox.Show(ProcessName & " isn't open!")
                Exit Sub
            End If
            Dim hProcess As IntPtr = OpenProcess(PROCESS_ALL_ACCESS, 0, MyP(0).Id)
            If hProcess = IntPtr.Zero Then
                MessageBox.Show("Failed to open " & ProcessName & "!")
                Exit Sub
            End If
    
            Dim hAddress As Integer
            Dim vBuffer As Single
    
            hAddress = Address
            vBuffer = Value
            WriteProcessMemory2(hProcess, hAddress, vBuffer, nsize, 0)
        End Sub
    
        Public Sub WriteLong(ByVal ProcessName As String, ByVal Address As Integer, ByVal Value As Long, Optional ByVal nsize As Integer = 4)
            If ProcessName.EndsWith(".exe") Then
                ProcessName = ProcessName.Replace(".exe", "")
            End If
            Dim MyP As Process() = Process.GetProcessesByName(ProcessName)
            If MyP.Length = 0 Then
                MessageBox.Show(ProcessName & " isn't open!")
                Exit Sub
            End If
            Dim hProcess As IntPtr = OpenProcess(PROCESS_ALL_ACCESS, 0, MyP(0).Id)
            If hProcess = IntPtr.Zero Then
                MessageBox.Show("Failed to open " & ProcessName & "!")
                Exit Sub
            End If
    
            Dim hAddress As Integer
            Dim vBuffer As Long
    
            hAddress = Address
            vBuffer = Value
            WriteProcessMemory3(hProcess, hAddress, vBuffer, nsize, 0)
        End Sub
    
        Public Function ReadInteger(ByVal ProcessName As String, ByVal Address As Integer, Optional ByVal nsize As Integer = 4) As Integer
            If ProcessName.EndsWith(".exe") Then
                ProcessName = ProcessName.Replace(".exe", "")
            End If
            Dim MyP As Process() = Process.GetProcessesByName(ProcessName)
            If MyP.Length = 0 Then
                MessageBox.Show(ProcessName & " isn't open!")
                Exit Function
            End If
            Dim hProcess As IntPtr = OpenProcess(PROCESS_ALL_ACCESS, 0, MyP(0).Id)
            If hProcess = IntPtr.Zero Then
                MessageBox.Show("Failed to open " & ProcessName & "!")
                Exit Function
            End If
    
            Dim hAddress, vBuffer As Integer
            hAddress = Address
            ReadProcessMemory1(hProcess, hAddress, vBuffer, nsize, 0)
            Return vBuffer
        End Function
    
        Public Function ReadFloat(ByVal ProcessName As String, ByVal Address As Integer, Optional ByVal nsize As Integer = 4) As Single
            If ProcessName.EndsWith(".exe") Then
                ProcessName = ProcessName.Replace(".exe", "")
            End If
            Dim MyP As Process() = Process.GetProcessesByName(ProcessName)
            If MyP.Length = 0 Then
                MessageBox.Show(ProcessName & " isn't open!")
                Exit Function
            End If
            Dim hProcess As IntPtr = OpenProcess(PROCESS_ALL_ACCESS, 0, MyP(0).Id)
            If hProcess = IntPtr.Zero Then
                MessageBox.Show("Failed to open " & ProcessName & "!")
                Exit Function
            End If
    
            Dim hAddress As Integer
            Dim vBuffer As Single
    
            hAddress = Address
            ReadProcessMemory2(hProcess, hAddress, vBuffer, nsize, 0)
            Return vBuffer
        End Function
    
        Public Function ReadLong(ByVal ProcessName As String, ByVal Address As Integer, Optional ByVal nsize As Integer = 4) As Long
            If ProcessName.EndsWith(".exe") Then
                ProcessName = ProcessName.Replace(".exe", "")
            End If
            Dim MyP As Process() = Process.GetProcessesByName(ProcessName)
            If MyP.Length = 0 Then
                MessageBox.Show(ProcessName & " isn't open!")
                Exit Function
            End If
            Dim hProcess As IntPtr = OpenProcess(PROCESS_ALL_ACCESS, 0, MyP(0).Id)
            If hProcess = IntPtr.Zero Then
                MessageBox.Show("Failed to open " & ProcessName & "!")
                Exit Function
            End If
    
            Dim hAddress As Integer
            Dim vBuffer As Long
    
            hAddress = Address
            ReadProcessMemory3(hProcess, hAddress, vBuffer, nsize, 0)
            Return vBuffer
        End Function
    
    End Module
    Da es ja sehr Lang ist wollte ich das eigentlich nicht Komplett hier einfügen, da es ja eh nur um die eine Funktion ging.


    • Bearbeitet Hans[VB] Freitag, 13. Februar 2015 11:28
    Freitag, 13. Februar 2015 11:27
  • Hallo Hans,

    wie man "bescheisst" sollte man schon wissen, wenn man nicht selbst das Opfer werden will ;)

    Anfangen tut es damit, dass man weiß wie eine hexadezimale Zahl aussieht, mit der Visual Basic im übrigen als Konstante (&H41FF70) umgehen kann. Der Windows Taschenrechner kennt eine Programmierer-Ansicht, die eine Umrechnung erlaubt.

    Bevor Du blind überschreibst, solltest Du gucken, ob Du die gesuchten Opcodes an der Stelle vorfindest.

    Der obige (wer-weiss-wo zusammengesuchte und recht schlampige) Code scheint seine Wurzeln Visual Basic Classic Zeiten zu haben und die Declares wie Funktions-Argumente sind durchweg fehlerhaft - in .NET arbeitet man mit IntPtr für Adressen. Er wäre besser weg geworfen und in eine anständige Klasse mit Fehlerbehandlung (anstatt MessageBox) umgewandelt.

    Passende Declares sollten sich bei PInvoke.NET (wie ReadProcessMemory, WriteProcessMemory) finden lassen... Wer etwas sucht, findet komplette Klassen im Netz (die ich jetzt nicht nennen werde) - abseits der noch häufiger zu findenden "schrottigen".

    Ansonsten hatten wir das Thema hier schon ein, zwei Male u. a.:  Bitte nochmal um Hilfe bei ReadProcessMemory und WriteProcessMemory

    und zu den Problemen bei neuerem OS (Vista++) auf externe Prozesse zuzugreifen: In welchem Kontext ist Speicherschutz zu verstehen? Was heutzutage ohne (echte) Administrator-Rechte einen Zugriff recht schwierig (unmöglich) macht.

    Gruß Elmar

    Freitag, 13. Februar 2015 14:16
    Beantworter
  • Ja ja schon gut...

    Das der Code von Oben nicht der neuste ist, ist mir auch schon Klar(sieht man ja schon an messagebox.Show statt einfach nur msgbox)

    Und Oh Gott ich schlaf gleich ein, ich will ja nicht unhöflich sein, aber dir sollte schon klar sein dass ich dass auch schon längst weiß. Aber eigentlich Danke für den Tipp das ich die Adresse ja auch Hex. einfügen kann. :D

    Und was passiert wenn ich die OP-Codes überschreibe weis ich ja auch. Ich habe sie mir ja schließlich selbst mit CE aus dem Game rausgesucht.

    Aber trotzdem Danke für den Tipp :D

    Freitag, 13. Februar 2015 15:22
  • Hallo Hans,

    was Du weißt, kann ich nicht wissen - und die Zweifel steigen, wenn jemand MsgBox (VB Classic) für neuer als MessageBox.Show hält und zum ersten Male mit einer Hexzahl in Kontakt kommt.

    Trotz allem, ich wünsche Dir viel Glück, etwas Schlaf und wenige Abstürze ;)

    Gruß Elmar

    Freitag, 13. Februar 2015 15:52
    Beantworter
  • Hallo Hans,

    Das der Code von Oben nicht der neuste ist, ist mir auch schon Klar(sieht man ja schon an messagebox.Show statt einfach nur msgbox)

    Und Oh Gott ich schlaf gleich ein, ich will ja nicht unhöflich sein, aber dir sollte schon klar sein dass ich dass auch schon längst weiß.

    ich sehe das wie Elmar und denke ebenfalls, dass Du doch nicht so wirklich weißt, von was Du sprichst. Das ist natürlich keinesfalls schlimm aber Du solltest noch mal ganz tief in dich gehen und überlegen, ob deine doch etwas überhebliche Antwort wirklich sinnvoll ist und ob Du die Tipps von Elmar nicht vielleicht doch berücksichtigen willst.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community

    Freitag, 13. Februar 2015 15:58
    Moderator