Autor |
Beitrag |
Don Krawallo
      
Beiträge: 45
Windows 10 x64
Delphi 10.4.1
|
Verfasst: So 25.07.10 23:12
Schönen Guten Abend hier im Forum und ein herzliches Hallo an alle Mitglieder.
Wie das Topic schon vermuten lässt handelt es sich ums Thema Spiele Trainer programmieren.
Folgender Fall... Ich habe bereits 2 Trainer in Delphi programmiert die auch hervorragend funktionieren.
Folgendes Beispiel ist aus meinem Trainer zu Die Sims 3 - Reiseabenteuer:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| WindowName := FindWindow(nil,Fenstertitel); ThreadId := GetWindowThreadProcessId(WindowName,@ProcessId); HandleWindow := OpenProcess(PROCESS_ALL_ACCESS,True,ProcessId); VirtualProtectEx(HandleWindow,pointer($00400408), 40, PAGE_EXECUTE_READWRITE, old); WriteProcessMemory(HandleWindow,pointer($00C3441E), @Patched[0],6,write); WriteProcessMemory(HandleWindow,pointer($00400408), @CC1[0],32,write); WriteProcessMemory(HandleWindow,pointer($00400428), @CC2[0],32,write); WriteProcessMemory(HandleWindow,pointer($00400448), @CC3[0],33,write); |
Wie ihr sehen könnt wird das Spiel, also der Process per Auslesen des Fenstertitels gesucht/gefunden.
Nun aber stehe ich vor einem neuen Problem. Ich versuche mich derzeit an einem neuen Projekt und zwar
an einem Trainer zu Command & Conquer 4. Das Spiel wird herkömmlich über eine EXE namens C&C4.exe gestartet.
Diese wiederrum startet einen Process namens C&C4.game. Würde ich den Trainer nach obigen Beispiel programmieren
hab ich im Endeffekt nur Zugriff auf die C&C4.exe.
Meine Überlegung ist nun folgende das ich den Process direkt suchen lasse. Hier im Forum habe ich dann folgendes
Codeschnipsel gefunden:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20:
| const ProcessName = 'DeineDatei.exe'; 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) = 0) then pID := ProcessEntry.th32ProcessID; Schleife := Process32Next(hSnapshot, ProcessEntry); end; CloseHandle(hSnapshot); hProcess := OpenProcess(PROCESS_ALL_ACCESS, True, pID); |
Diesen Codeschnipsel hab ich erstmal auf meinen Sims 3 Trainer übertragen um die ganze Sache erstmal zu testen.
Das sieht momentan auch so aus:
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:
| Uses ..., Tlhelp32, ...; var hSnapshot: THandle; hProcess: THandle; ProcessEntry: TProcessEntry32; Schleife: BOOL; pID: Integer; Const ProcessName = 'TS3EP01.exe';
Procedure TForm1.Hotkeyused( Var msg: TWMHotkey ) ; Begin If msg.hotkey = 1 Then Begin hSnapshot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); ProcessEntry.dwSize := Sizeof(ProcessEntry); Schleife := Process32First(hSnapshot, ProcessEntry); while Schleife do begin if (CompareText(ProcessEntry.szExeFile, ProcessName) = 0) then pID := ProcessEntry.th32ProcessID; Schleife := Process32Next(hSnapshot, ProcessEntry); end; CloseHandle(hSnapshot); hProcess := OpenProcess(PROCESS_ALL_ACCESS, True, pID); VirtualProtectEx(hProcess,pointer($00400408), 40, PAGE_EXECUTE_READWRITE, old); WriteProcessMemory(hProcess,pointer($00C3441E), @Patched[0],6,write); WriteProcessMemory(hProcess,pointer($00400408), @CC1[0],32,write); WriteProcessMemory(hProcess,pointer($00400428), @CC2[0],32,write); WriteProcessMemory(hProcess,pointer($00400448), @CC3[0],33,write); closehandle(hProcess); End; end; |
Aber und genau da liegt der Knackpunkt an der Geschichte, die Cheatcodes werden nicht geschrieben.
Wie gesagt, der Trainer funktioniert ohne Tadel mit dem Beispiel ganz oben, wo ich den Process
bzw. das Spielefenster per Fenstertitel auslesen suche.
Nur mal so am Rande... Wenn ich die Trainer so programmiere das diese den Fenstertitel des Spiels
suchen kann es ja ebenfalls zu Problemen kommen wenn beispielsweise der Fenstertitel des Spiels
und z.b. der Installationsordner denselben Namen haben.
Vielleicht hat ja jemand von euch noch eine Idee wo bei dem letzten Beispiel der Fehler steckt?
Ich bedanke mich schonmal im vorraus für eure Aufmerksamkeit und wünsche noch eine gute Nacht.
MFG Don Krawallo
|
|
Martok
      
Beiträge: 3661
Erhaltene Danke: 604
Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
|
Verfasst: Mo 26.07.10 01:24
Hallo und  im Forum!
Grundsätzlich ist (abgesehen von der etwas unübersichtlichen Einrückung) an dem Code nichts auszusetzen. Ich habe das mal schnell mit einer anderen Anwendung probiert: funktioniert.
Schonmal im Debugger durchgesteppt? ggf. Auch mit einer Anwendung probiert die nicht im Vollbild läuft und deswegen einfacher zum Testen ist?
Ansonsten bietet es sich auch an, möglichst detaillierte Logdateien zu schreiben, wenn das Problem nur mit dem Echt-Spiel auftritt aber dann schlecht zu debuggen ist.
Was mir spontan einfällt sind Probleme mit Unicode (Delphi 2007 +) oder 64bit; die hatte neulich jemand, der das Gleiche machen wollte. Sollte sich finden lassen: CREATETOOLHELP32SNAPSHOT
OT: übrigens schön, jemanden neues zu sehen der der deutschen Sprache mitsamt Höflichkeitsfloskeln mächtig ist. Du bist doch wirklich neu hier, oder? Der Nick kommt mir irgendwie bekannt vor. Weiß nur nicht woher...
cu
Martok
_________________ "The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
Für diesen Beitrag haben gedankt: Don Krawallo
|
|
Don Krawallo 
      
Beiträge: 45
Windows 10 x64
Delphi 10.4.1
|
Verfasst: Mo 26.07.10 01:58
Martok hat folgendes geschrieben : | ... OT: übrigens schön, jemanden neues zu sehen der der deutschen Sprache mitsamt Höflichkeitsfloskeln mächtig ist. Du bist doch wirklich neu hier, oder? Der Nick kommt mir irgendwie bekannt vor. Weiß nur nicht woher...
cu
Martok |
Danke für die Blumen
Yep, ich bin neu hier, aber auch in einem anderen Forum (Game Trainer-Forum) unter selbigen Namen angemeldet.
Im übrigen... Ja, ich nutze ein 64-Bit Betriebssystem (Win 7). Meine Delphi Entwicklungsumgebung ist die 2010er Version.
Wie ich schon schrieb hab ich bereits zwei Trainer programmiert welche auch funktionieren.
Da ich insofern erstmal glücklich drüber war/bin das diese auch funktionieren hab ich mich mit dem Programm selbst
auch bis dato weniger auseinandergesetzt.
OK, das ganze ist sehr ominös
Aber wenn mir die Frage an dieser Stelle noch gestattet sei? In welcher Hinsicht gibt bzw. könnte es Probleme
mit der Unicode Darstellung geben? Fällt Dir dazu ein fundiertes Beispiel ein?
MFG Don Krawallo
|
|
Martok
      
Beiträge: 3661
Erhaltene Danke: 604
Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
|
Verfasst: Mo 26.07.10 02:18
Hi,
Bezüglich Unicode kann es beim CompareText geben, wenn Delphi aus dem szExeFile einen String machen will.
Hier wäre was dazu: IsProcess funktioniert unter Delphi 2010 nicht mehr!. Da dann auch die verlinkte Diskussion in der DP beachten, dort gibts etwas Hintergrund dazu.
Fazit: Statt CompareText AnsiSameText nehmen.
Deswegen frug ich, ob denn der Prozess nicht gefunden wird oder danach was schiefgeht.
HTH,
Martok
_________________ "The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
|
|
jaenicke
      
Beiträge: 19314
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mo 26.07.10 06:02
Der Quelltext hat zwar noch Fehler, funktioniert aber auch mit Delphi 2010 sofern der Prozess läuft. Denn szExeFile liefert ein Array of WChar, sprich WideChar, das funktioniert also mit Unicode.
CompareText ist eine delphieigene Funktion während AnsiSameText auf die API-Funktion CompareStringW hinausläuft. In jedem Fall wird aber zuerst eine Umwandlung in einen UnicodeString durchgeführt. Bei AnsiSameText danach noch eine auf PChar sprich PWideChar.
Dass der Prozess gar nicht laufen könnte, wird da gar nicht beachtet. Deshalb sollte auch eine Compilerwarnung kommen, da pID evtl. nicht initialisiert ist...
Besser also: Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22:
| const ProcessName = 'DeineDatei.exe'; 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); pid := -1; while Schleife do begin if (CompareText(ProcessEntry.szExeFile, ProcessName) = 0) then pID := ProcessEntry.th32ProcessID; Schleife := Process32Next(hSnapshot, ProcessEntry); end; CloseHandle(hSnapshot); if pid >= 0 then hProcess := OpenProcess(PROCESS_ALL_ACCESS, True, pID); |
Für diesen Beitrag haben gedankt: Don Krawallo
|
|
Flamefire
      
Beiträge: 1207
Erhaltene Danke: 31
Win 10
Delphi 2009 Pro, C++ (Visual Studio)
|
Verfasst: Mo 26.07.10 11:07
UND: Schon mal mti Adminrechten starten versucht? Das problem hatte ich mal.
Auf jeden Fall aber erst mal Fehler suchen: Findet er die PID? Schreibt er? Was gibt er als Fehler zurück usw.
|
|
Don Krawallo 
      
Beiträge: 45
Windows 10 x64
Delphi 10.4.1
|
Verfasst: Mo 26.07.10 20:35
jaenicke hat folgendes geschrieben : | Der Quelltext hat zwar noch Fehler, funktioniert aber auch mit Delphi 2010 sofern der Prozess läuft. Denn szExeFile liefert ein Array of WChar, sprich WideChar, das funktioniert also mit Unicode. |
Naja, der Prozess bzw. das Spiel läuft ja, oder vielmehr... Der Prozess muss ja laufen damit die entsprechenden Bytes geschrieben werden
und letztenendes der Trainer funktioniert.
Oder hab ich jetzt in dieser Hinsicht Dich falsch verstanden?
Ich hab mich heute nochmal mit der ganzen Materie befasst, den Quellcode nach meinem genannten Beispiel auch wieder so aufgesetzt.
Soll heißen das sich der Quellcode in keiner weiße zum vorhergehenden Sourcecode unterscheidet.
Nunja, was soll ich sagen??? Auf einmal funktionierts.
Ich kann eigentlich von mir behaupten das ich ein recht großes Verständnis von den Computerdingen habe, programmiertechnisch wollt ich
mich hier ganz einfach absichern ob denn nicht doch ein Fehler im Quellcode steckt.
Aber ganz im Ernst, warum das auf einmal funktioniert... Bin ich absolut überfragt. Ich bin den neuen Quellcode mehrmals durchgegangen
hab aber keine Unterschiede festgestellt. Sehr mysteriös das ganze.
@jaenicke
Wenn ich Dich da jetzt richtig verstanden habe dann dient Deine (optimierte/fehlerbereinigte) Variante des Codes gewissermaßen
einer Vorbeugung zur unnötigen Prozessorauslastung? Oder bin ich da jetzt auf dem Holzweg?
MFG Don Krawallo
PS: Ich danke euch natürlich für eure bisherigen konstruktiven Beiträge. 
|
|
jaenicke
      
Beiträge: 19314
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mo 26.07.10 20:59
Don Krawallo hat folgendes geschrieben : | Wenn ich Dich da jetzt richtig verstanden habe dann dient Deine (optimierte/fehlerbereinigte) Variante des Codes gewissermaßen einer Vorbeugung zur unnötigen Prozessorauslastung? |
Nein, es wird nicht einfach OpenProcess aufgerufen egal ob der Prozess überhaupt existiert oder nicht. Denn dein Code oben achtet da nicht drauf.
Klar, normalerweise läuft der, aber man sollte schon immer auch mögliche Fehlerquellen ausschließen.
|
|
Gerd Kayser
      
Beiträge: 632
Erhaltene Danke: 121
Win 7 32-bit
Delphi 2006/XE
|
Verfasst: Di 27.07.10 00:59
Man sollte laut MSDN PROCESS_ALL_ACCESS vermeiden. Das könnte evtl. voll in die Hose gehen.
Zitat: "Windows Server 2003 and Windows XP/2000: The size of the PROCESS_ALL_ACCESS flag increased on Windows Server 2008 and Windows Vista. If an application compiled for Windows Server 2008 and Windows Vista is run on Windows Server 2003 or Windows XP/2000, the PROCESS_ALL_ACCESS flag is too large and the function specifying this flag fails with ERROR_ACCESS_DENIED. To avoid this problem, specify the minimum set of access rights required for the operation."
msdn.microsoft.com/e...ms684880(VS.85).aspx
nsylvain.blogspot.co...n32winnt-mayhem.html
|
|
Don Krawallo 
      
Beiträge: 45
Windows 10 x64
Delphi 10.4.1
|
Verfasst: Di 31.08.10 02:24
Ein scheenen guten Morgen allerseits...
Also mittlerweile, wie ich bereits schrieb, funktioniert das ganze anhand von CREATETOOLHELP32SNAPSHOT.
Mit dieser Funktion spiele ich momentan soweit rum, das ich an die Basisaddresse einer DLL komme...
Wie wir ja alle wissen werden diese dynamisch geladen und haben nach jedem Programmneustart eine neue/andere Basisaddresse.
So weit so gut...
Der Sourcecode sieht folgendermasßen aus:
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:
| var Form3: TForm3; ModuleEntry: TModuleEntry32; ProcessEntry: TProcessEntry32; hSnapshot, hProcess, SnapMod: THandle; DLLBaseAddy: PByte; Schleife, FindDLLBase : Boolean; pID: Integer; write: cardinal; old: DWORD; CC: array [0..7] of byte = ($90, $FF, $26, $EA, $C5, $62, $78, $34); Reset: array [0..7] of byte = ($00, $00, $00, $00, $00, $00, $00, $00);
Const Processname = 'Cheat Engine.exe'; DLLName = 'DBGHelp.dll';
procedure TForm3.Button1Click(Sender: TObject); begin hSnapshot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); ProcessEntry.dwSize := Sizeof(ProcessEntry); Schleife := Process32First(hSnapshot, ProcessEntry); pID := -1; while Schleife do begin if (CompareText(ProcessEntry.szExeFile, ProcessName) = 0) then pID := ProcessEntry.th32ProcessID; Schleife := Process32Next(hSnapshot, ProcessEntry); end; if pID >= 0 then begin hProcess := OpenProcess(PROCESS_ALL_ACCESS, True, pID); SnapMod:= CreateToolhelp32Snapshot(TH32CS_Snapmodule, pID); ModuleEntry.dwSize := Sizeof(ModuleEntry); FindDLLBase:= Module32First (SnapMod, ModuleEntry); while FindDLLBase do begin if (CompareText(Moduleentry.szModule, DLLName) =0) then DLLBaseAddy := ModuleEntry.modBaseAddr; FindDLLBase := Module32Next(SnapMod, ModuleEntry); end; CloseHandle(hSnapshot); VirtualProtectEx(hProcess,pointer(DLLBaseAddy+$0163AB), 5, PAGE_EXECUTE_READWRITE, old); WriteProcessMemory(hProcess,pointer(DLLBaseAddy+$0163AB), @CC[0],8,write); CloseHandle(hprocess); end; end; |
Das Programm bzw. die DLL in die geschrieben wird ist nur erstmal um zu testen ob mein SourceCode funktioniert...
Dieser funktioniert auch tadellos...
Problem gibts hierbei keines, da ich aber grade erst mit Delphi anfange möcht ich an dieser Stelle die Frage an
euch erfahrenen Programmierer richten...
Und zwar - Gibts jetzt an dem Code selbst, speziell die Routine SNAPMODULE, etwas auszusetzen bzw. zu optimieren
um eventuelle Fehlerquellen schon von vornherein auszuschließen?
Aber nun wünsch ich erstmal ne gute Nacht
Viele Grüße, Don Krawallo
|
|
|