Das Thema ist zwar schon älter, aber vllt. findets ja jemand nützlich.
Alles was du tun musst, um dein Cheat Engine Script in einen Trainer zu packen, ist die Bytes deiner Befehle an die entsprechenden Memory Adressen zu schreiben.
Die entsprechenden Bytes für jeden Befehl kannst du im Memory View von Cheat Engine sehen.
Beispiel:
00 b8 c3 50 00 34
ist gleich
add [eax+340050c3],bh
In deinem Trainer wirst du konkret folgendes brauchen:
1.) Eine function, mit der du die Prozess-ID des Spieles herausfinden kannst:
Delphi-Quellcode:
function GetProcessID(Const ExeFileName: string; var ProcessId: integer): boolean;
var
ContinueLoop: BOOL;
FSnapshotHandle: THandle;
FProcessEntry32: TProcessEntry32;
begin
result := false;
FSnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
FProcessEntry32.dwSize := Sizeof(FProcessEntry32);
ContinueLoop := Process32First(FSnapshotHandle, FProcessEntry32);
while integer(ContinueLoop) <> 0 do begin
if (StrIComp(PChar(ExtractFileName(FProcessEntry32.szExeFile)), PChar(ExeFileName)) = 0)
or (StrIComp(FProcessEntry32.szExeFile, PChar(ExeFileName)) = 0) then begin
ProcessId:= FProcessEntry32.th32ProcessID;
result := true;
break;
end;
ContinueLoop := Process32Next(FSnapshotHandle, FProcessEntry32);
end;
CloseHandle(FSnapshotHandle);
end;
2.) Procedures, mit denen du deine Bytes in den Speicher schreibst.
Diese hier benutze ich für NOPs
Delphi-Quellcode:
procedure poke1(Address: Cardinal; Data: Byte);
var
Written: Cardinal;
begin
WriteProcessMemory(PidHandle, Pointer(Address), @Data, SizeOf(Data), Written);
end;
Nutzungsbeispiel:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
if GetProcessID(ProgramName, PidId) then
begin
PidHandle := OpenProcess(PROCESS_ALL_ACCESS,False,PidId);
poke1($41ba76, $90);
poke1($41ba76 + 1, $90);
poke1($41ba76 + 2, $90);
poke1($41ba76 + 3, $90);
poke1($41ba76 + 4, $90);
poke1($41ba76 + 5, $90);
closehandle(PidHandle);
end;
end;
Hier schreibe ich an die Adresse 41ba76 und die 5 danach das Byte 90, also No Operation.
ProgramName ist dabei eine Konstante, die den Prozessnamen deines Spiels enthält
Delphi-Quellcode:
Const
ProgramName = 'hl2.exe';
Die folgende Procedure nutze ich, wenn ich mehr als ein Byte in eine Adresse schreibe
Delphi-Quellcode:
procedure pokeX(Address: Cardinal; Data: Array of Byte);
var
Written: Cardinal;
begin
WriteProcessMemory(PidHandle, Pointer(Address), @Data, SizeOf(Data), Written);
end;
Beispiel
Delphi-Quellcode:
procedure TForm1.Button2Click(Sender: TObject);
begin
if GetProcessID(ProgramName, PidId) then
begin
PidHandle := OpenProcess(PROCESS_ALL_ACCESS,False,PidId);
SetLength(byteArr, 4);
byteArr[0] := $C7;
byteArr[1] := $45;
byteArr[2] := $48;
byteArr[3] := $01;
pokeX($81B0000, byteArr);
SetLength(byteArr, 4);
byteArr[0] := $80;
byteArr[1] := $7d;
byteArr[2] := $48;
byteArr[3] := $00;
pokeX($81B0007, byteArr);
poke1($81B000B, $56);
SetLength(byteArr, 5);
byteArr[0] := $e9;
byteArr[1] := $3e;
byteArr[2] := $82;
byteArr[3] := $2d;
byteArr[4] := $F8;
pokeX($81B000C, byteArr);
SetLength(byteArr, 5);
byteArr[0] := $E9;
byteArr[1] := $B1;
byteArr[2] := $7D;
byteArr[3] := $d2;
byteArr[4] := $07;
pokeX($48824A, byteArr);
closehandle(PidHandle);
end;
end;
Das wars auch schon