# Speicheradresse mit neuem Wert füllen



## glnklein (6. Juni 2010)

hallo , also erstmal ich bin noch TOTALER anfänger mit c++ und bin gerade erst dabei die ganzen funktionen zu lernen , 

ich bin nicht so der Bücherwurm sondern eher* Learning by Doing* hab so auch schon einiges gelernt nur zu diesem thema oder auch zu c++  algemein muss
man leider nach guten hilfen viel suchen , (PHP war da einfacher)


*nun meine frage *

Ich habe einen Speicheradresse sagen wir mal *0x07250340*     diese hat  jetzt den wert  *5*   nun möchte ich mit c++ den wert ändern  sagen wir einfach in  *6* .

kann mir einer kurz erklären oder zeigen wie das geht ich habe schon einige tut durchgeschaut aber leider keine anleitung gefunden die wirklich so ein thema behandelt , 

*danke*


----------



## Endurion (6. Juni 2010)

Hast du ein Problem mit der Syntax?

Die direkte Version:

unsigned char*  pPointer = 0x07250340;
*pPointer = 6;


Allerdings sind die Zeiten andere geworden. Du kannst nicht wild im Speicher rumpörkeln. Der Bereich, auf den der Pointer zeigt, ist besser deiner und beschreibbar. Sonst musst du mit lustigen Effekten wie Abstürzen rechnen.


----------



## glnklein (6. Juni 2010)

ja irgentwie stimt mit dem syntax was nicht wen ich deinen benutze 


```
#include<iostream>


    
    unsigned char* pPointer = 0x07250340;
*pPointer = 6;
```

bekomme ich folgende fehler 

*zeile 5 C:\Dev-Cpp\Unbenannt1.cpp invalid conversion from `int' to `unsigned char*' 
zeile 6 C:\Dev-Cpp\Unbenannt1.cpp expected constructor, destructor, or type conversion before '=' token 
zeile 6 C:\Dev-Cpp\Unbenannt1.cpp expected `,' or `;' before '=' token *


ich dachte es geht so : 



```
#include<iostream>
   

    int main()
    {
     int *i_ptr = (int*)(0x07250340);
*i_ptr = 5;
    }
```

doch das geht auch nicht da stürzt es nur ab 

weist du was da falsch ist  ?


----------



## timestamp (6. Juni 2010)

glnklein hat gesagt.:


> doch das geht auch nicht da stürzt es nur ab
> 
> weist du was da falsch ist  ?



Was meinst du mit abstürzen? Wenn das alles ist, was dein Programm macht, dann dauert die Ausführung weniger als 1 Sekunde. Setze mal ein 

```
system("PAUSE");
```
dahinter.


----------



## glnklein (6. Juni 2010)

ich habso gemacht 



```
#include<iostream>
   

    int main()
    {
     int *i_ptr = (int*)(0x07250340);
     system("PAUSE");
*i_ptr = 5;

    };
```

und bekomme wieder einen absturz   die adresse ist aber richtig 

bildabsturz:


----------



## sheel (6. Juni 2010)

Was heißt das, die Adresse ist richtig?
Was soll denn das für eine Adresse sein?

Wie Endurion schon gesagt hat, verwindert Windows, dass du einfach so in den Speicher von anderen Programmen etc hineinschreibst.
Du kannst nur auf Speicher zugreifen, der dir auch gehört


----------



## glnklein (6. Juni 2010)

äHHHHHHHHHH WAS  mir gehören was meints du den damit 

also das program was diesen speicher benutz ist auf meinem rechner drauf und ist gestartet  wenn du das meinst     

und wenn ich mir den speicherbereich ansehe hat er derzeit einen wert von 5 und nun mmöchte ich den bereich ersetzen durch einen wertt von 6 das ist was ich vor habe fang ich das falsch an ?


----------



## sheel (6. Juni 2010)

Damit meine ich, der Speicherbereich, den du ändern willst,
muss nicht nur in deinem Computer sein, sondern auch *zu dem Programm gehören, das ihn ändern will*
In DOS-Zeiten hat man zwar den genzen RAM nach belieben beschreiben können, aber das ist bei der heutigen Virenverbreitung ziemlich undenkbar.
Windows hat inzwischen einen Schutzmechanismus, das ein Programm eben nur seinen eigenen, zugeteilten Speicherbereich bearbeiten darf.


----------



## glnklein (6. Juni 2010)

ok 
kann es sein das ich mich dan falsch ausgedrückt habe dann nochmal von vorne 

also ich habe das spiel solitär und die adresse *0x0045A394 * ist bei mir für den punktestand zuständig dieser ist jetzt 10 
nun möchte ich  c++ den wert auf 300 ändern , also das ich 300 punkte habe , das müste doch gehen oder  und wen ja wie ,weis das jemand 

könnte mir da jemand einen kleinen code geben das ich das mal testen kann ?


----------



## glnklein (6. Juni 2010)

So also ich hab es nun geschaft zumindest funktioniert es 

mein Code 


```
#include <stdio.h>
#include <iostream>

using namespace std;

int main()
{            
    cout << "neuer wert? ";
    int wert;
    cin>>wert;     
    
   
   
 

                 
    cout << "\nwert schreiben ?\n\n0=Nein 1=JA ";
    int eingabe;
    cin>>eingabe;     
    if(eingabe==0)
    {
                  return 0;
    }
  
    HWND window = NULL;
    while(window == NULL)
    {
                  Sleep(100);
                  window = FindWindow(NULL, "Solitär");
    }
    DWORD prozess;
    GetWindowThreadProcessId(window, &prozess);
    HANDLE handle;
    handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, prozess);
    DWORD puffer = NULL;
  
         switch(eingabe)
    {
    case 1:
        WriteProcessMemory(handle,(void*)(0x0045A394),&wert,6,&puffer);

        break;
  
 
     
    CloseHandle(handle);  
    
    
} 
return 0;   
}
```


könnte einer der ahnung hat mal drüberschauen und mir sagen ob das so alles sauber ist oder ob fehler drin sind ?

danke


----------



## ComFreek (6. Juni 2010)

Willst du etwa dein Spielstand ändern und sozusagen schummeln?


----------



## timestamp (6. Juni 2010)

ComFreek hat gesagt.:


> Willst du etwa dein Spielstand ändern und sozusagen schummeln?



Ja das will er. Also irgendwie finde ich das ziemlich arm. :-(


----------



## glnklein (6. Juni 2010)

das war nur ein test mit Solitär weil hier im forum viele das spiel solitär nehmen dachte ich das währe so der standart 


ich will in einem spiel die mindestzahl der spieler heraufsetzen nicht schummeln   

Stimmt mein code den jetzt so oder ist der müll ?


----------



## Pain-maker (6. Juni 2010)

Vielleicht kann mich ja mal jemand korrigieren, wenn ich falsch liege, aber ich bezweifel, dass das immer funktioniert.
Ich vermute mal, dass das unter Windows passiert und da sollte eigentlich der Speicherschutz greifen und den Zugriff auf den fremden Bereich verbieten, oder?!
Oder wird durch "OpenProcess()" automatisch der Zugriff daruf erlaubt?
Und noch was: Die Adresse kann theoretisch immer wieder eine andere sein, je nach dem wie das OS gerade den virtuellen Speicher zugewiesen hat, oder?


----------



## ComFreek (6. Juni 2010)

Pain-maker hat gesagt.:


> Und noch was: Die Adresse kann theoretisch immer wieder eine andere sein, je nach dem wie das OS gerade den virtuellen Speicher zugewiesen hat, oder?


Dachte ich auch. Ich habe das kurz ausprobiert, es ist immer die selbe Adresse, zumindest bei meinem Programm.

Ach ja, habe kurz dein Programm ausprobiert (natürlich mit Solitär im Hintergrund), aber es funktioniert nicht.


----------



## Pain-maker (6. Juni 2010)

Dann start mal deinen Rechner neu und machs dann nochmal.
Du arbeitest ja immer nur in einem virtuellen vom OS bereitsgestellten Speicherbereich. Wenn du dein Programm immer wieder startest wird die in der Regel der gleiche Bereich wieder zugeteilt, sofern nicht ein anderes Programm diesen bereits eingenommen hat.

Aber spätestens nach einem Neustart sollte das anders sein...


----------



## ComFreek (6. Juni 2010)

Werde es gleich mal ausprobieren
Schreibe dann hier rein.


----------



## sheel (6. Juni 2010)

So wie er es geschrieben hat, gehts schon.
Allerdings muss die Adresse wirklich nicht immer gleich sein.
Es gibt sogar Spiele, die extra zum Verhindern von solchen Eingriffen regelmäßig ihre Variablen woanders ablagern

Mit dem Solitär von Windows wirds zwar wahrscheinlich keine Probleme geben;
für welches Spiel willst du es denn dann verwenden (zum Spieleranzahl ändern)?


----------



## ComFreek (6. Juni 2010)

@PainMaker: Komischerweise ist es doch die gleiche Adresse. Bin selber verwirrt


----------



## Pain-maker (6. Juni 2010)

Seltsam... mein Weltbild wurde zerstört xD
Denke aber trotzdem dass das nicht immer funktionieren wird.

Aber warum das jetzt selbst nach nem Neustart noch gleich ist, verwirrt mich jetzt schon...
Jemand ne Erklärung?


----------



## glnklein (6. Juni 2010)

solitär hat leider keine feste adresse sobald ich meins zumache und wieder auf gehts auch nicht aber wenn ich die adresse kenn funktionierts 

weis einer wie ich es anstellen kann das der wert sich nach meiner änderung nicht mehr verändern kann ? weil das spiel selber möchte die spielerzahl immer wieder heraufsetzen



sheel hat gesagt.:


> So wie er es geschrieben hat, gehts schon.
> Allerdings muss die Adresse wirklich nicht immer gleich sein.
> Es gibt sogar Spiele, die extra zum Verhindern von solchen Eingriffen regelmäßig ihre Variablen woanders ablagern
> 
> ...



ModernWarfare 2 da sind die minimum und Maximum Spielerzahlen immer auf der selben adresse darum würde das schon funktionieren nur das spiel setzt die zahlen immer zurück suche noch einen weg um meinen wert fest einzustellen


----------



## Pain-maker (6. Juni 2010)

Du müsstest mal im Debug den Speicher observieren und schauen, wann Solitär das immer ändert.
Debug --> Windows --> Memory 1-4 (Windows, Visual Studio)
Vielleicht musst du kurz vor Spielbeginn (bzw. wenn das Spiel beginnt) den Wert nochmal ändern.


----------



## ComFreek (6. Juni 2010)

Ich glaube das geht gar nicht mehr, außer du setzt regelmäßig (alle 10 Sek.?) die Variable neu. Aber ich glaube, diese Art funktioniert nicht unbedingt bei Spielen, weil diese sich nicht neu initialisieren.


----------



## timestamp (6. Juni 2010)

glnklein hat gesagt.:
			
		

> ModernWarfare 2 da sind die minimum und Maximum Spielerzahlen immer auf der selben adresse darum würde das schon funktionieren nur das spiel setzt die zahlen immer zurück suche noch einen weg um meinen wert fest einzustellen



Vielleicht setzt MW2 den Wert immer wieder zurück damit ihn keiner ändert?


----------



## Matthias Reitinger (6. Juni 2010)

ComFreek hat gesagt.:


> @PainMaker: Komischerweise ist es doch die gleiche Adresse. Bin selber verwirrt


So überraschend ist das nicht. Wenn bei jedem Programmlauf die selbe Folge von Speicherallokationen erfolgt, ist es doch nachvollziehbar, dass das Betriebssystem immer dieselben Speicherbereiche vergibt. Ich denke ihr macht bei euren Überlegungen den Fehler, dass ihr davon ausgeht, diese Speicheradressen wären physische Adressen. In Wirklichkeit handelt es sich aber um virtuelle Adressen.

Grüße,
Matthias


----------



## glnklein (6. Juni 2010)

ja warscheinlich will der hersteller das nicht aber das ist einfach bescheuert weil wenn man nur zu 3 spielen will geht das nicht weil minimum 8 personen da sein müssen , 

ich habe bis jetzt das mit CHEAT ENGINE gemacht da kann man den wert locken als feststellen und dan klapt es so was mus man doch auch mit C++ können . 

könnte ich nicht eine schleife einbauen die den wert einfach jede sek. neu schreibt ,? diese schleife müsste nur im hintergrund laufen damit wen man die minimumspielerzahl festgelegt hat und die schleife anläuf auch noch die maximum zahl ändern kann


----------



## Pain-maker (6. Juni 2010)

Matthias Reitinger hat gesagt.:


> So überraschend ist das nicht. Wenn bei jedem Programmlauf die selbe Folge von Speicherallokationen erfolgt, ist es doch nachvollziehbar, dass das Betriebssystem immer dieselben Speicherbereiche vergibt. Ich denke ihr macht bei euren Überlegungen den Fehler, dass ihr davon ausgeht, diese Speicheradressen wären physische Adressen. In Wirklichkeit handelt es sich aber um virtuelle Adressen.
> 
> Grüße,
> Matthias


Nun, das mit den virtuellen Adressen habe ich ja schon geschrieben und da kann ich nicht immer davon ausgehen dass ich die gleiche Startdresse bekomme. Das mit den Allokationen ist natürlich richtig, aber wenn mein Programm einmal bei 0x00004C68 und einmal bei 0x0000684C startet, schieben sich weitere Adressen auch nach hitnen... und ich habe die Erfahrungen gemacht, dass das spätestens nach einem Neustart eintritt.



glnklein hat gesagt.:


> könnte ich nicht eine schleife einbauen die den wert einfach jede sek. neu schreibt ,? diese schleife müsste nur im hintergrund laufen damit wen man die minimumspielerzahl festgelegt hat und die schleife anläuf auch noch die maximum zahl ändern kann



Ja du kannst einen Timer (SetTimer()) schreiben, der aller 10ms oder so prüft ob sich der Speicher geändert hat und ihn erneut ändert.
Aber wenn MW2 einen entsprechenden Schutz hat, wird es wahrscheinlich ebenfalls darauf reagieren und so wird dein Programm immer wieder ins Hintertreffen geraten.


----------



## glnklein (6. Juni 2010)

> Ja du kannst einen Timer (SetTimer()) schreiben, der aller 10ms oder so prüft ob sich der Speicher geändert hat und ihn erneut ändert.
> Aber wenn MW2 einen entsprechenden Schutz hat, wird es wahrscheinlich ebenfalls darauf reagieren und so wird dein Programm immer wieder ins Hintertreffen geraten.




wie würde den so ein timer aussehen dann müsste ich ja die adresse wieder auslesen und in eine variable speichern , wie geht das den dan


----------



## Pain-maker (6. Juni 2010)

z.B. so:


```
void *targetAddr = (void*)0;
int  lastValue   = 0;

VOID CALLBACK adresseObserver(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime)
{
	int *ptr = (int*)targetAddr;

	// Auf Änderung prüfen
	if(*ptr != lastValue)
		*ptr = lastValue = 4; // Der neue Wert
}

void main()
{
	targetAddr = (void*)0x0F45A4xC6;
	UINT_PTR timerHndl  = SetTimer(NULL, 0, 10, &adresseObserver);
}
```


----------



## ComFreek (6. Juni 2010)

Guck doch mal in der MSDN: http://msdn.microsoft.com/en-us/library/ms644906(VS.85).aspx

(Du müsstest aber dann eine Nachrichtenschleife bauen (dazu müsstest du das Konsolenhandle bekommen))


----------



## glnklein (6. Juni 2010)

das ist viel ? keine ahnung
.was heist das den alles   
bin TOTALER anfänger 

kannst du mir das kurz (oder Lang ) erklären was ich wo wie benutzen muss


----------



## Pain-maker (6. Juni 2010)

Testweise könntest du auch einfach mal sowas machen:


```
void main()
{
	// Spiel via OpenProcess() starten
	// ...
	
	// Pointer auf die Adresse
	// Du müsstest wissen ob der Wert in einem int, unsigned, short, etc. gespeichert wird
	int *targetAddr = (int*)0x07250340;
	
	// Endlosschleife
	for(;;)
	{
		// Prüfen ob sich der Wert geändert hat
		// Schlimmstenfalls bekommst du hier eine "Access violation", wenn sich die Adresse wieder geändert hat
		if(*targetAddr != 4)
			*targetAddr = 4; // Der neue Wert

		// Gegen CPU-Überlastung
		Sleep(10);
	}
}
```


----------



## glnklein (6. Juni 2010)

Pain-maker hat gesagt.:


> Testweise könntest du auch einfach mal sowas machen:
> 
> 
> ```
> ...





danke also da ich das spiel ja schon auf habe brauch ich das mit dem öffnen ja nicht  jetzt wollt ich deinen code einfach mal eigenständig laufen lassen .
hab einfach mal das was ich eigentlich brauche genommen und das sleep rausgenommen ums genauer zu sehen . 
da bekomm ich nur immer die fehlermeldung

*Zeile 7 C:\Users\bellpc\Desktop\Unbenannt6.cpp `main' must return `int' * 

-ist bestimmt ein DUMME FRAGE aber warum geht das so nicht 



```
#include <iostream>


void main()
{
    // Spiel via OpenProcess() starten
    // ...
    
    // Pointer auf die Adresse
    // Du müsstest wissen ob der Wert in einem int, unsigned, short, etc. gespeichert wird
    int *targetAddr = (int*)0x067425D8;
    
    // Endlosschleife
    for(;;)
    {
        // Prüfen ob sich der Wert geändert hat
        // Schlimmstenfalls bekommst du hier eine "Access violation", wenn sich die Adresse wieder geändert hat
        if(*targetAddr != 0)
            *targetAddr = 1; // Der neue Wert

        // Gegen CPU-Überlastung
       
    }
}
```


----------



## ComFreek (6. Juni 2010)

@PainMaker: Ja das wäre auch eine mögliche Lösung. Aber seit wann ist Sleep gegen CPU-Auslastung, im Gegenteil es verursacht noch mehr Rechenarbeit.
@glnklein: Poste gleich mal ein Beispiel Folgendes sollte gehen:

```
int main()
{
  HWND hwnd = GetConsoleWindow();
  MSG message;
  while (GetMessage(&message, NULL, 0, 0))
  {
    TranslateMessage(&message);
    DispatchMessage(&message);
  }
}
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
  switch (message)
  {
    case WM_CREATE:
    {
      SetTimer(hwnd, 1, 50, NULL);  // Alle 50 Millisekunden
      break;
    }
    case WM_TIMER:
    {
       if (LOWORD(wParam==1)) // Timer-ID
       {
         // Variable setzen
       }
       break;
    }
    default:
      return DefWindowProc(hwnd, message, wParam, lParam);
  }
}
```
Ich weiß nicht ob das gehen würde, aber man könnte die ganze Nachrichtenschleife weglassen und einen Timer-Callback (letzer Parameter von SetTimer) setzen.


----------



## Pain-maker (6. Juni 2010)

Nun die Endlosschleife sollte doch eigentlich mehr Überlastung bringen ohne Sleep, oder? Aber is natürlich richtig, dass das auch weggelassen werden kann.

@glnklein:
Laut der Fehlermeldung würde ich darauf schließen dass du

```
int main()
```
statt

```
void main()
```
verwendest und da fehlt dann natürlich ein

```
return 0;
```
am Ende, da der Compiler einen Rückgabe-Wert "int" erwartet.

Mfg Pain-maker

*EDIT:

Könnte aber auch sein, dass dein Compiler nicht mit
*

```
void main()
```
*
zurecht kommt. In diesem Fall müsstest dus halt einfach in
*

```
int main()
```
*
ändern und noch eine 0 oder so zurückgeben.*


----------



## ComFreek (6. Juni 2010)

Laut Standard sollte es int sein!
@PainMaker: Habe ein Beispiel mit SetTimer gepostet (weiter oben)


----------



## Cromon (6. Juni 2010)

ComFreek hat gesagt.:


> @PainMaker: Ja das wäre auch eine mögliche Lösung. Aber seit wann ist Sleep gegen CPU-Auslastung, im Gegenteil es verursacht noch mehr Rechenarbeit.



Das stimmt nicht:


			
				MSDN hat gesagt.:
			
		

> This function causes a thread to relinquish the remainder of its time slice and become unrunnable for an interval based on the value of dwMilliseconds.


----------



## glnklein (6. Juni 2010)

erstmal danke für eure HILFE bin schon viel gelernt  nur ich weis leider nicht wo ich welchen teil einfügen müsste damit der speicher sich nicht mehr 
ändern kann oder halt bei änderung neu geschrieben wird , bin bis jetzt soweit das der speicher halt neu geschrieben werden kann 
mein code sieht bis jetzt so aus und fnktioniert 


```
#include <windows.h>
#include <stdio.h>
#include <iostream>

using namespace std;

int main()
{            
   
cout << " Tool\n\n";   
bool beenden=1;
while(beenden=1) 
{
                 
    cout << "Was willst du tun?\n\n\n 0=Beenden \n 1=Minimale Spielerzahl\n 2=Maximale Spielerzahl  \n";
    int eingabe=0;
    cin>>eingabe;     
    if(eingabe==0)
    {
                  return 0;
    }
    cout << "Suche Modern Warfare 2 \n";
    HWND window = NULL;
    while(window == NULL)
    {
                  Sleep(100);
                  window = FindWindow(NULL, "Modern Warfare 2"); 
    }
    DWORD prozess;
    GetWindowThreadProcessId(window, &prozess);
    HANDLE handle;
    handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, prozess);
    DWORD puffer = NULL;
   
         switch(eingabe)
    {
    case 1:
           cout << "\n neuer wert minimum Spieler ? ";
           
    int wert;
    cin>>wert;     
      
        WriteProcessMemory(handle,(void*)(0x0645C3F8),&wert,6,&puffer);  // das ändert mit das spiel immer wieder sobalt ich etwas im spiel mache 
    cout << "\n Schreibe ... \n"; 
      
        break;
        
    case 2:
         
       cout << "\nneuer wert maximum Spieler ? ";
    int wert2;
    cin>>wert2;     
         
        WriteProcessMemory(handle,(void*)(0x0645C408),&wert2,6,&puffer); // das ändert mit das spiel immer wieder sobalt ich etwas im spiel mache 
  cout << "\n Schreibe ... \n"; 
        break;

    }     
    CloseHandle(handle);  
      
} 
return 0;   
}
```


*
kann einer mir ewentuell direkt an meinem code zeigen was ich da machen muss ? 
Ich versteh davon einfach noch zuwenig *


*PS : Pain-maker  
wenn ich deinen vorschläge mit main und return übernehme dann kommt kein fehler mehr aber das program stürzt dan ab *


----------



## Cromon (6. Juni 2010)

Du setzt einfach einen der diversen Vorschläge um:
Über einen Timer
Über eine simple blockierende Schleife
Über einen Thread.


----------



## ComFreek (6. Juni 2010)

Das mit dem Timer ist ein wenig komplizierter, denn dann wird der Ablauf nicht mehr ganz "hintereinander ausgeführt", sondern über die Message-Schleife.


----------



## glnklein (6. Juni 2010)

Cromon hat gesagt.:


> Du setzt einfach einen der diversen Vorschläge um:
> Über einen Timer
> Über eine simple blockierende Schleife
> Über einen Thread.




also ich habs jetzt so versucht 


```
case 2:
         
       cout << "\nneuer wert maximum Spieler ? ";
    int wert2;
    cin>>wert2;     
         
        WriteProcessMemory(handle,(void*)(0x0645C408),&wert2,6,&puffer);
  cout << "\n Schreibe ... \n"; 
  
  
     
{
  
    int *targetAddr = (int*)0x0645C408;    // nehme mal an das ist lese adresse dachte immer adresse lesen ist ReadProcessMemory
    
    // Endlosschleife
    for(;;)
    {
   
        if(*targetAddr != wert2)
             WriteProcessMemory(handle,(void*)(0x0645C408),&wert2,6,&puffer);

        // Gegen CPU-Überlastung
        Sleep(10);
    }
}  
        
        break;
```



nur das bring mein kleines program immer zum absturz


----------



## Cromon (6. Juni 2010)

Also zum einen:
Verwende eine sinnvolle Formatierung, das ist ja schrecklich!

Zum anderen:
Das hatten wir doch jetzt schon auf langen 1.5 Seiten: 0x0645C408 gehört nicht in deinen Adressraum, daher musst da auch über ReadProcessMemory den Wert auslesen.


----------



## ComFreek (6. Juni 2010)

Cromon hat gesagt.:


> Also zum einenDas hatten wir doch jetzt schon auf langen 1.5 Seiten: 0x0645C408 gehört nicht in deinen Adressraum, daher musst da auch über ReadProcessMemory den Wert auslesen.



Hatte er irgendwie  auch im Kommentar (im Quelltext) geschrieben, dass er dachte, dass ReadProcessMemory richtig wäre, naja.
Ich habe gerade eine Internetseite gefunden, die genau dieses Thema Schritt für Schritt erläutert: http://www.spieleprogrammierer.de/index.php?page=Thread&threadID=9544


----------



## Maik (6. Juni 2010)

@glnklein: Es wäre fein, wenn du beim Verfassen deiner weiteren und zukünftigen Forenbeiträgen die Netiquette (Nr.15) bzgl. der erwünschten Groß- und Kleinschreibung beachtest - vielen Dank 

mfg Maik


----------



## Lesterdor (6. Juni 2010)

Guten Tag,

während ich mir den Thread aus Neugier durchgelesen habe, kam mir eine Frage auf:

Wie kann ich überhaupt sehen, in welche Speicheradresse ein Programm die Werte schreibt?

Da hier das Beispiel Solitär angeführt wurde, wäre ich dankbar, wenn mir das jemand erklären könnte. 

Danke im Voraus


----------



## ComFreek (6. Juni 2010)

Bei meinem Link (http://www.spieleprogrammierer.de/index.php?page=Thread&threadID=9544) ist beschrieben, dass man nach der Variablen irgendwie scannen soll (habes den Thread da noch nicht durchgelesen).


----------



## Cromon (6. Juni 2010)

Lesterdor hat gesagt.:


> Guten Tag,
> 
> während ich mir den Thread aus Neugier durchgelesen habe, kam mir eine Frage auf:
> 
> ...



Mit einem Dekompilierer versuchen den Maschinencode rückgängig zu machen oder aber stumpfsinnig einfach den gewünschten Wert im Speicher suchen, alle Vorkommnisse speichern, den Wert bisschen ändern, schauen, bei welchen von den vorherigen er nun auch so ist, usw.

Zum Thema Solitaire. Auf Windows 7 32 Bit ist der Spielstand zum Beispiel an folgender Adresse gespeichert:

```
[[[ImageBase + 0x97074] + 0x2C] + 0x10]
```

An ImageBase + 0x97074 ist nämlich ein Zeiger auf eine globale Instanz von CGSolitaireGame. Und CGSolitaireGame besitzt an Position 0x2C einen Zeiger auf eine Instanz der folgenden Klasse:

```
struct SolitaireGameState
{
	LPDWORD __vfptr;
	UINT uVersion;
	UINT uTime;
	UINT uDeckCycles;
	UINT uClassicalScore;
	UINT uVegasScore;
	UINT uNoTimeScore;
	bool fDeckLocked;
	bool fFirstMoveDone;
	USHORT usUnk;
	UINT uScoreMode;
	UINT uDeckDrawMode;
	bool fIsTimed;
	bool fUnk;
	UINT uDeckSeed;
};
```


----------



## ComFreek (6. Juni 2010)

@Cromon: Woher weißt du, dass der Zeiger da ist bzw. woher kennst du die Struktur der Daten?


----------



## Cromon (6. Juni 2010)

Durch Reverse Engineering der Exe in IDA. Du kannst es dir leicht machen, da Microsoft die PDB zur Exe anbietet, oder aber du verzichtest darauf und gehst anhand der Strings wie "Score: %u" vor.


----------



## Matthias Reitinger (6. Juni 2010)

Pain-maker hat gesagt.:


> Nun, das mit den virtuellen Adressen habe ich ja schon geschrieben und da kann ich nicht immer davon ausgehen dass ich die gleiche Startdresse bekomme.


Dass man im Allgemeinen nicht davon ausgehen kann, ist klar. Aber verwunderlich ist es auch nicht, wenn es mal passiert. Wo andere Programme im *physischen* Adressraum liegen hat ja keine Auswirkung auf meinen *virtuellen* Adressraum.



Pain-maker hat gesagt.:


> Das mit den Allokationen ist natürlich richtig, aber wenn mein Programm einmal bei 0x00004C68 und einmal bei 0x0000684C startet, schieben sich weitere Adressen auch nach hitnen... und ich habe die Erfahrungen gemacht, dass das spätestens nach einem Neustart eintritt.


Der Einstiegspunkt eines Programms befindet sich immer an derselben *virtuellen* Speicheradresse. Und nur mit virtuellen Adressen hat man es in einem Benutzer-Programm zu tun. Ich glaube so ganz hast du das Prinzip der virtuellen Speicherverwaltung noch nicht verstanden…

Grüße,
Matthias


----------



## Pain-maker (6. Juni 2010)

Matthias Reitinger hat gesagt.:


> So überraschend ist das nicht. Wenn bei jedem Programmlauf die selbe Folge von Speicherallokationen erfolgt, ist es doch nachvollziehbar, dass das Betriebssystem immer dieselben Speicherbereiche vergibt. Ich denke ihr macht bei euren Überlegungen den Fehler, dass ihr davon ausgeht, diese Speicheradressen wären physische Adressen. In Wirklichkeit handelt es sich aber um virtuelle Adressen.
> 
> Dass man im Allgemeinen nicht davon ausgehen kann, ist klar. Aber verwunderlich ist es auch nicht, wenn es mal passiert. Wo andere Programme im *physischen* Adressraum liegen hat ja keine Auswirkung auf meinen *virtuellen* Adressraum.
> 
> ...



Welche virtuelle Adresse ist das denn? Abgesehen davon rede ich die ganze Zeit ja von *virtuellen* und NICHT von *physikalischen* Adressen.
Hab eben mal 2 exakt gleiche Programme geschireben und die Adresse von main() geprüft, aber beide haben eine andere.
Wenn beide aber die gleiche Startadresse hätten, müsste ja auch demnach die Adresse der main() identisch sein, oder?

Mfg Pain-maker

*Edit: Meines Wissens nach ist das mit dem Einstiegspunkt übrigens Compiler und/oder OS abhängig. Aber wenn ich da was missverstanden hab, lasse ich mich gerne belehren*


----------



## Cromon (6. Juni 2010)

Sie ist identisch.


----------



## Pain-maker (6. Juni 2010)

Oki, dann danke ich für die Aufklärung 
Kann mir trotzdem noch jemand sagen, warum die main()-Adresse unterschiedlich ist?

(Hoffe das wird jetzt nich zu sehr Off-Topic)


----------



## Matthias Reitinger (6. Juni 2010)

Pain-maker hat gesagt.:


> Oki, dann danke ich für die Aufklärung
> Kann mir trotzdem noch jemand sagen, warum die main()-Adresse unterschiedlich ist?


Wie sieht denn dein Testprogramm aus?


----------



## Cromon (6. Juni 2010)

Die Adresse ist nicht unterschiedlich. Du musst nur immer sehen, dass du eine absolute Adresse betrachtest. Wenn du davon die absolute Imagebasis abziehst kommst du auch auf einen konstanten Wert. Wenn du jedoch die virtuellen Adressen beachtest ist auch die virtuelle Dateibasis (i.d.R. glaub 0x400000 bei Exe-Dateien) konstant, und daher auch die virtuelle Adresse von main.


----------



## Pain-maker (6. Juni 2010)

Also ich habe das Programm "Baseadress1" und "Baseadress2":

```
/**
 * Programm: Baseadress1
 */
int main() // 0x012B1350
{
	return 0;
}
```


```
/**
 * Programm: Baseadress2
 */
int main() // 0x00BB1350
{
	return 0;
}
```

Die Adresse von main() ist bei dem einen * 0x012B1350* und bei dem anderen *0x00BB1350*. (Differenz: *x700000*)
Erwartungsgemäß hätte die aber gleich sein müssen, oder?

Mfg Pain-maker


----------



## glnklein (6. Juni 2010)

Also ich habs jetz mit verschiedenen möglichkeiten getestet aber ich komm leider nicht weiter  , 
ich nehme mal an es sind nur 3 oder 4 Zeilen die ich noch in meinen Code einfügen muss allerdings weis ich ncht welche und wo

ewentuell könnte jemand meinen Code soweit ergänzen das das der Speicher auf dauer so bleibt wie ich ihn eingestellt habe


----------



## Cromon (6. Juni 2010)

Pain-maker hat gesagt.:


> Also ich habe das Programm "Baseadress1" und "Baseadress2":
> 
> ```
> /**
> ...



Warum sollte die Adresse der Main-Funktion in zwei unterschiedlichen Programmen gleich sein?


----------



## Pain-maker (6. Juni 2010)

Also ich habs jetzt verstanden. (Danke liebes Google^^)
Ja die Startadresse ist unter Windows immer 0x400000, ausser unter Windows Vista / 7, da das eine "Baseadress randomization" benutzt.
(Daher hat das auch bei mir unter Win 7 auch alles nich ganz hingehaun)
siehe: http://blogs.technet.com/b/askperf/...der-and-address-space-load-randomization.aspx
Wo ich aber wieder zu meiner vorherigen Aussage komme, nämlich das das auch durchaus OS bzw. Compiler/Linker-Abhängig sein KANN.

@glnklein:
Nun wir haben ja bereits festgestellt, dass MW2 den Wert immer wieder zu ändern scheint, daher geht es nicht diesen dauerhaft zu ändern ohne das du jedesmal wieder eingreifst.
Was bekommst du denn für einen Fehler wenn du folgenden Code hast:

```
case 2:
	{
		cout << "\nneuer wert maximum Spieler ? ";
		int wert2;
		cin>>wert2;     
		cout << "\n Schreibe ... \n"; 
		 
		 int *targetAddr = (int*)0x0645C408;
		 
		 // Endlosschleife
		 for(;;)
		 {
		     if(*targetAddr != wert2)
		          WriteProcessMemory(handle,(void*)(0x0645C408),&wert2,6,&puffer);

		     // Gegen CPU-Überlastung
		     Sleep(10);
		 }
	}
	break;
```


----------



## glnklein (6. Juni 2010)

Pain-maker hat gesagt.:


> @glnklein:
> Nun wir haben ja bereits festgestellt, dass MW2 den Wert immer wieder zu ändern scheint, daher geht es nicht diesen dauerhaft zu ändern ohne das du jedesmal wieder eingreifst.
> Was bekommst du denn für einen Fehler wenn du folgenden Code hast:
> 
> ...



wenn ich das so übernehme dann kommt 

_*Test.exe Funktioniert nicht mehr *
Windows kann online nach einer Lösung für das Problem suchen . 

usw. _

Warum weis ich nicht


----------



## Pain-maker (6. Juni 2010)

Also mir fallen dazu noch 2 Dinge ein:

1. Ich habe noch nie sowas versucht aber es könnte sein, dass du nicht einfach mit

```
*targetAddr
```
auf den Wert zugreifen kannst, sondern

```
ReadProcessMemory()
```
benutzen musst.

2. Begib dich mal in den Debug-Modus, dann solltest du sehen wo dein Programm den Löffel abgibgt.

Mfg Pain-maker

*BTW: Bist du mal dem Link von ComFreek nachgegangen?*


----------



## Cromon (6. Juni 2010)

Also:
Lemma 1: Du kannst keine Adressen, die nicht in deinem Adressraum sind über Zeiger auslesen!
Lemma 2: Du kannst keine Adressen, die nicht in deinem Adressraum sind über Zeiger modifizieren!

Du musst ReadProcessMemory und WriteProcessMemory verwenden.


----------



## glnklein (6. Juni 2010)

ja den Link hab ich das ist aber im grunde das selbe wie ich hier habe nur das da die adresse erst gesucht wird aber ich werd mal weiter suchen 

ich hab mir gedacht ich fang es so an ich lese den jetzigen wert speicher ihn in eine Variable und packe es dan in eine if schleife , 




ich hab das jetzt nochmal mit  *Microsoft Visual Studio* durchlaufen lassen und der meldet mir bevor das programm abstürzt 

*Unhandled exceptio at 0x00401597 in test.exe:0xC0000005:access violation reading location 0x0645C408*

hilft das weiter ?


----------



## ComFreek (6. Juni 2010)

glnklein hat gesagt.:


> *Unhandled exceptio at 0x00401597 in test.exe:0xC0000005:access violation reading location 0x0645C408*


Das ist eindeutig eine Speicherschutzverletzung.
Wie Cromon gesagt hat, geht das nur über Read/WriteprocessMemory.


----------



## glnklein (6. Juni 2010)

ich bin ein stück weiter nur eine kleine frage 
warum bekomme ich mit 


```
ReadProcessMemory(handle,(void*)(0x0645C408),&wert3,6,&puffer);
        cout << &wert3;
```

nicht den aktuellen wert angezeigt sondern eine speicheradresse , ich wollte den aktuellen wert eigentlich in &wert3 speichern


----------



## Cromon (6. Juni 2010)

Du kannst in &wert3 nichts speichern, dass ist ein R-Wert....


----------



## glnklein (6. Juni 2010)

und in was kann ich den aktuellen wert speichern oder ausgeben damit ich es weiter in einer if anweisung benutzen kann


----------



## Cromon (6. Juni 2010)

Der Wert wird in wert3 gespeichert, du übergibst ja dessen Adresse an ReadProcessMemory.


----------



## glnklein (6. Juni 2010)

Cromon hat gesagt.:


> Der Wert wird in wert3 gespeichert, du übergibst ja dessen Adresse an ReadProcessMemory.



ok danke muss aber leider mitteilen das es so nicht geht , als eigentlich geht es aber  das dauernde überprüfen un neu schreiben des wertes führt zu einem absturz des spiels , ich muss die lösung finden um den angegebenen wert zu locken


----------



## Maik (6. Juni 2010)

@glnklein: Lässt du hier nun wieder den Schlendrian einziehen?

Meine Bitte in Post #44 war ernst gemeint, denn unsere Forenregeln hast du mit deiner Registrierung anerkannt.



> Unser Forum ist kein Chatroom. Kurz-Beiträge ("Ein-Zeilen Postings"), die einfach so ins Forum "geklatscht" werden, werden ohne Vorwarnung von einem Moderator oder Administrator gelöscht. Das gleiche gilt insbesondere für Beiträge, die in Rechtschreibung, Satzbau und Verständlichkeit nicht ein vernünftiges, allgemein übliches und altersgruppen-übergreifendes Niveau erfüllen. Jugendsprache, regional verbreitete Dialekte und *durchgehend kleingeschriebene Beiträge sind ebenfalls unerwünscht. Mit anderen Worten: wer erfolgreich die im Deutsch-Unterricht erlernten Kenntnisse praxisnah auf unserem Forum anwenden kann, wird nicht mit dieser Regel in Konflikt kommen. "Wiederholungstäter" werden, nachdem sie zuvor von einem Moderator auf die Mängel hingewiesen wurden, ggf. unbefristet gesperrt.*



Zitat-Quelle: http://www.tutorials.de/netiquette.html (Nr.15)

Also halte dich bitte nun d'ran,  und nicht blos für die kommenden zwei oder drei Beiträge - vielen Dank!

mfg Maik


----------



## Cromon (6. Juni 2010)

glnklein hat gesagt.:


> ok danke muss aber leider mitteilen das es so nicht geht , als eigentlich geht es aber  das dauernde überprüfen un neu schreiben des wertes führt zu einem absturz des spiels , ich muss die lösung finden um den angegebenen wert zu locken



Du kannst einen Wert nicht "locken". Du kannst ihn nur immer wieder zurücksetzen. Wenn du den Bereich über VirtualProctect sperrst führt das nicht dazu, dass der Speicher nicht neu beschrieben werden kann, sondern dass das Spiel beim nächsten Durchlauf einen Fehler bekommt wegen einer Zugriffsverletzung. Dass es bei dir nicht funktioniert kann verschiedene Gründe haben: Du hast eine nicht gebremste Endlosschleife gemacht, was dann sehr schnell mal zu Dateninkosistenz führt, wenn deine Schleife gleichzeitig mit anderen Threads das Datum modifiziert.


----------



## ComFreek (7. Juni 2010)

Also weitere Chancen sehe ich da auch nicht, aber eventuell greift das folgendes Flag bei VirtualProtect:

```
PAGE_WRITECOPY
0x08
```

Wenn ich das in der MSDN richtig verstanden habe, dann darf ein Prozess nur den Inhalt in eine Variable kopieren und den Inhalt der Variable ändern. (Bitte korrigiert mich, falls ich falsch liege!)

EDIT: Link zu den möglichen Flags: http://msdn.microsoft.com/en-us/library/aa366786(v=VS.85).aspx


----------



## brunlorenz (10. Juni 2010)

Was viele schon sagten, Windows erlaubt kein Zugriff ausserhalb des Stacks. Übrigens wurde ja kein Speicher alloziert.


----------



## Cromon (10. Juni 2010)

Doch, du kannst schon auf Speicher fremder Prozesse zugreiffen, sofern die das nicht explizit verbieten und du die von der API bereitgestellten Funktionalitäten verwendest (ReadProcessMemory, WriteProcessMemory, CreateRemoteThread, usw...)


----------



## brunlorenz (11. Juni 2010)

Wieso weiss der eigentlich, wo sich genau die Daten befinden? Übrigens ändert sich bei jedem Start die Positionierung dieser!


----------



## sheel (11. Juni 2010)

Lies mal die letzten 5 Seiten; da haben mindestens 7 Leute darüber diskutiert.


----------



## Cromon (11. Juni 2010)

brunlorenz hat gesagt.:


> Wieso weiss der eigentlich, wo sich genau die Daten befinden? Übrigens ändert sich bei jedem Start die Positionierung dieser!



Herausfinden ist nicht schwer. Debuger und Disassembler helfen da ungemein . Grundsätzlich ändert sich keine virtuelle Adresse. Im Endeffekt ist es nur von der Reihenfolge der Allokation abhängig. Aber z.B. globale Variabeln oder statische Member einer Klasse sind bei jedem Programmstart an derselben virtuellen Adresse. Von da kommst du dann auf die einzelnen Adressen dieser Programminstanz. So hat Solitaire zum Beispiel eine Klasse SolitaireGame und entweder ist diese nach dem Singleton-Prinzip mit einem statischen Member erstellt worden oder aber es existiert eine globale Variable davon. Diese wird mit new alloziert. Diese Adresse ist fix und ihr Wert ist ein Zeiger auf eben die allozierte Instanz von SolitaireGame. Von daher kann es dir nacher Wurst sein, wo das ist, der Zeiger darauf ist global und daher immer an der gleichen virtuellen Adresse.


----------

