Gut, da geb ich dir recht Na mal schaun, was sich da noch so machen lässt... Ist wirklich ein wenig unübersichtlich das ganze... Ich werds mir nochmal vornehmen
LG Darius83
Edit1:
So habs nochmal ein wenig aufgeräumt...
Ich hoffe, es ist jetzt ein wenig übersichtlicher geworden
[code=delphi]
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, tlhelp32, ExtCtrls, StdCtrls;
type
TWMHotkey = record
Msg: Cardinal;
idHotKey: Word;
Modifiers: Integer;
VirtKey: Integer;
end;
type
TForm1 = class(TForm)
Timer1: TTimer;
Memo1: TMemo;
procedure Timer1Timer(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure FormCreate(Sender: TObject);
private
procedure WMHotKey(var Msg: TWMHotKey); message WM_HOTKEY;
public
end;
var
Form1: TForm1;
Pid: Integer = 0;
BaseAddr: Pointer;
GameGestartet: Boolean = False;
GoldCheatAktiv: Boolean = False;
EnergieCheatAktiv: Boolean = False;
Written, Caveadress1, Caveadress2, Caveadress3, Pidhandle: Cardinal = 0;
implementation
{$R *.dfm}
const
PROCESS : String = 'game.dat'; // Prozessname des Spiels
GOLDSAMMELN: Integer = $00566D77; // Adresse 1 Gold
GOLDAUSGEBEN: Integer = $00566CD5; // Adresse 2 Gold
ENERGIEVERBRAUCH: Integer = $00566EBF; // Adresse Energieverbrauch
ID = $FF;
JmpGoldSammeln:array[0..10] of byte = ($68,$00,$00,$00,$00,$C3,$90,$90,$90,$90,$90);
JmpGoldSammelnOriginal:array[0..10] of byte = ($89,$46,$04,$C7,$44,$24,$74,$FF,$FF,$FF,$FF);
JmpGoldAusgeben:array[0..10] of byte = ($68,$00,$00,$00,$00,$C3,$90,$90,$90,$90,$90);
JmpGoldAusgebenOriginal:array[0..10] of byte = ($89,$47,$04,$C7,$44,$24,$74,$FF,$FF,$FF,$FF);
JmpEnergieverbrauch:array[0..7] of byte = ($68,$00,$00,$00,$00,$C3,$90,$90);
JmpEnergieverbrauchOriginal:array[0..7] of byte = ($89,$4E,$08,$8B,$C1,$8B,$4E,$0C);
// $00004E20; 20000 Gold (Bytes 2-5)
CodeCave1:array[0..21] of byte = ($B8,$20,$4E,$00,$00,$89,$46,$04,$C7,$44,$24,$74,$FF,$FF,$FF,$FF,$68,$82,$6D,$56,$00,$C3);
CodeCave2:array[0..21] of byte = ($B8,$20,$4E,$00,$00,$89,$47,$04,$C7,$44,$24,$74,$FF,$FF,$FF,$FF,$68,$E0,$6C,$56,$00,$C3);
CodeCaveEnergieverbrauch:array[0..18] of byte = ($B9,$00,$00,$00,$00,$89,$4E,$08,$8B,$C1,$8B,$4E,$0C,$68,$C7,$6E,$56,$00,$C3);
function GetID(Const ExeFileName: string; var ProcessId: integer): boolean;
//Funktion zum Suchen der ProzessID
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; // function GetID
function GetAdress(Pidhandle: Integer; BasePointer: Cardinal; Offsets: Array of Cardinal) : Cardinal;
// Kleine Hilfsfunktion um eine Adresse via Basisadresse und Offsets zu suchen.
var
i, Anzahl: Integer;
begin
Result := BasePointer;
Anzahl := High(Offsets);
if Anzahl = 1 then
Result := Result + Offsets[1]
else begin
for i := 1 to Anzahl do begin
ReadProcessMemory(Pidhandle, Pointer(Result), @Result, 4, Written);
Result := Result + Offsets[i];
end;
end;
end; // function GetAdress
procedure WriteBytesToMem(Processhandle, Adress, Written: Cardinal; ByteArray: Array of Byte);
// Kleine Hilfsprozedur, um ein Array of Byte in den Speicher zu schreiben
var i: Cardinal;
begin
for i := 0 to high(ByteArray) do
WriteProcessMemory(Processhandle, Pointer(Adress+i), @ByteArray[i], 1, Written);
end; // procedure WriteBytesToMem
procedure Start();
{*
Hier wird, wenn der Trainer das Spiel als gestartet erkennt, einmalig
Speicher im Prozess reserviert und die Codecaves in den neuen Speicher
geschrieben.
*}
var
lBuf, Adress: Cardinal;
Offsets: Array of Cardinal;
begin
Adress := $0096c9b0;
SetLength (Offsets, 3);
Offsets[1] := $0C;
Offsets[2] := $34;
if GetID(PROCESS, Pid) then begin
Pidhandle := OpenProcess(PROCESS_ALL_ACCESS,False,Pid);
try
lBuf := GetAdress(Pidhandle, Adress, Offsets);
ReadProcessMemory(Pidhandle, Pointer(lBuf), @lBuf, 4, Written);
if lBuf > 0 then begin
BaseAddr := VirtualAllocEx(Pidhandle,NIL,2048,MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE);
Caveadress1 := Cardinal(BaseAddr)+$000;
Caveadress2 := Cardinal(BaseAddr)+$100;
Caveadress3 := Cardinal(BaseAddr)+$200;
WriteBytesToMem(Pidhandle,Caveadress1,Written,CodeCave1);
WriteBytesToMem(Pidhandle,Caveadress2,Written,CodeCave2);
WriteBytesToMem(Pidhandle,Caveadress3,Written,CodeCaveEnergieverbrauch);
//ShowMessage(IntToHex(Cardinal(BaseAddr), 8));
end;
finally
closehandle(Pidhandle);
end;
end;
end; // procedure Start
procedure ChangeGoldHack();
// Hier wird das Vermögen im Spiel eingefroren auf 20000 Gold
begin
if GetID(PROCESS, Pid) then begin
Pidhandle := OpenProcess(PROCESS_ALL_ACCESS,False,Pid);
try
if not GoldCheatAktiv then begin
WriteBytesToMem(Pidhandle, GOLDSAMMELN, Written, JmpGoldSammeln);
WriteProcessMemory(Pidhandle, Pointer(GOLDSAMMELN+$01), @Caveadress1, 4, Written);
WriteBytesToMem(Pidhandle, GOLDAUSGEBEN, Written, JmpGoldAusgeben);
WriteProcessMemory(Pidhandle, Pointer(GOLDAUSGEBEN+$01), @Caveadress2, 4, Written);
GoldCheatAktiv := true;
end else begin
WriteBytesToMem(Pidhandle, GOLDSAMMELN, Written, JmpGoldSammelnOriginal);
WriteBytesToMem(Pidhandle, GOLDAUSGEBEN, Written, JmpGoldAusgebenOriginal);
GoldCheatAktiv := false;
end;
finally
closehandle(Pidhandle);
end;
end;
end; // procedure Change
procedure ChangeEnergieHack();
//Hier wird der Energieverbrauch-Cave aktiviert/deaktiviert
begin
if GetID(PROCESS, Pid) then begin
Pidhandle := OpenProcess(PROCESS_ALL_ACCESS,False,Pid);
try
if not EnergieCheatAktiv then begin
WriteBytesToMem(Pidhandle, ENERGIEVERBRAUCH, Written, JmpEnergieverbrauch);
WriteProcessMemory(Pidhandle, Pointer(ENERGIEVERBRAUCH+$01), @Caveadress3, 4, Written);
EnergieCheatAktiv := true;
end else begin
WriteBytesToMem(Pidhandle, ENERGIEVERBRAUCH, Written, JmpEnergieverbrauchOriginal);
EnergieCheatAktiv := false;
end;
finally
closehandle(Pidhandle);
end;
end;
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
{*
Hier werden die registrierten Hotkeys wieder freigegeben und falls
das Spiel noch läuft, der reservierte Speicher für den Trainer
ebenfalls.
*}
begin
UnRegisterHotKey(Form1.Handle, ID);
UnRegisterHotKey(Form1.Handle, ID+1);
if GetID(PROCESS, Pid) then begin
Pidhandle := OpenProcess(PROCESS_ALL_ACCESS,False,Pid);
try
VirtualFreeEx(Pidhandle,BaseAddr,0,MEM_RELEASE);
finally
closehandle(Pidhandle);
end;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
//Hier werden die für den Trainer benötigten Hotkeys angelegt
begin
RegisterHotKey(Form1.Handle, ID, MOD_Alt, Ord('A'));
RegisterHotKey(Form1.Handle, ID+1, MOD_Alt, Ord('B'));
end;
procedure TForm1.Timer1Timer(Sender: TObject);
{*
Prüfen, ob das Spiel gestartet ist,
wenn ja, schreibe die Codecaves und aktiviere die Hotkeys,
wenn nein, warte 1 Sekunde, dann prüfe erneut.
*}
begin
if not GameGestartet then
Start()
else begin
if GetID(PROCESS, Pid) then
GameGestartet := true
else
GameGestartet := false;
end;
end;
procedure TForm1.WMHotKey(var Msg: TWMHotkey);
{*
Hier wird geprüft, ob das Spiel bereits läuft.
Wenn ja, dann werden die Hotkeys ausgewertet und je nachdem,
welche Tastenkombination betätigt wurde, der entsprechende
Bereich ausgeführt. Dieser enthält entweder den Originalcode
oder aber den Sprung zur Codecave.
*}
begin
if GameGestartet then
case Msg.IdHotKey of
ID:
begin
ChangeGoldHack();
end;
ID+1:
begin
ChangeEnergieHack();
end;
// Abhängig von der ID wird entschieden, was getan werden soll.
end;
inherited;
end;
end.
[/code]
LG Darius83
Edit1:
So habs nochmal ein wenig aufgeräumt...
Ich hoffe, es ist jetzt ein wenig übersichtlicher geworden
[code=delphi]
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, tlhelp32, ExtCtrls, StdCtrls;
type
TWMHotkey = record
Msg: Cardinal;
idHotKey: Word;
Modifiers: Integer;
VirtKey: Integer;
end;
type
TForm1 = class(TForm)
Timer1: TTimer;
Memo1: TMemo;
procedure Timer1Timer(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure FormCreate(Sender: TObject);
private
procedure WMHotKey(var Msg: TWMHotKey); message WM_HOTKEY;
public
end;
var
Form1: TForm1;
Pid: Integer = 0;
BaseAddr: Pointer;
GameGestartet: Boolean = False;
GoldCheatAktiv: Boolean = False;
EnergieCheatAktiv: Boolean = False;
Written, Caveadress1, Caveadress2, Caveadress3, Pidhandle: Cardinal = 0;
implementation
{$R *.dfm}
const
PROCESS : String = 'game.dat'; // Prozessname des Spiels
GOLDSAMMELN: Integer = $00566D77; // Adresse 1 Gold
GOLDAUSGEBEN: Integer = $00566CD5; // Adresse 2 Gold
ENERGIEVERBRAUCH: Integer = $00566EBF; // Adresse Energieverbrauch
ID = $FF;
JmpGoldSammeln:array[0..10] of byte = ($68,$00,$00,$00,$00,$C3,$90,$90,$90,$90,$90);
JmpGoldSammelnOriginal:array[0..10] of byte = ($89,$46,$04,$C7,$44,$24,$74,$FF,$FF,$FF,$FF);
JmpGoldAusgeben:array[0..10] of byte = ($68,$00,$00,$00,$00,$C3,$90,$90,$90,$90,$90);
JmpGoldAusgebenOriginal:array[0..10] of byte = ($89,$47,$04,$C7,$44,$24,$74,$FF,$FF,$FF,$FF);
JmpEnergieverbrauch:array[0..7] of byte = ($68,$00,$00,$00,$00,$C3,$90,$90);
JmpEnergieverbrauchOriginal:array[0..7] of byte = ($89,$4E,$08,$8B,$C1,$8B,$4E,$0C);
// $00004E20; 20000 Gold (Bytes 2-5)
CodeCave1:array[0..21] of byte = ($B8,$20,$4E,$00,$00,$89,$46,$04,$C7,$44,$24,$74,$FF,$FF,$FF,$FF,$68,$82,$6D,$56,$00,$C3);
CodeCave2:array[0..21] of byte = ($B8,$20,$4E,$00,$00,$89,$47,$04,$C7,$44,$24,$74,$FF,$FF,$FF,$FF,$68,$E0,$6C,$56,$00,$C3);
CodeCaveEnergieverbrauch:array[0..18] of byte = ($B9,$00,$00,$00,$00,$89,$4E,$08,$8B,$C1,$8B,$4E,$0C,$68,$C7,$6E,$56,$00,$C3);
function GetID(Const ExeFileName: string; var ProcessId: integer): boolean;
//Funktion zum Suchen der ProzessID
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; // function GetID
function GetAdress(Pidhandle: Integer; BasePointer: Cardinal; Offsets: Array of Cardinal) : Cardinal;
// Kleine Hilfsfunktion um eine Adresse via Basisadresse und Offsets zu suchen.
var
i, Anzahl: Integer;
begin
Result := BasePointer;
Anzahl := High(Offsets);
if Anzahl = 1 then
Result := Result + Offsets[1]
else begin
for i := 1 to Anzahl do begin
ReadProcessMemory(Pidhandle, Pointer(Result), @Result, 4, Written);
Result := Result + Offsets[i];
end;
end;
end; // function GetAdress
procedure WriteBytesToMem(Processhandle, Adress, Written: Cardinal; ByteArray: Array of Byte);
// Kleine Hilfsprozedur, um ein Array of Byte in den Speicher zu schreiben
var i: Cardinal;
begin
for i := 0 to high(ByteArray) do
WriteProcessMemory(Processhandle, Pointer(Adress+i), @ByteArray[i], 1, Written);
end; // procedure WriteBytesToMem
procedure Start();
{*
Hier wird, wenn der Trainer das Spiel als gestartet erkennt, einmalig
Speicher im Prozess reserviert und die Codecaves in den neuen Speicher
geschrieben.
*}
var
lBuf, Adress: Cardinal;
Offsets: Array of Cardinal;
begin
Adress := $0096c9b0;
SetLength (Offsets, 3);
Offsets[1] := $0C;
Offsets[2] := $34;
if GetID(PROCESS, Pid) then begin
Pidhandle := OpenProcess(PROCESS_ALL_ACCESS,False,Pid);
try
lBuf := GetAdress(Pidhandle, Adress, Offsets);
ReadProcessMemory(Pidhandle, Pointer(lBuf), @lBuf, 4, Written);
if lBuf > 0 then begin
BaseAddr := VirtualAllocEx(Pidhandle,NIL,2048,MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE);
Caveadress1 := Cardinal(BaseAddr)+$000;
Caveadress2 := Cardinal(BaseAddr)+$100;
Caveadress3 := Cardinal(BaseAddr)+$200;
WriteBytesToMem(Pidhandle,Caveadress1,Written,CodeCave1);
WriteBytesToMem(Pidhandle,Caveadress2,Written,CodeCave2);
WriteBytesToMem(Pidhandle,Caveadress3,Written,CodeCaveEnergieverbrauch);
//ShowMessage(IntToHex(Cardinal(BaseAddr), 8));
end;
finally
closehandle(Pidhandle);
end;
end;
end; // procedure Start
procedure ChangeGoldHack();
// Hier wird das Vermögen im Spiel eingefroren auf 20000 Gold
begin
if GetID(PROCESS, Pid) then begin
Pidhandle := OpenProcess(PROCESS_ALL_ACCESS,False,Pid);
try
if not GoldCheatAktiv then begin
WriteBytesToMem(Pidhandle, GOLDSAMMELN, Written, JmpGoldSammeln);
WriteProcessMemory(Pidhandle, Pointer(GOLDSAMMELN+$01), @Caveadress1, 4, Written);
WriteBytesToMem(Pidhandle, GOLDAUSGEBEN, Written, JmpGoldAusgeben);
WriteProcessMemory(Pidhandle, Pointer(GOLDAUSGEBEN+$01), @Caveadress2, 4, Written);
GoldCheatAktiv := true;
end else begin
WriteBytesToMem(Pidhandle, GOLDSAMMELN, Written, JmpGoldSammelnOriginal);
WriteBytesToMem(Pidhandle, GOLDAUSGEBEN, Written, JmpGoldAusgebenOriginal);
GoldCheatAktiv := false;
end;
finally
closehandle(Pidhandle);
end;
end;
end; // procedure Change
procedure ChangeEnergieHack();
//Hier wird der Energieverbrauch-Cave aktiviert/deaktiviert
begin
if GetID(PROCESS, Pid) then begin
Pidhandle := OpenProcess(PROCESS_ALL_ACCESS,False,Pid);
try
if not EnergieCheatAktiv then begin
WriteBytesToMem(Pidhandle, ENERGIEVERBRAUCH, Written, JmpEnergieverbrauch);
WriteProcessMemory(Pidhandle, Pointer(ENERGIEVERBRAUCH+$01), @Caveadress3, 4, Written);
EnergieCheatAktiv := true;
end else begin
WriteBytesToMem(Pidhandle, ENERGIEVERBRAUCH, Written, JmpEnergieverbrauchOriginal);
EnergieCheatAktiv := false;
end;
finally
closehandle(Pidhandle);
end;
end;
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
{*
Hier werden die registrierten Hotkeys wieder freigegeben und falls
das Spiel noch läuft, der reservierte Speicher für den Trainer
ebenfalls.
*}
begin
UnRegisterHotKey(Form1.Handle, ID);
UnRegisterHotKey(Form1.Handle, ID+1);
if GetID(PROCESS, Pid) then begin
Pidhandle := OpenProcess(PROCESS_ALL_ACCESS,False,Pid);
try
VirtualFreeEx(Pidhandle,BaseAddr,0,MEM_RELEASE);
finally
closehandle(Pidhandle);
end;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
//Hier werden die für den Trainer benötigten Hotkeys angelegt
begin
RegisterHotKey(Form1.Handle, ID, MOD_Alt, Ord('A'));
RegisterHotKey(Form1.Handle, ID+1, MOD_Alt, Ord('B'));
end;
procedure TForm1.Timer1Timer(Sender: TObject);
{*
Prüfen, ob das Spiel gestartet ist,
wenn ja, schreibe die Codecaves und aktiviere die Hotkeys,
wenn nein, warte 1 Sekunde, dann prüfe erneut.
*}
begin
if not GameGestartet then
Start()
else begin
if GetID(PROCESS, Pid) then
GameGestartet := true
else
GameGestartet := false;
end;
end;
procedure TForm1.WMHotKey(var Msg: TWMHotkey);
{*
Hier wird geprüft, ob das Spiel bereits läuft.
Wenn ja, dann werden die Hotkeys ausgewertet und je nachdem,
welche Tastenkombination betätigt wurde, der entsprechende
Bereich ausgeführt. Dieser enthält entweder den Originalcode
oder aber den Sprung zur Codecave.
*}
begin
if GameGestartet then
case Msg.IdHotKey of
ID:
begin
ChangeGoldHack();
end;
ID+1:
begin
ChangeEnergieHack();
end;
// Abhängig von der ID wird entschieden, was getan werden soll.
end;
inherited;
end;
end.
[/code]
Es gibt 10 verschiedene Typen von Personen, die, die ich mag und die, die ich nicht verstehen kann...