Entwickler-Ecke

Delphi Tutorials - Spiele Trainer erstellen


en!gma - Sa 25.12.04 13:21
Titel: Spiele Trainer erstellen
hi!
also erstmal...
dies ist mein allererstes tutorial überhaupt...ich hab es geschrieben, da ich bis jetzt noch kein ausführliches (ka ob das hier ausführlich is ;D ) tutorial auf deutsch und für delphi gefunden habe...
kritik is gerne erwünscht...
achja und gewöhnt euch schonmal dran das ich alles klein schreibe ^^
bin halt faul und das wird sich auch so schnell nicht ändern...

hmm wie fang ich am besten an?
okey dann versuch ich das tutorial am besten mal in mehrere teile zu unterteilen...

1. was ist überhaupt ein trainer und was wird in diesem tutorial eklärt?
2. was brauchen wir?
3. wie finde ich addressen heraus?
4. wie pack ich das ganze in einen delphi code?



1. was ist überhaupt ein trainer und was wird in diesem tutorial eklärt?

okey ich machs einfach mal knapp...
also...ein trainer is meistens da, um sich einen vorteil in einem spiel zu verschaffen. sei es nun um kein leben/geld oder einfach nur keine munition zu verlieren. diese ganzen werte wie leben geld usw werden im ram gespeichert,
unsere aufgabe ist nun, die position der werte herauszufinden und diese "einzufrieren".
dabei sollte man wissen, das es 2 sorten von werten...einmal den static memory addresses (dms) und den dynamic memory addresses (dma)...die sma bleiben immer an der gleichen stelle im ram, sie sind also einfach zu finden und zu editieren,
dann gibt es aber noch die dma...diese werte ändern diese position zB nach jedem spielneustart oder nach jedem reboot.
sobald wir diese werte herausgefunden haben, werden wir ein kleines programm mit delphi schreiben um sie "einzufrieren".



2. was brauchen wir?

hmm also erstmal das wichtigste...

-tsearch (könnt ihr hier runterladen http://fly.to/mtc)
-delphi (ich habe delphi 7 benutzt)
-ein opfer für unseren trainer (hab mal einfach starcraft genommen)
-nen kaltes getränk, gute musik und ein gehirn ;D



3. wie finde ich addressen heraus?

so, als erstes starten wir das spiel für das wir den trainer programmieren wollen, ich habe mich für starcraft entschieden, da es relativ alt ist und es noch dort noch nicht ganz so viele addressen gibt die man durchsuchen muss.
am besten starten wir einmal eine eigene map gegen den computer.

als erstes wollen wir die addresse von unseren mineralien herausfinden,
am anfang haben wir ja 50 mineralien wie wir oben rechts im spiel sehen können. also starten wir nun tsearch und klicken auf den fetten "open process" button mit dem chip drüber...
nun öffnet sich ein fenster in dem wir unseren prozess auswählen sollen, in diesem fall halt starcraft.

nun klicken wir auf die kleine lupe links unter dem "open process" button...
in diesem search fenster müssen wir erst einmal "exact value" auswählen, da
wir ja wissen, wie viele mineralien wir haben (am anfang immer 50)...
also tippen wir die 50 bei "value" ein und lassen den "type" auf 4 bytes.
normalerweise sind 1 byte 2 zahlen, 2 byte 4 zahlen, 3 byte 6 usw...
aber anfangs soll uns dies nicht kümmern und wir drücken auf ok.

nun sucht er alle addressen mit dem wert 50 für uns raus, meist findet er anfangs viele addressen (bei neueren spielen manchmal bis zu 7-9 stellige zahlen), aber wir suchen sofort weiter =).
also gehen wir zurück ins spiel und sammeln ein paar ressourcen auf...
sobald wir mehr haben als zuvor, merken wir uns wie viele mineralien wir nun
haben und gehen wieder zurück zu tsearch und klicken auf die lupe mit den 3 punkten dahinter (direkt rechts neben dem knopf nur mit der lupe)...
dieser knopf steht für weiter suchen, also schaut er nach veränderungen in den addressen die wir zuvor durch die suche davor gefunden haben.
dort sollten die einstellungen die gleichen sein wie zuvor beim suchen, nur das wir nun bei "value" unseren neuen wert von den mineralien eintippen.
bei mir wären das nun 106.

er sollte nun 4 verschiedene addressen finden. (falls dies nicht der fall ist und er doch ein paar mehr findet, sammelt einfach wieder ein paar mineralien auf und wiederholt den letzten schritt)

bisher haben wir immer nur mineralien dazubekommen, aber jetzt sollten wir mal schaun was passiert, wenn wir mineralien ausgeben...
also gehen wir wieder in starcraft, geben ein paar mineralien aus und suchen wieder nach unserem neuen mineralienwert...
und *tadaa* sind nur noch 2 addressen über...
einer von diesen beiden werten ist wahrscheinlich für die anzeige selbst, und die andere für die mineralien selbst, womit das spiel arbeitet.
also machen wir jeweils einen doppelklick auf jede der beiden addressen und wir haben sie in unserer "cheats list".
hier können wir die werte bei "value" verändern und so ausprobieren, welcher der wert für die anzeige ist und welcher für die andere.
angenommen ihr lasst einen wert auf 50 und ändert den anderen auf 5...
wenn ihr nun in das spiel geht und er oben 5 anzeigt, so ist die addresse, wo ihr die 5 eingegeben habt, für die anzeige, also brauchen wir die andere addresse.

nun wollen wir ausfindig machen, was genau passiert, wenn sich ein wert verändert, also klicken wir in tsearch oben auf "autohack", und wählen "enable debugger" aus...dann wählen wir im "cheats list" fenster die zweite (wie grad schon erklärt könnt ihr mit dem verändern der "value's" herausfinden welche ihr braucht) der beiden variablen mit einem rechtsklick aus und wählen ganz unten autohack aus...
nun prüft tsearch was passiert, wenn sich dieser wert verändert...
also gehen wir zurück ins spiel und geben wieder ein paar mineralien aus...

zurück in tsearch klicken wir oben auf "autohack" und anschliessend auf "autohack window"...
in diesem fenster sollte sich jex eine zeile stehen...
(401F75: (und irgendein befehl) falls ihr mineralien dazubekommen habt, wird dort auch noch der befehl 401F75: (und irgendein befehl))
dies ist der befehl der ausgeführt wird, wenn ihr mineralien ausgebt...
und damit haben wir eigentlich schon unser ziel für dieses kapitel erreicht...
um zu testen ob ihr wirklich die richtige addresse habt, klickt einfach mal auf das kleine quadrat neben diesem befehl, so dass dieser befehl zu nop (no operations) gesetzt wird...also wenn das spiel diesen befehl ausführen möchte, macht er einfach nichts, also das spiel gibt den befehl "mineralien abziehen"
aber wir haben nun den befehl "mineralien abziehen" so modifiziert, dass nichts passiert.
also sollte logischerweise nichts passieren wenn wir nun mineralien ausgeben...
also nichts wie zurück ins game und ausprobieren...
und *tadaa* es werden keine mineralien mehr abgezogen.

also noch einmal ein paar addressen falls ihr kleine probleme hattet =)

mineralien abziehen : 401F75 mit dem wert 8990A0D44F00
vespin-gas abziehen : 401F89 mit dem wert 8988D9D44F00

die werte könnt ihr unten im autohack window ablesen, aber diese werte sind nur wichtig, falls ihr den trainer wieder ausstellen wollt.

so nun haben wir unsere beiden addressen herausgefunden, die wir in unserem trainer benutzen möchten.
damit ist diese kapitel abgeschlossen und wir kommen endlich dazu das ganze in ein delphi programm zu schreiben.



4. wie pack ich das ganze in einen delphi code?

hier werd ich mich mal auf das gröbste beschränken und nur erzählen was wichtig ist, um einen trainer zu erstellen...
auf die einzelnen funktionen werde ich nicht extra eingehen, da ich auch selber weiss das man diese gerne überspringt ^^.

also erstellen wir einfach mal eine neue form und klatschen einfach mal einen button in die mitte und nennen ihn "buttonStart".
nun springen wir mal in den code und fügen ein paar variablen hinzu...

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
var
  WindowName  :  integer;
  ProcessId  :  integer;
  ThreadId  :  integer;
  buf  :  PChar;
  HandleWindow  :  Integer;
  write  :  cardinal;      

  Const  WindowTitle  =  'Starcraft';  //hier einfach den namen von unserm fenster eingeben! einfach spiel starten,
          //dann alt+tab drücken und in der taskleiste einfach nachschaun welche caption
                                        //unser programm hat und diese einfach einfügen.


zurück auf der form machen wir mal einen doppelklick auf unseren button...nun sollte sich das code-fenster
wieder öffnen und wir sollten direkt bei der TForm1.buttonStart prozedur landen.
hier fügt ihr einfach folgenden code ein:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
const v1 = $90
begin
 WindowName  :=  FindWindow(nil,WindowTitle);
          If  WindowName  =  0  then MessageDlg('...erst spiel starten...dann trainer starten =)',  mtwarning,[mbOK],0);
    ThreadId  :=  GetWindowThreadProcessId(WindowName,@ProcessId);
    HandleWindow  :=  OpenProcess(PROCESS_ALL_ACCESS,False,ProcessId);
    GetMem(buf,1);
    buf^  :=  Chr(v1);
    FreeMem(buf);
    closehandle(HandleWindow);
end;


also "v1 = $90" ist die variable die wir einer bestimmten addresse geben wollen. 90 steht für nop, also das keine aktion durchgeführt wird.
im folgenden code wird erst einmal geschaut ob das spiel überhaupt geöffnet ist, wenn nicht, kommt die fehlermeldung:
"...erst spiel starten...dann trainer starten =)"
danach wird der ram ausgelesen und anschliessend wieder mit "FreeMem(buf)" freigegeben. "GetMem(buf,1)" ist pflicht um überhaupt etwas verändern zu können,
"FreeMem(buf)" hingegen ist nicht pflicht, aber dennoch empfohlen, da es den pc sonst unnötig langsamer macht.
nun brauchen wir noch unsern code der unsere addressen verändert.

erstmal müssen wir ein wenig rechnen und unser gehirn einschalten...
also wir haben ja die addresse 401F75 mit dem wert 8990A0D44F00 für mineralien herausgefunden und ich habe vorher schon einmal kurz angesprochen, dass
1 byte für 2 zahlen stehen...wir haben nun 8990A0D44F00 und müssen diese durch 909090909090 austauschen, und dies jeweils mit 1 byte...
also brauchen wir insgesamt 6 befehle um diesen code umzuschreieben. 6x2 zahlen, also 6x90...
401F75 selbst kann nur 1 byte zugewiesen werden...und wir müssen ja insgesamt 6 byte zuweisen...also müssen wir den 5 addressen direkt hinter 401F75
auch jeweils eine 90 zuweisen...

401F75
401F76
401F77
401F78
401F79
401F7A
...usw...jetzt haben wir unsere 6 addressen, welchen wir die 90 zuweisen müssen...

nun mal wieder ein bischen code:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
WriteProcessMemory(HandleWindow,ptr($401F75),buf,1,write); //es wird der speicher umgeschrieben in der addresse 401F75 und es wird 1 byte geschrieben
WriteProcessMemory(HandleWindow,ptr($401F76),buf,1,write);
WriteProcessMemory(HandleWindow,ptr($401F77),buf,1,write);
WriteProcessMemory(HandleWindow,ptr($401F78),buf,1,write);
WriteProcessMemory(HandleWindow,ptr($401F79),buf,1,write);
WriteProcessMemory(HandleWindow,ptr($401F7A),buf,1,write);


diese paar zeilen müssen wir nun zwischen "buf^ := Chr(v1);" und "FreeMem(buf);" einfügen...
das war der code für die mineralien, nun versucht einmal das ganze mit dem vespin-gas,
die addresse und den wert habt ihr ja schon...

so ich hab den ganzen code nochmal als rar datei hinzugefügt...
das ganze könnt ihr hier -> http://www.phoenix-designz.de/zod/starcraft%20trainer.rar herunterladen


so damit ist mein tutorial beendet denke ich...ich hoffe es war für alle verständlich, ansonsten bin ich noch gerne für fragen offen...
ich hoffe auf viel kritik und son kram =)

mfG
en!gma


WeBsPaCe - Mo 27.12.04 20:00

Zitat:
einmal den static memory addresses (dms) und den dynamic memory addresses (dma)


SCHREIBFEHLER... muss richtig heißen:

einmal den static memory addresses (sma) und den dynamic memory addresses (dma)

schreibst du ja auch später:

Zitat:
die sma's bleiben


en!gma - Mo 27.12.04 20:03

ja danke...war mir nich ganz sicher ob ich jex mit oder ohne ' schreiben soll...
ich änder das mal zu dma und sma...


WeBsPaCe - Mo 27.12.04 20:04

Zitat:
tsearch (könnt ihr hier runterladen fly.to/mtc


n direktlink zum Programm wär besser...

http://membres.lycos.fr/tsearch/tsearch_16.zip

:-) :-) :-)


WeBsPaCe - Mo 27.12.04 20:06

Zitat:
delphi (ich habe delphi 7 benutzt)


warum sonst auch ins delphi-forum schreiben ???

:-) :wink:


WeBsPaCe - Mo 27.12.04 20:17

Zitat:
//hier einfach den namen von unserm fenster eingeben, einfach spiel starten,
//dann alt+tab drücken und in der taskleiste schaun wie das programm heisst


Das hab ich net so wirklich kapiert... :-)

Soll man hier die Caption des Spielefensters eintragen??


WeBsPaCe - Mo 27.12.04 21:02

Ahhh, ok, muss ja die Caption vom Spiel sein, weil:


Delphi-Quelltext
1:
FindWindow(nil,WindowTitle);                    


ja sonst nix richtiges findet... macht ja nur so sinn...


Karlson - Mo 27.12.04 21:03

Hab ich da jetzt was verpasst, oder muss man jedesmal wenn den Cheat benutzen will erst wieder TSearch bemühen und die Adresse finden? Denn diese ändert sich doch bei jedem neustart! :?


WeBsPaCe - Mo 27.12.04 21:09

Also, sorry, aber ich raff' schon wieder was net...

In diesem Quellcode:

Zitat:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
const v1 = $90  
begin  
 WindowName  :=  FindWindow(nil,WindowTitle);  
          If  WindowName  =  0  then MessageDlg('...erst spiel starten...dann trainer starten =)',  mtwarning,[mbOK],0);  
    ThreadId  :=  GetWindowThreadProcessId(WindowName,@ProcessId);  
    HandleWindow  :=  OpenProcess(PROCESS_ALL_ACCESS,False,ProcessId);  
    GetMem(buf,1);  
    buf^  :=  Chr(v1);  
    FreeMem(buf);  
    closehandle(HandleWindow);  
end;


wird zwar abgefragt, ob das Game überhaupt läuft:


Delphi-Quelltext
1:
2:
3:
const v1 = $90  
 WindowName  :=  FindWindow(nil,WindowTitle);  
          If  WindowName  =  0  then MessageDlg('...erst spiel starten...dann trainer starten =)',  mtwarning,[mbOK],0);


...aber wird dann der nachfolgende Code nicht trotzdem ausgeführt??? Müsste man da nicht eine if-then-else-Konstruktion verwenden, also dann so:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
const v1 = $90  
begin  
WindowName  :=  FindWindow(nil,WindowTitle);  
If  WindowName  =  0  then MessageDlg('...erst spiel starten...dann trainer starten =)',  mtwarning,[mbOK],0else begin
    ThreadId  :=  GetWindowThreadProcessId(WindowName,@ProcessId);  
    HandleWindow  :=  OpenProcess(PROCESS_ALL_ACCESS,False,ProcessId);  
    GetMem(buf,1);  
    buf^  :=  Chr(v1);  
    FreeMem(buf);  
    closehandle(HandleWindow);  
end
end;


??????? Ich lerne gerne dazu.... :-)


WeBsPaCe - Mo 27.12.04 21:22

Also die Frage da oben bitte nicht vergessen, ich möcht nur mal kurz was zu Karlson sagn, also: @Karlson

Das hab ich eignlich au gedacht, habs aber mal mit der Zeit die bei MS Minesweeper durchläuft, ausprobiert, es scheint immer die 100579C zu sein.

Komisch oda net???


Karlson - Mo 27.12.04 22:03

Nein, wenn man sich etwas mit dem Windowsspeichermanagment auskennt nicht :lol:

Bei Minesweeper mag die Adresse zur Zeit der aktiven Windowssession durch glück konstant bleiben. Bei einem richtigem Spiel, mit sicherheit schon nach dem laden einer neuen map nicht mehr.

ps.: Zu deiner Frage: Stimmt, da hat der Threadersteller einen Fehler gemacht.


EUOCheffe - Di 28.12.04 01:57

Den Code könnte man etwas kürzer schreiben.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
procedure WriteValues;
var
  c : Cardinal;
begin  
  c:=FindWindow(nil,'Starcraft'); //Get WindowHandle
  if c=0 then
  begin 
    MessageDlg('...erst spiel starten...dann trainer starten =)',mtwarning,[mbOK],0);  
    Exit;
  end;
  GetWindowThreadProcessId(c,@c); //Get ProcessID and ignore ThreadID
  c:=OpenProcess(PROCESS_ALL_ACCESS,False,c);  //Get ProcessHandle
  WriteProcessMemory(c,Pointer($401F76),#144#144#144#144#144#144,6,nil);
  CloseHandle(c);  
end;


Die Adressen für dynamische Variablen ändern sich zwar immer wieder, aber deshalb modifiziert er ja den Code in diesem Tutorial. Der Programmcode greift über Pointer immer auf den richtigen Speicherbereich zu. Das ist ja auch gleich eine weitere Lösung zum "dna" Problem. Das Game legt die Variablen irgendwo im Speicher ab. Um diese selber wieder zu finden, muss es irgendwo Pointer auf diesen dynamischen Speicherbereich haben. Wenn diese Pointer dann statisch gespeichert sind, dann kann man über diese die Variablen finden. Einfach in TSearch im Range Mode nach der Adresse der gefundenen dma Variable suchen. Wenn das Game neu gestartet wird, dann ändert sich zwar die Adresse der Variable, der Pointer zeigt dann aber wider brav drauf (oder immer mit selbem Abstand davor).

Übrigens gibt's auf diesem Board auch einen Bereich für Tutorials.


Karlson - Di 28.12.04 03:26

EUOCheffe hat folgendes geschrieben:

Die Adressen für dynamische Variablen ändern sich zwar immer wieder, aber deshalb modifiziert er ja den Code in diesem Tutorial. Der Programmcode greift über Pointer immer auf den richtigen Speicherbereich zu. Das ist ja auch gleich eine weitere Lösung zum "dna" Problem. Das Game legt die Variablen irgendwo im Speicher ab. Um diese selber wieder zu finden, muss es irgendwo Pointer auf diesen dynamischen Speicherbereich haben. Wenn diese Pointer dann statisch gespeichert sind, dann kann man über diese die Variablen finden. Einfach in TSearch im Range Mode nach der Adresse der gefundenen dma Variable suchen. Wenn das Game neu gestartet wird, dann ändert sich zwar die Adresse der Variable, der Pointer zeigt dann aber wider brav drauf (oder immer mit selbem Abstand davor).

Übrigens gibt's auf diesem Board auch einen Bereich für Tutorials.


Hört sich intressant an! Das muss ich mir aber mal genauer noch anschauen...
Btw. Das Tutorial ist doch in der Tutorial-Sparte :lol: Du meintest wohl die Faq's...


EUOCheffe - Di 28.12.04 07:46

War es? Dann muss ich irgendwie falsch geguckt haben...


en!gma - Di 28.12.04 16:32

jo...also erstmal @ webspace:
Zitat:
n direktlink zum Programm wär besser...

also...war halt mein erstes tut überhaupt und wusste nich ob man sowas direkt verlinken darf oda sowas...
aber ich denke man konnte das tool auch so finden =)

Zitat:

Zitat:
delphi (ich habe delphi 7 benutzt)
warum sonst auch ins delphi-forum schreiben ???


es ging mir eher darum zu sagen dass ich version 7 benutz und nicht das programm delphi, villeicht funktioniert es ja bei älteren versionen nicht.

Zitat:

Das hab ich net so wirklich kapiert... :-)

Soll man hier die Caption des Spielefensters eintragen??

jo hab mich villeicht etwas komisch ausgedrückt...ich versuchs sofort etwas verständlicher zu schreiben.


dann mal @ karlson:
Zitat:
Hab ich da jetzt was verpasst, oder muss man jedesmal wenn den Cheat benutzen will erst wieder TSearch bemühen und die Adresse finden? Denn diese ändert sich doch bei jedem neustart! :?


also...villeicht sollte ich das im tut auch noch mal ein bischen besser erklären...
das hat halt mit den dma und sna zu tun...mit der methode vom autohack, umgehen wir diese dma und machen sogesehen daraus eine sma, damit wir immer darauf zugreifen können.

manche alte spiele benutzen immder die gleichen addressen.
aber trotzdem kann man hierbei die selbe methode verwenden wie bei den spielen mit dma.

Zitat:
ps.: Zu deiner Frage: Stimmt, da hat der Threadersteller einen Fehler gemacht.

was für einen fehler meintest du jex nochmal genau?
damit ich ihn verbessern kann =)

und zu guter letzt noch @EUOCheffe:
Zitat:

Den Code könnte man etwas kürzer schreiben.


also ich hab es ehrlichgesagt auch schon so probiert bzw ein wenig anders, aber dennoch hat er bei mir (nfsu2) immer einen fehler angezeigt und das spiel ist abgestürzt. deswegen hab ich erst einmal so aufgeschrieben, wie es bei mir funktioniert hat. aber ich werde es noch einmal genauso probieren wie du es vorgeschlagen hast und ggf verbessern. aber danke für den hinweis =)


WeBsPaCe - Di 28.12.04 16:34

Zitat:
jo...also erstmal @ webspace:
Zitat:
n direktlink zum Programm wär besser...

also...war halt mein erstes tut überhaupt und wusste nich ob man sowas direkt verlinken darf oda sowas...
aber ich denke man konnte das tool auch so finden =)


Natürlich!!! S'war ja net bös gemeint oda so... ich dacht nur s' waär vielleicht praktischer einfach drauf zu klickln anstatt zu suchen (Komfort für den Leser...) :-)

Nimms mir nich übel...


WeBsPaCe - Di 28.12.04 16:35

Zitat:
Zitat:

Zitat:
delphi (ich habe delphi 7 benutzt)
warum sonst auch ins delphi-forum schreiben ???


es ging mir eher darum zu sagen dass ich version 7 benutz und nicht das programm delphi, villeicht funktioniert es ja bei älteren versionen nicht.


OK.... sorry...
Hättest du "Delphiversion: 7" hätt ich ja nix gesagt....


WeBsPaCe - Di 28.12.04 16:36

Zitat:
Zitat:

Das hab ich net so wirklich kapiert...

Soll man hier die Caption des Spielefensters eintragen??

jo hab mich villeicht etwas komisch ausgedrückt...ich versuchs sofort etwas verständlicher zu schreiben.


Hatt sich ja dann beim Quellcode lesen geklärt... Von was sollte man sonst die ProcessID suchen....


WeBsPaCe - Di 28.12.04 16:37

Zitat:
Zitat:
ps.: Zu deiner Frage: Stimmt, da hat der Threadersteller einen Fehler gemacht.

was für einen fehler meintest du jex nochmal genau?
damit ich ihn verbessern kann =)


Er meinte den, den ich oben angesprochen hab, den mit der Abfrage, ob das Spiel läuft...


Karlson - Di 28.12.04 16:40

Sag mal WebSpace, sind da jetzt wirklich 4 Posts für nötig gewesen? :lol:

@en1gma: Du hast ein Exit beim abfragen ob das Handle = 0 ist vergessen.


WeBsPaCe - Di 28.12.04 16:42

@Karlson

Guck mal auf die Zeit... Ich hab direkt geantwortet und da isses doch wohl besser wenn er die Antwort teilweise zu den Fragen passend bekommt, als wenn ich einen Roman schreibe... oda?? :-)


en!gma - Di 28.12.04 16:49

naja is ja auch unwichtig...
aber jex hab ich auch den fehler gesehen...danke...
ich werd heute abend mal schaun was ich noch verbessern kann und das ganze tut ein wenig überarbeiten =)


WeBsPaCe - Di 28.12.04 17:18

Ich bin grad dabei die Zeit bei MineSweeper zu "freezen". Mein MineSweeper is von MS Win XP Pro Schülerversion (glaub aba net das es da Unterschiede gibbt..). Un die Zeit is da bei mir an Adresse 100579C. Bei euch auch???

Das mit dem einfrieren klappt eignlich auch, aber wat is mit "auftauen" (:-)) Geht das auch??? Und ich hab eignlich noch net so ganz kapiert, was ich überhaupt mach... :(

Ich hol mal noch schnell den Quellcode vom Trainer und poste den dann noch...

Und das mit dem Speicher ist jeze glaub ich klar... Ich versuchs mal in meinen Worten zu sagn: Also, das Programm (bei mir MineSweeper, bei en!gma Starcraft...) bekommt einen Bereich im Speicher zugewiesen. Dieser variiert je nach dem was grad auf dem PC läuft, weil ja alle Programm nen Teil bekommen und nicht immer den selben... So, unser Spiel hat nun seinen Bereich und in diesem Bereich ist die Verteilung aber immer gleich... Variablen werden immer an folgende Stelle geschrieben: <<SPEICHERBEREICH DES SPIELS>> + <<BEKANNTER WERT>>. Der "bekannte Wert" bleibt immer gleich, der Speicherbereich variiert... Wir können jetzt aber in unserm Trainer den Speicherbereich des Spiel rausfinden und addieren den bekannten Wert dazu (Wir laufen zu unserer "Variablen" mit dem Inhalt z.B. die Zeit oder Ammo oder sonst wat..) und sind am Ziel. Dort verändern wir irgendwas (dat is dat wat ich noch nich kapiert hab, falls das hier richtig is, sonst raff ich gar nix.. :-( ) und schon isses feddisch...

Stimmt das jeze so ungefähr???


en!gma - Di 28.12.04 18:07

jo so im groben isses richtig...
um das ganze mal gaaaaaaaaaaaaaanz grob im code zu erklären:


Quelltext
1:
2:
3:
4:
5:
if linkeTaste.gedrueckt=True then
       begin
        Schiessen;
        MunnitionAbziehen; //zB in der Addresse 123456AB und hat den wert 1283
       end;


und unser ziel is nun das daraus zu machen ->


Quelltext
1:
2:
3:
4:
5:
if linkeTaste.gedrueckt=True then
       begin
        Schiessen;
        macheNichts; //wir weisen 123456AB den wert 9090 zu (also 90 für nop wie im tut erklärt)
       end;


so sieht also unser trainer anschliessend aus...wenn du ihn nun "unfreezen" willst
musst du einfach der addresse 123456AB wieder den wert 1283 zuweisen...

hoffe das is jex ein bischen verständlicher.


WeBsPaCe - Di 28.12.04 18:30

Jop, dat isses... Dann muss ich aber auch ersma den Wert wissen, der vorher drinne is.. also muss ich ihn auslesn... Also: Frage: Wie mach ich dat???


en!gma - Di 28.12.04 18:42

also du hast ja mit autohack deine addresse herausgefunden...
also in tsearch -> autohack...
und da hat er dir ja die addresse gezeigt die du verändern musst...
wenn du diese addresse oben anklickst, steht unten der wert dieser addresse...
und den musst du dir aufschreiben.

und die 9090 dann halt wieder durch 1283 ersetzen.


WeBsPaCe - Di 28.12.04 19:01

Zitat:
und die 9090 dann halt wieder durch 1283 ersetzen.


Is diese 1283 jeze nur ein beliebiger Wert, den du aus Starcraft genommen hast, oder is dat wie die 90, die für nichts steht (ist dat ungefähr vergleichbar mit nil bei Delphi oder void bei C ???)... Und bei MineSweeper ändert sich die Zeit ja immer... also muss ich die Zeit vorher auslesn??? Also wenn der User bei 5 sek stoppt muss es ja nach dem unfreezen bei 6 weitergehn...

:-)


Karlson - Di 28.12.04 19:20

WeBsPaCe hat folgendes geschrieben:
@Karlson

Guck mal auf die Zeit... Ich hab direkt geantwortet und da isses doch wohl besser wenn er die Antwort teilweise zu den Fragen passend bekommt, als wenn ich einen Roman schreibe... oda?? :-)


Nein ist es nicht :?

Aber ich denke mal ein Moderator wird dir das noch erklären.


en!gma - Di 28.12.04 22:22

in meinem tutorial wird mehr erklärt, wie man verhindert dass in deinem beispiel die zeit weiterläuft.

also ersetzen wir sogesehen die "setze zeit+1 prozedur" durch ein einfaches "nil".
ja damit hast du recht also nil ist wie die 90...

also erstmal die 1283 war auch nur ein beispiel...

ums noch einmal zu erklären ;D :

addresse 123456AB wert 1283("setze zeit+1 prozedur")
daraus machen wir ->
addresse 123456AB wert 9090("nichts und nochnmal nichts prozedur ^^")

und so kannste auch ganz einfach anstatt den 9090 wieder 1283 einfügen und hast die alte prozedur


Delete - Mi 29.12.04 00:34
Titel: Re: spiele trainer erstellen
en!gma hat folgendes geschrieben:
normalerweise sind 1 byte 2 zahlen, 2 byte 4 zahlen, 3 byte 6 usw...

So ein Quatsch. 126 bekomme ich auch in ein Byte rein. Es geht schlicht und ergreifend um den Wertebereich von Datentypen, hier insbesondere um ganzzahlige Datentypen.

Quelltext
1:
2:
3:
4:
5:
6:
7:
Shortint  –128..127                 signed 8-bit
Smallint  –32768..32767             signed 16-bit
Longint   –2147483648..2147483647   signed 32-bit
Int64     –2^63..2^63–1             signed 64-bit
Byte      0..255                    unsigned 8-bit
Word      0..65535                  unsigned 16-bit
Longword  0..4294967295             unsigned 32-bit

Ich kann auch meine 50 Mineralien Einheiten in ein LongInt packen. Und dann hast du nämlich ein zusätzliches Problem. Kennst du den Datentyp nämlich nicht, stimmt zwar deine Adresse, aber hast du ihn zu groß gewählt, überschreibst du den Speicher an den nachfolgenden Adressen. Und hast du ihn zu klein gewählt, hast du nachher Schrott im Spiel stehen.


Udontknow - Mi 29.12.04 11:36

Zitat:
So ein Quatsch. 126 bekomme ich auch in ein Byte rein. Es geht schlicht und ergreifend um den Wertebereich von Datentypen, hier insbesondere um ganzzahlige Datentypen.

Ja, er hat es ungeschickt ausgedrückt. Er meinte einfach die hexadezimale Darstellung, die bei einem Byte in zwei Ziffern, bei einem Word in 4 Ziffern usw. möglich ist.

CU,
Udontknow


en!gma - Mi 29.12.04 15:18

jo das stimmt wohl...da hab ich mich wirklich ein wenig ungeschickt ausgedrückt...

aber ich denke jeder der mehr als 1 woche mit delphi arbeitet weiss, dass zB 4 byte mehr als 8 zahlen sein können.


Heiko - Mi 29.12.04 16:06

Gibt es eigentlich auch unsigned 64-bit Varaiablen (also Int64 ohne Vorzeichen)?


Delete - Mi 29.12.04 21:56

en!gma hat folgendes geschrieben:

aber ich denke jeder der mehr als 1 woche mit delphi arbeitet weiss, dass zB 4 byte mehr als 8 zahlen sein können.

Das stimmt ja schon wieder nicht! Aus den Ziffern 0 bis 9 sind Zahlen zusammen gesetzt:
18 das ist eine Zahl bestehen aus den Ziffern 1 und 8.
Und ein Integer mit 4 Byte kann 4294967295 verschiedenen Werte annehmen. Und dann spricht man von einem Wertebereich. Ich will ja nicht kleinlich wirken, aber wenn man schon ein Tutorial schreibt, dann sollte man sich auch korrekt ausdrücken (können).


retnyg - Mi 29.12.04 22:58

WeBsPaCe hat folgendes geschrieben:
Zitat:
und die 9090 dann halt wieder durch 1283 ersetzen.


Is diese 1283 jeze nur ein beliebiger Wert, den du aus Starcraft genommen hast, oder is dat wie die 90, die für nichts steht (ist dat ungefähr vergleichbar mit nil bei Delphi oder void bei C ???)... Und bei MineSweeper ändert sich die Zeit ja immer... also muss ich die Zeit vorher auslesn??? Also wenn der User bei 5 sek stoppt muss es ja nach dem unfreezen bei 6 weitergehn...

:-)


es geht hier um maschinencode, also assembler. der wert 90h (h für hex) steht für den Befehl NOP, also No Operation.
üblicherweise steht an der zu überschreibenden speicherposition das commando JMP + eine Speicheradresse, welche die nun auszuführende Funktion beinhaltet.
Sollte aber nicht JMP drin stehen sondern z.b. ADD AX, 1 oder etwas anderes, ist der Befehl möglicherweise auch länger als 2 bytes.

Deswegen versteh ich auch nicht enigma's ableitung über die byte-länge bei zahlen, macht ja irgendwie keinen Sinn denn hier gehts um Assembleranweisungen - das macht nur anfangs Sinn um die Speicherposi der Zahl rauszufinden.


WeBsPaCe - Do 30.12.04 00:02

Ich glaub' so langsam kapier ich's... :D

Ich mach mal an meinem MineSweeper-Ding weiter...


Karlson - Fr 31.12.04 18:04

Sehr schön, ich kannte zwar TSearch, aber dort nicht dieses "AutoHack" :)
Jetzt kann ich endlich versuchen meinen Trainer HL2 weiter zuschreiben...

Aber folgendes: Ich habe den Wert gesucht, der dafür verantwortlich ist, ob eine Waffe verfügbar ist. Habe ihn auch gefunden, habe jetzt auch den Pointer mit diesem Autohack gefunden. Aber wie kann ich den Wert mithilfe des Pointers überschreiben? Du tutst den Befehl ja mit NOP überschreiben, so dass der Befehl praktisch blockiert wird. Was muss ich den machen um den Wert von 0 in 1 zu ändern?

danke!


retnyg - Sa 01.01.05 03:07

if wert = 0 then wert := 1;


Karlson - Sa 01.01.05 06:05

retnyg hat folgendes geschrieben:
if wert = 0 then wert := 1;


bitte? Meinst du das jetzt ernst, oder soll das ein Sylvesterscherz sein :lol:


retnyg - Sa 01.01.05 09:41

:wink: war schon so gemeint, schreib einfach mal den Wert $1 (statt $90) an die betreffende speicheradresse...

wie hast du die eigentlich ausfindig gemacht ? gibt ja sicher tausende Posititonen im Speicher die gerade auf 0 oder 1 stehen :gruebel:


en!gma - Sa 01.01.05 14:39

das is halt eine sache des ausprobierens...

für hl² zb nimmste ne waffe...und suchst erstmal alle werte ab...also unknown value...
dann kommt halt das ausprobieren...
nimmst andre waffe und gehst auf weiter suchen und has changed...weil du ja deine waffe gewechselt hast...
dann wechselste wieda zur alten waffe und suchst wieder has changed...
dann bissl rumballern leben verlieren hin und herhüpfen...
dann suchste zB mal has not changed...dann musste halt aber aufpassen das du die selbe waffe hast wie zuvor...


Karlson - Sa 01.01.05 18:54

retnyg hat folgendes geschrieben:
:wink: war schon so gemeint, schreib einfach mal den Wert $1 (statt $90) an die betreffende speicheradresse...

wie hast du die eigentlich ausfindig gemacht ? gibt ja sicher tausende Posititonen im Speicher die gerade auf 0 oder 1 stehen :gruebel:


Nein, das kann doch nicht klappen. Ich würde dann ja schließlich den Befehl mit $1 überschreiben! Die Speicherstelle kenne ich ja im Grunde garnicht (bzw. nur wenn ich mit TSearch danach suche). ICh kenne nur diesen Pointer, zum Befehl, der ausgeführt wird wenn die Adresse geändert wird. Wenn ich diese dann mit NOP überschreibe, kann ich die Waffe nicht mehr bekommen :) Ich will aber irgendwie an die Waffe kommen!


en!gma - Sa 01.01.05 20:02

hmm...
dann solltest du villeicht erstmal die addresse der waffe herausfinden...
erst keine waffe in der hand...nach addressen suchen (unknown value) dann aufsammeln und schaun was sich verändert...
wieder wegschmeissen und wieda suchen und wieda und wieda....bis nur noch wenige übrig sind...


Karlson - Sa 01.01.05 20:11

Ja, das habe ich doch schon längst getan. Dann habe ich mit TSearch auf Autohack geklickt...das gleiche wie du oben. Die Adresse nutzt mir aber halt leider nichts, denn diese ändert sich ja ständig!


retnyg - So 02.01.05 16:28

Karlson hat folgendes geschrieben:

Nein, das kann doch nicht klappen. Ich würde dann ja schließlich den Befehl mit $1 überschreiben! Die Speicherstelle kenne ich ja im Grunde garnicht (bzw. nur wenn ich mit TSearch danach suche). ICh kenne nur diesen Pointer, zum Befehl, der ausgeführt wird wenn die Adresse geändert wird. Wenn ich diese dann mit NOP überschreibe, kann ich die Waffe nicht mehr bekommen :) Ich will aber irgendwie an die Waffe kommen!


Also, wenn an der betreffenden Stelle im Speicher der Wert $0 steht, dann ist das ein Speicherbereich der Daten enthält (also den Wert SpielerHatWaffeX : 0 oder 1 ... wenn der Wert ein Boolean ist wirst du dir aber wahrscheinlich schwertun...is ja nur ein bit ;-)). Die Daten kannst du problemlos überschreiben.
Ansonsten musst du dir was andres einfallen lassen... z.b. findest du den JMP Befehl zu der Prozedur die eine Megawaffe zu deinem arsenal hinzufügt. dann suchst du eine Prozedur die häufig vorkommt (wie Z.B. PickupEnforcer...das pistölchen bei UT), du aber nicht unbedingt brauchst und lässt von dorthin immer an deine speicherstelle springen...sicher keine besonders elegante lösung, aber mir fällt momentan nix bessres ein :P


WeBsPaCe - Mo 03.01.05 17:30

Hi!!

Sorry, ich hab' schon wieder ne Frage!! Das mit MineSweeper war ja irgendwie noch einfach... ich schreib euch mal auf, was ich gemacht hab:

1. TSearch nach der aktuellen Zeit gesucht.
2. Adresse 100579C rausbekommen.
3. Auch nach Neustart von Windows und mehreren anderen Programmen im Hintergrund: Adresse bleibt gleich!
4. Das Programm von en!gma umgeschrieben (Window-Title geändert, den Gas-Cheat-Abschnitt gelöscht, die letzten 5 WriteProcessMemory-Zeilen gelöscht, in der ersten WriteProcessMemory-Zeile die Adresse $401F76 durch $100579C ersetzt.
5. Es funktioniert.

So, jetzt nehm ich mir SCPT ran!!

1. TSearch nach den aktuell vorhandenen Blendgranaten gesucht.
2. Adresse 2D36A9C rausbekommen.
3. Bei Neustart des Levels andere Adresse: 2DB771C :-(
4. Ich bin verzweifelt... :-)
5. Im AutoHack einen BreakPoint gesetzt mit der aktuellen Adresse mit dem Wert von den Blendgranaten, bei BspSize einfach mal die 1 gelassen und bei Type Write reingemacht.
6. In der Liste bei Debug event steht jetzt: "10A54AAB: cmp dword ptr [ebp+0x324],0xA" und "10A54AD5: mov eax,[ebp+0x324]"
7. In SCPT eine Blendgranate geworfen.
8. Es taucht der Eintrag "10AC0EBD: mov [edi+0x324],ecx" neu dazu auf.
9. Vermutung, dass das die Aktion ist, die da was bei der Ammo abzieht.
10. Den letzten dazugekommenen Punkt "gepatch" und siehe da: Bei Blendganateschmeißen geht die Ammo nichmehr runter. :-)

Problem: Wenn ich jetzt die Adresse 10AC0EBD im Delphiprogramm reinschreib, stürzt das Spiel ab... :-(

Ich glaube, dass das der Punkt ist, den ich noch nicht verstanden habe, also BITTE sagt mir was ich falsch gemacht habe. Am besten wäre es, wenn ihr einfach den Code posten könntet, der das herabzählen freezt.

THX


F34r0fTh3D4rk - Mo 03.01.05 18:25

wenns fertig ist hätte ichs auch mal gerne um zu schaun wies funzt :)


retnyg - Mo 03.01.05 20:45

SCPT ? was ist denn das ^^


WeBsPaCe - Mo 03.01.05 20:51

SCPT = Splinter Cell Pandora Tomorrow :D


retnyg - Di 04.01.05 00:36

WeBsPaCe hat folgendes geschrieben:

8. Es taucht der Eintrag "10AC0EBD: mov [edi+0x324],ecx" neu dazu auf.

Problem: Wenn ich jetzt die Adresse 10AC0EBD im Delphiprogramm reinschreib, stürzt das Spiel ab... :-(


poste mal die Prozedur mit der du das machst


WeBsPaCe - Di 04.01.05 20:27

Damit:


Delphi-Quelltext
1:
WriteProcessMemory(HandleWindow,ptr($10AC0EBD),buf,1,write);                    


F34r0fTh3D4rk - Di 04.01.05 20:29

kann denn hier nochmal die fehlerfreie version gepostet werden plz :? ?


retnyg - Di 04.01.05 22:56

WeBsPaCe hat folgendes geschrieben:
Damit:


Delphi-Quelltext
1:
WriteProcessMemory(HandleWindow,ptr($10AC0EBD),buf,1,write);                    


du überschreibst nur ein byte - die länge des befehls mov [edi+0x324],ecx ist aber 4 bytes


WeBsPaCe - Mi 05.01.05 12:50

Gut okay, vielen Dank, ich probiers mal... :D
Woher weißt du eigentlich, dass es 4 Bytes sind???


MrSaint - Mi 05.01.05 13:00

$10AC0EBD = 4 byte..
1 byte = 2 Hex-Zeichen


WeBsPaCe - Mi 05.01.05 13:02

Gott bin ich blöd!!! Da hätt' ich auch selber draufkommen können!!! :autsch:


retnyg - Mi 05.01.05 13:04

MrSaint hat folgendes geschrieben:
$10AC0EBD = 4 byte..
1 byte = 2 Hex-Zeichen


moment mal:
$10AC0EBD ist ein Zeiger zu einem speicherbereich, und in dem fall kein Maschinencode
du liegst also falsch


WeBsPaCe - Mi 05.01.05 13:05

Wat jetzt??? :shock: :? :roll:


MrSaint - Mi 05.01.05 13:05

retnyg hat folgendes geschrieben:
moment mal:
$10AC0EBD ist ein Zeiger zu einem speicherbereich, und in dem fall kein Maschinencode
du liegst also falsch


:oops: natürlich... da hab ich wohl zu schnell geantwortet :oops: geb mich geschlagen ;)


retnyg - Mi 05.01.05 13:10

@webspace: ich habe nach mov commandos gegoogelt, und mir angesehen wieviel bytes das commando üblicherweise benötigt wenn 2 bytes an daten übergeben werden (0324h)

ich wünschte ich hätte eine tabelle wo zu jedem assemblercommando der entsprechende byte-wert dabeistünde, oder umgekehrt.
oder einen "mini-compiler", der mir ein commando wie "add bx,cx" in den entsprechenden maschinencode umwandelt.


WeBsPaCe - Mi 05.01.05 13:17

Gut, ich muss also vier Zeilen Code verwenden, für die 4 Bytes, ähnlich dem nachfolgenden:

Delphi-Quelltext
1:
2:
3:
4:
WriteProcessMemory(HandleWindow,ptr($10AC0EBD),buf,1,write);
WriteProcessMemory(HandleWindow,ptr($10AC0EBD),buf,1,write);
WriteProcessMemory(HandleWindow,ptr($10AC0EBD),buf,1,write);
WriteProcessMemory(HandleWindow,ptr($10AC0EBD),buf,1,write);


Nur das, was ich unterlegt hab, muss ja anders aussehen, nählich die Zahlen, die danach kömmen.. Nur wie zählt man beim Hexadezimalsystem??

1--01
2--02
3--03
4--04
5--05
6--06
7--07
8--08
9--09
10--0A
11--0B
12--0C
13--0D
14--0E
15--0F
16--10
17--11
18--12
19--13
20--14

Stimmt das so ungefähr?? (Ich hab' das vorher noch nie gesehen!! Ich denk mir das nur so, weil n bissele logisch ist, kann also total falsch sein!! :D)

Also ist die Reihenfolge so??

$10AC0EBD
$10AC0EBE
$10AC0EBF
$10AC0EC0


MrSaint - Mi 05.01.05 13:20

WeBsPaCe hat folgendes geschrieben:
Also ist die Reihenfolge so??

$10AC0EBD
$10AC0EBE
$10AC0EBF
$10AC0EC0


Ja. Oder du packst in deinen Puffer gleich alle 4 Bytes rein und machst dann ein


Delphi-Quelltext
1:
WriteProcessMemory(HandleWindow,ptr($10AC0EBD),buf,4,write);                    


WeBsPaCe - Mi 05.01.05 13:23

Zitat:
Ja. Oder du packst in deinen Puffer gleich alle 4 Bytes rein und machst dann ein


:rofl: Ich glaubs nich!! So ein Sch.... Da hätt' ich mir das da oebn ja sparn können!!! Egal jetzt weiß ich wenigstens was von Hexadezimalzahlen!! Brauch ich vielleicht irgendwann... oder auch nich'... :rofl: :rofl:


retnyg - Mi 05.01.05 13:25

das kannst du ganz sicher gebrauchen...
tut dein programm jetzt ?


WeBsPaCe - Mi 05.01.05 13:46

Nein!!! :cry:

Also:
Ich hab da jetzt die Zeile da stehen:WriteProcessMemory(HandleWindow,ptr($10AC0EBD),buf,4,write);

Wenn ich das Prog jetzt so starte, verreckt SCPT wieder!! Ich hab dann nochmal mit TSearch nachgeguckt, ob es auch wirklich die Adresse ist... Und dann stand auch ne andre drin: $10AC0EF7!!!

Ich hab dann mal das Debug-Fester offen gelassen und die neue Adresse in mein Prog reingeschrieben und es ist wieder abgestürzt.. Im AutoHack-Ding stand dann noch zusätzlich zu dem vorherigen Eintrag das da drin:

10AC0EBD: dec dword ptr [ecx+0x324]

Das ist wieder die alte Adresse!!! Aber mit nem andren Assembler-Code!!! Ich blicks nichmehr... Im Debugfenster steht also jetzt insgesamt:

10AC0EF7: mov [edi+0x324],ecx
10AC0EBD: dec dword ptr [ecx+0x324]


HILFE!! Sorry, ich piens' wohl zu arg rum, wat?? Aber das kotzt mich irgendwie schon an!!!


F34r0fTh3D4rk - Mi 05.01.05 14:36

ich verstehs ehrlich gesagt überhaupt nich, was macht der code, unterdrückt er einen command ? wie kann man werte mit delphi verändern oder was tut dieser code ?
was ist wenn ich in starcraft meinetwegen 9999 mineralieren haben und freezen möchte, welchen hexcode muss ich wovon wofür wie nehmen ? :oops: :? :shock:


WeBsPaCe - Mi 05.01.05 14:40

Hast du dir das Tutorial auf Seite 1 denn überhaupt mal durch gelesen?? Deine Fragen werden dadrin eigentlich beantwortet.. :wink:

Wenn nicht, dann poste sie nochmal, aber n bissele präziser!! :wink:


F34r0fTh3D4rk - Mi 05.01.05 14:45

ja ich habs auch verfolgt, wenn man diesen wert im autohack window freezt wird der Befehl zB. um health abgezogen zu bekommen blockiert und mit dem anderen hex dingels kann man den wert verändern, aber wie kann ich denn in delphi machen ja ich will jede sekunde + 1 health oda so ?


WeBsPaCe - Mi 05.01.05 14:49

Dann musst du in die Speicheradresse einen anderen Assemblercode reinschreiben, also nich diese lustige 90, die für "gar-nichts-machen" steht, sondern was was für "health+1" steht. Was genau das ist, weiß ich auch nich'...

Ich guck' mich aber mal nach einem Assembler-Tut um... :roll:


retnyg - Mi 05.01.05 15:29

hmm nett... ich hab das jetzt eben zum ersten mal probiert. habe in 5 min bereits einen funktionierenden GOD-Mode Trainer für UT erstellt =)
sehr cooles tool das tsearch.

bei dem autohack sieht man die Prozessspeicherposition des Kommandos, das ausgeführt wird wenn sich der im TSearch beobachtete Wert ändert. bei UT also: 10133C14: mov [edi],eax (wenn von der health was abgezogen wird).
Rein theoretisch sollte sich der Programmcode immer an der selben Posi im Speicher befinden, ausser an der exe wurde was geändert.


WeBsPaCe - Mi 05.01.05 15:36

Hi retnyg!!! :D

Kannst du deinen Unit-Code vielleicht mal schnell posten??


retnyg - Mi 05.01.05 15:39

gerne, is zwar nix berühmtes...

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
procedure WriteValues;
var
  c : Cardinal;
  buf: pchar;
begin
  c:=FindWindow(nil,'Unreal Tournament'); //Get WindowHandle
  buf := #144#144;
  if c=0 then
  begin
    MessageDlg('...erst spiel starten...dann trainer starten =)',mtwarning,[mbOK],0);
    Exit;
  end;
  GetWindowThreadProcessId(c,@c); //Get ProcessID and ignore ThreadID
  c:=OpenProcess(PROCESS_ALL_ACCESS,False,c);  //Get ProcessHandle
  WriteProcessMemory(c,Ptr($10133c14),buf,2,write);
  CloseHandle(c);
end;


WeBsPaCe - Mi 05.01.05 15:44

Ist das wirklich alles, poste doch mal wirklich die ganze Unit, weil wenn ich deinen Code bei mir compilieren will, sagt er: [Error] Unit1.pas(40): E2033 Types of actual and formal var parameters must be identical!!! :cry:


retnyg - Mi 05.01.05 15:48

ups sorry

so wärs richtig:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
procedure WriteValues;
var
  c, write : Cardinal;
  buf: pchar;
begin
  c:=FindWindow(nil,'Unreal Tournament'); //Get WindowHandle
  buf := #144#144;
  if c=0 then
  begin
    MessageDlg('...erst spiel starten...dann trainer starten =)',mtwarning,[mbOK],0);
    Exit;
  end;
  GetWindowThreadProcessId(c,@c); //Get ProcessID and ignore ThreadID
  c:=OpenProcess(PROCESS_ALL_ACCESS,False,c);  //Get ProcessHandle
  WriteProcessMemory(c,Ptr($10133c14),buf,2,write);
  CloseHandle(c);
end;


WeBsPaCe - Mi 05.01.05 16:17

VIELEN DANK!!!! SO FUNKTIONIERTS!!!! :dance: :dance2:

Es lag daran, dass dieser Assembler-Befehl doch nur 2 und keine 4 Bytes hatte!!! Wie bekomme ich das denn jetzt wirklich raus?? Weiß das jemand?? Woher wusstest du denn das retnyg??

@F34r0fTh3D4rk
Brauchst du den Code noch??


F34r0fTh3D4rk - Mi 05.01.05 16:23

also ich finde Tsearch nicht so gut, vor allem wenn wie bei diablo die werte für health nicht bekannt sind, der generic game trainer ist da besser geeignet.

Ich habe versucht die punkte im 3d pinball von windows zu freezen, das spiel ist abgestürzt, wenn ich das gleiche bei dem anderen hex wert gemacht habe hatte ich irgendwas um die 4 millionen punkte.

Die Zeit beim minesweeper zu freezen hab ich auch ausprobiert, das geht:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
var
Form1: TForm1;
WindowName: integer;
ProcessId: integer;
ThreadId: integer;
buf: PChar;
HandleWindow: Integer;
write: cardinal;

Const
WindowTitle = 'MineSweeper';

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
const
v1 = $90;
begin
WindowName  :=  FindWindow(nil,WindowTitle);
If  WindowName  =  0  then showmessage('Bitte starten Sie zuerst das Spiel' + #13 + 'bevor Sie den Trainer aktivieren!'else begin
ThreadId  :=  GetWindowThreadProcessId(WindowName,@ProcessId);
HandleWindow  :=  OpenProcess(PROCESS_ALL_ACCESS,False,ProcessId);
GetMem(buf,1);
buf^  :=  Chr(v1);
WriteProcessMemory(HandleWindow,ptr($1002FF5),buf,4,write);
FreeMem(buf);
closehandle(HandleWindow);
showmessage('Die Zeit wurde eingefroren!');
end;
end;


Wie kann ich das jetzt aber wieder unfreezen und wie kann ich den Wert bearbeiten ? Also zB: 50 Sek ?


retnyg - Mi 05.01.05 16:30

gern geschehen. dass der befehl bei mir 2 bytes hat liegt daran dass es nur ein mov register1, register2 ist. was immer 2 bytes lang ist...
ich habe die routine oben mal so geändert, dass man ihr als parameter den Spiele-Titel, die Adresse des zu patchenden Codes, und die Anzahl an Bytes reinschreiben kann:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
procedure WriteProcMem(procWndTitle: string;CodeAddr:integer; numberNops:byte);
var
  c, write : Cardinal;
  buf: pchar;
  i: byte;
begin
  c:=FindWindow(nil,pchar(procWndTitle)); //Get WindowHandle
  if c=0 then
  begin
    MessageDlg('...erst spiel starten...dann trainer starten =)',mtwarning,[mbOK],0);
    Exit;
  end;
  buf := '';
  for i := 1 to numbernops do  buf := buf + $90;
  GetWindowThreadProcessId(c,@c); //Get ProcessID and ignore ThreadID
  c:=OpenProcess(PROCESS_ALL_ACCESS,False,c);  //Get ProcessHandle
  WriteProcessMemory(c,Ptr(CodeAddr),buf,numberNops,write);
  CloseHandle(c);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  writeprocMem('Unreal Tournament',$10133c14,2);
end;


WeBsPaCe - Mi 05.01.05 16:31

Zitat:
der generic game trainer ist da besser geeignet.

Wo bekomm' ich den her??

Zitat:
Ich habe versucht die punkte im 3d pinball von windows zu freezen, das spiel ist abgestürzt, wenn ich das gleiche bei dem anderen hex wert gemacht habe hatte ich irgendwas um die 4 millionen punkte.

Poste mal den Code, sonst kann man da ja nich' viel sagn, ne?? :wink:

Zitat:
Die Zeit beim minesweeper zu freezen hab ich auch ausprobiert, das geht:

Welches Windows, bzw. welches MineSweeper hast du?? Weil ich hab' ne andere Adresse wie du: $100579C

Zitat:
Wie kann ich das jetzt aber wieder unfreezen und wie kann ich den Wert bearbeiten ? Also zB: 50 Sek ?

Dazu musst du wieder Assembler können. Wenn ich ein Tutorial finden, schreib ichs als EDIT dazu.. :D

//EDIT:http://andremueller.gmxhome.de/intro.html


retnyg - Mi 05.01.05 16:36

oder

http://www.deinmeister.de/wasmtut.htm <- win32 asm tut
http://www.onlinetutorials.de/asm-002.htm <- DOS asm tut


F34r0fTh3D4rk - Mi 05.01.05 16:37

danke ich werds mir anschauen :)

EDIT:

http://www.telus.net/jz/gentrain

da ist der generic druf


retnyg - Mi 05.01.05 16:40

lol

sehe grade dass mein UT-Trainer noch anderes kann: Jumpboots und AMMO werden auch ned abgezogen ;)

war zwar nicht geplant, aber bitte...


F34r0fTh3D4rk - Mi 05.01.05 16:41

ist assembler dringend notwendig, das muss doch so ähnlich gehen oda nich ?


retnyg - Mi 05.01.05 16:43

im prinzip musst du dir nur vorstellen können was da passiert, und an der richtigen stelle die nops setzen. ASM musst du nur können, wenn du da komplett eigene routinen reinschreiben willst.


WeBsPaCe - Mi 05.01.05 16:44

@F34r0fTh3D4rk

Irgendwie ist dein Link bissele komisch!! Hast du keinen Direktlink zur .zip oder .exe?? Wär besser... DANKE!!


F34r0fTh3D4rk - Mi 05.01.05 16:44

und wie sähe das denn aus ich finde das pass hier inst tut ganz gut rein (geht ja auch um trainer :)) Also StarCraft Minaralien auf 9999 setzen oda so ?


retnyg - Mi 05.01.05 16:52

bei anzahl mineralien handelt es sich um daten, nicht um code. das autohack nützt dir hir also nix, weil du damit nur die stellen im code rauskriegst die diesen wert verändern. du musst direkt in den adressbereich des wertes schreiben, den du bei der Suche mit THack zu der "liste" hinzufügst.
Dort schreibst du dann nicht $90 - NOP rein, sondern $FF - 255. das halt 4 mal, wenn der wert 4 bytes lang ist.
problematischerweise wird sich die adresse des Datenspeichers aber bei jedem Start des Spiels ändern. ein trainer nützt da also ned wirklich was


Karlson - Mi 05.01.05 16:56

retnyg hat folgendes geschrieben:
ups sorry

so wärs richtig:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
procedure WriteValues;
var
  c, write : Cardinal;
  buf: pchar;
begin
  c:=FindWindow(nil,'Unreal Tournament'); //Get WindowHandle
  buf := #144#144;
  if c=0 then
  begin
    MessageDlg('...erst spiel starten...dann trainer starten =)',mtwarning,[mbOK],0);
    Exit;
  end;
  GetWindowThreadProcessId(c,@c); //Get ProcessID and ignore ThreadID
  c:=OpenProcess(PROCESS_ALL_ACCESS,False,c);  //Get ProcessHandle
  WriteProcessMemory(c,Ptr($10133c14),buf,2,write);
  CloseHandle(c);
end;


Moin Günther (ich geh mal davon aus dass du so heisst ;) )

Das ist also ein Gottmode...jetzt gibts nur folgende Frage für mich: Was bedeutet dieses #144#144 :lol: Das gleiche wie nop?

Ich muss nochmal wegen meinem HL2 Trainer fragen:

Also, irgndwo im Speicher befindet sich eine Booleanvariable, die für "Waffe verfügbar" den wert 1 und für "Waffe nicht verfügbar" den Wert 0 annimmt. Also bin ich mit TSearch hergegangen, und habe mithilfe des bekannten Verfahrens nach der Adresse gesucht. Ich habe sie gefunden und es ist sagen wir mal die Adresse $123456. Diese Adresse könnte ich jetzt mit WriteProcessMemory umschreiben. Bekanntes Problem: Sobald ich das Spiel neustarte ist die Adresse wo anders. Also greife ich auf dieses Tutorial zurück, und mach es wie en1gma es beschrieben hat, und such mit TSearch's Autohack, nach der Adresse des Befehls. Diese Adresse (kann ich nicht auswendig) von mir aus ist es $a123202. An dieser stelle wird der ASM Befehl "Dec DWORD". Also Decrease DWORd. DWord ist der wert unserer Adresse $123456. Wunderbar, doch hilft es mir nun herzlich wenig, den Befehl mit Nop zu überschreiben. Es würde lediglich bewirken, dass ich die Waffe auch noch besitze nachdem ich sie eigentlich weggeschmissen habe. Problem: Wenn ich die Waffe überhaupt nicht habe! Der Wert ist 0. Ich muss den Wert der Adresse $123456 allerdings in $1 umschreiben. Es gibt dann natürlich auch noch den Befehl an der Stelle $a1234234, der INC dWord [irgendwas] heisst. Also increase Adresse $123456. Ich müsste es also schaffen, das PRogramm dazu anzustiften, diesen Befehl auszuführen. Wie gehts das? :mrgreen:


Stefan-W - Mi 05.01.05 16:57

hi Leut's ich verfolge das hier schon von anfag ann und ich finds interessant!

Ich hab mal den Link [http://www.downloads.de/details.php?id=3503&tabelle=Computerspiele] zum Generic Game Trainer 1.61 raus gesucht :-)

Cu


F34r0fTh3D4rk - Mi 05.01.05 17:01

hier noch n paar interessante toolz

http://www.downloads.de/rubrik.php?seite=1&tabelle=Computerspiele&rubrik=Cheatprogramme&sort=datum_update


retnyg - Mi 05.01.05 17:03

Karlson hat folgendes geschrieben:
Was bedeutet dieses #144#144 :lol: Das gleiche wie nop?

tach karlson :)
also, ja.

NOP = 90 hex oder 144 dezimal

also ist #144 genau das gleiche wie $90

ich würde dir aber empfehlen die angepasste prozedur WriteProcMem zu verwenden, die ich 2-3 einträge später gepostet habe.

gruss retnyg (wo siehst du da ein H ?) ;)


F34r0fTh3D4rk - Mi 05.01.05 17:06

also hat jemand n code parat wie man zB in minesweeper die zeit zb. auf 30 oder zeit+1 setzen kann, plz code sonst steig ich da nich druch (habs net so mit theorie :lol: )

:oops:


Karlson - Mi 05.01.05 17:12

F34r0fTh3D4rk hat folgendes geschrieben:
also hat jemand n code parat wie man zB in minesweeper die zeit zb. auf 30 oder zeit+1 setzen kann, plz code sonst steig ich da nich druch (habs net so mit theorie :lol: )

:oops:


Bingo, da hat jemand die selbe Frage wie ich! Lest euch bitte meinen dazu editierten Text oben durch ;) ich dachte nicht dass ihr so schnell seid.

@Retnyg: Jo alles klar also ist #144 = $90. Wieder was dazu gelernt :lol: Und stimmt Günther? Weil wenn man Retnyg rückwerts auspricht kommt günther raus :)


retnyg - Mi 05.01.05 17:44

Karlson hat folgendes geschrieben:
$a123202. An dieser stelle wird der ASM Befehl "Dec DWORD". Also Decrease DWORd. DWord ist der wert unserer Adresse $123456. Wunderbar, doch hilft es mir nun herzlich wenig, den Befehl mit Nop zu überschreiben. Es würde lediglich bewirken, dass ich die Waffe auch noch besitze nachdem ich sie eigentlich weggeschmissen habe. Problem: Wenn ich die Waffe überhaupt nicht habe! Der Wert ist 0. Ich muss den Wert der Adresse $123456 allerdings in $1 umschreiben. Es gibt dann natürlich auch noch den Befehl an der Stelle $a1234234, der INC dWord [irgendwas] heisst. Also increase Adresse $123456. Ich müsste es also schaffen, das PRogramm dazu anzustiften, diesen Befehl auszuführen. Wie gehts das? :mrgreen:


also wenn schon, dann steht da z.b dec dword ptr [ecx+0x28] also quasi hole adresse aus register ECX, tu 28h dazu, und ziehe eins bem Inhalt der daraus resultierenden adresse ab.
das wäre also der befehl, wenn du deine waffe verlierst. das kannst du ausnop'en und du verlierst die knarre nichtmehr.
um waffen zu kriegen die du nicht hast musst du wahrscheinlich selber die adresse im speicher aus dem assemblercode berechnen lassen (was auch erfordert dass du die entsprechenden register - zum richtigen zeitpunkt - ausliest), oder irgendwo im spielcode deinen eigenen assemblercode einbauen. das zu erläutern ginge aber zu weit, da ich es noch nie gemacht habe...

edit: von en!gma, dem threadstarter habe ich auch schon länger nichts mehr gehört... er kann dir sicher weiterhelfen :mrgreen:


retnyg - Mi 05.01.05 22:53

F34r0fTh3D4rk hat folgendes geschrieben:
also hat jemand n code parat wie man zB in minesweeper die zeit zb. auf 30 oder zeit+1 setzen kann, plz code sonst steig ich da nich druch (habs net so mit theorie :lol: )

:oops:



Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
procedure WriteProcMem(procWndTitle: string;CodeAddr:integer; numberNops:byte);
var
  c, write : Cardinal;
  buf: pchar;
  i: byte;
begin
  c:=FindWindow(nil,pchar(procWndTitle)); //Get WindowHandle
  if c=0 then
  begin
    MessageDlg('...erst spiel starten...dann trainer starten =)',mtwarning,[mbOK],0);
    Exit;
  end;
  buf := '';
  for i := 1 to numbernops do  buf := buf + $00;
  GetWindowThreadProcessId(c,@c); //Get ProcessID and ignore ThreadID
  c:=OpenProcess(PROCESS_ALL_ACCESS,False,c);  //Get ProcessHandle
  WriteProcessMemory(c,Ptr(CodeAddr),buf,numberNops,write);
  CloseHandle(c);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  writeprocMem('Minesweeper',$100579C,4);
end;


man beachte dass statt NOPs $00's an die SpeicherAdresse des Datenwertes von ElapsedTime bei Minesweeper geschrieben werden.


F34r0fTh3D4rk - Do 06.01.05 15:48

versteh ich net is das nich das gleiche wie vorhin ?

mach mal n beispiel wo du die elapsedtime auf 40 oda so hast !

Wo soll das geändert werden hier doch net etwa oder ?


Delphi-Quelltext
1:
for i := 1 to numbernops do  buf := buf + $00;                    


plz beispiel :D


retnyg - Do 06.01.05 16:30

der unterschied ist dass vorher 4 NOPs ($90) in den OP-CODE Bereich des Programmspeichers geschrieben wurden, und nun 4 mal der Wert $00 in den Datenbereich !

hier extra für dich ein minesweeper patch der die Zeit auf 40 stellt.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
procedure WriteProcMem(procWndTitle: string;CodeAddr:integer; Buffer: pchar; BufLen:byte);
var
  c, write : Cardinal;
  i: byte;
begin
  c:=FindWindow(nil,pchar(procWndTitle)); //Get WindowHandle
  if c=0 then
  begin
    MessageDlg('...erst spiel starten...dann trainer starten =)',mtwarning,[mbOK],0);
    Exit;
  end;
  GetWindowThreadProcessId(c,@c); //Get ProcessID and ignore ThreadID
  c:=OpenProcess(PROCESS_ALL_ACCESS,False,c);  //Get ProcessHandle
  WriteProcessMemory(c,Ptr(CodeAddr),buffer,buflen,write);
  CloseHandle(c);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  writeprocMem('Minesweeper',$100579C,#40#00#00#00,4);
end;


F34r0fTh3D4rk - Do 06.01.05 16:34

wäre

Delphi-Quelltext
1:
writeprocMem('Minesweeper',$100579C,#60#00#00#00,4);                    


dann 60 ?


retnyg - Do 06.01.05 16:41

ja, weil #60 = dezimal 60
$60 = hex 60 = dezimal 96

warum probierst dus nicht einfach aus ? :gruebel:


F34r0fTh3D4rk - Do 06.01.05 19:15

und was haben die hier zu bedeuten: #00#00#00 :gruebel:
sind das die 3 byte die noch zu 4 fehlen ?


retnyg - Sa 08.01.05 02:18

genau. der wert ist halt in einer 4 byte grossen variable gespeichert, obwohl 2 byte für die zahlen 1-999 auch reichen würden.


F34r0fTh3D4rk - Sa 08.01.05 18:49

dann wäre das tutorial (für mich) vollständig, hab alles verstanden und bin froh jetzt auch sowas zu können echt nice danke an alle :D


F34r0fTh3D4rk - Mo 10.01.05 16:02

ich habe einen trainer für counter strike source gemacht der das geld einfriert,
wenn ich das in Tsearch einfriere funktioniert alles wunderbar nur wenn ich das mit meinem Programm mache stürzt das spiel ab sobald ich etwas kaufe. wenn ich 6 bytes statt 4 einstelle kann ich was kaufen aber wenn ich sterbe und geld dazubekomme stürzt das spiel wieder ab, warum ?

Es hat auch schon mit 4 bytes funktioniert aber dann hab ich css beendet das design verbessert (form) und dann gings wieder nich.

Hier mal der Code:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
procedure WriteProcMem(procWndTitle: string;CodeAddr:integer; numberNops:byte);
var  
  c, write : Cardinal;  
  buf: pchar;  
  i: byte;  
begin  
  c:=FindWindow(nil,pchar(procWndTitle)); //Get WindowHandle
  if c=0 then  
  begin
    showmessage('Bitte zuerst das Spiel und dann den Trainer starten');
    Application.Terminate;
    end;
  buf := '';  
  for i := 1 to numbernops do  buf := buf + $90;  
  GetWindowThreadProcessId(c,@c); //Get ProcessID and ignore ThreadID  
  c:=OpenProcess(PROCESS_ALL_ACCESS,False,c);  //Get ProcessHandle  
  WriteProcessMemory(c,Ptr(CodeAddr),buf,numberNops,write);  
  CloseHandle(c);
  showmessage('Geld eingefroren!');
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
WriteProcMem('Counter-Strike Source'$2205AE106);//Normalerweise 4 aber nur 6 funzt 8 auch net
end;


WeBsPaCe - Mo 10.01.05 16:04

Wieso denn gleich von 4 Bytes auf 6 Bytes springen?? Die 5 gibbet au noch!! :wink:


F34r0fTh3D4rk - Mo 10.01.05 16:08

bei tsearch gehts ja auch mit 4 !!!


WeBsPaCe - Mo 10.01.05 16:12

F34r0fTh3D4rk hat folgendes geschrieben:
bei tsearch gehts ja auch mit 4 !!!


Immer??


F34r0fTh3D4rk - Mo 10.01.05 16:13

immer

die speicheradresse fürs geld ändert sich immer aber der befehl damit geld weniger bzw mehr wird bleibt gleich


WeBsPaCe - Mo 10.01.05 16:16

F34r0fTh3D4rk hat folgendes geschrieben:
die speicheradresse fürs geld ändert sich immer aber der befehl damit geld weniger bzw mehr wird bleibt gleich


Weiß ich auch.. Poste mal den Assembler-Code, der da drin steht... Daran sieht man wieviele Bytes das sind... Du darfst nich nach den Bytes des eigentlichen Werts gehen!! Welchen Wert hast du denn dann in TSearch gefreezt??


F34r0fTh3D4rk - Mo 10.01.05 16:18

genau das was ich oben im code habe nur mit 4 bytes


WeBsPaCe - Mo 10.01.05 16:20

F34r0fTh3D4rk hat folgendes geschrieben:
genau das was ich oben im code habe nur mit 4 bytes


Bitte was hast du oben geschrieben?? Ich seh da nur den Code, wo n paar Adressen drin sind.. Ich wollt den Befehl, also sowas mit eax und dec und so..


F34r0fTh3D4rk - Mo 10.01.05 16:26

da steht

Quelltext
1:
2205AE10 mov[ecx+0xD7C],edx                    


WeBsPaCe - Mo 10.01.05 16:39

Probiers mal mit 2 bytes!!! Und führ (so blöd das klingt) wenns nich geht die Prozedur nochmal aus. Also nommal auf den Button klicken!! :roll:


F34r0fTh3D4rk - Mo 10.01.05 16:40

ich habs im oncreate das formulares :?


WeBsPaCe - Mo 10.01.05 16:41

F34r0fTh3D4rk hat folgendes geschrieben:
ich habs im oncreate das formulares :?


Egal... funzt es trotzdem??


WeBsPaCe - Mo 10.01.05 16:45

Ansonsten kannstu den Code auch so abändern, dass es auf jeden Fall zweimal kommt.. Das macht au nix.. :


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
procedure WriteProcMem(procWndTitle: string;CodeAddr:integer; numberNops:byte);  
var    
  c, write : Cardinal;    
  buf: pchar;    
  i: byte;    
begin    
  c:=FindWindow(nil,pchar(procWndTitle)); //Get WindowHandle  
  if c=0 then    
  begin  
    showmessage('Bitte zuerst das Spiel und dann den Trainer starten');  
    Application.Terminate;  
    end;  
  buf := '';    
  for i := 1 to numbernops do  buf := buf + $90;    
  GetWindowThreadProcessId(c,@c); //Get ProcessID and ignore ThreadID    
  c:=OpenProcess(PROCESS_ALL_ACCESS,False,c);  //Get ProcessHandle    
  WriteProcessMemory(c,Ptr(CodeAddr),buf,numberNops,write);    
  WriteProcessMemory(c,Ptr(CodeAddr),buf,numberNops,write);    
  CloseHandle(c);  
  showmessage('Geld eingefroren!');  
end;  

 
procedure TForm1.FormCreate(Sender: TObject);  
begin  
WriteProcMem('Counter-Strike Source'$2205AE102);
end;


F34r0fTh3D4rk - Mo 10.01.05 16:48

bei 2 bytes hängt das spiel wenn ich eetwas kaufe dann höre ich 2 fehlermeldungen kann das spiel aber nicht beenden, den anderen code probiere ich gleich aus


F34r0fTh3D4rk - Mo 10.01.05 16:59

jetzt hängt sich das spiel nicht mehr auf da kommt ne fehlermeldung das hatte ich auch schonmal !


retnyg - Mo 10.01.05 17:23

probiers mal mit 3, 4 , 5 - irgendwann hast du den richtigen wert.

huch ? bei zeile 17 und 18 steht bei dir derselbe befehl ? warum das ? macht doch keinen sinn


F34r0fTh3D4rk - Mo 10.01.05 19:08

nicht bei mir war ne idee von webspace naja ich werd rumprobieren bis ichs hab (komisch dass es bei tsearch fehlerfrei funzt)


WeBsPaCe - Mo 10.01.05 19:51

retnyg hat folgendes geschrieben:
huch ? bei zeile 17 und 18 steht bei dir derselbe befehl ? warum das ? macht doch keinen sinn

Ich weiß, dass es eigentlich keinen Sinn macht, jedoch hab ich die Erfahrung gemacht, dass mein Trainer irgendwie erst funktioniert hat, nachdem ich zum zweiten Mal auf den Button geklickt hab. Also hab ich die Write(..)Prozedur einfach nochmal reingeschrieben und es hat auch bei ersten Klick geklappt...

Ihr könnt jetzt von mir aus auf mir rumhacken, aber mir ist es lieber, dass etwas funktioniert, als dass ich mir nächtelang überleg warum... :D :wink:

//EDIT: @F34r0fTh3D4rk
Hast du schon mal mehrmals nach der "Ändere-den-folgenden-Wert"-Adresse (also die mit dem Assembler) gesucht, weil bei mir, bei meinem SCPT-Trainer gab es irgendwie zwei Adressen, die sich "abgewechselt" haben. Einmal die eine, dann die andere. Ich hab dann einfach bei reingeschrieben.


F34r0fTh3D4rk - Mo 10.01.05 19:53

bei mir hängt das spiel danach auch net mehr es stürzt gleich ab ich finds auch besser :D


uall@ogc - Mo 10.01.05 19:53

naja also probieren sollte man das net unbedingt, man kann ja einfach schaun wie viele bytes man noppen muss

http://www.uall.org/addr.JPG

daran erkennste das es 6 bytes sind
desweiteren muss der assembler code nicht immer an der selben adresse sein, einfach aus dem grund da die engine in einer dll ausgelagert ist, bzw valve sich nen eigenen dll loader gemacht hat

und so wie ich das hier rausgelesen habe hat keiner von euch beiden so viel ahnung über den aufbau einer exe, bzw assembler (soll nu net heißen das ihr dumm seid :P)

aber es gibt verschiedene methode auch die adresse des assembler codes dynamisch zu bekommen
hab leider keine tutorials mehr da, hatte mal eins für CS 2D das der nebel weg ist (no fog)
desweiteren solltest dir im klaren sein das es nur im singleplayer modus funktioniert da es 2 unterschiedliche client.dlls gibt

wenn CS bischen aktiver spielst kennste mich ja vielleicht ;>


WeBsPaCe - Mo 10.01.05 19:56

F34r0fTh3D4rk hat folgendes geschrieben:
bei mir hängt das spiel danach auch net mehr es stürzt gleich ab ich finds auch besser

??? Das kann aber nich sein, gelle?? Weil wir freezen ja einfach nochmal dieselbe Adresse, warum soll sich also was ändern??


F34r0fTh3D4rk - Mo 10.01.05 19:56

ich spiele jetzt source weil 1.6 nicht mehr geht :(

ich kenne ogc aber dich net erzähl mal

ventrilo garnich im system tray ich find da unten nervt es immer so rum :)


F34r0fTh3D4rk - Mo 10.01.05 19:59

mit 6 funktioniert es ja auch aber wenn ich sterbe kackt es ab :(

geht es im multiplayer denn auch wenn ichs da nochmal mache ?


uall@ogc - Mo 10.01.05 19:59

kurze info:

OGC = Online Game Cheats
CD = Cheatings Death (http://www.unitedadmins.com, Anti Cheat Programm)
me = CDD Coder (Cheatings Death`s Death, http://www.uall.org)

einer der bekanntesten cheat programmierer für CS
und leidenschaftlicher HL debugger(er?) :P

im multiplayer wirste das nicht hinbekommen, es sei den ndu machst den server auf
dort kannste lediglich die anzeige ändern d.h. bei dir steht dann du hast 16000 $ oder halt 500 Schuss oder 999999 health
aber der server speichert die variablen d.h. wenn du getroffen wirst, ändert sich die variable aufm server und irgendwann lässt der dich net mehr schiessen


WeBsPaCe - Mo 10.01.05 20:01

F34r0fTh3D4rk hat folgendes geschrieben:
ich kenne ogc aber dich net erzähl mal

Hey, hey, nich offtopic werden!! :roll: :D

@uall@ogc
Wo genau soll man da sehen wie viele Bytes, was braucht??

@F34r0fTh3D4rk
Hast du meinen Edit von dem vorletzten Post gesehen??


F34r0fTh3D4rk - Mo 10.01.05 20:03

wurden die programmierer von ogc nich von valve verklagt ?

ogc ging bei mir noch nie, kA warum

ist cdd das tool welches cd simuliert und somit so tut als wäre alles in ordnung aber in wirklichkeit hat der client die fetten cheats am start ?

ist nicht gerade sowas in der esl vorgekommen mit deinem tool ?

unser clan ist deshalb nämlich aus der esl ausgetreten


uall@ogc - Mo 10.01.05 20:12

genau das tool war es :> aber waurm gleich deshalb ausse ESL raus
wirst eh bald nen artikel auf mTw lesen können wo ziemlich viel näheres über cheaten drin steht

also du erkennst das auf dem pic daran


0044C86C 89917C0D0000 mov [ecx+$00000d7c], edx
^------------ assembler code
^-------- opcode in hex (was in der hl.exe drinsteht wenn sie mit hexeditor öffnest

^-- adresse in der HL.exe (die ausführbare exe fängt zu 99% imm bei 00400000 an)


8991 steht für mov [ecx+$adresse], edx
7c0d0000 -> umgedreht als hex -> 00000d7c ist die adresse
ECX und EDX sind register
in EDX steht halt das geld oder health jenachdem

mov [...], ...
schreibt an die stelle von dem ersten ... nen wert

als als bsp.

ECX = $00480000
EDX = 100 (dezimal / HP anzeige)

dann macht der befehl
an adresse $00480000+$00000D7C nen ascii 100


89917C0D0000 <- durch 909090909090 erstetzen und du hast den befehl gelöscht (überschriben mit NOP)
und es wird nix mehr an die adresse geschrieben


retnyg - Mo 10.01.05 20:13

uall@ogc hat folgendes geschrieben:

aber es gibt verschiedene methode auch die adresse des assembler codes dynamisch zu bekommen


erzähl mal, würd mich intressieren. vielleicht weisst du ja auch wie man die dynamisch erteilten speicherpositionen von Datenwerten rausfindet (wie z.b. AmmoCount)


F34r0fTh3D4rk - Mo 10.01.05 20:15

jetzt glaub ich habs verstanden :D aber das spiel stürzt ab wenn ich sterbe


uall@ogc - Mo 10.01.05 20:18

also ist das jetzt für die health anzeige?
wenn ja ändert die sich denn wenn du nur angeschossen wirst?

@retnyg hab da noch eins meiner tuts gefunden

http://www.mpcheatz.com/wbb2/thread.php?threadid=6147&sid=

kannst dir das ja mal anschauen da sieht man auch das der code in nem anderen speicherbereich liegt
und wie man dann da drann kommt bzw sogar die exe patchen kann


The-FoX - Mo 10.01.05 21:08

Hallo,

Ich habe da noch eine andere Methode gefunden / gesagt bekommen.

Ich habe schon vor ein paar Monaten versucht einen The sims Trainer zu schreiben. Dabei fand ich auch eine Speicherstelle, die ich von 0 in 1 ändern musste. Diese Adresse veränderte sich allerdings dynamisch, und ich habe gegoogelt, gegoogelt, gegoogelt, auch dein Tutorial bei Mpcheatz.de gefunden, doch nichts hat geholfen.

Dann kam ich auf die Idee jemanden zu fragen, der schon mal einen Trainer für das Spiel geschrieben hat, also hab ich auf http://www.cheats.de einfach gesucht und einen Trainer gefnden, der genau das kann was ich wollte. Hab ihm ne eMail geschrieben und bekam sogar den Code, aber keine Erläuterung...der Herr war nicht so kommukativ so zu sagen.

Also, der Code ist VB:


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long 
Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long 
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long 
Private Declare Function WriteProcessMemory Lib "kernel32" (ByVal hProcess As Long, ByVal lpBaseAddress As Any, ByVal lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long 
Private Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Long, ByVal lpBaseAddress As Any, ByVal lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long 
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long 

Public Function ConvertNumberToString(Number As Double) As String 
Dim b1, b2, b3, b4 
If Number < 256 Then ConvertNumberToString = Chr(Number): Exit Function 
If Number < 65536 Then 
ConvertNumberToString = Chr(Number And 255) & Chr((Number And 65280) / 256) 
Exit Function 
End If 
b4 = Number And 255: Number = Int(Number / 256) 
b3 = Number And 255: Number = Int(Number / 256) 
b2 = Number And 255: Number = Int(Number / 256) 
b1 = Number And 255: Number = Int(Number / 256) 
ConvertNumberToString = Chr(b4) & Chr(b3) & Chr(b2) & Chr(b1) 
End Function 

Private Sub cmd01_Click() 
Dim hwnd As Long, ProcessID As Long, pHandle As Long 
hwnd = FindWindow(vbNullString, "SIMS") 
If hwnd = 0 Then 
lbl01.Caption = "TS not found" 
Exit Sub 
End If 
GetWindowThreadProcessId hwnd, ProcessID 
pHandle = OpenProcess(&H1F0FFF, False, ProcessID) 
If pHandle = 0 Then 
lbl01.Caption = "No process handle found!" 
Exit Sub 
End If 

WriteProcessMemory Handle, &H6F406FCA, ConvertNumberToString(&H33), 1, 0& 
WriteProcessMemory Handle, &H6F406FC9, ConvertNumberToString(&H41), 1, 0& 
WriteProcessMemory Handle, &H6F406FCE, ConvertNumberToString(&H46), 1, 0& 
WriteProcessMemory Handle, &H6F406FCF, ConvertNumberToString(&H33), 1, 0& 
WriteProcessMemory Handle, &H6F406FD0, ConvertNumberToString(&HF6), 1, 0& 
WriteProcessMemory Handle, &H6F406FCB, ConvertNumberToString(&HC9), 1, 0& 
WriteProcessMemory Handle, &H6F2A22A3, ConvertNumberToString(&H40), 1, 0& 
WriteProcessMemory Handle, &H6F148E58, ConvertNumberToString(&HEB), 1, 0& 
WriteProcessMemory Handle, &H6F2A22A4, ConvertNumberToString(&H33), 1, 0& 
WriteProcessMemory Handle, &H6F149D3C, ConvertNumberToString(&HEB), 1, 0& 
WriteProcessMemory Handle, &H6F2A22A3, ConvertNumberToString(&H40), 1, 0& 
WriteProcessMemory Handle, &H6F2A22A5, ConvertNumberToString(&HC0), 1, 0& 
WriteProcessMemory Handle, &H6F2A22A6, ConvertNumberToString(&H42), 1, 0& 
WriteProcessMemory Handle, &H6F2A22A7, ConvertNumberToString(&H33), 1, 0& 
WriteProcessMemory Handle, &H6F2A22A8, ConvertNumberToString(&HD2), 1, 0& 
WriteProcessMemory Handle, &H6F148E58, ConvertNumberToString(&HEB), 1, 0& 

Close Handle, pHandle 
lbl01.Caption = "Go get her ;-)" 
End Sub 

Private Sub cmd02_Click() 
Dim hwnd As Long, ProcessID As Long, pHandle As Long 
hwnd = FindWindow(vbNullString, "SIMS") 
If hwnd = 0 Then 
lbl01.Caption = "TS not found" 
Exit Sub 
End If 
GetWindowThreadProcessId hwnd, ProcessID 
pHandle = OpenProcess(&H1F0FFF, False, ProcessID) 
If pHandle = 0 Then 
lbl01.Caption = "No process handle found!" 
Exit Sub 
End If 

WriteProcessMemory Handle, &H6F2A22A3, ConvertNumberToString(&H42), 1, 0& 
WriteProcessMemory Handle, &H6F406FCE, ConvertNumberToString(&H70), 1, 0& 
WriteProcessMemory Handle, &H6F2A22A6, ConvertNumberToString(&H52), 1, 0& 
WriteProcessMemory Handle, &H6F148E58, ConvertNumberToString(&H75), 1, 0& 
WriteProcessMemory Handle, &H6F406FC9, ConvertNumberToString(&H48), 1, 0& 
WriteProcessMemory Handle, &H6F149D3C, ConvertNumberToString(&H75), 1, 0& 

CloseHandle pHandle 
lbl01.Caption = "Hm, she's hating you again (deactivated)" 
End Sub


Wie man sieht, schreibt er einige Speicherstellen um. Ich habe den Code in Delphi konvertiert, und er funktioniert. Aber ich habe absolut keine Ahnung, wie der Autor darauf kommt die Adresse xyz in $40 umzuschreiben...vielleicht kann mir ja jemand mal sagen, wie er vorgegangen ist, meine momentane Lösung funktioniert zwar, aber ich habe nicht ohne grund 4 Monate lang gesucht wie ein verrückter, nur um funktionierenden Code zu bekommen ohne zu verstehen wie er klappt :gruebel:

ICh bin dankbar für jede Hilfe.


retnyg - Mo 10.01.05 21:30

das sieht aber nicht nach einem dynamisch zugewiesenen speicherbereich aus

genau genommen macht der nichts anderes, als wir hier mit unserm code-schnipsel, wenn ich das richtig lese.
und die paar werte die der umschreibt sind vermutlich irgendwelche assemblerbefehle, die umgebogen werden ^^


Karlson - Mo 10.01.05 21:33

retnyg hat folgendes geschrieben:
das sieht aber nicht nach einem dynamisch zugewiesenen speicherbereich aus


Ich kenne die Problematik aus meinem HL2 Waffencheat. Der Bereich in dem The-Fox's variable gespeichert wird, wird scheinbar schon dynamisch belegt, die Befehle (dir hier wohl umgeschrieben werden) scheinen gleich zu bleiben.

Naja, jetzt bleibt uns nur noch übrig darauf zu warten, was der Meister dazu meint ;)


en!gma - Mo 10.01.05 21:42

hmm hast du mal nachgeschaut
was die beiden codes machen?

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
WriteProcessMemory Handle, &H6F406FCA, ConvertNumberToString(&H33), 1, 0& 
WriteProcessMemory Handle, &H6F406FC9, ConvertNumberToString(&H41), 1, 0& 
WriteProcessMemory Handle, &H6F406FCE, ConvertNumberToString(&H46), 1, 0& 
WriteProcessMemory Handle, &H6F406FCF, ConvertNumberToString(&H33), 1, 0& 
WriteProcessMemory Handle, &H6F406FD0, ConvertNumberToString(&HF6), 1, 0& 
WriteProcessMemory Handle, &H6F406FCB, ConvertNumberToString(&HC9), 1, 0& 
WriteProcessMemory Handle, &H6F2A22A3, ConvertNumberToString(&H40), 1, 0& 
WriteProcessMemory Handle, &H6F148E58, ConvertNumberToString(&HEB), 1, 0& 
WriteProcessMemory Handle, &H6F2A22A4, ConvertNumberToString(&H33), 1, 0& 
WriteProcessMemory Handle, &H6F149D3C, ConvertNumberToString(&HEB), 1, 0& 
WriteProcessMemory Handle, &H6F2A22A3, ConvertNumberToString(&H40), 1, 0& 
WriteProcessMemory Handle, &H6F2A22A5, ConvertNumberToString(&HC0), 1, 0& 
WriteProcessMemory Handle, &H6F2A22A6, ConvertNumberToString(&H42), 1, 0& 
WriteProcessMemory Handle, &H6F2A22A7, ConvertNumberToString(&H33), 1, 0& 
WriteProcessMemory Handle, &H6F2A22A8, ConvertNumberToString(&HD2), 1, 0& 
WriteProcessMemory Handle, &H6F148E58, ConvertNumberToString(&HEB), 1, 0&

und

Quelltext
1:
2:
3:
4:
5:
6:
WriteProcessMemory Handle, &H6F2A22A3, ConvertNumberToString(&H42), 1, 0& 
WriteProcessMemory Handle, &H6F406FCE, ConvertNumberToString(&H70), 1, 0& 
WriteProcessMemory Handle, &H6F2A22A6, ConvertNumberToString(&H52), 1, 0& 
WriteProcessMemory Handle, &H6F148E58, ConvertNumberToString(&H75), 1, 0& 
WriteProcessMemory Handle, &H6F406FC9, ConvertNumberToString(&H48), 1, 0& 
WriteProcessMemory Handle, &H6F149D3C, ConvertNumberToString(&H75), 1, 0&

??
wenn ich das spiel hätte könnte das das villeicht mal nachschaun...
villeicht kannst du ja mal schaun was das erste teil macht was er verändert...
sieht ja fast so aus als wenn er einer variable einen statischen speicher zuweist und diesen dann umschreibt...
villeicht is der speicher von vorher einfach nur unbenutzt oder was auch immer


uall@ogc - Mo 10.01.05 21:51

also ohne das ich das spiel habe

WriteProcessMemory Handle, &H6F406FC9, ConvertNumberToString(&H41), 1, 0&
WriteProcessMemory Handle, &H6F406FCA, ConvertNumberToString(&H33), 1, 0&
WriteProcessMemory Handle, &H6F406FCB, ConvertNumberToString(&HC9), 1, 0&
WriteProcessMemory Handle, &H6F406FCE, ConvertNumberToString(&H46), 1, 0&
WriteProcessMemory Handle, &H6F406FCF, ConvertNumberToString(&H33), 1, 0&
WriteProcessMemory Handle, &H6F406FD0, ConvertNumberToString(&HF6), 1, 0&

WriteProcessMemory Handle, &H6F2A22A3, ConvertNumberToString(&H40), 1, 0&
WriteProcessMemory Handle, &H6F2A22A4, ConvertNumberToString(&H33), 1, 0&
WriteProcessMemory Handle, &H6F2A22A5, ConvertNumberToString(&HC0), 1, 0&
WriteProcessMemory Handle, &H6F2A22A6, ConvertNumberToString(&H42), 1, 0&
WriteProcessMemory Handle, &H6F2A22A7, ConvertNumberToString(&H33), 1, 0&
WriteProcessMemory Handle, &H6F2A22A8, ConvertNumberToString(&HD2), 1, 0&

WriteProcessMemory Handle, &H6F148E58, ConvertNumberToString(&HEB), 1, 0&

WriteProcessMemory Handle, &H6F149D3C, ConvertNumberToString(&HEB), 1, 0&

ich hab das mal sortiert, einige WPM waren doppelt
es handelt sich dabei um eine dll die er wahrscheinlich patched
die beiden einzelnen EBs sind short jumps und verursachen im code das immer gesprungen wird, also wird davor etwas vom spiel
sehr wahrscheinlich geprüft mit cmp oder test

die 40 bzw 41 ist nen "inc Register" komischerweise wird aber beim 1. fall das register darauf wieder gexort also auf 0 gesetzt
33 steht für
xor register, register -> mov register, 0
auch ist mir gleich aufgefallen das beim 1 fall ne adresse fehlt -> an dieser wird wahrscheinlich ein einzelner byte befehl stehen wie push oder nop, schön ist es nicht wenn man den auch wenns sinnlos ist noch selber mal da reinschreibt

aber ohne dll bzw mehr infos kann ich dir da leider net weiterhelfen


retnyg - Mo 10.01.05 21:56

hier http://www.google.at/search?q=cache:f4gEydpG01cJ:http://www.codeproject.com/threads/MDumpAll.asp+sendmessage+SW_SHOWMINIMIZED&hl=de
gibts ein programm zum download, das den speicher eines prozesses abspeichert. wenn du einen Dump von deinem Sims-Spiel machst, könnten wir dir sicher weiterhelfen.


retnyg - Mo 10.01.05 22:21

uall@ogc hat folgendes geschrieben:

es handelt sich dabei um eine dll die er wahrscheinlich patched

ich nehm mal an du erkennst das an der speicherposi, aber an was genau ?


uall@ogc - Mo 10.01.05 22:37

naja da wo der das hinschreibt

6F2A22A8 z.b.

ne dll beginnt immer an einer adresse X*0x10000

in dem fall z.b. bei 0x6f2a0000 oder 0x6f200000 oder 0x6f100000 oder oder oder
das es patches sind die häufig vorkommen und sogar einen sinn ergeben
EB = jmp
xor eax, eax z.b.

wird es sich um assemblercodes handeln
und da exe speicher sehr wahrscheinlich an 0x00040000 gemaped wird kannes der net sein
und da es auch auf anderen PCs fuznt wirds nicht dynamisch sein
also wird die DLL ihre "richtige" image base adresse bekommen (ohne reloc patches) was bei dynamischen speicher über virtuallalloc z.b. nicht sein wird
also denk ich mal isses ne DLL das würde auch als einziges einen sinn ergeben


Karlson - Sa 15.01.05 16:41

Hab auch mal wider ne Frage, bei Virtua Tennis gibts manchmal ne zeitbeschränkung.

Die läuft dann etwa nach dem Schema 30:00 sec -> 29:99 -> 29:98 -> 29:97. Es läuft also mit 100'stel Sekunden nach unten.

Ich finde diesen wert aber einfach nicht mit TSearch. Weissjemand wie das Spiel die Zeit evt. speichern könnte?

Wenn ich nach 2999 suche, wenn die Zeit auf 29:99 steht findet er nichts.
Ebensowenig wie wenn ich nur nach 29 suche.


uall@ogc - Sa 15.01.05 17:08

ist auch logisch...
ich würd mal die ganze zeit in msek bzw sek umwandeln und dann suchen


wh89 - Sa 15.01.05 17:37

TDateTime in Delphi is aber nich die Zeit in Milisekunden... schon mal versucht die so um zu wandeln?


Karlson - Sa 15.01.05 18:43

uall@ogc hat folgendes geschrieben:
ist auch logisch...
ich würd mal die ganze zeit in msek bzw sek umwandeln und dann suchen


In Sekunden liegt die Zeit ja schon vor.

In Millisekunden habe ich doch bereits gesucht!

19''34 Sekunden sind doch 1934 Millisekunden, glaub ich zumindest, ich steh grad etwas aufem Schlauch... :Lol:


wh89 - Sa 15.01.05 21:52

19 Sekunden sind 19000 Millisekunden.
:D

cu
wh89


Karlson - Sa 15.01.05 21:54

wh89 hat folgendes geschrieben:
19 Sekunden sind 19000 Millisekunden.
:D

cu
wh89


Dito, habe mich vertippt ;) Habe schon nach dem richtigen gesucht. Aber wie gesagt, es ist nichts zu finden :(


wh89 - So 16.01.05 15:11

Dann wandels mal mir Delphi inne TDateTime um und gibs dann aus. Danach kannste mal suchen...

cu
wh89


Karlson - So 16.01.05 15:46

Problem: Wie kann ich mir denn die Zeit anzeigen lassen? Ich kenne nur timetoStr, und der wandelts ja schon wieder um :shock:


uall@ogc - So 16.01.05 15:52

mit nem debugger wärs kein problem rauszufinden
da kann man dann noc nach dem string suchen etc.
aber wenn du gar keine ahnung hast wie die zeit intern gespeichert wird mussu versuchen nach änderungen zu suchen
und dann aus den daten die übrich bleiben schaun welche die zeit sein kann (durch testen oder so)


wh89 - So 16.01.05 16:09

so viel ich weiß sind TDateTimes Floats...


Karlson - So 16.01.05 16:17

wh89 hat folgendes geschrieben:
so viel ich weiß sind TDateTimes Floats...


jop. Dann geht das mit Floattostr, stimmt. Nach welchem Foramt muss ich die Zeit zuweisen?

@uall@ogc: Ich habe keine Ahnung wie die Zeit gespeichert wird. man sieht ingame nur dieses Label mit dem Countdown. Habe jetzt auch mit nem Debugger einfach mal nach dem String gesucht, aber auch da nichts gefunden...


wh89 - So 16.01.05 16:25

mach einfach n datetimepicker(kompo) und lass bei button click mit floattostr die zeit ausgeben.


uall@ogc - So 16.01.05 16:43

isses in delphi porgrammiert und sicher das es nen label ist? dann gehts ganz easy :P


Karlson - So 16.01.05 16:50

uall@ogc hat folgendes geschrieben:
isses in delphi porgrammiert und sicher das es nen label ist? dann gehts ganz easy :P


Nein, es ist sicher nicht in Delphi programmiert, und es ist auch kein Label! Es handelt sich um Virtua Tennis ;)
Ich hab einfach mal nur Label gesagt weil es eben ein Textfeld ist, sicherlich kein TLabel. Außerdem ises ja Direct X, also komm ich über den Weg bestimmtn icht dran.

@Wh89: Also das der Wert in dem TDateTime Format gespeichert wird kann ich mir absolut nicht vorstellen. Hab jetzt in der OH ein paar Sachen darüber gelesen, deswegen lass ich das. Trotzdem danke für den Tip! :)


wh89 - So 16.01.05 18:04

hast dus schon probiert, indem du einfach nach veränderten Werten suchst... hat uall@ogc glaub ich schon vorgeschlagen...


Karlson - So 16.01.05 18:09

inwiefern soll ich nach veränderten Wert suchen? Das wären einfach zuviele. Im Grunde können 30 Sekunden schließlich als 1 aber auch als 300000000 gespeichert sein. Da bräuchte ich jetzt einen Ansatz.


wh89 - So 16.01.05 19:05

du machst bei TSearch bei der Suche nicht "Exact Value" sondern "Unknown Value". Dann beim weitersuchen machst du "Value has changed". Das machst du mehrere Male. evtl. Kannst du das Programm auch neustarten oder sogar den Rechner und dann nochmal suchen. du suchst solange bis noch noch ein oder zwei übrig bleieben. wen n einer davon danach aussieht, als ob es die zeit wäre, dann versuch mal ihn zu freezen(über Tsearch). wenn es dir nicht gelingt ist der zweite Wert ein CheckWert, der den Wert verschlüsselt enthält und von dem die ganze zeit die zeit errechnet wird. das sollte aber nicht so sein, weil das berechnen viel zu lange braucht und ein solches verfahren nur bei sehr microsoftartigen spiele benutzt wird.

cu
wh89


Karlson - So 16.01.05 20:13

wh89 hat folgendes geschrieben:
das sollte aber nicht so sein, weil das berechnen viel zu lange braucht und ein solches verfahren nur bei sehr microsoftartigen spiele benutzt wird.


:mrgreen: War ja klar :mrgreen:

Okay, also ich denke so müsste er doch zu finden sein ;) Vielleicht kennt jemand ja das Problem. Die Minispiele sind beinahe unschaffbar, weil dieser ätzende Zeitdruck sowas von nervt :roll: Allerdings muss ich alle Minispiele absolvieren, um den letzten geheimen spieler zu bekommen. Und es gibt absolut 0 Cheats für das Spiel...

Also vielen dank, ich melde mich dann wieder.


edit: er findet 111 werte :lol: Ich kann nur hoffen das die nicht alle damit zusammenhängen...


luckyluke84 - Sa 29.01.05 16:59
Titel: Wert nicht ändern, sondern auslesen
Ich wollte für Solitär eine Highscore schreiben und
hab mit TSearch die Adresse für die Punkte im Speicher
rausgefunden.

Nachteil : die Adresse ändert sich immer wieder
nach einem Neustart ist sie nicht mehr zu gebrauchen.

Meine Frage : Wie kann ich den Punktewert aus dem Speicher von
Solitär auslesen, wenn er sich ständig ändert?
Ich will den Wert nur lesen und nicht verändern!


*treky - Mi 02.02.05 00:36

hi all
da ich das erste mal mit tsearch arbeite hab ich noch net viel drauf.
und folglich ein problem und zwar folgendes:
hab in einem spiel versucht mein health zu ändern bzw zu erst hab ich es mit tsearch gesucht.
soweit sogut :)
da gibt es dann 8 verschieden werte, die sich immer mit der gesundheit ändern.
ich kann sie aber net ändern,denn wenn ich das mache springen sie direkt wieder auf den ausgangswert zurück. hab kein plan was ich da machn kann.
kann mir jemand helfen ???
plz

mfg *treky-@-tsearch-n00b :oops:


delphischaf - Mo 07.02.05 11:54

Also ich hab das ganze, was im Tut zum Anfang beschrieben wurde mal realisiert ( kopiert ) und verändert, so das es für Battlefield 1942 v1.6 klappt. Es funktioniert auch im Multiplayer. Ich hab eingerichtet, das man keine Lebenspunkte oder Munition verliert. Die Waffen werden auch nicht heiß. Problem: Da die Funktion, die das leben abzieht, ja nicht mehr ausgeführt wir, sterbe nicht nur ich nicht mehr, sondern auch kein anderer. Die Panzer gehen nicht mehr kaputt. Also muss ich nicht die Funktion auf Null setzen, sondern raus finden, welche Adressen der funktion, die das leben veringert übergeben werden, damit ich die Werte die im Speicher stehen ändern kann. Aber wie mache ich das. Die Werte bzw die Variablen werden ja dynamisch angelegt. Also ändern sich die Adressen dauernd. Tja....


derDoc - Mo 07.02.05 13:05

Ich nehme an, dass du die Reduktions-Routinen mit 0x90 überschreibst. Dadurch wird jeglicher Abzug verhindert.

Deshalb solltest du nach der Adresse der Lebensenergie suchen und mit einem Debugger wie SoftIce einen Breakpoint darauf setzen. Nun musst du etwas Lebensenergie verlieren. Der Debugger bekommt das mit und zeigt dir an, welcher Code diese Veränderung herbeigeführt hat. Dort musst du ansetzen und dir die wahre Lebensenergieadresse geben lassen (Dein Trainer muss das machen). Dort kannst du dann den Wert verändern, sodass nur du eine extrem hohe Lebensenergie bekommst, womit du fast unsterblich bist.


WeBsPaCe - Mo 07.02.05 13:20

Dadrum geht's doch! Wie bekommt er die mit DMA vergebene RAM-Adresse raus!?! Die ändert sich doch jedes Mal, aber in dem Code-Schnipsel, der er ja schon für seinen Trainer gefunden hat, steht sie drin. Und da möchte er sie rauslesen.


derDoc - Mo 07.02.05 14:52

Nun denn, Schritt für Schritt.

Benötigt:
SoftIce


Erklärung:
kursive Teile sind Kommandos für die SoftIce Kommandozeile
[ekige Klammern bedeuten Tastendruck]
%Prozente dienen als Platzhalter%

[Strg]+[D] drücken, um SoftIce aufzurufen.


Folgende Fenster werden gebraucht:

REGISTER WINDOW (WR [return])
DUMP WINDOW (WD [return])
CODE WINDOW (WC [return])


Aktuelle Adresse suchen
Mit TSearch nach der Lebensenergie suchen. Wenn der Wert gefunden wurde zurück in SoftIce ([Strg]+[D]) folgendes
eingeben:
BPM %Adresse% W [return]

Beispiel:
BPM 786ca4 W [return]


Lebensenergie verändern
SoftIce sollte in den Vordergrund treten und so etwas zeigen:

Quelltext
1:
2:
3:
4:
0041A736  8B8308020000  MOV     EAX,[EBX+00000208]; verschiebt die Lebensenergie nach EAX
0041A73C  D983CC000000  FLD     REAL4 PTR [EBX+000000CC] 
0041A742  D8B3C8000000  FDIV    REAL4 PTR [EBX+000000C8]
0041A748  A3A46C7800    MOV     [00786CA4],EAX; verschiebt die Lebensenergie in die Anzeigeadresse


Test:
D EBX+208 [return]
Im DUMP Fenster kann man nun den Wert verändern und sehen, dass man den richtigen Wert hat.


Auf Einzigartigkeit prüfen
Zuerst alle Breakpoints löschen:
BC* [return]

Breakpoint auf die Veränderung der Anzeige setzen:
BPX 41A736 [return]

[F5] mehrmals drücken und nachsehen, ob der Inhalt von EBX sich ändert.
Falls nicht, haben wir die richtige Adresse.


Codecave suchen
Den Namen des Fensters suchen:
TASK [return]

Die Sektionen anzeigen:
MAP32 %Fenstername% [return]

Nun sollte man soetwas sehen:

Quelltext
1:
2:
3:
4:
5:
6:
7:
:map32 %Fenstername%
Owner         Obj Name  Obj#  Address        Size      Type
%Internername%.text     0001  017F:00401000  0004BE10  CODE  RO
%Internername%.data     0002  0187:0044D000  00006718  IDATA RW
%Internername%.bss      0003  0187:00454000  0035CDB4  UDATA RW
%Internername%.idata    0004  0187:007B1000  000014F0  IDATA RW
%Internername%.rsrc     0005  0187:007B3000  0000095C  IDATA RO SHARED


Normalerweise ist am Ende der Data-Sektion viel freier Platz. Daher gehen wir mit
D 454000 [return]
an den Anfang der folgenden Sektion und gehen nur ein Stückchen zurück. Wir nehmen ín diesem Beispiel 453f00.


Gateway erzeugen
Zurück zu unserer ersten Ansicht
U 41a736 [return]

Gateway einbauen:
A 41a736 [return]
jmp 453f00 [return]
nop [return] (Die Byteanzahl muss mit der vorherigen übereinstimmen)
[return]

Beispiel:
ORIGINAL

Quelltext
1:
2:
3:
4:
0041A736  8B8308020000  MOV     EAX,[EBX+00000208]
0041A73C  D983CC000000  FLD     REAL4 PTR [EBX+000000CC]
0041A742  D8B3C8000000  FDIV    REAL4 PTR [EBX+000000C8]
0041A748  A3A46C7800    MOV     [00786CA4],EAX


GATEWAY

Quelltext
1:
2:
3:
4:
5:
0041A736  E9C5970300    JMP     00453F00
0041A73B  90            NOP
0041A73C  D983CC000000  FLD     REAL4 PTR [EBX+000000CC]; hierhin müssen wir nachher zurück
0041A742  D8B3C8000000  FDIV    REAL4 PTR [EBX+000000C8]
0041A748  A3A46C7800    MOV     [00786CA4],EAX



Codecave beschreiben
Zur Codecave springen:
U 453f00 [return]
In die Codecave schreiben:
A 453f00 [return]

Zuerst den erstzten Teil wieder einbauen:
mov eax,[ebx+208] [return]
Dann die echte Adresse EBX in eine statische Speicheradresse in der Nähe unserer Codecave schreiben (hier 453f30):
mov dword ptr [453f30],ebx [return]
Zurück zur eigentlichen Funktion:
jmp 41a73c [return]
Fertig:
[return]

Die Codesektion sollte jetzt so aussehen:

Quelltext
1:
2:
3:
00453F00  8B8308020000  MOV     EAX,[EBX+00000208]
00453F06  891D303F4500  MOV     [00453F30],EBX
00453F0C  E92B68FCFF    JMP     0041A73C



Trainer erstellen
Im Trainer muss man jetzt alle diese Änderungen auch vornehmen; bei jedem Start. Dazu muss man z.B. an Adresse 453F00 die Bytes 8B 83 08 02 00 00 schreiben, etc.

Danach kann man die Speicheradresse 453F30 auslesen, 0x208 hinzuaddieren und den dortigen Wert ändern.


retnyg - Mo 07.02.05 15:47

guter artikel, derDoc :)
mal schauen wie das ganze mit ollydbg zu machen ist - nach der ausführlichen beschreibung sollte das aber kein problem sein.


Assun - Di 08.02.05 13:48

Hi !

Hab das mit dem Trainer auch mal versucht ! Opfer : NFSU II

Mit AutoHack gehts, wenn ich auf "Freezen" klicke, aber in Delphi verjagst mir dat game !

hab bei WriteProcessMemory alles von 1 - 8 ausprobiert, aber jedesmal verjagst mir dat ding !!!

Ich verzweifle bald ! weiss jemand, wass ich falsch mache ?


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
procedure WriteValues;
var
  c, write : Cardinal;
  buf: pchar;
begin
  c:=FindWindow(nil,'NFS Underground 2'); //Get WindowHandle
  buf := #144#144;
  if c=0 then
  begin
    MessageDlg('You have to run the game first !',mtwarning,[mbOK],0);
    Exit;
  end;
  GetWindowThreadProcessId(c,@c); //Get ProcessID and ignore ThreadID
  c:=OpenProcess(PROCESS_ALL_ACCESS,False,c);  //Get ProcessHandle
  WriteProcessMemory(c,Ptr($547156),buf,4,write);                    // Diese 4 habe ich schon durch alles von  1-8 ersetzt !
  CloseHandle(c);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
WriteValues;
end;

Vielen Dank im Voraus !

ächz, ich saß da ne halbe Nacht dran und verzweifle blald !


uall@ogc - Di 08.02.05 13:57

ist uach logisch wenn buf

buf := #144#144; (2 bytes sind)

und du 4 überschreibst

WriteProcessMemory(c,Ptr($547156),buf,4,write);


WriteProcessMemory(c,Ptr($547156),buf,2,write); müsste es sein wenn die adresse stimmt und du nur 2 bytes nopen willst (144 = $90)


Assun - Di 08.02.05 14:08

also wenn ich nu 3 bytes bei WriteProcess..... hab ,dann muss ich #144#144#144 schreiben oder was?

und bei 2 : #144#144

und bei 5 dann : #144#144#144#144#144

richtig?


uall@ogc - Di 08.02.05 14:16

du weißt schon was es mit der #144 auf sich hat oder :> du musst die assembler funktion überschreiben die die variable erhöht 144 = $90 = NOP = no operation solltest halt schaun wie groß die ist


Assun - Di 08.02.05 14:20

und woher weiss ich wie groß die is ? :shock:


delphischaf - Di 08.02.05 15:52

Mit der Funktion

WriteProcessMemory(c,Ptr($547156),buf,4,write);


überschreibst du 4 aufeinanderfolgende Byte im Arbeitsspeicher. D.h. Du musst wissen, aus wie viel Byte Deine Variable besteht. Von Mir aus probiers aus.

Die 4 Sagt, wieviel Byte überschrieben werden. Die werden mit dem, was in Buf drin steht, überschrieben. und buf soll als wert $90 oder #144 haben.

Also ich sehen wenn ich mit TSearch die Funktion noppe, wie viele Bytes er überschreibt. Unten im Debugfenster. Da würde dann wenn er 4 Byte noppen würde 4 mal unter einander nop rechts stehen.


F34r0fTh3D4rk - Di 08.02.05 18:07

wenn du mit tsearch nach adressen mit 4 byte suchst sind es automatisch 4,
dann nimmst du $90 und das denn 4 mal, oder halt oben deine #144#144, das sind schon 2byte, dann müsste das net 4 sein um 4 zu ergeben sondern 2, weil 2 * 2 = 4, oder du lässt unten 4 stehen und machst oben nur einmal #144


delphischaf - Mi 09.02.05 08:51

@derDoc

Welches SoftIce muss ich da nehemen? Das mit Vanille und Schoko oder? :lol:
Ne wrn Spass. Ich habe jetzt die Version 4.05 für WinNT Aber wenn ich das Starte, kommt nur ein Dos-Fenster, indem Steht, das die Prozedur nicht gefunden werden kann. Muss ich da noch irgendwas einstellen?


delphischaf - Fr 11.02.05 09:42

Wasn los, schreibt keiner mehr?
Das SoftIce geht auf XP irgenwie nicht.


WeBsPaCe - Fr 11.02.05 11:45

Kannst du denn auch wirklich nichts eintippen? Probier's doch einfach mal. Soweit ich das verstanden hab', ist dieses SoftICE auch nur ein Kommandzeilenutility, also mit diesem schwarzen Fenster. :roll:


retnyg - Fr 11.02.05 15:17

WeBsPaCe hat folgendes geschrieben:
Soweit ich das verstanden hab', ist dieses SoftICE auch nur ein Kommandzeilenutility, also mit diesem schwarzen Fenster. :roll:

falsch verstanden. das ist ein programm was sich ganz tief in dein system einklinkt. sobald du STRG-D drückst steht dann alles und ein textbildschirm tut sich auf.


delphischaf - Mo 14.02.05 10:27

Ah, gut. Ich werds heute nachmittag nochmal probieren.


*treky - Sa 19.02.05 15:25

delphischaf hat folgendes geschrieben:
Also ich hab das ganze, was im Tut zum Anfang beschrieben wurde mal realisiert ( kopiert ) und verändert, so das es für Battlefield 1942 v1.6 klappt. Es funktioniert auch im Multiplayer. Ich hab eingerichtet, das man keine Lebenspunkte oder Munition verliert. Die Waffen werden auch nicht heiß. Problem: Da die Funktion, die das leben abzieht, ja nicht mehr ausgeführt wir, sterbe nicht nur ich nicht mehr, sondern auch kein anderer. Die Panzer gehen nicht mehr kaputt. Also muss ich nicht die Funktion auf Null setzen, sondern raus finden, welche Adressen der funktion, die das leben veringert übergeben werden, damit ich die Werte die im Speicher stehen ändern kann. Aber wie mache ich das. Die Werte bzw die Variablen werden ja dynamisch angelegt. Also ändern sich die Adressen dauernd. Tja....





du hast das mit bf1942 aber net im internet ausprobbiert oder..???
denn da hätte ja jeder seine eigenen werte auf seinem eigene pc.... oder speicher der server die variablen
nur du würdest nix an energie verlieren, oder?

da sich die adressen ändern:

da gibs doch pointer du musst nur die pointer finden (die wissen ja wo die adresse steht) und die sind immer gleich ,glaube ich ;)


delphischaf - Mo 21.02.05 14:19

Ich habs nicht im Internet getestet. Im LAN hab ich es aber probiert und da gings. Es hatten aber alle teilenhmer(2) das Tool. Da die BOTS mit auf meinem PC laufen und der die funktionen bereit stellt, haben die auch unendlich munition.


Alex_ITA01 - Di 22.02.05 09:25

so ich habe das jetzt mal alles hier verfolgt und habe auch mal ein bischen rumgetestet...
Ich habe nur mal eine Frage zu Herr der Ringe:Schlacht um Mittelerde.
Ich finde ja bei "dlh" einige trainer nur leider funktioniert keiner... Nagut dann versuche ich mein Geld mittels TSearch mal einzufrieren aber leider wird der Geldwert (beim Spielstart = 1000) insgesamt 97 mal gefunden. Jetzt habe ich mir ein Gebäude für 350 gekauft und nach 650 im Speicher suchen lassen... Leider findet er überhaupt nichts mehr. Hat jemand eine Idee, woran das liegen könnte oder was ich ändern kann? Wäre echt super wenn ihr ein "Denkanstoß" für mich hättet.
MFG Alex


delphischaf - Di 22.02.05 10:13

Du hast vieleicht nach 2 Byte gesucht, müsstest aber warscheinlich nach einem Wert mit 3 oder 4 Byte suchen.


Alex_ITA01 - Di 22.02.05 14:16

ich habe "leider" von 1 Byte bis Double alle Werte durchsucht und nichts gefunden. Ich habe das Spiel gestartet und dann bei TSearch gesehen, dass noch ein zweiter Prozess (der mit dem Spiel verbunden ist) gestartet wurde und habe auch in dem nach dem "Geld"-Wert gesucht.... Leider nichts

MFG Alex


en!gma - Di 22.02.05 14:28

ansonsten versuchs einfach erst mal mit "unknown value" und dann such nach "has increased" oder "has decreased"


Alex_ITA01 - Di 22.02.05 15:27

oh, danke für den Tip.
Das habe ich noch nicht probiert...
Aber nur mal rein theoretisch, wenn das mit dem "HAS Increased" gehen sollte, müsste dass dann nicht auch mit der Variante gehen, wie ich es in dem oberen Beitrag erklärt habe?

MFG Alex


en!gma - Di 22.02.05 17:14

nicht unbedingt.
es könnte ja mal reintheoretisch sein, dass die programmierer
bei dem wert immer +1 oder sowas in der art (warum auch immer) hinzufügen.
schon dann würde es nicht klappen


Alex_ITA01 - Di 22.02.05 17:47

sorry aber verstehe ich grade nicht?
ich habe doch für mein Geld ein "festen" Wert und den suche ich ja im Speicher.
Wie meinst du das mit dem +1? Dann müsste ich doch trotzdem mein Startkapital von 1000 finden und dann nach paar Sekunden 1005.. Nur leider gibt es manche Geldbeträge die ich im Spiel habe, überhaupt nicht im Speicher... Naja ich versuche es heute Abend mal mit "Has Increased"

MFG Alex


Alex_ITA01 - Mi 23.02.05 10:01

also ich habe es gestern Abend mal mit dem "HAS INCREASED" probiert.
Folgende Situtation:
-Ich habe beim Spielstart 1000 "Geldeinheiten"...
-Ich habe nach "unknown value" gesucht -> glaube über 500000 oder so gefunden
-Ich habe dann 350 Geldeinheiten abgezogen bekommen
-Ich habe nach "HAS DECREASED" suchen lassen und als 2Byte (650 restliche Geldeinheiten=2Byte!?)
Schlussfolgerung: Leider 0 Einträge gefunden.
Ich verstehe es echt nicht mehr...
Hat zufällig jemand das Spiel und kennt sich mit dem Thema "Spiele-Trainer erstellen" aus?
Mir fehlen langsam echt die Ideen...

MFG Alex


Alex_ITA01 - Mi 23.02.05 15:06

jippi :D
Ich habe es jetzt mit Cheat 'O Matic (ist unter http://www.downloads.de zu finden) hinbekommen, die Speicheradressen für die Geldeinheiten in Herr der Ringe - Schlacht um Mittelerde auszulesen.
Ich hänge mal den Screenshot an...
Nur leider weiß ich nichts mit dieser Speicheradresse anzufangen (also wie schreibe ich mir ein Trainer in Delphi zu einer Speicheradresse x6152C58:731 x50A81F4:701 ???)
Ich wäre über jeden Tip dankbar.

MFG Alex

sorry aber ich bin anscheind zu blö... ein Bild hier anzuhängen...
Jedenfalls wird mir die oben genannte Speicheradresse angezeigt.
Wie kann ich die in Delphi einbinden?

@retnyg: Habe es grade gemerkt....


retnyg - Mi 23.02.05 15:08

Alex_ITA01 hat folgendes geschrieben:
Ich hänge mal den Screenshot an...

hrhrhr denkste. in diesem forum nicht möglich. da musst du wohl erst irgenwo einen webspace anmieten... :twisted:


Alex_ITA01 - Do 24.02.05 14:48

Hat keiner eine Idee, wie ich folgende Speicheradresse in Delphi "ändern" kann?
x6152C58:731 x50A81F4:701
Muss ich da jetzt beide überschreiben mit "NIL" ($90) oder nur eine?
Und was bedeutet das :731 bzw. :701 dahinter?

MFG Alex


F34r0fTh3D4rk - Do 24.02.05 15:14

ich habe immer das problem bei tsearch, wenn ich eine adresse gefunden habe, (autohack window) und dann etwas noppe, dann funzt es, im delphi programm dann aber nicht mehr.
ich gucke mir immer im disassembler an, wie viel da genoppt wird, und das mache ich dann nach, funktioniert aber nicht mit jedem code ...

welcher code sit denn absolut zuverlässig ?


retnyg - Do 24.02.05 15:21

vielleicht nimmst du einfach einer der routinen die in dem thread rumschwirren und nimmst halt diese adresse : 6152C58
das x davor bedeutet nur dass es sich um einen hexwert handelt. was das 701 bedeutet weiss ich auch nicht, könnte aber der wert sein. da das min. ein word ist musst du also min. 2 bytes überschreiben. probier halt mal rum


F34r0fTh3D4rk - Do 24.02.05 15:29

ich finde es bei hl2 komisch, ich habe gesucht und gefunden womit die lebensenergie vermindert wird, wenn ich die adresse noppe, dann sind auch die gegner unsterblich, dann habe ich die adresse gefunden, mit der sich nur die eigene lebensenergie verringert (nicht erhöht) aber mein programm killt damit immer den prozess.
und die adresse finde ich net wieder ... :(


Alex_ITA01 - Do 24.02.05 15:41

wie meinst du das:
Zitat:

vielleicht nimmst du einfach einer der routinen die in dem thread rumschwirren und nimmst halt diese adresse : 6152C58


Wieso routinen die im thread rum schwirren?
Oder meinst du jetzt einfach nur ich soll nur die adresse 6152C58 nehmen und die zweite gar nicht beachten?!

MFG Alex


F34r0fTh3D4rk - Do 24.02.05 15:45

ich glaube er meint mich :lol: :?: :gruebel: :think:


Alex_ITA01 - Do 24.02.05 16:12

warum schreibt er dann:
Zitat:

vielleicht nimmst du einfach einer der routinen die in dem thread rumschwirren und nimmst halt diese adresse : 6152C58

Die Adresse habe ich ja oben genannt. Trifft die auch auf dich zu?
Ist ja auch egal...

MFG Alex


retnyg - Do 24.02.05 17:23

Alex_ITA01 hat folgendes geschrieben:
wie meinst du das:
Zitat:

vielleicht nimmst du einfach einer der routinen die in dem thread rumschwirren und nimmst halt diese adresse : 6152C58


Wieso routinen die im thread rum schwirren?
Oder meinst du jetzt einfach nur ich soll nur die adresse 6152C58 nehmen und die zweite gar nicht beachten?!

MFG Alex

ich meine die Speicher-NOP routine die ich hier mal gepostet habe (glaube seite 3 oder so)

als speicheradresse nimmst du die 2 werte die du da genannt hast, nur ohne das X davor


Alex_ITA01 - Fr 25.02.05 14:46

Hallo erstmal,
ich habe es jetzt wie folgt probiert:
Ich habe mir ein Thread geschrieben, der alle Speicheradressen (die mir das Programm Cheat 'O Matic anzeigt) mit "NIL" überschreibt.
$6152C50 ; $50A8208 ; $12E54FC (<- diese 3 Stück meine ich)
Juhu...
Das funktioniert auf meinem PC super. Mein Geldwert hat ein gigantischen Wert und ist eingefroren.
Mein Problem ist jetzt aber, ich teste genau das gleiche Delphiprogramm auf einem anderen PC (wo Herr der Ringe auch installiert ist) und es geht nicht!!! Mit Cheat 'O Matic bekomme ich auch ganz andere Speicheradressen angezeigt.
Wie kann ich jetzt den Trainer so programmieren, dass es auch auf jeden Rechner geht? Das die Speicherbereiche unterschiedlich sind, hängt ja sicherlich mit den Programmen ab, die noch so im Speicher rumschwirren...

Ich wäre über jeden Tip dankbar

MFG Alex


uall@ogc - Fr 25.02.05 14:54

die ersten beiden adressen könnten in einer dll liegen - da die aber auf dem anderen PC anders sind werden is wohl mit HeapAlloc / Virtualalloc erst allociert also ändern sich auch von PC zu PC

du musst halt nun das spiel debuggen um zu schaun wie das spiel an diese adresen drankommt, es wird mindestens eine fixe adresse geben die darauf hinzeigt z.b.


Delphi-Quelltext
1:
2:
3:
4:
5:
asm
  mov eax, [$00401111]     <- fixe adresse, an der steht immer $6152C50 die kann aber auf jedem PC anders sein
  mov eax, [eax]           // $6152C50  <- hier wird mit deiner adresse weitergerechnet
  add [eax], $10           // $10 addieren
end;


die 3 adresse ist definitiv aufm stack, die würde ich net ändern, nicht mal an deinem PC ;>


Net-Spider - Fr 25.02.05 14:57

in vielen spielen wird DMA genutzt, "dynamic memory allocation" oder sowas in der art.
wenn man sich die stellen mal mit einem debugger anschaut, dann sieht man, dass nicht eine feste stelle geändert wird,
sondern das mit pointer gemacht ist.
die adresse, die geändert werden soll steht dann irgendwo anders im speicher IMMER AN DER SELBEN STELLE,
also müsstest du diese feste adresse lesen und dann an dieser gelesenen adresse nachschauen und verändern.

da fällt mir gerade ein, geht es um das ändern eines wertes (geld,leben,...) oder darum, einen wert einzufrieren?

beim einfrieren muss das immer an der selben stelle sein, bei dem wert wird dma genutzt.

[edit]zu langsam :-)[/edit]
[edit2]hm, das stand ja schon alles auf seite 1, so ein mist...[/edit2]


Alex_ITA01 - Fr 25.02.05 14:58

ich habe folgende Vorlage:
Mein PC:
$6152C50
$50A8208
$12E54FC

Der andere PC hat folgende Adressen:
$E71C420
$560B030
$12E54FC

Wie meinst du das jetzt mit "HeapAlloc / Virtualalloc " ?
Kennst du ein Beispiel dafür oder kannst du es vielleicht ein wenig genauer erklären?

Danke schön...
MFG Alex

Edit: es geht nur darum Geld einzufrieren...
edit: macht nix net-spider :-)


Alex_ITA01 - Fr 25.02.05 15:23

wie soll ich das Spiel debuggen? In einem Thread der die ganze Zeit eine Speicheradresse liest?

Delphi-Quelltext
1:
2:
3:
4:
5:
asm  
  mov eax, [$00401111]     <- fixe adresse, an der steht immer $6152C50 die kann aber auf jedem PC anders sein  
  mov eax, [eax]           // $6152C50  <- hier wird mit deiner adresse weitergerechnet  
  add [eax], $10           // $10 addieren  
end;

Soll ich anstatt der $00401111 jetzt $6152C50 nehmen?
Sorry, aber ich stehe grade ziemlich auf dem Schlauch...

MFG Alex


uall@ogc - Fr 25.02.05 15:33

ich ab das bestimmt schon 20 mal gepostet aber versuch erstmal das tutorial nachzumachen:
http://www.arschvoll.net/tutcs2d.pdf (hab nu mal als PDF gemacht)
dann verstehste auch wie das alles funzt

solltest das tut net schaffen mussuauch net mit deinem trainer weitermachen


Alex_ITA01 - Fr 25.02.05 15:37

sorry,dass ich deine 20Post's noch nicht gelesen habe...
Werde mir das Tutorial mal anschauen und ich denke, wenn es gut erklärt ist, dann werde ich es auch hinbekommen.
Danke!

Alex


SAiBOT - So 27.02.05 02:14

Warum Funktioniert das nicht ?


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
..
var
s: String;
..
begin
..
s:= '$123456';
WriteProcessMemory(HandleWindow,Pointer(s),buf,1,write);
..


So ändert er die Werte im Spiel nicht warum nicht :(?
So klappt es:


Delphi-Quelltext
1:
2:
3:
4:
5:
..
begin
..
WriteProcessMemory(HandleWindow,Ptr($123456),buf,1,write);
..


MrSaint - So 27.02.05 12:13

weil POinter('$12345') <> Pointer($12345)? Du weißt schon was ein String ist und wie der im Speicher aussieht?


SAiBOT - So 27.02.05 12:43

ja aber wie soll ich das jetzt machen ?

also ich habe einen String den ich dem Befehl als pointer übergeben möchte (oberes Code Beispeiel)

ist das unmöglich ?


Net-Spider - So 27.02.05 12:48

so sollte es eigentlich gehen:

Delphi-Quelltext
1:
2:
3:
4:
5:
var i:integer;
begin
  i:=$123456;
  WriteProcessMemory(HandleWindow,Pointer(i),buf,1,write);
end;

da musst du nur eben einen integer übergeben...


SAiBOT - So 27.02.05 13:08

-=LordEvil=- hat folgendes geschrieben:

also ich habe einen String den ich dem Befehl als pointer übergeben möchte (oberes Code Beispeiel)


ja nur leider kann ein offset auch Buchstaben enthalten, deswegen habe ich mich für string entschieden :cry:


uall@ogc - So 27.02.05 13:19

warum wolle nalle eiegtlich immer einen trainer schreiben die gerade mal bisl mit delphi umgehen können und gar ent wissen was assembler ist?

var s: string;
s := '$12345678';

allein das zeigt doch schon das du überhaupt nicht weißt was du da machst
weißt du was eine adresse ist? und wie ein pchar aufgebaut ist? wie da alles verwaltet wird etc.
wenn nicht dann lern bitte erstmal delphi


SAiBOT - So 27.02.05 13:24

das das so nicht klappt weis ich selbst!, es ist nur als bs gedacht um nach einer lösung zu suchen, aber da du die antwort auch nicht kennst -.-, frage ich mich was dein post soll?
Enigma hat ein Tutorial geschrieben und ich versuch draus schlau zu werden, wenns dir nicht passt schreib ne PM spämmer!

Edit: ich habs geschafft, danke an alle die mir GEHOLFEN haben!


F34r0fTh3D4rk - So 27.02.05 13:27

Die "Buchstaben" sind in wirklichkeit auch nur Zahlen, nur dass es in diesem
Fall im HEXA-Dezimalsystem angegeben ist. Man kann HEX Zahlen auch in andere Zahlensysteme Umwandeln. Damit das Programm weiß, dass der nächste integer eine Zahl ist, werden HEX-Zahlen mit "$" gekennzeichnet :!:

aber es kann glaube ich mit strtoint umgewandelt werden


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
..  
var  
s: String;  
..  
begin  
..  
s:= '$123456';  
WriteProcessMemory(HandleWindow,Pointer(strtoint(s)),buf,1,write);  
..

aber dann kann man auch gleich integer nehmen


uall@ogc - So 27.02.05 13:32

1. spammer und nicht spämmer
2. ja nur leider kann ein offset auch Buchstaben enthalten, deswegen habe ich mich für string entschieden
hab dir mal den rat gegeben dich mit pchar integer auseinaderzusetzen, diese buchstaben nennt man hexwert
den begriff solltest eigentlich shconmal gehört haben wenn du mit sowas anfängst
3. so wie die meisten sich einen trainer hier zusammen schuster (einfach mal wild noppen, aber net mal wissen
was ne assembler instruction ist, irgendwelche daten ändern etc.) da frage ich mich wirklich
ob das der richtige anfang ist programmieren zu lernen


F34r0fTh3D4rk - So 27.02.05 13:56

ok wenn man den code serviert bekommt ist es ja auch net alzu schwer :D
Aber man sollte schon verstehen was der code macht, wenn man einfach wild im
speicher rumnoppt, können schonmal unannehmlichkeiten passieren
(meistens äußert sich das als sogenannter "Systemcrash" oder auch "Computerabsturz")
:wink:


Kedariodakon - Di 08.03.05 10:26

Da Holle ich mal den alten Tread hervor um ein wenig diesbezuglich ein paar Fragen loszuwerden :D

1. Wenn ich eine Speicherstelle gefunden hab, an welcher warscheinlich ein Wert gespeichert wird ATM, kann ich auf diese Speicherstelle mir selber einen MBP erstellen, also sprich mit einem Selbstgeschriebenene Programm sozusagen?
Sprich ich bekomm ne Nachricht, wenn jemand darauf zugreift, vielleicht auch mit ner Stelle von der zugegriffen wird, damit ich dann den ASM-Code draus interpretieren kann... ?!?

Dann hab ich die Sache mit SoftIce gelesen, und wollte es mal versuchen, leider aber bekomm ichs auf XPsp2 nicht zum laufen, er kann immer irgendwelche Geräte nicht finden :roll: Welche das auch immer seien mögen...

Na ok, hab ich mal OllyDbg getestet, wo alle so davon schwärmen... Naja misserfolg, 1.Das Spiel ist gepackt, also mekert der ma schon rum ok klinke ich mich hald in einen vorhandenen Prozess ein, naja setz einen MBP, spiele ein Stück wups MBP scheind anzulaufen, naja ok doch nicht hat das Spiel und OllyDbg geschrottet...

Tja irgendwie komm ich in Sachen RuntimeDebugger nicht weiter, da ich irgendwie nichts mehr auf meinem System mehr zu laufen bekomm...

Falls da noch wer nen Tip hätte, vielleicht auch nen software tip, wär ich diebezüglich Ohr :wink:
Von mir aus auch per PM 8)

Bye


uall@ogc - Di 08.03.05 11:04

das problem wird wohl an den anti-debugger code liegen die die meisten spiele haben. den mussu natürlich vorher wegpatchen und dafür brauchste halt viel asm ahnunh, man kann jedes programm mit ollydebug debuggen nur halt die debugger detetcion muss man entfernen und frag jetzt aber nicht wie das ist bei jedem spiel anders


Kedariodakon - Di 08.03.05 11:09

Hmm den muß man ja erst mal finden um den wegzu machen :roll:

Am liebsten würd ich wieder mit Sice arbeiten, aber das Dinge läuft mal überhaupt nicht, vermute schon, das es ev. am Fx-51 Prozessor liegt :x

gibts sonst noch brauchbare Dèbugger, möglichst als free :wink:

Bye


uall@ogc - Di 08.03.05 11:13

http://www.programmerstools.org/


SAiBOT - So 27.03.05 18:23

ok ich habe sehr viel aus diesem Treath gelernt aber eine Frage stellt sich mir immer noch!

Nehmen wir als Bsp. Diablo II 1.10 SingelPlayer.

1. ich ermittel den Gold Wert mit TSearch bekomme irgend eine Adresse.
2. Jetzt finde ich den Pointer mit dem Debugger/AutoHack heraus (9F6D17).

So wenn ich jetzt ein Trainer schreiben will, der den wert zb auf 1000 setzen soll, bräuchte ich ja die gefundene Adresse von Punkt 1, das wäre auch kein Problem! Da sich Wert aber immer ändert (DMA) habe ich es mit dem Pointer den ich mit dem Debugger/AutoHack herausgefunden habe versucht.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
function WriteProcess(Title: String; Address, PokeValue:Integer): Boolean;
begin
Result := True;
WindowName  :=  FindWindow(nil,PCHAR(Title));
          If  WindowName  =  0  then Result := False;
    ThreadId  :=  GetWindowThreadProcessId(WindowName,@ProcessId);
    HandleWindow  :=  OpenProcess(PROCESS_ALL_ACCESS,False,ProcessId);
    GetMem(buf,1);
    randomize;
    buf^  :=  Chr(PokeValue);
 WriteProcessMemory(HandleWindow,ptr(Address),buf,1,write);
 FreeMem(buf);
 closehandle(HandleWindow);
end;

...

WriteProcess('Diablo II'$9F6D17$01);
WriteProcess('Diablo II'$9F6D18$00);
WriteProcess('Diablo II'$9F6D19$00);

...


dies sollte den GoldWert doch jetzt auf 1 setzen oder nicht ? Leider stürtzt das Spiel immer ab!
Wobei es mit volgendem Code den GoldWert erfolgreich einfriert:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
...

WriteProcess('Diablo II'$9F6D17$90);
WriteProcess('Diablo II'$9F6D18$90);
WriteProcess('Diablo II'$9F6D19$90);

...


So nun möcht ich gerne wissen warum ich den Wert nur einfrieren kann und nicht neu setzten!
drückt mal ein Auge zu falls ich irgendwas durcheinander gebracht habe :lol: thx!


Karlson - So 27.03.05 19:02

Hallo,

Der Wert den du nopst ist nicht der Goldwert.
Im TSearch Debuggerfenster müsste irgendwas mit Dec (decrease) stehen. Das ist der Befehl der Ausgeführt wird, wenn der Goldwert verändert wird, oder besser gesagt wenn die Adresse umgeschrieben wird.

wie du die Adresse des eigentlichen Goldwerts herausfinden kannst wurde hier sehr sehr lang diskutiert ;)


SAiBOT - So 27.03.05 20:24

???? wo denn bitte ?


Karlson - So 27.03.05 20:47

hier [http://www.delphi-forum.de/viewtopic.php?p=214919#214919] da bitte.


Kedariodakon - Mi 30.03.05 09:33

Nur das leider nicht jeder SofIce hat... :(


Bye


noctua - Sa 30.04.05 17:17

das tut is voll geil :D es funktioniert perfekt

mit dem tut kann man es so machen das der wert, der verändert wird nicht verändert wird, aber kann man den wert nicht selber verändern?

TSearch kann ja den wert verändern, und wie kann man das in unser delphi projekt einbauen.


WeBsPaCe - Sa 30.04.05 21:45

Lies doch einfach mal ein paar Seiten nach vorne. ;) Irgendwo ist da ein supereinfacher Beitrag dazu. ;)


noctua - Sa 30.04.05 22:24

habe ich schon gemacht, alles funktionier wunderbar ;)

sry hätte wöhl früher auch mal in der mitte und nicht nur den anfang lesen sollen


TH€_BR@!N - Fr 03.06.05 21:32

Hallo,

ich habe einen Trainer der ohne probleme funzt,

nur ist er so gecodet das er sich automatisch abschaltet wenn ein mitspieler am anfang seines namens [AH] stehen hat.

gibt es nicht eine möglichkeit das abschalten zu verhindern,
oder einfach das [AH] gegen [XY] aus zu tauschen?

vielen dank für eure hilfe.


en!gma - Fr 03.06.05 21:36

versuchs einfach mal mit nem hex editor : )
weiss nicht, ob dabei was vernünftiges rauskommen kann, aber ich würd sagen ja


TH€_BR@!N - Fr 03.06.05 21:39

habe ich schon probiert aber das hat nicht geklapt....

leider habe ich kein plan von der ganzen programmier sache..... *heul*


Der Blaue Gott Balmung - Mi 22.06.05 15:51

Hi @all!

Das Tut find ich echt gut. Ich hab' auch schonmal 'n Buch über 's Game Cheating gelesen. Mich würden jetzt auch die lowlevel Prozesse interessieren (vor allem wie ich zuverlässig 'ne Speicheradresse für bestimmte Daten rausbekomme und überschreibe; ohne Pointer, wenn das möglich ist). Ich werd mich mal mit Assembler auseinandersetzen. Vielleicht wurde die Frage schon beantwortet, wie das funktioniert und ich hab' es nur nicht verstanden.

@ ulla@ogc:
Könntest du den Link nochmal aktualisieren oder an dersinndeslebenz@gmx.net schreiben?
http://www.mpcheatz.com/wbb2/thread.php?threadid=6147&sid=


retnyg - Mi 22.06.05 15:57

user profile iconDer Blaue Gott Balmung hat folgendes geschrieben:

@ ulla@ogc:
Könntest du den Link nochmal aktualisieren oder an dersinndeslebenz@gmx.net schreiben?
http://www.mpcheatz.com/wbb2/thread.php?threadid=6147&sid=

das tut is jetzt glaub auf http://www.uall.info


F34r0fTh3D4rk - Fr 01.07.05 13:44

eines meiner beliebtesten probleme ist immer noch "unbegrenzt leben", den wert des lebens selbst kann ich wunderbar verändern, aber der befehl, der leben abzieht gilt für alle spieler, das heißt, man ist unverwundbar für die gegner, aber auch umgekehrt, gibt es da ne möglichkeit, außer alle 0.1 sekunden das leben wieder auf 100 oder auch 1000 prozent zu setzen ?


Neidhard von Reuental - Fr 01.07.05 14:19

mir ist keine möglichkeit bekannt. zudem müßte dein programm nach jedem spielneustart die neue addi finden wo der wert gespeichert ist. weiß ja nicht was es für ein spiel ist aber zu 99% ändert sich die speicheraddi deswegen verändern trainer auch den programmcode und nicht die speicherstelle in der z.b. die Lebensanzahl gespeichert ist.
diese methode verwendete das actionreplay (c64,megadrive,snes)


F34r0fTh3D4rk - Fr 01.07.05 14:22

das mit dem programmcode hab ich auch immer noch nicht verstanden, ich hab zwar schon 2 tutorials gelesen (eins hier und eins von uall), aber ich steigt da net durch :lol:


Der Blaue Gott Balmung - Di 05.07.05 17:43

Vielen Dank für die Hilfe retnyg :D


derDoc - Fr 08.07.05 14:52

Es ist nicht ohne weiteres Möglich eine unbegrenzte Anzahl an Leben für den Spieler bereitzustellen. Nur für den Fall, dass der menschliche Spieler hier eine eigene Routine besitzt, kann das Problem einfach gelöst werden. Für alle weiteren Lösungen bedarf es fortgeschrittener Assembler-Kenntnisse.

Im Prinzip muss das Spiel jeden Spieler indizieren. Dort kann man ansetzen. Also muss auch der Funktion, die den Lebenswert reduziert mitgeteilt werden, welcher Spieler denn getroffen wurde. Wenn man jetzt durch Beobachtung (Breakpoint auf Ausführen der Funktion in einem Low-Level-Debugger) herausfindet, was den Menschen vom Computer unterscheidet, kann man dies im Programmcode so verändern, dass nur der menschliche Spieler unendlich viele Leben hat.

Beispiel (Original):

Quelltext
1:
2:
3:
4:
5:
6:
7:
004C873D   660FBEC8             movsx cx,al
004C8741   663BD9               cmp bx,cx
004C8744   7E09                 jle short 0x004C874F
004C8746   C6866403000000       mov byte ptr [esi+0x364],0x0
004C874D   EB08                 jmp short 0x004C8757
004C874F   2AC3                 sub al,bl
004C8751   888664030000         mov [esi+0x364],al

Verändert:

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
004C873D    82BEDC0200005A      cmp byte ptr [esi+0x2DC],0x5A
004C8744    7F0B                jg short 0x004C8751
004C8746    2AC3                sub al,bl
004C8748    3C00                cmp al,0x0
004C874A    7F05                jg short 0x004C8751
004C874C    B000                mov al,0x0
004C874E    90                  nop
004C874F    90                  nop
004C8750    90                  nop


Es gibt keine anderen Möglichkeiten, den Computer vom Menschen im Spiel zu unterscheiden.


Intruder - Do 14.07.05 12:18

Wo ist denn dieses Prog? Ich werd immer weiterverlinkt! Kann das nicht mal wer anhängen oder sO?


en!gma - Mo 18.07.05 14:13

probier mal
Suche bei Google DOWNLOAD TSEARCH , da der 1. link


wolle- - So 24.07.05 00:00


Delphi-Quelltext
1:
    WriteProcessMemory(HandleWindow,ptr($4609F0),PChar(chr(7) + chr(161) + chr(32)),3,write);                    


Ich hatte das eigentlich so vor


Delphi-Quelltext
1:
    WriteProcessMemory(HandleWindow,ptr($4609F0),PChar(chr(7) + chr(161) + chr(32)),Edit1.text,write);                    


Das der in dem Prog den wert so macht die ich den im Edit1 stehen habe aber dann kommt immer

[Fehler] test.pas(43): Inkompatible Typen: 'Cardinal' und 'String'

EDIT:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
procedure TForm1.Button1Click(Sender: TObject);
begin
buf := '99';
wolle := '102';
hackPid := findprocess('Programm');
HandleWindow  :=  OpenProcess(PROCESS_ALL_ACCESS,False,hackPid);
    WriteProcessMemory(HandleWindow,ptr($4609F0),wolle,4,write);
    closehandle(HandleWindow);
    HandleWindow  :=  OpenProcess(PROCESS_ALL_ACCESS,False,hackPid);
   WriteProcessMemory(HandleWindow,ptr($4609EC),buf,4,write);
    closehandle(HandleWindow);
end;


Folgendes problem:
Bei 99 kommt beim Programm 14360 raus und bei wert über 100 kommt über 3 000 000 ...
Ich wollte aber so 40.000 ?!


JayEff - So 24.07.05 01:34

user profile iconen!gma hat folgendes geschrieben:
probier mal
Suche bei Google DOWNLOAD TSEARCH , da der 1. link

[OT]Mit solchen Angaben aufpassen, Google behält es sich vor, ab und zu die Reihenfolge zu ändern oO Meine HP war schonmal auf platz 1 wenn man nach JayEff oder Jayy gesucht hat, und irgentwann dann mal auf seite 12... -.-


wolle- - So 24.07.05 01:38

hat das jetzt was mit meiner frage zutun?


JayEff - So 24.07.05 02:01

[OT]Zitat: [OT] = Off-Topic = Ausserhalb des Themas.[/OT]


wolle- - So 24.07.05 02:52

Achso okay, kannst du mir bei dem problem helfen?


JayEff - So 24.07.05 15:20

[ot]nein :oops: Ich wollte nur mal wieder meinen Senf dazu geben:oops: sorry... [/ot]


retnyg - So 24.07.05 16:59

@wolle:

Delphi-Quelltext
1:
2:
3:
4:
var s: pchar;
begin
  s:=#144#144#144#144// buffer aus dezimalwerten erstellen, darf aber keine #0 drin vorkommen (wegen pchar)
  WriteProcessMemory(HandleWindow,ptr($4609F0),s,length(s),write);


wolle- - So 24.07.05 19:07

danke


Der Blaue Gott Balmung - Mi 27.07.05 14:17

Hi,

Hab rausgefunden, wie man dem Buffer für WriteProcessMemory 'ne Variable übergeben kann (ist aber umständlich):


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
function CarToPChr(Car: Cardinal) : PChar;
VAR
  TChar: array[0..3of Char;
begin
    TChar[0] := Char(Lo(Car));    
    TChar[1] := Char(Lo(Car shr 8));
    TChar[2] := Char(Lo(Car shr 16));
    TChar[3] := Char(Hi(Car));
    Result := @TChar;
end;


Wenn man z.B. eine Eingabe in eine Dezimalzahl umwandelt, kann man sie der Funktion übergeben und ihren Rückgabewert vom Typ PChar in writeProcessMemory verwenden.


retnyg - Do 18.08.05 03:01

user profile iconDer Blaue Gott Balmung hat folgendes geschrieben:

Hab rausgefunden, wie man dem Buffer für WriteProcessMemory 'ne Variable übergeben kann (ist aber umständlich):

geht auch einfacher

Delphi-Quelltext
1:
2:
3:
4:
var value,write: cardinal;
begin
value := $FFFFFFFF;
writeprocessmemory(HandleWindow,ptr($4609F0),@value,4,write);


uall@ogc - Do 18.08.05 12:01

wenn man ein array of char hat sollte man das so machen:


Delphi-Quelltext
1:
2:
3:
4:
5:
var bla: array[0..7of char;
begin
  pcardinal(@bla[0])^ := $FFFFFFFF;
  pcardinal(@bla[4])^ := $FFFFFFFF;
end;


Der Blaue Gott Balmung - Do 18.08.05 13:46

Vielen Dank,

Da hab ich wohl den Pointer mit der Adresse verwechselt :(
Hab nämlich immer sowas versucht:

Delphi-Quelltext
1:
writeprocessmemory(HandleWindow,ptr($4609F0),ptr(value),4,write);                    


War schon ganz verzweifelt.


Aretures - Do 15.09.05 21:21

Ich würde auch gerne nen Trainer schreiben, aber ich kann Tsearch nicht downloaden.Kann mir jemand sagen woher ich das noch bekomme.Ich hab eins bei googel gefunden aber das scheint was anderes zu sein...help me!!!


F34r0fTh3D4rk - Do 15.09.05 21:26

versuchs mit dem generic game trainer, den solltest du locker bei google finden :wink:


en!gma - Do 15.09.05 21:29

ja so, oder nimm das tsearch hier:

http://www.xcheater.com/download.aspx?file=cheat_tools/tsearch_16.zip


F34r0fTh3D4rk - Do 15.09.05 21:37

schöne tools, da ist ja sogar einer von diesen bösen disassemblern :lol:


PierreB - Sa 15.10.05 21:15

Moin,

also ich hab schon ein bisschen mit dem hier so beworbenen TSearch gespielt, bin jetzt aber leider steckengeblieben:

Zitat:
am anfang haben wir ja 50 mineralien wie wir oben rechts im spiel sehen können. also starten wir nun tsearch und klicken auf den fetten "open process" button mit dem chip drüber...
Schön und gut, was mache ich aber wenn im Spiel nicht einfach direkt der Wert (als Zahl) da steht, sondern z.B. in Form eines Balkens ? Im konkreten Fall meine ich die Lebens- und Schildanzeige bei GTA San Andreas, wie komme ich da an die Adressen ?

Vielen Dank für die Hilfe,

Pierre


retnyg - Sa 15.10.05 22:30

z.b. ne suche nach: wert ist kleiner/grösser/gleich/ungleich als startwert, und das einige male müsste dich schlussendlich zum ziel führen -> so machts auch der snes emulator ZSNES.

das geht so: new search - unknown value
wert im spiel ändern
search next
has increased, usw

... und das so lange bis nur noch ein paar adressen (am besten nur 1 ;)) übrig sind


PierreB - So 23.10.05 14:54

Hey,

vielen Dank, nach langer Zeit hab ichs nun endlich geschafft.

Jetzt hab ich aber schonwieder ne neue Frage:

Ich wollte jetzt mal nen Trainer für mein eigenes Spiel schreiben, klappt auch ganz gut. Nur bekommt man nach einigen Missionen in meinem Spiel ein Ranking, welches als Text im Spiel ausgegeben wird. Kann man nun den String auch verändern wie man will (hatte in TSearch schonmal nach dem String gesucht, auch umgewandelt nach Hex, nie findet er was). Also ich möchte praktisch das man im Trainer ein Wort eingibt und das dann im Spiel an Stelle des Rankings erscheint. :-)

Kann mir einer helfen ?

Thx


uall@ogc - Mi 26.10.05 13:45

das müsste man auch finden können.

es gibt 2 Arten von Strings, AnsiChar und WideChar

wenn man nun den Text 'Test' hat kann man den in hex umwandeln: 54 65 73 74

das wäre für Ansi: 5465737400 und
Wide: 54006500730074000000

jetzt muss man halt aufpassen, da zahlen als integers nicht 00 00 00 01 für die zahl 1 gespeichert werden sondern
01 00 00 00 in umgekehrter reihenfolge

willst du also den ANSI String 'Test' als Dword suchem musst du 0x74736554 nehmen ;>


moddin - Fr 15.12.06 21:11

und wenn ich nun einen DMA wert gefunden habe - wie/wo finde ich den pointer auf die adresse?
ich will auch nicht freezen oder so einen quatsch sondern nur altmodisch die variable verändern

ich finde keine "Range Mode" in TSrearch

hab jetzt durch Autohack sowas


555irgendwas : sub [eax],ecx

eax ist dann doch der pointer auf meine variable - und ist statisch aber wie lese ich den jetzt aus
sodass ich im endeffekt

WriteProcessMemory(hProcess,[b]@MeinGefundenerZeigerAufVariable,@lpBuffer,4,BytesRead);

benutzen kann umd die variable indirekt über zeiger zu verändern


uall@ogc - So 17.12.06 16:49

EAX muss nicht statisch sein. Falls es statisch ist (was ich nciht gelaube) musst du halt debuggen und schaun welchen wert EAX hat.


iPlayboy - Mo 05.02.07 03:03

Soooo

Ich hab auch mal ne Frage =)

Und zwar hät ich sehr gerne statt dem WindowTitle das der den Prozessnamen erkennt !

wie würd ich das anstellen ?^^


derDoc - Di 06.02.07 12:55

Natürlich geht das auch. Allerdings ist es halt ein wenig Arbeit.

Mit folgenden Quellcode sollte es dennoch funktionieren:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
const
  ProcessName = 'DeineDatei.exe'// Bitte entsprechend ändern
var
  hSnapshot: THandle;
  hProcess: THandle;
  ProcessEntry: TProcessEntry32;
  Schleife: BOOL;
  pID: Integer;
begin
  hSnapshot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  ProcessEntry.dwSize := Sizeof(ProcessEntry);
  Schleife := Process32First(hSnapshot, ProcessEntry);
  while Schleife do
  begin
    if (CompareText(ProcessEntry.szExeFile, ProcessName) = 0then
      pID := ProcessEntry.th32ProcessID; // <-- Das ist die ProzessID
    Schleife := Process32Next(hSnapshot, ProcessEntry);
  end;
  CloseHandle(hSnapshot);
  hProcess := OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID); // <-- Das ist dann das gesuchte Handle
//(...)


Wegi - Fr 23.03.07 16:32

Hallo, bin Delphi-Anfänger und habe ein paar fragen dazu...

WriteProcessMemory(HandleWindow,ptr($401F75),buf,1,write); //es wird der speicher umgeschrieben in der addresse 401F75 und es wird 1 byte geschrieben
WriteProcessMemory(HandleWindow,ptr($401F76),buf,1,write);
WriteProcessMemory(HandleWindow,ptr($401F77),buf,1,write);
WriteProcessMemory(HandleWindow,ptr($401F78),buf,1,write);
WriteProcessMemory(HandleWindow,ptr($401F79),buf,1,write);
WriteProcessMemory(HandleWindow,ptr($401F7A),buf,1,write);

diese zeile:

Wenn ich es richtig verstanden habe muss ich dort um einen Wert mit 8 Zeichen zu ändern nur 4 Zeilen schreiben oder?

Und wo kann ich dort den Wert eintragen wenn ich zum Beispiel will das meine Goldmine auf 20000 Aufgestockt oder auf dieser zahl gefreezed wird?

Mein Fall:

Will den Goldvorrat der Goldmine in Warcraft 3 ändern. Es war die Adresse 4A50444 mit 6F39727.

Muss ich also folgendes schreiben?:



Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
procedure TForm1.Button1Click(Sender: TObject);
const v1 = $90;
begin  
WindowName  :=  FindWindow(nil,WindowTitle);  
If  WindowName  =  0  then MessageDlg('...erst spiel starten...dann trainer starten =)',  mtwarning,[mbOK],0)
else
   begin
    ThreadId  :=  GetWindowThreadProcessId(WindowName,@ProcessId);  
    HandleWindow  :=  OpenProcess(PROCESS_ALL_ACCESS,False,ProcessId);  
    GetMem(buf,1);  
    buf^  :=  Chr(v1);
    WriteProcessMemory(HandleWindow,ptr($4A50444),buf,1,write);
    WriteProcessMemory(HandleWindow,ptr($4A50445),buf,1,write);
    WriteProcessMemory(HandleWindow,ptr($4A50446),buf,1,write);
    WriteProcessMemory(HandleWindow,ptr($4A50447),buf,1,write);
    FreeMem(buf);  
    closehandle(HandleWindow);
   end;
end;


derDoc - So 08.04.07 17:07

Ein paar Erläuterungen zu folgendem Quellcode:


Delphi-Quelltext
1:
WriteProcessMemory(HandleWindow, ptr($401F75), buf, 1, write);                    


Wie du richtig erkannst hast, stellt $401F75 die Adresse dar. Zudem wird ein Byte aus der Variable buf dort hingeschrieben. Die Variable write, welche in deinem Beispiel undefiniert wäre, gibt die Anzahl der tatsächlich geschriebenen Bytes wieder.

Weiterhin würdest du in deinem Beispiel den Goldbestand mit 0x90 überschreiben. Das gäbe dir dann ca. 2,5 Mrd. Einheiten. Eigentlich ist 0x90 als Opcode für den Assembler Befehl nop gedacht und soll wohl den Wert einfrieren. Dazu darfst du aber nicht den tatsächlichen Wert überschreiben, sondern musst die entsprechende Funktion - üblicherweise ein sub oder mov Befehl - überschreiben.

Gesetz den Fall, du wolltest nur den Wert ändern, dann kannst du das mit folgendem Code, der schon eine Seite weiter vorne stand, machen:

Delphi-Quelltext
1:
2:
3:
4:
5:
var
  Value: Cardinal;
begin
  Value := $FFFFFFFF// <-- Hier kommt der gewünschte Betrag im Hexadezimal-System hin
  WriteProcessMemory(hWindow, ptr($4A50444), @Value, 4, Write);


M4$73R$ - Fr 03.08.07 01:31
Titel: C&C Tiberium Wars
Hi Leute,

Kann mir jemand dabei helfen einen Trainer für C&C Tiberium Wars zu erstellen?

Ich weis zwar wie ich die resurcen und die energie manipulieren kann weis aber überhaubt nicht wie ich mit TSearch machen kann das ich z.B. Schnell Bauen, Immer die Superwaffen bereit habe oder einheiten unendlich leben geben und Befördern kann?

Das mit "Einheiten befördern" wär mir am wichtigsten, ich denke das es eigentlich gehn müsste da man ja auch Einheiten unendlich leben geben kann.

Wäre für eure HILFE sehr dankbar :-)


napsterxx - Mi 15.08.07 10:42

Also ich wollte mich mal an COmman & Conquer Generäle - Die Stunde Null probieren.
Geldhack!
Adresse für das Geld war schnell gefunden. Wenn ich die in Autohack einfrier bekomm ich beim bauen nichts mehr abgezogen :)
Nun dachte ich geht das ja auch in Delphi:

Meine Adresse:


Quelltext
1:
4ff9d5  mov [edi+0x4],eax                    




Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
  Const  WindowTitle  =  'Command & Conquer Generäle - Die Stunde Null';


  implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
const v1 = $90;
begin
 WindowName  :=  FindWindow(nil,WindowTitle);
          If  WindowName  =  0  then MessageDlg('',  mtwarning,[mbOK],0);
    ThreadId  :=  GetWindowThreadProcessId(WindowName,@ProcessId);
    HandleWindow  :=  OpenProcess(PROCESS_ALL_ACCESS,False,ProcessId);
    GetMem(buf,1);
    buf^  :=  Chr(v1);
    WriteProcessMemory(HandleWindow,ptr($4FF9D5),buf,1,write); //Habe schon alles getestet anstatt der 1 eine 2,3,4 und 5
    FreeMem(buf);
    closehandle(HandleWindow);
end;



Aber egal was ich als Byte verwende, 1,2,3 oder 4, mein Game stürtzt IMMER ab sobald ich was bauen will, wenn ich auf den button geklickt habe. Kann jemand helfen?

//Edit
Mit Generice Game Trainer hab ich jetzt auch mal die Adresse rausgesucht. Da ist die "Size" aber nicht Byte sonder DWord. Hat das was zu sagen? Ist das vielleicht die Ursache warum mein Game immer abstürzt?


uall@ogc - Fr 17.08.07 14:58

versuch mal:


Delphi-Quelltext
1:
2:
3:
4:
var buf: integer;
begin
    buf := $90909090;
    WriteProcessMemory(HandleWindow,ptr($4FF9D5),@buf,3,write); //Habe schon alles getestet anstatt der 1 eine 2,3,4 und 5


Dark-§hadow - Sa 29.09.07 02:12

Hey!
Ich habe mich am Trainer versucht ( Command & Conquer - Alarmstufe Rot 2) und habe jedoch noch ein paar Probleme. Ich krieg zum Beispiel (es handelt sich um eine dynamische Adresse) nicht die richtige Adresse heraus und ich hab das noch nicht so ganz mit den Hexzahlen verstanden, wie man es ausrechnet, wozu usw.
Wäre dankbar, wenn mir das einer nochmal erklären könnte, am liebsten auch in aller Ruhe über ICQ o.ä., falls Interesse besteht, addet mich doch bitte ICQ: 261-419-131
Ansonsten bin ich natürlich auch über Posts hier im Thread erfreut.
Danke im Vorraus
D-§


elundril - Sa 29.09.07 12:07

irr ich mich oder kann man mit diesem Tutorial auch nen cheat für onlinegames erstellen z.b: Unendlich leben bei WarRock??

lg elundril


uall@ogc - Sa 29.09.07 17:30

@Dark-Shadow: Um an die reale Adresse dranzukommen musst du eben einen Hardware Breakpoint setzen. (Bzw. Das Programm Debuggen) Das ist weitaus schwieriger und ich glaube es hat keiner so viel Zeit das über ICQ zu erklären. (Wenn ich langeweile habe mach ich dazu vielleicht mal ein Tutorial)

@elundril: Die Informationen über HealthPoints/Geld etc. in Onlinespielen wird auf dem Server gespeichert. Hast du Zugriff dadrauf (bzw. hostest selbst einen) dann ist das natürlich möglich.


elundril - So 30.09.07 11:30

ich mein eigentlich so onlinespiele wie Counterstrike. also eine exe die ich ausführe. oder meintest du das eh??

lg elundril


uall@ogc - So 30.09.07 12:59

genau das meinte ich


Regan - So 30.09.07 13:41

user profile iconelundril hat folgendes geschrieben:
ich mein eigentlich so onlinespiele wie Counterstrike. also eine exe die ich ausführe. oder meintest du das eh??

lg elundril

Des Weiteren sind die meisten CS Server durch Vac geschützt. Das erkennt Veränderungen :wink: .


elundril - So 30.09.07 14:36

ja bei cs aber es gibt ja noch so spiele wie warrock oder americas armz und so weiter. ich wollt eigentlich nur theoretisch fragen. ich hasse cheater sowieso!

lg elundril


gamer94 - Sa 17.11.07 15:03

Ich kann die Search-Komponente unter keinem der Links finden. Auch bei Google bin ich nicht fündig geworden. Kennt jemand noch ne Seite, oder kann sie jemand hochladen? Das wäre echt total super!


KIEZBOZZ - Fr 07.12.07 01:23

kann mir einer helfen ein trainer für DIE ERBEN VON ST. PAULI zu erstellen?
ich blick da nämlich voll nicht durch


elundril - Fr 07.12.07 14:00

was sind denn allgemein deine Erfahrungen mit Delphi?? Was hast du schon programmiert und so? Wenn du noch ziemlicher Neuling bist, würd ich dir von diesem Projekt abraten, da es schon sehr "extrem" ist.

lg elundril


KIEZBOZZ - So 09.12.07 02:03

wie kann man das denn machen weil für das spiel gibt es keine cheats und ich komm ned weiter
deswegen brauch ich hilfe kann mir einer son ding erstellen oder sagen wie das geht


cherrymoon69 - Di 19.02.08 16:33

hallo erst mal. ich finde das ein super thema.

bin grad dabei einen trainer für Hearts of iron - doomsday zu schreiben.

ich habe mit tsearch den wert für geld ermittelt. leider handelt es sich hierbei auch um immer wieder eine neue adresse pro instanz.

habe dann den pointer gefunden. $480802 Wert D99EF41B0000.

tsearch schreibt 6 bytes zum freezen. damit klappt es wunderbar. freezen unfreezen, kein thema.

jetzt habe ich den trainer folgendermaßen geschrieben:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
var
  Form1: TForm1;
  WindowName  :  integer;
  ProcessId  :  integer;
  ThreadId  :  integer;
  buf  :  PChar;
  HandleWindow  :  Integer;
  write  :  cardinal;

  Const  WindowTitle  =  'HoI 2';

  implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
const v1 = $90;
begin
    WindowName  :=  FindWindow(nil,WindowTitle);
          If  WindowName  =  0  then MessageDlg('...erst spiel starten...dann trainer starten =)',  mtwarning,[mbOK],0);
    ThreadId  :=  GetWindowThreadProcessId(WindowName,@ProcessId);
    HandleWindow  :=  OpenProcess(PROCESS_ALL_ACCESS,False,ProcessId);
    GetMem(buf,1);
        buf^  :=  Chr(v1);
              WriteProcessMemory(HandleWindow,ptr($480802),buf,1,write); //es wird der speicher umgeschrieben in der addresse 401F75 und es wird 1 byte geschrieben
              WriteProcessMemory(HandleWindow,ptr($480803),buf,1,write);
              WriteProcessMemory(HandleWindow,ptr($480804),buf,1,write);
              WriteProcessMemory(HandleWindow,ptr($480805),buf,1,write);
              WriteProcessMemory(HandleWindow,ptr($480806),buf,1,write);
              WriteProcessMemory(HandleWindow,ptr($480807),buf,1,write);
        FreeMem(buf);
    closehandle(HandleWindow);
    MessageDlg('Geld ist eingefroren',  mtwarning,[mbOK],0);
end;

procedure TForm1.Button2Click(Sender: TObject);
var
 Value1: Cardinal;
 Value2: Cardinal;
begin
    Value1 := $D99EF41B;
    Value2 := $0000;
    WindowName  :=  FindWindow(nil,WindowTitle);
          If  WindowName  =  0  then MessageDlg('...erst spiel starten...dann trainer starten =)',  mtwarning,[mbOK],0);
    ThreadId  :=  GetWindowThreadProcessId(WindowName,@ProcessId);
    HandleWindow  :=  OpenProcess(PROCESS_ALL_ACCESS,False,ProcessId);
    GetMem(buf,1);
                      WriteProcessMemory(HandleWindow,ptr($480802),@Value1,4,write); //es wird der speicher umgeschrieben in der addresse 401F75 und es wird 1 byte geschrieben
                      WriteProcessMemory(HandleWindow,ptr($480806),@Value2,2,write);
        FreeMem(buf);
    closehandle(HandleWindow);
    MessageDlg('Geld ist nicht mehr eingefroren',  mtwarning,[mbOK],0);
end;

end.

das freezen geht jetzt spitzenmäßig. wenn ich das richtig verstanden habe, dann muß beim unfreezeb der alte wert geschrieben werden. nämlich D99EF41B0000.

habe anfänglich die gleiche vorgehensweise wie beim freezen, nur umgekehrt, verwandt. geht nicht. was ich auch tu, das spiel stürzt sofort ab. weiß jemand rat?

ach ja. und wie kann ich denn im delphicode den wert f+r geld verändern. also nicht nur freezen. die adresse ist ja immer anders. das habe ich nicht verstanden.

bitte um hilfe.

danke

PS: ich weiss, dass ich 6 bytes beim freezen geschrieben habe. mit 6 bytes beim unfreezen hat es nicht gefunzt. der code beim unfreezen ist nur ein versuch.

Moderiert von user profile iconNarses: Delphi-Tags hinzugefügt


*Knust* - Do 21.02.08 22:58

Moin!
Wie ist der Speicher angeordnet?
Also nach blablabla7 folgt blablabla8 sowei war ich schon...:P
und nach 9 kommt A(lässt sich bei dir erkennen^^) aber wie gehts dann weiter?
werden dann alle buchstaben genommen???

Knust


cherrymoon69 - Fr 22.02.08 21:52

um ehrlich zu sein weiß ich nicht genau was du jetzt von mir wissen möchtest. :-)

möchtest du ein speicherabbild? z.b. ?


uall@ogc - Di 04.03.08 10:48


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
var bla: array[0..5of byte = ($90,$90,$90,$90,$90,$90);
// bzw = ($D9,$9E,$F4,$1B,$00,$00)

procedure TForm1.Button1Click(Sender: TObject);
begin
    WindowName  :=  FindWindow(nil,WindowTitle);
          If  WindowName  =  0  then MessageDlg('...erst spiel starten...dann trainer starten =)',  mtwarning,[mbOK],0);
    ThreadId  :=  GetWindowThreadProcessId(WindowName,@ProcessId);
    HandleWindow  :=  OpenProcess(PROCESS_ALL_ACCESS,False,ProcessId);
              WriteProcessMemory(HandleWindow,pointer($480802), @bla[0],6,write);
    closehandle(HandleWindow);
    MessageDlg('Geld ist eingefroren',  mtwarning,[mbOK],0);
end;


versuch mal obiges


cherrymoon69 - Di 04.03.08 15:43

vielen dank. das scheint so zu funktionieren.

aber es gibt das nächste problem. wenn ich in einen bereich des speichers schreiben möchte wo noch nichts steht, also z.b.:
00400F87 - 00 00 - add [eax],al

dann schreibt die prozedur nichts. absolut keine veränderung. weiß jemand rat? ich möchte an diese position 22 Bytes (als hex) schreiben.

---Moderiert von user profile iconNarses: Beiträge zusammengefasst---

habe etwas rausgefunden. wenn ich mit ein em hexeditor mir die speicheradresse angucke, gibt es die option make writable. wenn ich das mache, kann ich mit der prozedur meinen wert schreiben. ich suche jetzt also eine lösung um einen speicherbereich von 22 byte schreibfähig zu machen. wie geht das in kombination mit der oben genannten prozedur?


uall@ogc - Mi 05.03.08 13:43


Delphi-Quelltext
1:
2:
3:
4:
5:
var old: DWord;
begin
VirtualProtectEx(processhandle, pointer(@addresse{$00400F87}), size{22}, PAGE_EXECUTE_READWRITE, old);
WriteProcessMemory(processhandle...);
VirtualProtectEx(processhandle, pointer(@addresse{$00400F87}), size{22}, old, old);


das gilt aber nur wenn der speicher schon existiert. du schreibst da den imageheader putt, wenn du selbst speicher brauchst dann hol dir welchen mit


Delphi-Quelltext
1:
2:
3:
4:
5:
var mem: pointer;
begin
mem := VirtualAllocEx(processhandle, nil, size, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE);
WriteProcessMemory(processahndle,...);
VirtualFreeEx(processhandle, mem, 0, MEM_RELEASE);


cherrymoon69 - Mi 05.03.08 14:11

das mit dem speicher holen klingt interessant, aber welche adresse bekomme ich dann?

ich muß ja den jmp-befehl auf diese adresse legen.

vielen dank soweit.

acj ja. und was macht diese zeile?

VirtualProtectEx(processhandle, pointer(@addresse{$00400F87}), size{22}, old, old);


uall@ogc - Mi 05.03.08 18:55

den Jump-Befehl kannst du ja dynamisch berechnen, ein $E9 distance jump berechnet man durch ZUadresse-VONadresse-5
das VirtualProtect setzt wieder den alten Wert, sollte es aber ausführbarer code bleiben solltest du es auf PAGE_EXECUTE_READWRITE belassen


cherrymoon69 - Mi 05.03.08 19:00

du hast mir sehr geholfen. danke.

aber:
zitat: den Jump-Befehl kannst du ja dynamisch berechnen, ein $E9 distance jump berechnet man durch ZUadresse-VONadresse-5

habe ich nicht wirklich verstanden. dafür bin ich wohl noch nicht weit genug fortgeschritten, fürchte ich. :roll:


bensch - Sa 19.04.08 20:11
Titel: wie sieht das bei dma aus?
der trainer ist ja speziell für sma erstellt wurden. wie würde das jetzt bei dma aussehen?

also ich hab hier ein game, wo sich der wert der mannschaft nach jedem neustart ändert. der wert wird also auf einer dynamischen speicheradresse abgelegt. nun habe ich den static pointer gesucht, der auf die speicheradresse der mannschaft zeigt. den habe ich gefunden, dieser liegt unter der adresse 9D903C. dieser pointer zeigt auf einen weiteren (dynamischen) pointer. ich müsste jetzt also den wert der adresse 9D903C (dem statischen pointer) auslesen, um die adresse für den dynamischen pointer zu erhalten, der widerrum auf die mannschaftsadresse zeigt. wie mache ich das?

das auslesen von der adresse 9D903C habe ich so gemacht:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
var
    hProcess: THandle; //Prozesshandle des Spiels
    wert:integer;  //wert des ausgelesenen speichers
    BytesRead: DWORD;
    adresse:pointer;  //adresse, die ausgelesen werden soll

...

adresse:=ptr($9D903C);

ReadProcessMemory(hProcess,adresse,@wert,sizeof(wert), BytesRead );

...


jetzt habe ich einen wert, den ich mit 96 addieren müsste, um an die speicheradresse des nächsten dynamischen pointers zu gelangen. aber da hängt es schon: wie kann ich den eben ausgelesenen wert, der in der variable wert gespeichert wurde, mit 96 addieren, und dann die speicheradresse dieses ergebnisses wieder auszulesen?


EDIT: mir wurde jetzt in diesem thread ( http://www.delphi-forum.de/viewtopic.php?p=498803#498803 ) geholfen. falls jemand ähnliche schwierigkeiten hat wie ich, so hats bei mir funktioniert:


Delphi-Quelltext
1:
2:
3:
4:
5:
ReadProcessMemory(hProcess, adresse, @wert, SizeOf(wert), BytesRead);  // originaladresse lesen
adresse := Ptr(wert + $60);  // Wert + 96dez
ReadProcessMemory(hProcess, adresse, @wert, SizeOf(wert), BytesRead);  // eben berechnette adresse auslesen
CloseHandle(hProcess);
Edit1.Text := IntToStr(wert);


gruß bensch


gemy - Do 28.08.08 02:09
Titel: Mein Erkentnisse darüber.
Hallo,

hab auch mal eine Frage. Momentan schreibe ich in den Speicher fremder Programme mit diese Funktion:



Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
function WriteMemory(Adress:Pointer; Buffer:array of char):Bool;
begin
        try
                Result:=False;
                VirtualProtectEx(handlewindow, Pointer(Adress), Length(Buffer), PAGE_EXECUTE_READWRITE, old);
                If (WriteProcessMemory(handleWindow, Pointer(Adress), @Buffer, Length(Buffer), BytesWritten)
                and (BytesWritten = Length(Buffer)))
                then Result:=True else Result:=False;
        finally
        VirtualProtectEx(Handlewindow, Pointer(Adress), Length(Buffer), old, old);
        end;
end;



aufrufen tue ich die Funktion mit:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
Adress:= Ptr($00400400);
                pcardinal(@buffer[0])^ := $8B4154A3;
                pcardinal(@buffer[4])^ := $00054000;
                pcardinal(@buffer[8])^ := $C3000000;
                pcardinal(@buffer[12])^:= $00000000;
                pcardinal(@buffer[16])^:= $00000000;

                If WriteMemory(Adress, Buffer) = True then Memo1.Lines.Add('OK'else Memo1.Lines.Add('Err');


Klappt auch wunderbar. Was mir nun aufgefallen ist, ist das der Speicher bei $00400400 nicht so beschrieben wird:

8B 41 54 A3 00 05 40 00 C3 00 00 00

sondern so :

A3 54 41 8B

usw.. Also genau umgekehrt. ich habe ganz oben in meinem Project die variable "Buffer: array [0..19] of char;". Nun habe ich aber nicht immer 20 Bytes zum schreiben. Manchmal auch nur 8 oder 12.

Hat jemand eine Lösung oder Function, die


a) die 4 bytes im Buffer immer umdreht, und
b) nur soviel Buffer schreibt wie auch nur tatsächlich bytes da sind.

also manchmal: z.b.

($89,$96,$88,$09,$00,$00,$89,$15,$40,$05,$40,$00,$C3); und ein andermal
($8B,$41,$54,$A3,$00,$05,$40,$00,$C3);.

Also immer verschieden lang.


Gruß, gemy #delphi.de@quakenet


elundril - Do 28.08.08 04:15

probiers doch mal mit einem dynamischen array und einer bitweisen operation (and,or,xor)

lg elundril


ness - Fr 31.07.09 23:41

Ich habe jetzt den vollkommenen Blackout und aus meinem Gehirn spruehen FUNKEN heraus!

Mal ein ganz einfaches Beispiel,damit ich es auch verstehen kann!

Aaalso,keine Angst,mein Ziel ist NICHTS BOESES und damit hole ich mir kein Vorteil,es ist auch kein Internetspiel etc.

Ich habe die Adresse mit CHEAT ENGINE herausgekriegt:

0103EB28

Und der Value betraegt 24!

Type ist 4 Bytes!

Wie kann ich das auf 50 mit Delphi erfolgreich aendern?