Laden...

WriteProcessMemory: Wert wird nicht geschrieben

Letzter Beitrag vor 12 Jahren 9 Posts 1.494 Views
WriteProcessMemory: Wert wird nicht geschrieben

Hallo c#-Community,

ich habe ein kleines Problem beim Ersetzen eines Wertes mit WriteProcessMemory. Aber mal von Anfang an, Ich lese einen Wert im Speicher aus über:


 // funktioniert!
 byte[] bytes = new byte[4];
 uint size = sizeof(int);
 ReadProcessMemory(readHandle, (IntPtr)Adress, bytes, (UIntPtr)size, ref rw);
 TextBox.Text = BitConverter.ToInt32(bytes, 0).ToString();

Jetzt möchte ich diesen Wert ersetzen und habe folgendes programmiert:


byte[] bytes = new byte[4];
                int calcvalue = Convert.ToInt32(TextBox.Text);
                if (calcvalue >= 16777216)
                {
                    bytes[3] = Convert.ToByte(calcvalue / 16777216);
                    calcvalue = calcvalue % 16777216;
                }
                if (calcvalue >= 65536)
                {
                    bytes[2] = Convert.ToByte(calcvalue / 65536);
                    calcvalue = calcvalue % 65536;
                }
                if (calcvalue >= 256)
                {
                    bytes[1] = Convert.ToByte(calcvalue / 256);
                    calcvalue = calcvalue % 256;
                }
                bytes[0] = Convert.ToByte(calcvalue);
                Console.WriteLine(TextBoxPoints.Text = bytes[0].ToString() + "  " + bytes[1].ToString() + "  " + bytes[2].ToString() + "  " + bytes[3].ToString());
                uint size = sizeof(int);
                WriteProcessMemory(readHandle, (IntPtr)Adress, bytes, (UIntPtr)size, ref rw);

Die Umwandlung erfolgt korrekt. In bytes steht am Ende was ich erwarte, nur anscheinend wird das nicht in den Speicher geschrieben. Kann mir jemand sagen, wo mein Fehler liegt?

Vielen Dank
mirrowwinger

  1. Du musst entsprechende Schreibrechte haben. Evtl. also zuerst VirtualProtectEx aufrufen.
  2. Mit GetLastError kannst du rausfinden, was bei WriteProcessMemory schiefgegangen ist.

Also ich habe jetzt mal Admin-Rechte nach dem Tutorial Anwendung mit Administratorrechten neu starten (Windows Vista / 7) angefordert und das funktioniert auch. Weiterhin habe ich mir die Marshal.GetLastWin32Error in der Console ausgeben lassen. Als Wert habe ich bei 4Byte 10000 genommen. Als Consolen-Ausgabe habe ich

16 39 0 0
0

erhalten.

Die erste Zahl ist die erwartete Umwandlung von 10000 in den erwarteten HexCode (ist richtig) und 0 der Fehlercode. Obwohl mir das anscheinend sagt, dass der Speicher erfolgreich beschrieben wurde, steht der Wert 10000 nicht an der Stelle (Überprüft mit ReadProcessMemory).

Ich denke du musst noch SeDebugPrivilege auf Remote Process aktivieren. Da sind noch ein paar Beispiele für dich sehr hilfreich

Hacking Minesweeper and Beating DMA

How to enable SeDebugPrivilege?

Hmm werde ich mir mal anschauen. Komischer Weise kann ich mit CE direkt in die Addresse schreiben. Ok natürlich weiß ich nicht, ob die auch die SeDebugPrivilege für den Remote Process setzen.

Also habe mir jetzt nach dem Tutorial die SeDebugPrivilege geholt. Leider hat sich immer noch keine Verbesserung eingestellt.


Process[] process = Process.GetProcessesByName("ProcessName");
            if (process.Length != 0)
            {
                Timer.Start();
                WorkProcess = process[0];
                readHandle = OpenProcess(0x10, false, (uint)WorkProcess.Id);
            }
            else
            {
                MessageBox.Show("No Success", "Process dosn´t exist", MessageBoxButtons.OK);
                this.Close();
            }
            if (!OpenProcessToken(WorkProcess.Handle, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, out hToken))
            {
                Console.WriteLine("OpenProcessToken() failed, error = {0} . SeDebugPrivilege is not available", Marshal.GetLastWin32Error());
                return;
            }
            else
            {
                Console.WriteLine("OpenProcessToken() successfully");
            }
            if (!LookupPrivilegeValue(null, SE_DEBUG_NAME, out luidSEDebugNameValue))
            {
                Console.WriteLine("LookupPrivilegeValue() failed, error = {0} .SeDebugPrivilege is not available", Marshal.GetLastWin32Error());
                CloseHandle(hToken);
                Environment.Exit(0);
            }
            else
            {
                Console.WriteLine("LookupPrivilegeValue() successfully");
            }
            tkpPrivileges.PrivilegeCount = 1;
            tkpPrivileges.Luid = luidSEDebugNameValue;
            tkpPrivileges.Attributes = SE_PRIVILEGE_ENABLED;

            if (!AdjustTokenPrivileges(hToken, false, ref tkpPrivileges, 0, IntPtr.Zero, IntPtr.Zero))
            {
                Console.WriteLine("LookupPrivilegeValue() failed, error = {0} .SeDebugPrivilege is not available", Marshal.GetLastWin32Error());
            }
            else
            {
                Console.WriteLine("SeDebugPrivilege is now available");
            }

Gemäß Konsole wird die SeDebugPrivilege aktiviert.

Hast du VirtualProtectEx probiert? Das ist bei einigen Speicherbereichen auf jeden Fall nötig.

Also die meisten Werte schreibe ich jetzt korrekt. SeDebugPrivilege hat also funktioniert. Der letzt Fehler lag in der Verwendung eines falschen Handles in der WriteProcessMemory-Funktion.
Nur bei einem Wert kommt es zu einer kuriosen Situation. Es wird zwar in die entsprechende Adresse geschrieben und der Wert wird bis zur nächsten Änderung so angezeigt, wie ich das will. ABER bei der nächsten Änderung des Wertes ändert sich der Wert in der Anzeige des Programms wieder.

Ja dann änderst du den Wert vielleicht an der falschen Stelle und das Programm hält den Wert noch woanders vor...