mirror of
https://github.com/cheat-engine/cheat-engine
synced 2026-08-15 02:26:08 -04:00
2018 lines
65 KiB
ObjectPascal
2018 lines
65 KiB
ObjectPascal
unit MemoryTrainerUnit;
|
|
|
|
interface
|
|
|
|
|
|
uses
|
|
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
|
|
StdCtrls, ExtCtrls,settingsunit,tlhelp32,shellapi,math,extratrainercomponents,
|
|
userdefinedformunit, newkernelhandler, symbolhandler, cefuncproc,
|
|
autoassembler,hotkeyhandler, jpeg;
|
|
|
|
|
|
|
|
type TBytes= array of integer;
|
|
|
|
type TcodeEntry = record
|
|
address: dword;
|
|
modulename: string;
|
|
moduleoffset: dword;
|
|
originalopcode: array of byte;
|
|
end;
|
|
|
|
type TCEPointer=record
|
|
Address: Dword; //only used when last pointer in list
|
|
interpretableaddress: string;
|
|
offset: integer;
|
|
end;
|
|
|
|
type TAddressEntry = record
|
|
address: dword;
|
|
interpretableaddress: string;
|
|
ispointer: boolean;
|
|
pointers: array of TCEPointer;
|
|
bit: byte;
|
|
memtyp: integer;
|
|
frozen: boolean;
|
|
frozendirection: byte;
|
|
setvalue: boolean;
|
|
userinput: boolean;
|
|
value: string;
|
|
|
|
valuei: int64;
|
|
valuef: double;
|
|
valuea: array of byte;
|
|
valuelength: integer;
|
|
|
|
autoassemblescript: string;
|
|
allocs: TCEAllocArray;
|
|
end;
|
|
|
|
type Ttrainerdata = record
|
|
description: string;
|
|
hotkeytext: string;
|
|
hotkey: TKeyCombo;
|
|
active: boolean;
|
|
codeentrys: array of TCodeEntry;
|
|
addressentrys: array of TAddressEntry;
|
|
end;
|
|
|
|
|
|
type
|
|
TfrmMemoryTrainer = class(TForm)
|
|
Panel2: TPanel;
|
|
Button1: TButton;
|
|
ScrollBox1: TScrollBox;
|
|
Label1: TLabel;
|
|
Label2: TLabel;
|
|
Panel1: TPanel;
|
|
Image1: TImage;
|
|
btnLaunch: TButton;
|
|
Timer1: TTimer;
|
|
OpenDialog1: TOpenDialog;
|
|
Freezer: TTimer;
|
|
Button2: TButton;
|
|
Button3: TButton;
|
|
Timer2: TTimer;
|
|
Timer3: TTimer;
|
|
procedure FormClose(Sender: TObject; var Action: TCloseAction);
|
|
procedure FormCreate(Sender: TObject);
|
|
procedure Timer1Timer(Sender: TObject);
|
|
procedure btnLaunchClick(Sender: TObject);
|
|
procedure FreezerTimer(Sender: TObject);
|
|
procedure Button1Click(Sender: TObject);
|
|
procedure Button2Click(Sender: TObject);
|
|
procedure Button3Click(Sender: TObject);
|
|
procedure Timer2Timer(Sender: TObject);
|
|
procedure Timer3Timer(Sender: TObject);
|
|
procedure CheatClick(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
|
private
|
|
{ Private declarations }
|
|
|
|
reinitializedesired: boolean;
|
|
|
|
filecount: integer;
|
|
|
|
procedure redefinecodeentries;
|
|
procedure reinterpretaddresses;
|
|
|
|
procedure hotkeyhandler(var Message: TWMHotKey); message WM_HOTKEY2;
|
|
procedure checkforprocess;
|
|
procedure executecheat(sender: tobject);
|
|
public
|
|
{ Public declarations }
|
|
filename,process: string;
|
|
autolaunch:boolean;
|
|
|
|
aboutboxtext: string;
|
|
viewdefault: boolean;
|
|
trainerdata: array of TTrainerdata;
|
|
clist: tcheatlist;
|
|
end;
|
|
|
|
|
|
|
|
type TSetColorThread = class(TThread)
|
|
private
|
|
recordnr: integer;
|
|
procedure setcolor;
|
|
public
|
|
|
|
Constructor MyCreate(recnr: integer);
|
|
procedure Execute; override;
|
|
end;
|
|
|
|
|
|
|
|
var
|
|
frmMemoryTrainer: TfrmMemoryTrainer;
|
|
|
|
implementation
|
|
|
|
{$R *.DFM}
|
|
|
|
function StrToFloat(const S: string): Extended;
|
|
begin
|
|
//gets rid of international confusion
|
|
|
|
DecimalSeparator:='.';
|
|
try
|
|
result:=sysutils.StrToFloat(s);
|
|
except
|
|
DecimalSeparator:=',';
|
|
result:=sysutils.StrToFloat(s);
|
|
end;
|
|
end;
|
|
|
|
function ReadProcessMemory(hProcess: THandle; const lpBaseAddress: Pointer; lpBuffer: Pointer; nSize: DWORD; var lpNumberOfBytesRead: DWORD): BOOL; stdcall;
|
|
var c: _context;
|
|
y: ^byte;
|
|
begin
|
|
if protect then
|
|
begin
|
|
c.ContextFlags:=CONTEXT_FULL or CONTEXT_FLOATING_POINT or CONTEXT_DEBUG_REGISTERS;
|
|
getthreadcontext(getcurrentthread,c);
|
|
if (c.dr6<>0) or (c.dr7<>0) then exit;
|
|
|
|
y:=@newkernelhandler.readprocessMemory;
|
|
if y^=$cc then exit;
|
|
|
|
if dword(@newkernelhandler.ReadProcessMemory)>dword(WindowsKernel) then
|
|
newkernelhandler.ReadProcessMemory(hProcess,lpBaseAddress,lpBuffer,nSize, lpNumberOfBytesRead);
|
|
end
|
|
else
|
|
newkernelhandler.ReadProcessMemory(hProcess,lpBaseAddress,lpBuffer,nSize, lpNumberOfBytesRead);
|
|
end;
|
|
|
|
function WriteProcessMemory(hProcess: THandle; const lpBaseAddress: Pointer; lpBuffer: Pointer; nSize: DWORD; var lpNumberOfBytesWritten: DWORD): BOOL; stdcall;
|
|
var c: _context;
|
|
y: ^byte;
|
|
begin
|
|
if protect then
|
|
begin
|
|
c.ContextFlags:=CONTEXT_FULL or CONTEXT_FLOATING_POINT or CONTEXT_DEBUG_REGISTERS;
|
|
getthreadcontext(getcurrentthread,c);
|
|
if (c.dr6<>0) or (c.dr7<>0) then exit;
|
|
|
|
y:=@newkernelhandler.writeprocessMemory;
|
|
if y^=$cc then exit;
|
|
|
|
|
|
if dword(@newkernelhandler.writeprocessMemory)>dword(WindowsKernel) then
|
|
newkernelhandler.writeprocessMemory(hProcess,lpBaseAddress,lpBuffer,nSize, lpNumberOfBytesWritten);
|
|
end
|
|
else
|
|
newkernelhandler.writeprocessMemory(hProcess,lpBaseAddress,lpBuffer,nSize, lpNumberOfBytesWritten);
|
|
end;
|
|
|
|
procedure setbit(bitnr: integer; var bt: Byte;state:integer);
|
|
{
|
|
pre: bitnr=bit between 0 and 7
|
|
bt=pointer to the byte
|
|
post: bt has the bit set specified in state
|
|
result: bt has a bit set or unset
|
|
}
|
|
begin
|
|
if state=1 then
|
|
bt:=bt or trunc(power(2,bitnr)) //set that bit to 1
|
|
else
|
|
bt:=bt and ($ff xor trunc(power(2,bitnr))); //set the bit to 0
|
|
end;
|
|
|
|
function getbit(bitnr: integer; bt: Byte):integer;
|
|
begin
|
|
if (trunc(power(2,bitnr)) and bt)>0 then result:=1 else result:=0;
|
|
end;
|
|
|
|
|
|
|
|
constructor TSetColorThread.MyCreate(recnr: integer);
|
|
begin
|
|
recordnr:=recnr;
|
|
inherited create(false);
|
|
end;
|
|
|
|
procedure TSetColorThread.setcolor;
|
|
var i: integer;
|
|
begin
|
|
if userdefinedform<>nil then
|
|
begin
|
|
for i:=0 to length(userdefinedform.cheat)-1 do
|
|
if userdefinedform.cheat[i].cheatnr=recordnr then
|
|
userdefinedform.cheat[i].activated:=frmMemoryTrainer.trainerdata[recordnr].active;
|
|
|
|
for i:=0 to length(userdefinedform.cheatlist)-1 do
|
|
userdefinedform.cheatlist[i].Items[recordnr].activated:=frmMemoryTrainer.trainerdata[recordnr].active;
|
|
|
|
end;
|
|
frmMemoryTrainer.clist.Items[recordnr].activated:=frmMemoryTrainer.trainerdata[recordnr].active;
|
|
end;
|
|
|
|
procedure TSetColorThread.Execute;
|
|
begin
|
|
FreeOnTerminate:=true;
|
|
sleep(500);
|
|
synchronize(setcolor);
|
|
end;
|
|
|
|
//copy/paste from the ce source
|
|
procedure ConvertStringToBytes(scanvalue:string; hex:boolean;var bytes: TBytes);
|
|
var i,j,k: integer;
|
|
helpstr:string;
|
|
begin
|
|
while scanvalue[length(scanvalue)]=' ' do
|
|
scanvalue:=copy(scanvalue,1,length(scanvalue)-1);
|
|
|
|
if (pos('-',scanvalue)>0) or (pos(' ',scanvalue)>0) then
|
|
begin
|
|
//syntax is xx-xx-xx or xx xx xx
|
|
j:=1;
|
|
k:=0;
|
|
scanvalue:=scanvalue+' ';
|
|
|
|
for i:=1 to length(scanvalue) do
|
|
begin
|
|
if (scanvalue[i]=' ') or (scanvalue[i]='-') then
|
|
begin
|
|
helpstr:=copy(scanvalue,j,i-j);
|
|
j:=i+1;
|
|
setlength(bytes,k+1);
|
|
try
|
|
if hex then bytes[k]:=strtoint64('$'+helpstr)
|
|
else bytes[k]:=strtoint64(helpstr);
|
|
except
|
|
bytes[k]:=-1;
|
|
//if it is not a '-' or ' ' or a valid value then I assume it is a wildcard.(
|
|
end;
|
|
inc(k);
|
|
end;
|
|
end;
|
|
end else
|
|
begin
|
|
//syntax is xxxxxx
|
|
k:=0;
|
|
j:=1;
|
|
for i:=1 to length(scanvalue) do
|
|
begin
|
|
if (i mod 2)=0 then
|
|
begin
|
|
helpstr:=copy(scanvalue,j,i-j+1);
|
|
j:=i+1;
|
|
setlength(bytes,k+1);
|
|
try
|
|
bytes[k]:=strtoint64('$'+helpstr);
|
|
except
|
|
bytes[k]:=-1;
|
|
end;
|
|
inc(k);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TFrmMemoryTrainer.reinterpretaddresses;
|
|
var i,j: integer;
|
|
begin
|
|
reinitializedesired:=false;
|
|
for i:=0 to length(trainerdata)-1 do
|
|
begin
|
|
for j:=0 to length(trainerdata[i].addressentrys)-1 do
|
|
begin
|
|
if trainerdata[i].addressentrys[j].interpretableaddress<>'' then
|
|
begin
|
|
try
|
|
trainerdata[i].addressentrys[j].address:=symhandler.getAddressFromName(trainerdata[i].addressentrys[j].interpretableaddress);
|
|
except
|
|
reinitializedesired:=true;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
{
|
|
|
|
//update reinterpetable addresses
|
|
for i:=0 to numberofrecords-1 do
|
|
begin
|
|
if memrec[i].interpretableaddress<>'' then
|
|
begin
|
|
try
|
|
memrec[i].address:=symhandler.getAddressFromName(memrec[i].interpretableaddress,false); //don't wait for symbols here
|
|
except
|
|
|
|
end;
|
|
end;
|
|
|
|
if memrec[i].IsPointer and (memrec[i].pointers[length(memrec[i].pointers)-1].interpretableaddress<>'') then
|
|
memrec[i].pointers[length(memrec[i].pointers)-1].Address:=symhandler.getAddressFromName(memrec[i].pointers[length(memrec[i].pointers)-1].interpretableaddress,false);
|
|
end; }
|
|
end;
|
|
|
|
procedure TFrmMemoryTrainer.redefinecodeentries;
|
|
var i,j: integer;
|
|
begin
|
|
symhandler.loadmodulelist;
|
|
|
|
for i:=0 to length(trainerdata)-1 do
|
|
begin
|
|
for j:=0 to length(trainerdata[i].codeentrys)-1 do
|
|
begin
|
|
if trainerdata[i].codeentrys[j].modulename<>'' then //make sure a modulename was filled in otherwise keep the old address
|
|
trainerdata[i].codeentrys[j].address:=symhandler.getaddressfromname(trainerdata[i].codeentrys[j].modulename)+trainerdata[i].codeentrys[j].moduleoffset
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TFrmMemoryTrainer.checkforprocess;
|
|
Var SNAPHandle: THandle;
|
|
ProcessEntry: ProcessEntry32;
|
|
Check: Boolean;
|
|
FullProcessName,ProcessName: String;
|
|
I: Integer;
|
|
begin
|
|
SNAPHandle:=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
|
|
If SnapHandle>0 then
|
|
begin
|
|
ProcessEntry.dwSize:=SizeOf(ProcessEntry);
|
|
Check:=Process32First(SnapHandle,ProcessEntry);
|
|
while check=true do
|
|
begin
|
|
ProcessName:='';
|
|
FullProcessName:='';
|
|
FullProcessName:=processentry.szExeFile;
|
|
i:=Length(FullProcessName);
|
|
while (i>0) and (FullProcessname[i-1]<>'\') do dec(i);
|
|
processname:=copy(FullProcessName,i,length(FullProcessname)-i+1);
|
|
|
|
if uppercase(processname)=uppercase(process) then
|
|
begin
|
|
processhandler.ProcessID:=ProcessEntry.th32ProcessID;
|
|
btnLaunch.Enabled:=false;
|
|
|
|
if processhandle=0 then
|
|
processhandler.processhandle:=openprocess(process_all_access,false,processid);
|
|
|
|
symhandler.showmodules:=true;
|
|
symhandler.showsymbols:=true;
|
|
symhandler.reinitialize;
|
|
|
|
reinterpretaddresses;
|
|
exit;
|
|
end;
|
|
|
|
check:=Process32Next(SnapHandle,ProcessEntry);
|
|
end;
|
|
end;
|
|
|
|
if processhandle<>0 then closehandle(processhandle);
|
|
processhandler.processhandle:=0;
|
|
btnLaunch.Enabled:=true;
|
|
end;
|
|
|
|
procedure TFrmMemoryTrainer.hotkeyhandler(var Message: TWMHotKey);
|
|
var i,j,k,l,m,err: integer;
|
|
v: int64;
|
|
v2: double;
|
|
bytes: dword;
|
|
nops: array of byte;
|
|
original: dword;
|
|
|
|
newvalue1: byte;
|
|
newvalue2: word;
|
|
newvalue3: dword;
|
|
newvalue4: single;
|
|
newvalue5: double;
|
|
newvalue6: int64;
|
|
|
|
dontputback: boolean;
|
|
|
|
bl: integer;
|
|
newbytes: array of byte;
|
|
newinput: string;
|
|
realaddress,realaddress2,count:dword;
|
|
|
|
sl: tstringlist;
|
|
|
|
aa: tCEAllocArray;
|
|
dobeep: boolean;
|
|
begin
|
|
dobeep:=false;
|
|
checkforprocess;
|
|
//handle the hotkeys
|
|
i:=message.HotKey;
|
|
|
|
if i=$bfff then //pop-up
|
|
begin
|
|
application.Restore;
|
|
if userdefinedform<>nil then
|
|
begin
|
|
//show userdefined window
|
|
userdefinedform.Show;
|
|
userdefinedform.Position:=poScreenCenter;
|
|
end
|
|
else
|
|
begin
|
|
//show default window
|
|
frmmemorytrainer.Show;
|
|
frmmemorytrainer.Position:=poScreenCenter;
|
|
end;
|
|
application.BringToFront;
|
|
|
|
end;
|
|
|
|
|
|
if (i>=0) and (i<length(trainerdata)) then
|
|
begin
|
|
if processhandle=0 then exit;
|
|
|
|
if trainerdata[i].active then //is currenly active
|
|
begin
|
|
//deactivate (if needed)
|
|
for j:=0 to length(trainerdata[i].codeentrys)-1 do
|
|
begin
|
|
//find this codeentry in other trainerdatas
|
|
dontputback:=false;
|
|
|
|
for k:=0 to length(trainerdata)-1 do
|
|
begin
|
|
if (k<>i) and (trainerdata[k].active) then
|
|
begin
|
|
for l:=0 to length(trainerdata[k].codeentrys)-1 do
|
|
begin
|
|
//it has also code entrys
|
|
//check if it has a code entry that matches mine
|
|
if trainerdata[i].codeentrys[j].address=trainerdata[k].codeentrys[l].address then
|
|
begin
|
|
//CRAAAAAAAAAAAAAAAP! Cant people just use their brains ?
|
|
dontputback:=true;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
if not dontputback then
|
|
begin
|
|
original:=0;
|
|
VirtualProtectEx(processhandle, pointer(trainerdata[i].codeentrys[j].address),length(nops),PAGE_EXECUTE_READWRITE,original);
|
|
writeprocessmemory(processhandle,pointer(trainerdata[i].codeentrys[j].address),@trainerdata[i].codeentrys[j].originalopcode[0],length(trainerdata[i].codeentrys[j].originalopcode),bytes);
|
|
|
|
//set old security back
|
|
VirtualProtectEx(processhandle,pointer(trainerdata[i].codeentrys[j].address),length(nops),original,original);
|
|
end;
|
|
end;
|
|
|
|
|
|
{$ifdef standalonetrainerwithassembler}
|
|
//see if it contains a auto assemble entry
|
|
for j:=0 to length(trainerdata[i].addressentrys)-1 do
|
|
begin
|
|
if trainerdata[i].addressentrys[j].memtyp=255 then
|
|
begin
|
|
//auto assemble script
|
|
//dissable it
|
|
sl:=tstringlist.Create;
|
|
sl.Text:=trainerdata[i].addressentrys[j].autoassemblescript;
|
|
|
|
try
|
|
try
|
|
if autoassemble(sl,false,false,false,false,trainerdata[i].addressentrys[j].allocs)=false then
|
|
begin
|
|
symhandler.reinitialize; //second chance, else death sentence
|
|
autoassemble(sl,false,false,false,false,trainerdata[i].addressentrys[j].allocs);
|
|
end;
|
|
|
|
reinterpretaddresses;
|
|
finally
|
|
sl.free;
|
|
end;
|
|
except
|
|
on e: exception do
|
|
raise exception.create(e.Message);
|
|
end;
|
|
|
|
end;
|
|
end;
|
|
{$endif}
|
|
|
|
trainerdata[i].active:=false; //also disables the freezer
|
|
end
|
|
else //not currently active
|
|
begin
|
|
//activate (if needed)
|
|
redefinecodeentries;
|
|
|
|
for j:=0 to length(trainerdata[i].codeentrys)-1 do
|
|
begin
|
|
setlength(nops,length(trainerdata[i].codeentrys[j].originalopcode));
|
|
readprocessmemory(processhandle,pointer(trainerdata[i].codeentrys[j].address),@nops[0],length(trainerdata[i].codeentrys[j].originalopcode),bytes);
|
|
{ if not comparemem(@trainerdata[i].codeentrys[j].originalopcode[0],@nops[0],length(trainerdata[i].codeentrys[j].originalopcode)) then
|
|
begin
|
|
//it not as expected
|
|
//check if it got nopped
|
|
for k:=0 to length(nops)-1 do
|
|
begin
|
|
if nops[k]<>$90 then
|
|
begin
|
|
messagedlg('Incorrect version, or the process got messed up!',mterror,[mbok],0);
|
|
application.Terminate;
|
|
exit;
|
|
end;
|
|
end;
|
|
end; }
|
|
|
|
for k:=0 to length(nops)-1 do
|
|
nops[k]:=$90;
|
|
|
|
original:=0;
|
|
VirtualProtectEx(processhandle, pointer(trainerdata[i].codeentrys[j].address),length(nops),PAGE_EXECUTE_READWRITE,original);
|
|
writeprocessmemory(processhandle,pointer(trainerdata[i].codeentrys[j].address),@nops[0],length(nops),bytes);
|
|
|
|
//set old security back
|
|
VirtualProtectEx(processhandle,pointer(trainerdata[i].codeentrys[j].address),length(nops),original,original);
|
|
trainerdata[i].active:=true;
|
|
end;
|
|
|
|
|
|
//enable auto assemble scripts
|
|
for j:=0 to length(trainerdata[i].addressentrys)-1 do
|
|
begin
|
|
if trainerdata[i].addressentrys[j].memtyp=255 then
|
|
begin
|
|
//auto assemble script
|
|
//enable it
|
|
sl:=tstringlist.Create;
|
|
sl.Text:=trainerdata[i].addressentrys[j].autoassemblescript;
|
|
|
|
try
|
|
try
|
|
setlength(trainerdata[i].addressentrys[j].allocs,1);
|
|
if autoassemble(sl,false,true,false,false,trainerdata[i].addressentrys[j].allocs) = false then
|
|
begin
|
|
//failure to inject script, try again but not reload the symbols
|
|
symhandler.reinitialize;
|
|
autoassemble(sl,false,true,false,false,trainerdata[i].addressentrys[j].allocs);
|
|
end;
|
|
|
|
reinterpretaddresses;
|
|
finally
|
|
sl.free;
|
|
end;
|
|
except
|
|
//failed
|
|
on e: exception do
|
|
raise exception.create(e.Message);
|
|
end;
|
|
|
|
end;
|
|
end;
|
|
|
|
|
|
for j:=0 to length(trainerdata[i].addressentrys)-1 do
|
|
begin
|
|
//set value
|
|
if trainerdata[i].addressentrys[j].ispointer then
|
|
begin
|
|
realaddress2:=trainerdata[i].addressentrys[j].pointers[length(trainerdata[i].addressentrys[j].pointers)-1].Address;
|
|
for k:=length(trainerdata[i].addressentrys[j].pointers)-1 downto 0 do
|
|
begin
|
|
readprocessmemory(processhandle,pointer(realaddress2),@realaddress,4,count);
|
|
if count=4 then
|
|
realaddress2:=realaddress+trainerdata[i].addressentrys[j].pointers[k].offset
|
|
else
|
|
begin
|
|
realaddress2:=0;
|
|
break;
|
|
end;
|
|
end;
|
|
if realaddress2=0 then
|
|
begin
|
|
reinitializedesired:=true;
|
|
continue;
|
|
end;
|
|
realaddress:=realaddress2;
|
|
end else realaddress:=trainerdata[i].addressentrys[j].address;
|
|
|
|
if trainerdata[i].addressentrys[j].setvalue then
|
|
begin
|
|
if trainerdata[i].addressentrys[j].userinput then
|
|
begin
|
|
//find a new value
|
|
|
|
newinput:=clist.Items[i].Editvalue; //default
|
|
if userdefinedform<>nil then
|
|
if length(userdefinedform.cheatlist)>0 then
|
|
newinput:=userdefinedform.cheatlist[0].Items[i].Editvalue
|
|
else
|
|
begin
|
|
//no cheatlist!!!!
|
|
//try to find a tcheatlist
|
|
for k:=0 to length(userdefinedform.cheat)-1 do
|
|
if userdefinedform.cheat[k].cheatnr=i then
|
|
begin
|
|
newinput:=userdefinedform.cheat[k].Editvalue;
|
|
break;
|
|
end;
|
|
end;
|
|
|
|
val(newinput,v,err);
|
|
if err=0 then trainerdata[i].addressentrys[j].valuei:=v;
|
|
|
|
val(newinput,v2,err);
|
|
if err=0 then trainerdata[i].addressentrys[j].valuef:=v2;
|
|
|
|
if trainerdata[i].addressentrys[j].memtyp=7 then //string
|
|
begin
|
|
setlength(trainerdata[i].addressentrys[j].valuea, length(newinput)+1); //newinput+1 so the 0-terminator is copied
|
|
copymemory(@trainerdata[i].addressentrys[j].valuea[0], @newinput[1], length(newinput)+1);
|
|
end;
|
|
end;
|
|
|
|
VirtualProtectEx(processhandle, pointer(realaddress),1,PAGE_EXECUTE_READWRITE,original);
|
|
|
|
case trainerdata[i].addressentrys[j].memtyp of
|
|
0 : begin //byte
|
|
newvalue1:=byte(trainerdata[i].addressentrys[j].valuei);
|
|
WriteProcessMemory(processhandle,pointer(realaddress),@newvalue1,1,bytes);
|
|
end;
|
|
|
|
1 : begin //word
|
|
newvalue2:=word(trainerdata[i].addressentrys[j].valuei);
|
|
WriteProcessMemory(processhandle,pointer(realaddress),@newvalue2,2,bytes);
|
|
end;
|
|
|
|
2 : begin //dword
|
|
newvalue3:=dword(trainerdata[i].addressentrys[j].valuei);
|
|
WriteProcessMemory(processhandle,pointer(realaddress),@newvalue3,4,bytes);
|
|
end;
|
|
|
|
3 : begin //single
|
|
newvalue4:=trainerdata[i].addressentrys[j].valuef;
|
|
WriteProcessMemory(processhandle,pointer(realaddress),@newvalue4,4,bytes);
|
|
end;
|
|
|
|
4 : begin //single
|
|
newvalue5:=trainerdata[i].addressentrys[j].valuef;
|
|
WriteProcessMemory(processhandle,pointer(realaddress),@newvalue5,8,bytes);
|
|
end;
|
|
|
|
5 : begin //binary
|
|
bl:=1+((length(trainerdata[i].addressentrys[j].value)-1) div 8);
|
|
setlength(newbytes,bl);
|
|
ReadProcessMemory(processhandle,pointer(realaddress),@newbytes[0],bl,bytes);
|
|
|
|
l:=trainerdata[i].addressentrys[j].bit;
|
|
k:=0;
|
|
for m:=length(trainerdata[i].addressentrys[j].value) downto 1 do
|
|
begin
|
|
case trainerdata[i].addressentrys[j].value[i] of
|
|
'0' : setbit(l,newbytes[k],0);
|
|
'1' : setbit(l,newbytes[k],1);
|
|
'*','?','x': ;
|
|
end;
|
|
|
|
inc(l);
|
|
if l>=8 then
|
|
begin
|
|
inc(k);
|
|
l:=0;
|
|
end;
|
|
end;
|
|
|
|
writeprocessmemory(processhandle,pointer(realaddress),@newbytes[0],bl,bytes);
|
|
setlength(newbytes,0);
|
|
end;
|
|
|
|
6 : begin //int64
|
|
newvalue6:=dword(trainerdata[i].addressentrys[j].valuei);
|
|
WriteProcessMemory(processhandle,pointer(realaddress),@newvalue6,8,bytes);
|
|
end;
|
|
|
|
7 : begin //string
|
|
|
|
|
|
writeprocessmemory(processhandle,pointer(realaddress),@trainerdata[i].addressentrys[j].valuea[0],min(length(trainerdata[i].addressentrys[j].valuea),trainerdata[i].addressentrys[j].valuelength),bytes);
|
|
end;
|
|
|
|
8 : begin //array of bytes
|
|
writeprocessmemory(processhandle,pointer(realaddress),@trainerdata[i].addressentrys[j].valuea[0],trainerdata[i].addressentrys[j].valuelength,bytes);
|
|
end;
|
|
end;
|
|
|
|
VirtualProtectEx(processhandle, pointer(realaddress),1,original,original);
|
|
|
|
end;
|
|
|
|
//freeze
|
|
if trainerdata[i].addressentrys[j].frozen then
|
|
begin
|
|
//get the current value of the address and set that as the freeze address
|
|
if not trainerdata[i].addressentrys[j].setvalue then
|
|
case trainerdata[i].addressentrys[j].memtyp of
|
|
0 : begin //byte
|
|
readprocessmemory(processhandle,pointer(realaddress),@newvalue1,1,bytes);
|
|
trainerdata[i].addressentrys[j].valuei:=newvalue1;
|
|
end;
|
|
|
|
1 : begin //word
|
|
readprocessmemory(processhandle,pointer(realaddress),@newvalue2,2,bytes);
|
|
trainerdata[i].addressentrys[j].valuei:=newvalue2;
|
|
end;
|
|
|
|
2 : begin //dword
|
|
readprocessmemory(processhandle,pointer(realaddress),@newvalue3,4,bytes);
|
|
trainerdata[i].addressentrys[j].valuei:=newvalue3;
|
|
end;
|
|
|
|
3 : begin //single
|
|
ReadProcessMemory(processhandle,pointer(realaddress),@newvalue4,4,bytes);
|
|
trainerdata[i].addressentrys[j].valuef:=newvalue4;
|
|
end;
|
|
|
|
4 : begin //single
|
|
ReadProcessMemory(processhandle,pointer(realaddress),@newvalue5,8,bytes);
|
|
trainerdata[i].addressentrys[j].valuef:=newvalue5;
|
|
end;
|
|
|
|
5 : begin //binary
|
|
bl:=1+((length(trainerdata[i].addressentrys[j].value)-1) div 8);
|
|
setlength(newbytes,bl);
|
|
ReadProcessMemory(processhandle,pointer(realaddress),@newbytes[0],bl,bytes);
|
|
|
|
l:=trainerdata[i].addressentrys[j].bit;
|
|
k:=0;
|
|
for m:=length(trainerdata[i].addressentrys[j].value) downto 1 do
|
|
begin
|
|
trainerdata[i].addressentrys[j].value[m]:=IntToStr(getbit(l,newbytes[k]))[1];
|
|
inc(l);
|
|
if l>=8 then
|
|
begin
|
|
inc(k);
|
|
l:=0;
|
|
end;
|
|
end;
|
|
setlength(newbytes,0);
|
|
end;
|
|
|
|
6 : begin //int64
|
|
ReadProcessMemory(processhandle,pointer(realaddress),@newvalue6,8,bytes);
|
|
newvalue6:=dword(trainerdata[i].addressentrys[j].valuei);
|
|
end;
|
|
|
|
7,8: begin //array of bytes , or array of char
|
|
readprocessmemory(processhandle,pointer(realaddress),@trainerdata[i].addressentrys[j].valuea[0],trainerdata[i].addressentrys[j].valuelength,bytes);
|
|
end;
|
|
end;
|
|
|
|
|
|
trainerdata[i].active:=true;
|
|
end;
|
|
|
|
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
//indicate that this hotkey got pressed
|
|
|
|
if userdefinedform<>nil then
|
|
begin
|
|
for j:=0 to length(userdefinedform.cheat)-1 do
|
|
if userdefinedform.cheat[j].cheatnr=i then
|
|
begin
|
|
userdefinedform.cheat[j].activated:=true;
|
|
if userdefinedform.cheat[j].beeponactivate then
|
|
dobeep:=true;
|
|
end;
|
|
|
|
for j:=0 to length(userdefinedform.cheatlist)-1 do
|
|
userdefinedform.cheatlist[j].Items[i].activated:=true;
|
|
end else dobeep:=true; //always beep
|
|
|
|
if dobeep then beep;
|
|
|
|
frmMemoryTrainer.clist.Items[i].activated:=true;
|
|
//and activate the thread that sleeps 500 ms and keeps the collor to activated when active , and black when not
|
|
|
|
TSetColorThread.mycreate(i);
|
|
end;
|
|
|
|
end;
|
|
|
|
procedure TfrmMemoryTrainer.FormClose(Sender: TObject;
|
|
var Action: TCloseAction);
|
|
var i: integer;
|
|
begin
|
|
try
|
|
{
|
|
for i:=0 to length(trainerdata)-1 do
|
|
unregisterhotkey(self.Handle,i);
|
|
|
|
unregisterhotkey(self.Handle,$bfff);}
|
|
finally
|
|
application.Terminate;
|
|
end;
|
|
end;
|
|
|
|
procedure TfrmMemoryTrainer.FormCreate(Sender: TObject);
|
|
var temp: dword;
|
|
x: pchar;
|
|
i,j,k,l,err: integer;
|
|
|
|
bp1,bp2: ^byte;
|
|
imagestream: Tmemorystream;
|
|
buf: pchar;
|
|
|
|
temp2: integer;
|
|
|
|
temptb: TBytes;
|
|
|
|
tempab: array of byte;
|
|
tempb: boolean;
|
|
tempc: tcolor;
|
|
tempi: integer;
|
|
tempbc: tbevelcut;
|
|
tempbk: tbevelkind;
|
|
tempcursor: tcursor;
|
|
temps: string;
|
|
|
|
popup: boolean;
|
|
|
|
keymod:word;
|
|
|
|
pid: dword;
|
|
ownprocesshandle: THandle;
|
|
tokenhandle: thandle;
|
|
tp:TTokenPrivileges;
|
|
prev: TTokenPrivileges;
|
|
|
|
hotkey: TKeyCombo;
|
|
|
|
ReturnLength: Dword;
|
|
|
|
f: tfilestream;
|
|
begin
|
|
f:=nil;
|
|
pid:=GetCurrentProcessID;
|
|
|
|
ownprocesshandle:=OpenProcess(PROCESS_ALL_ACCESS,true,pid);
|
|
tokenhandle:=0;
|
|
|
|
if ownprocesshandle<>0 then
|
|
begin
|
|
if OpenProcessToken(ownprocesshandle,TOKEN_QUERY or TOKEN_ADJUST_PRIVILEGES ,tokenhandle) then
|
|
begin
|
|
if lookupPrivilegeValue(nil, 'SeDebugPrivilege' ,tp.Privileges[0].Luid) then
|
|
begin
|
|
tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
|
|
tp.PrivilegeCount := 1; // One privilege to set
|
|
AdjustTokenPrivileges(tokenhandle,false,tp,sizeof(tp),@prev,returnlength);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
viewdefault:=true;
|
|
|
|
clist:=tcheatlist.create(nil);
|
|
with clist do
|
|
begin
|
|
Left:=0;
|
|
Top:=15;
|
|
Width:=scrollbox1.Width-3;
|
|
Height:=50;
|
|
AutoSize:=true;
|
|
Anchors:=[akleft,aktop,akright];
|
|
parent:=scrollbox1;
|
|
end;
|
|
|
|
trainerfile.ReadBuffer(temp,4); //version (can be discarded)
|
|
|
|
//trainerdatasize
|
|
trainerfile.ReadBuffer(temp,4);
|
|
setlength(trainerdata,temp);
|
|
|
|
for i:=0 to length(trainerdata)-1 do
|
|
begin
|
|
trainerdata[i].active:=false;
|
|
|
|
//description
|
|
trainerfile.ReadBuffer(temp,4);
|
|
getmem(x,temp+1);
|
|
trainerfile.ReadBuffer(pointer(x)^,temp);
|
|
x[temp]:=#0;
|
|
trainerdata[i].description:=x;
|
|
freemem(x);
|
|
|
|
//hotkeytext
|
|
trainerfile.ReadBuffer(temp,4);
|
|
getmem(x,temp+1);
|
|
trainerfile.ReadBuffer(pointer(x)^,temp);
|
|
x[temp]:=#0;
|
|
trainerdata[i].hotkeytext:=x;
|
|
freemem(x);
|
|
|
|
trainerfile.ReadBuffer(trainerdata[i].hotkey,sizeof(trainerdata[i].hotkey));
|
|
|
|
//nr of code entries
|
|
trainerfile.ReadBuffer(temp,4);
|
|
setlength(trainerdata[i].codeentrys,temp);
|
|
|
|
for j:=0 to length(trainerdata[i].codeentrys)-1 do
|
|
begin
|
|
trainerfile.ReadBuffer(temp,4);
|
|
|
|
if protect then temp:=temp xor $11221122;
|
|
trainerdata[i].codeentrys[j].address:=temp;
|
|
|
|
|
|
//modulename
|
|
trainerfile.ReadBuffer(temp,4);
|
|
getmem(x,temp+1);
|
|
trainerfile.ReadBuffer(pointer(x)^,temp);
|
|
x[temp]:=#0;
|
|
trainerdata[i].codeentrys[j].modulename:=x;
|
|
freemem(x);
|
|
|
|
//moduleoffset
|
|
trainerfile.ReadBuffer(temp,4);
|
|
if protect then temp:=temp xor $22112211;
|
|
|
|
trainerdata[i].codeentrys[j].moduleoffset:=temp;
|
|
|
|
|
|
|
|
|
|
|
|
trainerfile.ReadBuffer(temp,4);
|
|
setlength(trainerdata[i].codeentrys[j].originalopcode,temp);
|
|
|
|
trainerfile.ReadBuffer(pointer(trainerdata[i].codeentrys[j].originalopcode)^,temp);
|
|
end;
|
|
|
|
//address entrys
|
|
trainerfile.ReadBuffer(temp,4);
|
|
setlength(trainerdata[i].addressentrys,temp);
|
|
|
|
for j:=0 to length(trainerdata[i].addressentrys)-1 do
|
|
begin
|
|
trainerfile.readBuffer(temp,sizeof(trainerdata[i].addressentrys[j].address));
|
|
if protect then temp:=temp xor $dead1337;
|
|
|
|
trainerdata[i].addressentrys[j].address:=temp;
|
|
|
|
//interpretableaddress
|
|
trainerfile.ReadBuffer(temp,4);
|
|
getmem(x,temp+1);
|
|
trainerfile.ReadBuffer(pointer(x)^,temp);
|
|
x[temp]:=#0;
|
|
|
|
if protect then //decrypt temps
|
|
for k:=0 to temp-1 do
|
|
x[k]:=chr(ord(x[k]) xor (k+2));
|
|
|
|
trainerdata[i].addressentrys[j].interpretableaddress:=x;
|
|
|
|
|
|
trainerfile.readBuffer(trainerdata[i].addressentrys[j].ispointer,sizeof(trainerdata[i].addressentrys[j].ispointer));
|
|
|
|
trainerfile.ReadBuffer(tempi,4);
|
|
setlength(trainerdata[i].addressentrys[j].pointers,tempi);
|
|
for k:=0 to tempi-1 do
|
|
begin
|
|
trainerfile.readBuffer(trainerdata[i].addressentrys[j].pointers[k].address,sizeof(trainerdata[i].addressentrys[j].pointers[k].address));
|
|
|
|
//interpretableaddress for pointer
|
|
trainerfile.ReadBuffer(temp,4);
|
|
getmem(x,temp+1);
|
|
trainerfile.ReadBuffer(pointer(x)^,temp);
|
|
x[temp]:=#0;
|
|
|
|
if protect then //decrypt temps
|
|
for l:=0 to temp-1 do
|
|
x[l]:=chr(ord(x[l]) xor (l+3));
|
|
trainerdata[i].addressentrys[j].pointers[k].interpretableaddress:=x;
|
|
|
|
trainerfile.readBuffer(trainerdata[i].addressentrys[j].pointers[k].offset,sizeof(trainerdata[i].addressentrys[j].pointers[k].offset));
|
|
end;
|
|
|
|
trainerfile.ReadBuffer(trainerdata[i].addressentrys[j].bit,sizeof(trainerdata[i].addressentrys[j].bit));
|
|
trainerfile.readBuffer(trainerdata[i].addressentrys[j].memtyp,sizeof(trainerdata[i].addressentrys[j].memtyp));
|
|
trainerfile.readbuffer(trainerdata[i].addressentrys[j].frozen,sizeof(trainerdata[i].addressentrys[j].frozen));
|
|
trainerfile.readbuffer(trainerdata[i].addressentrys[j].frozendirection,sizeof(trainerdata[i].addressentrys[j].frozendirection));
|
|
trainerfile.readbuffer(trainerdata[i].addressentrys[j].setvalue,sizeof(trainerdata[i].addressentrys[j].setvalue));
|
|
trainerfile.readbuffer(trainerdata[i].addressentrys[j].userinput,sizeof(trainerdata[i].addressentrys[j].userinput));
|
|
|
|
trainerfile.ReadBuffer(temp,4);
|
|
getmem(x,temp+1);
|
|
trainerfile.ReadBuffer(pointer(x)^,temp);
|
|
x[temp]:=#0;
|
|
trainerdata[i].addressentrys[j].value:=x;
|
|
freemem(x);
|
|
|
|
trainerdata[i].addressentrys[j].valuelength:=length(trainerdata[i].addressentrys[j].value);
|
|
|
|
//autoassemblerscript
|
|
trainerfile.ReadBuffer(temp,4);
|
|
getmem(x,temp+1);
|
|
trainerfile.ReadBuffer(pointer(x)^,temp);
|
|
x[temp]:=#0;
|
|
|
|
if protect then //decrypt temps
|
|
for k:=0 to temp-1 do
|
|
x[k]:=chr(ord(x[k]) xor (k+1));
|
|
|
|
trainerdata[i].addressentrys[j].autoassemblescript:=x;
|
|
freemem(x);
|
|
end;
|
|
end;
|
|
|
|
//title
|
|
//trainerfile.ReadBuffer(temp,4);
|
|
|
|
temp:=0;
|
|
trainerfile.ReadBuffer(temp,4);
|
|
getmem(x,temp+1);
|
|
trainerfile.ReadBuffer(pointer(x)^,temp);
|
|
x[temp]:=#0;
|
|
|
|
if protect then
|
|
begin
|
|
for i:=0 to temp-1 do
|
|
x[i]:=chr(ord(x[i]) xor 56);
|
|
end;
|
|
|
|
caption:=x;
|
|
application.Title:=caption;
|
|
freemem(x);
|
|
|
|
//launch filename
|
|
trainerfile.ReadBuffer(temp,4);
|
|
getmem(x,temp+1);
|
|
trainerfile.ReadBuffer(x^,temp);
|
|
x[temp]:=#0;
|
|
filename:=x;
|
|
|
|
//autolaunch
|
|
trainerfile.ReadBuffer(autolaunch,sizeof(autolaunch));
|
|
|
|
//popup on keypress
|
|
trainerfile.ReadBuffer(popup,sizeof(popup));
|
|
|
|
//processname
|
|
trainerfile.ReadBuffer(temp,4);
|
|
getmem(x,temp+1);
|
|
trainerfile.ReadBuffer(x^,temp);
|
|
x[temp]:=#0;
|
|
process:=x;
|
|
freemem(x);
|
|
|
|
//hotkeytext (discarded)
|
|
trainerfile.ReadBuffer(temp,4);
|
|
getmem(x,temp);
|
|
trainerfile.ReadBuffer(x^,temp);
|
|
freemem(x);
|
|
|
|
//hotkey+shiftstate
|
|
trainerfile.ReadBuffer(hotkey,sizeof(hotkey));
|
|
|
|
if popup then //register this hotkey
|
|
begin
|
|
registerhotkey2(self.Handle,$bfff,hotkey)
|
|
end;
|
|
|
|
|
|
//aboutboxtext
|
|
trainerfile.ReadBuffer(temp,4);
|
|
getmem(x,temp+1);
|
|
trainerfile.ReadBuffer(x^,temp);
|
|
x[temp]:=#0;
|
|
|
|
if protect then
|
|
begin
|
|
for i:=0 to temp-1 do
|
|
x[i]:=chr(ord(x[i]) xor 166);
|
|
end;
|
|
|
|
aboutboxtext:=x;
|
|
freemem(x);
|
|
|
|
//freeze timer interval
|
|
trainerfile.ReadBuffer(tempi,sizeof(tempi));
|
|
freezer.Interval:=tempi;
|
|
|
|
trainerfile.ReadBuffer(temp,4);
|
|
if temp=$666 then
|
|
begin
|
|
//default uid
|
|
//image
|
|
trainerfile.ReadBuffer(temp,4); //size of extension
|
|
getmem(x,temp+1);
|
|
trainerfile.ReadBuffer(x^,temp);
|
|
x[temp]:=#0;
|
|
|
|
temps:=tempdir+inttostr(getcurrentprocessid)+'-'+inttostr(filecount)+x;
|
|
freemem(x);
|
|
|
|
f:=tfilestream.Create(temps, fmCreate or fmShareDenyNone);
|
|
|
|
trainerfile.ReadBuffer(temp,4);
|
|
getmem(x,temp);
|
|
trainerfile.ReadBuffer(x^,temp);
|
|
f.WriteBuffer(x^,temp);
|
|
freemem(x);
|
|
f.free;
|
|
|
|
|
|
if temp<>0 then //size=0
|
|
image1.Picture.LoadFromFile(temps);
|
|
|
|
DeleteFile(temps);
|
|
|
|
|
|
trainerfile.ReadBuffer(temp2,sizeof(width));
|
|
width:=temp2;
|
|
|
|
trainerfile.ReadBuffer(temp2,sizeof(height));
|
|
height:=temp2;
|
|
|
|
trainerfile.ReadBuffer(temp2,sizeof(panel1.width));
|
|
panel1.width:=temp2;
|
|
|
|
trainerfile.ReadBuffer(temp2,sizeof(panel1.height));
|
|
panel1.height:=temp2;
|
|
|
|
|
|
end
|
|
else
|
|
begin
|
|
//user defined ui
|
|
viewdefault:=false;
|
|
|
|
|
|
|
|
userdefinedform:=tuserdefinedform.create(self);
|
|
userdefinedform.Caption:=caption;
|
|
|
|
//windowwidth
|
|
trainerfile.readbuffer(temp,4);
|
|
userdefinedform.Width:=temp;
|
|
|
|
//windowheight
|
|
trainerfile.readbuffer(temp,4);
|
|
userdefinedform.height:=temp;
|
|
userdefinedform.Position:=poscreencenter;
|
|
userdefinedform.BorderStyle:=bsSingle;
|
|
|
|
while true do
|
|
begin
|
|
trainerfile.ReadBuffer(temp,4);
|
|
case temp of
|
|
0: with tbutton2.create(nil) do
|
|
begin
|
|
trainerfile.ReadBuffer(temp,sizeof(integer));
|
|
left:=temp;
|
|
trainerfile.ReadBuffer(temp,sizeof(integer));
|
|
top:=temp;
|
|
trainerfile.ReadBuffer(temp,sizeof(integer));
|
|
width:=temp;
|
|
trainerfile.ReadBuffer(temp,sizeof(integer));
|
|
height:=temp;
|
|
|
|
//caption
|
|
trainerfile.ReadBuffer(temp,4);
|
|
getmem(x,temp+1);
|
|
trainerfile.ReadBuffer(x^,temp);
|
|
x[temp]:=#0;
|
|
caption:=x;
|
|
freemem(x);
|
|
|
|
//wordwrap
|
|
trainerfile.ReadBuffer(tempb,sizeof(tempb));
|
|
wordwrap:=tempb;
|
|
|
|
|
|
//onclick
|
|
trainerfile.ReadBuffer(temp,sizeof(tag));
|
|
case temp of
|
|
1: onclick:=button1.OnClick;
|
|
2: onclick:=btnlaunch.onClick;
|
|
3: onclick:=button2.onClick;
|
|
4: onclick:=button3.OnClick;
|
|
else
|
|
begin
|
|
if temp>=5 then //it's an execute cheat
|
|
begin
|
|
tag:=temp-5;
|
|
onclick:=executecheat;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
trainerfile.ReadBuffer(temp,4);
|
|
getmem(x,temp+1);
|
|
trainerfile.ReadBuffer(x^,temp);
|
|
x[temp]:=#0;
|
|
command:=x;
|
|
freemem(x);
|
|
|
|
parent:=userdefinedform;
|
|
end;
|
|
|
|
1: begin //tcheatlist
|
|
setlength(userdefinedform.cheatlist,length(userdefinedform.cheatlist)+1);
|
|
userdefinedform.cheatlist[length(userdefinedform.cheatlist)-1]:=tcheatlist.create(nil);
|
|
|
|
with userdefinedform.cheatlist[length(userdefinedform.cheatlist)-1] do
|
|
begin
|
|
trainerfile.ReadBuffer(temp,sizeof(integer));
|
|
left:=temp;
|
|
trainerfile.ReadBuffer(temp,sizeof(integer));
|
|
top:=temp;
|
|
trainerfile.ReadBuffer(temp,sizeof(integer));
|
|
width:=temp;
|
|
trainerfile.ReadBuffer(temp,sizeof(integer));
|
|
height:=temp;
|
|
|
|
trainerfile.ReadBuffer(tempc,sizeof(tcolor));
|
|
activationcolor:=tempc;
|
|
trainerfile.ReadBuffer(tempc,sizeof(tcolor));
|
|
color:=tempc;
|
|
trainerfile.ReadBuffer(tempc,sizeof(tcolor));
|
|
textcolor:=tempc;
|
|
|
|
trainerfile.ReadBuffer(tempi,sizeof(integer));
|
|
hotkeyleft:=tempi;
|
|
trainerfile.ReadBuffer(tempi,sizeof(integer));
|
|
descriptionleft:=tempi;
|
|
trainerfile.ReadBuffer(tempi,sizeof(integer));
|
|
editleft:=tempi;
|
|
trainerfile.ReadBuffer(tempi,sizeof(integer));
|
|
editwidth:=tempi;
|
|
|
|
trainerfile.ReadBuffer(tempbc,sizeof(tbevelcut));
|
|
bevelinner:=tempbc;
|
|
trainerfile.ReadBuffer(tempbc,sizeof(tbevelcut));
|
|
bevelouter:=tempbc;
|
|
trainerfile.ReadBuffer(tempi,sizeof(integer));
|
|
bevelwidth:=tempi;
|
|
trainerfile.ReadBuffer(tempbk,sizeof(tbevelkind));
|
|
bevelkind:=tempbk;
|
|
|
|
trainerfile.ReadBuffer(tempb,sizeof(boolean));
|
|
hascheckbox:=tempb;
|
|
trainerfile.ReadBuffer(tempb,sizeof(boolean));
|
|
beeponactivate:=tempb;
|
|
trainerfile.ReadBuffer(tempb,sizeof(boolean));
|
|
showhotkeys:=tempb;
|
|
|
|
parent:=userdefinedform;
|
|
end;
|
|
end;
|
|
|
|
2: begin //tcheat
|
|
setlength(userdefinedform.cheat,length(userdefinedform.cheat)+1);
|
|
userdefinedform.cheat[length(userdefinedform.cheat)-1]:=tcheat.create(nil);
|
|
|
|
with userdefinedform.cheat[length(userdefinedform.cheat)-1] do
|
|
begin
|
|
trainerfile.ReadBuffer(temp,sizeof(integer));
|
|
left:=temp;
|
|
trainerfile.ReadBuffer(temp,sizeof(integer));
|
|
top:=temp;
|
|
trainerfile.ReadBuffer(temp,sizeof(integer));
|
|
width:=temp;
|
|
trainerfile.ReadBuffer(temp,sizeof(integer));
|
|
height:=temp;
|
|
|
|
trainerfile.ReadBuffer(cheatnr,sizeof(integer));
|
|
trainerfile.ReadBuffer(tempc,sizeof(tcolor));
|
|
activationcolor:=tempc;
|
|
trainerfile.ReadBuffer(tempc,sizeof(tcolor));
|
|
color:=tempc;
|
|
trainerfile.ReadBuffer(tempc,sizeof(tcolor));
|
|
textcolor:=tempc;
|
|
|
|
trainerfile.ReadBuffer(tempi,sizeof(integer));
|
|
hotkeyleft:=tempi;
|
|
trainerfile.ReadBuffer(tempi,sizeof(integer));
|
|
descriptionleft:=tempi;
|
|
trainerfile.ReadBuffer(tempi,sizeof(integer));
|
|
editleft:=tempi;
|
|
trainerfile.ReadBuffer(tempi,sizeof(integer));
|
|
editwidth:=tempi;
|
|
|
|
trainerfile.ReadBuffer(tempb,sizeof(boolean));
|
|
hascheckbox:=tempb;
|
|
trainerfile.ReadBuffer(tempb,sizeof(boolean));
|
|
beeponactivate:=tempb;
|
|
trainerfile.ReadBuffer(tempb,sizeof(boolean));
|
|
showhotkey:=tempb;
|
|
|
|
parent:=userdefinedform;
|
|
end;
|
|
end;
|
|
|
|
3: with timage2.create(nil) do //timage
|
|
begin
|
|
trainerfile.ReadBuffer(temp,sizeof(integer));
|
|
left:=temp;
|
|
trainerfile.ReadBuffer(temp,sizeof(integer));
|
|
top:=temp;
|
|
trainerfile.ReadBuffer(temp,sizeof(integer));
|
|
width:=temp;
|
|
trainerfile.ReadBuffer(temp,sizeof(integer));
|
|
height:=temp;
|
|
|
|
trainerfile.ReadBuffer(tempcursor,sizeof(tcursor));
|
|
cursor:=tempcursor;
|
|
|
|
trainerfile.ReadBuffer(tempb,sizeof(tempb));
|
|
stretch:=tempb;
|
|
trainerfile.ReadBuffer(tempb,sizeof(tempb));
|
|
transparent:=tempb;
|
|
|
|
trainerfile.ReadBuffer(temp,sizeof(integer));
|
|
case temp of
|
|
1: onclick:=button1.OnClick;
|
|
2: onclick:=btnlaunch.onClick;
|
|
3: onclick:=button2.onClick;
|
|
4: onclick:=button3.OnClick;
|
|
else
|
|
begin
|
|
if temp>=5 then //it's an execute cheat
|
|
begin
|
|
onclick:=executecheat;
|
|
tag:=temp-5;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
trainerfile.ReadBuffer(temp,4); //size of extension
|
|
getmem(x,temp+1);
|
|
trainerfile.ReadBuffer(x^,temp);
|
|
x[temp]:=#0;
|
|
|
|
temps:=tempdir+inttostr(getcurrentprocessid)+'-'+inttostr(filecount)+x;
|
|
inc(filecount);
|
|
freemem(x);
|
|
|
|
f:=tfilestream.Create(temps, fmCreate or fmShareDenyNone);
|
|
|
|
trainerfile.ReadBuffer(temp,4);
|
|
getmem(x,temp);
|
|
trainerfile.ReadBuffer(x^,temp);
|
|
f.WriteBuffer(x^,temp);
|
|
freemem(x);
|
|
f.free;
|
|
|
|
Picture.LoadFromFile(temps);
|
|
|
|
DeleteFile(temps);
|
|
|
|
trainerfile.ReadBuffer(temp,4);
|
|
getmem(x,temp+1);
|
|
trainerfile.ReadBuffer(x^,temp);
|
|
x[temp]:=#0;
|
|
command:=x;
|
|
freemem(x);
|
|
|
|
|
|
parent:=userdefinedform;
|
|
end;
|
|
|
|
4: with tlabel2.Create(nil) do
|
|
begin
|
|
trainerfile.ReadBuffer(temp,sizeof(integer));
|
|
left:=temp;
|
|
trainerfile.ReadBuffer(temp,sizeof(integer));
|
|
top:=temp;
|
|
trainerfile.ReadBuffer(temp,sizeof(integer));
|
|
width:=temp;
|
|
trainerfile.ReadBuffer(temp,sizeof(integer));
|
|
height:=temp;
|
|
|
|
//caption
|
|
trainerfile.ReadBuffer(temp,4);
|
|
getmem(x,temp+1);
|
|
trainerfile.ReadBuffer(x^,temp);
|
|
x[temp]:=#0;
|
|
caption:=x;
|
|
freemem(x);
|
|
|
|
//wordwrap
|
|
trainerfile.ReadBuffer(tempb,sizeof(tempb));
|
|
wordwrap:=tempb;
|
|
|
|
trainerfile.ReadBuffer(tempc,sizeof(tcolor));
|
|
font.Color:=tempc;
|
|
|
|
//command
|
|
trainerfile.ReadBuffer(temp,4);
|
|
getmem(x,temp+1);
|
|
trainerfile.ReadBuffer(x^,temp);
|
|
x[temp]:=#0;
|
|
command:=x;
|
|
freemem(x);
|
|
|
|
//cursor
|
|
trainerfile.ReadBuffer(tempcursor,sizeof(tcursor));
|
|
cursor:=tempcursor;
|
|
|
|
//tag
|
|
trainerfile.ReadBuffer(temp,sizeof(integer));
|
|
case temp of
|
|
1: onclick:=button1.OnClick;
|
|
2: onclick:=btnlaunch.onClick;
|
|
3: onclick:=button2.onClick;
|
|
4: onclick:=button3.OnClick;
|
|
else
|
|
begin
|
|
if temp>=5 then //it's an execute cheat
|
|
begin
|
|
onclick:=executecheat;
|
|
tag:=temp-5;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
trainerfile.ReadBuffer(tempb,sizeof(tempb));
|
|
if tempb then
|
|
Font.Style:=[fsUnderline]
|
|
else
|
|
Font.Style:=[];
|
|
|
|
parent:=userdefinedform;
|
|
|
|
|
|
end;
|
|
|
|
$ffffffff: break;
|
|
else raise exception.Create('The trainer has been corrupted');
|
|
end;
|
|
end;
|
|
|
|
userdefinedform.show;
|
|
end;
|
|
|
|
//fill in the list
|
|
for i:=0 to length(trainerdata)-1 do
|
|
begin
|
|
tempb:=false;
|
|
for j:=0 to length(trainerdata[i].addressentrys)-1 do
|
|
if trainerdata[i].addressentrys[j].userinput then
|
|
begin
|
|
tempb:=true;
|
|
temps:=trainerdata[i].addressentrys[j].value;
|
|
end;
|
|
|
|
|
|
if userdefinedform<>nil then
|
|
begin
|
|
for j:=0 to length(userdefinedform.cheatlist)-1 do
|
|
begin
|
|
with userdefinedform.cheatlist[j] do
|
|
begin
|
|
addcheat(trainerdata[i].hotkeytext,trainerdata[i].description,temps,tempb);
|
|
end;
|
|
end;
|
|
|
|
for j:=0 to length(userdefinedform.cheat)-1 do
|
|
begin
|
|
with userdefinedform.cheat[j] do
|
|
begin
|
|
Description:=trainerdata[j].description;
|
|
Hotkey:=trainerdata[j].hotkeytext;
|
|
HasEditBox:=tempb;
|
|
Editvalue:=temps;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
clist.addcheat(trainerdata[i].hotkeytext,trainerdata[i].description,temps,tempb);
|
|
|
|
//if not registerhotkey(self.Handle,i,trainerdata[i].hotshift,trainerdata[i].hotkey) then
|
|
if not RegisterHotKey2(self.handle,i,trainerdata[i].hotkey) then
|
|
begin
|
|
//couldn't assign hotkey
|
|
//disable that hotkey
|
|
if userdefinedform<>nil then
|
|
for j:=0 to length(userdefinedform.cheatlist)-1 do
|
|
begin
|
|
with userdefinedform.cheatlist[j] do
|
|
begin
|
|
userdefinedform.cheatlist[j].Items[i].Description:='';
|
|
userdefinedform.cheatlist[j].Items[i].Hotkey:='';
|
|
userdefinedform.cheatlist[j].Items[i].HasEditBox:=false;
|
|
end;
|
|
end else
|
|
begin
|
|
clist.Items[i].Description:='';
|
|
clist.Items[i].Hotkey:='';
|
|
clist.Items[i].HasEditBox:=false;
|
|
end;
|
|
|
|
if userdefinedform<>nil then
|
|
for j:=0 to length(userdefinedform.cheat)-1 do
|
|
begin
|
|
with userdefinedform.cheat[j] do
|
|
begin
|
|
if cheatnr=i then
|
|
begin
|
|
Description:='';
|
|
Hotkey:='';
|
|
HasEditBox:=false;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
for j:=0 to length(trainerdata[i].addressentrys)-1 do
|
|
begin
|
|
if trainerdata[i].addressentrys[j].setvalue then
|
|
case trainerdata[i].addressentrys[j].memtyp of
|
|
0,1,2,6 : begin
|
|
try
|
|
trainerdata[i].addressentrys[j].valuei:=StrToInt64(trainerdata[i].addressentrys[j].value);
|
|
except
|
|
raise exception.Create('The value of '+trainerdata[i].description+' is invalid');
|
|
end;
|
|
end;
|
|
|
|
3,4: begin
|
|
try
|
|
trainerdata[i].addressentrys[j].valuef:=StrToFloat(trainerdata[i].addressentrys[j].value);
|
|
except
|
|
raise exception.Create('The value of '+trainerdata[i].description+' is invalid');
|
|
end;
|
|
end;
|
|
|
|
5: trainerdata[i].addressentrys[j].valuelength:=length(trainerdata[i].addressentrys[j].value);
|
|
|
|
7: begin
|
|
setlength(trainerdata[i].addressentrys[j].valuea,length(trainerdata[i].addressentrys[j].value));
|
|
for k:=0 to length(trainerdata[i].addressentrys[j].value)-1 do
|
|
trainerdata[i].addressentrys[j].valuea[k]:=ord(trainerdata[i].addressentrys[j].value[k+1]);
|
|
|
|
trainerdata[i].addressentrys[j].valuelength:=length(trainerdata[i].addressentrys[j].valuea);
|
|
end;
|
|
|
|
8: begin
|
|
ConvertStringToBytes(trainerdata[i].addressentrys[j].value,true,temptb);
|
|
setlength(trainerdata[i].addressentrys[j].valuea,length(temptb));
|
|
for k:=0 to length(temptb)-1 do
|
|
trainerdata[i].addressentrys[j].valuea[k]:=byte(temptb[k]);
|
|
|
|
setlength(temptb,0);
|
|
trainerdata[i].addressentrys[j].valuelength:=length(trainerdata[i].addressentrys[j].valuea);
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
if userdefinedform<>nil then
|
|
begin
|
|
for i:=0 to length(userdefinedform.cheat)-1 do
|
|
userdefinedform.cheat[i].onmousedown:=cheatclick;
|
|
|
|
for i:=0 to length(userdefinedform.cheatlist)-1 do
|
|
for j:=0 to userdefinedform.cheatlist[i].Count-1 do
|
|
userdefinedform.cheatlist[i].Items[j].OnMouseDown:=cheatclick;
|
|
end;
|
|
|
|
//find out if the process is open
|
|
CheckForProcess;
|
|
|
|
if processhandle<>0 then
|
|
begin //check and see if the process got changed. (check the code and see if they are nopped)
|
|
for i:=0 to length(trainerdata)-1 do
|
|
for J:=0 to length(trainerdata[i].codeentrys)-1 do
|
|
begin
|
|
//check for nops
|
|
//if yes then set it to active
|
|
setlength(tempab,length(trainerdata[i].codeentrys[j].originalopcode));
|
|
readprocessmemory(processhandle,pointer(trainerdata[i].codeentrys[j].address),@tempab[0],length(tempab),temp);
|
|
if not comparemem(@trainerdata[i].codeentrys[j].originalopcode[0],@tempab[0],length(tempab)) then
|
|
begin
|
|
//it is not the same
|
|
//check if tempab consists out of nops
|
|
for k:=0 to length(tempab)-1 do
|
|
if tempab[k]<>$90 then raise exception.Create('The version of '+process+' that is currently running, is not compatible with this trainer!');
|
|
|
|
//if we get here then it got nopped so set it to activated
|
|
trainerdata[i].active:=true;
|
|
|
|
if userdefinedform<>nil then
|
|
begin
|
|
for k:=0 to length(userdefinedform.cheatlist)-1 do
|
|
userdefinedform.cheatlist[k].Items[i].activated:=true;
|
|
|
|
for k:=0 to length(userdefinedform.cheat)-1 do
|
|
if (userdefinedform.cheat[k].cheatnr=i) then
|
|
userdefinedform.cheat[k].activated:=true;
|
|
end
|
|
else clist.Items[i].activated:=true;
|
|
end;
|
|
end;
|
|
end else if autolaunch then btnlaunch.Click;
|
|
end;
|
|
|
|
procedure TfrmMemoryTrainer.Timer1Timer(Sender: TObject);
|
|
begin
|
|
CheckForProcess;
|
|
timer1.Enabled:=false;
|
|
timer1.interval:=15000;
|
|
timer1.enabled:=true;
|
|
end;
|
|
|
|
procedure TfrmMemoryTrainer.btnLaunchClick(Sender: TObject);
|
|
begin
|
|
if fileexists(filename) then
|
|
begin
|
|
shellexecute(0,'open',pchar(filename),'','',sw_show);
|
|
btnlaunch.Enabled:=false;
|
|
timer1.Enabled:=false;
|
|
timer1.interval:=10000;
|
|
timer1.enabled:=true;
|
|
end
|
|
else
|
|
if fileexists(extractfilename(filename)) then
|
|
begin
|
|
shellexecute(0,'open',pchar(extractfilename(filename)),'','',sw_show);
|
|
btnlaunch.Enabled:=false;
|
|
timer1.Enabled:=false;
|
|
timer1.interval:=10000;
|
|
timer1.enabled:=true;
|
|
end
|
|
else
|
|
begin
|
|
opendialog1.FileName:=extractfilename(filename);
|
|
if opendialog1.Execute then
|
|
begin
|
|
btnlaunch.Enabled:=false;
|
|
timer1.Enabled:=false;
|
|
timer1.interval:=10000;
|
|
timer1.enabled:=true;
|
|
filename:=opendialog1.filename;
|
|
shellexecute(0,'open',pchar(filename),'','',sw_show);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TfrmMemoryTrainer.FreezerTimer(Sender: TObject);
|
|
var i,j,k,l,m: integer;
|
|
newvalue1: byte;
|
|
newvalue2: word;
|
|
newvalue3: dword;
|
|
newvalue4: single;
|
|
newvalue5: double;
|
|
newvalue6: int64;
|
|
|
|
oldvalue1: byte;
|
|
oldvalue2: word;
|
|
oldvalue3: dword;
|
|
oldvalue4: single;
|
|
oldvalue5: double;
|
|
oldvalue6: int64;
|
|
|
|
|
|
bl: integer;
|
|
newbytes: array of byte;
|
|
bytes: dword;
|
|
realaddress,realaddress2,count:dword;
|
|
original:dword;
|
|
begin
|
|
for i:=0 to length(trainerdata)-1 do
|
|
begin
|
|
if trainerdata[i].active then
|
|
begin
|
|
for j:=0 to length(trainerdata[i].addressentrys)-1 do
|
|
begin
|
|
if trainerdata[i].addressentrys[j].frozen then
|
|
begin
|
|
if trainerdata[i].addressentrys[j].IsPointer then
|
|
begin
|
|
//find the real address
|
|
realaddress2:=trainerdata[i].addressentrys[j].pointers[length(trainerdata[i].addressentrys[j].pointers)-1].Address;
|
|
for k:=length(trainerdata[i].addressentrys[j].pointers)-1 downto 0 do
|
|
begin
|
|
readprocessmemory(processhandle,pointer(realaddress2),@realaddress,4,count);
|
|
if count=4 then
|
|
realaddress2:=realaddress+trainerdata[i].addressentrys[j].pointers[k].offset
|
|
else
|
|
begin
|
|
realaddress2:=0;
|
|
break;
|
|
end;
|
|
end;
|
|
if realaddress2=0 then continue;
|
|
realaddress:=realaddress2;
|
|
end else realaddress:=trainerdata[i].addressentrys[j].Address;
|
|
|
|
|
|
VirtualProtectEx(processhandle, pointer(realaddress),1,PAGE_EXECUTE_READWRITE,original);
|
|
//set value
|
|
case trainerdata[i].addressentrys[j].memtyp of
|
|
0 : begin //byte
|
|
if trainerdata[i].addressentrys[j].frozendirection=0 then
|
|
begin
|
|
newvalue1:=byte(trainerdata[i].addressentrys[j].valuei);
|
|
WriteProcessMemory(processhandle,pointer(realaddress),@newvalue1,1,bytes);
|
|
end
|
|
else
|
|
begin
|
|
readprocessmemory(processhandle,pointer(realaddress),@newvalue1,1,bytes);
|
|
if trainerdata[i].addressentrys[j].Frozendirection=1 then
|
|
begin
|
|
//allow decreased values
|
|
if newvalue1<byte(trainerdata[i].addressentrys[j].valuei) then trainerdata[i].addressentrys[j].valuei:=newvalue1
|
|
else
|
|
begin
|
|
newvalue1:=byte(trainerdata[i].addressentrys[j].valuei);
|
|
WriteProcessMemory(processhandle,pointer(realaddress),@newvalue1,1,bytes);
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
//allow increased values
|
|
if newvalue1>byte(trainerdata[i].addressentrys[j].valuei) then trainerdata[i].addressentrys[j].valuei:=newvalue1
|
|
else
|
|
begin
|
|
newvalue1:=byte(trainerdata[i].addressentrys[j].valuei);
|
|
WriteProcessMemory(processhandle,pointer(realaddress),@newvalue1,1,bytes);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
1 : begin //word
|
|
newvalue2:=word(trainerdata[i].addressentrys[j].valuei);
|
|
if trainerdata[i].addressentrys[j].frozendirection=0 then WriteProcessMemory(processhandle,pointer(realaddress),@newvalue2,2,bytes)
|
|
else
|
|
begin
|
|
ReadProcessMemory(processhandle,pointer(realaddress),@oldvalue2,2,bytes);
|
|
if trainerdata[i].addressentrys[j].frozendirection=1 then
|
|
begin
|
|
//allow decrease
|
|
if oldvalue2<newvalue2 then
|
|
trainerdata[i].addressentrys[j].valuei:=oldvalue2
|
|
else
|
|
WriteProcessMemory(processhandle,pointer(realaddress),@newvalue2,2,bytes);
|
|
|
|
end
|
|
else
|
|
begin
|
|
//allow inc
|
|
if oldvalue2>newvalue2 then
|
|
trainerdata[i].addressentrys[j].valuei:=oldvalue2
|
|
else
|
|
WriteProcessMemory(processhandle,pointer(realaddress),@newvalue2,2,bytes);
|
|
end;
|
|
|
|
|
|
end;
|
|
end;
|
|
|
|
2 : begin //dword
|
|
newvalue3:=dword(trainerdata[i].addressentrys[j].valuei);
|
|
if trainerdata[i].addressentrys[j].frozendirection=0 then WriteProcessMemory(processhandle,pointer(realaddress),@newvalue3,4,bytes)
|
|
else
|
|
begin
|
|
ReadProcessMemory(processhandle,pointer(realaddress),@oldvalue3,4,bytes);
|
|
if trainerdata[i].addressentrys[j].frozendirection=1 then
|
|
begin
|
|
//allow decrease
|
|
if oldvalue3<newvalue3 then
|
|
trainerdata[i].addressentrys[j].valuei:=oldvalue3
|
|
else
|
|
WriteProcessMemory(processhandle,pointer(realaddress),@newvalue3,4,bytes)
|
|
end
|
|
else
|
|
begin
|
|
if oldvalue3>newvalue3 then
|
|
trainerdata[i].addressentrys[j].valuei:=oldvalue3
|
|
else
|
|
WriteProcessMemory(processhandle,pointer(realaddress),@newvalue3,4,bytes)
|
|
|
|
end;
|
|
|
|
end;
|
|
end;
|
|
|
|
3 : begin //single
|
|
newvalue4:=trainerdata[i].addressentrys[j].valuef;
|
|
if trainerdata[i].addressentrys[j].frozendirection=0 then WriteProcessMemory(processhandle,pointer(realaddress),@newvalue4,4,bytes)
|
|
else
|
|
begin
|
|
ReadProcessMemory(processhandle,pointer(realaddress),@oldvalue4,4,bytes);
|
|
if (not isnan(oldvalue4)) and (not isinfinite(oldvalue4)) then
|
|
begin
|
|
if trainerdata[i].addressentrys[j].frozendirection=1 then
|
|
begin
|
|
//allow decrease
|
|
if oldvalue4<newvalue4 then
|
|
trainerdata[i].addressentrys[j].valuef:=oldvalue4
|
|
else
|
|
WriteProcessMemory(processhandle,pointer(realaddress),@newvalue4,4,bytes)
|
|
end
|
|
else
|
|
begin
|
|
if oldvalue4>newvalue4 then
|
|
trainerdata[i].addressentrys[j].valuef:=oldvalue4
|
|
else
|
|
WriteProcessMemory(processhandle,pointer(realaddress),@newvalue4,4,bytes);
|
|
|
|
end;
|
|
end else WriteProcessMemory(processhandle,pointer(realaddress),@newvalue4,4,bytes);
|
|
end;
|
|
end;
|
|
|
|
4 : begin //double
|
|
newvalue5:=double(trainerdata[i].addressentrys[j].valuef);
|
|
if trainerdata[i].addressentrys[j].frozendirection=0 then WriteProcessMemory(processhandle,pointer(realaddress),@newvalue5,8,bytes)
|
|
else
|
|
begin
|
|
ReadProcessMemory(processhandle,pointer(realaddress),@oldvalue5,8,bytes);
|
|
if (not isnan(oldvalue5)) and (not isinfinite(oldvalue5)) then
|
|
begin
|
|
if trainerdata[i].addressentrys[j].frozendirection=1 then
|
|
begin
|
|
//allow decrease
|
|
if oldvalue5<newvalue5 then
|
|
trainerdata[i].addressentrys[j].valuef:=oldvalue5
|
|
else
|
|
WriteProcessMemory(processhandle,pointer(realaddress),@newvalue5,8,bytes)
|
|
end
|
|
else
|
|
begin
|
|
if oldvalue5>newvalue5 then
|
|
trainerdata[i].addressentrys[j].valuef:=oldvalue5
|
|
else
|
|
WriteProcessMemory(processhandle,pointer(realaddress),@newvalue5,8,bytes)
|
|
|
|
end;
|
|
end else WriteProcessMemory(processhandle,pointer(realaddress),@newvalue5,8,bytes)
|
|
end;
|
|
|
|
end;
|
|
|
|
5 : begin //binary
|
|
bl:=1+((length(trainerdata[i].addressentrys[j].value)-1) div 8);
|
|
setlength(newbytes,bl);
|
|
ReadProcessMemory(processhandle,pointer(realaddress),@newbytes[0],bl,bytes);
|
|
|
|
|
|
l:=trainerdata[i].addressentrys[j].bit;
|
|
k:=0;
|
|
for m:=length(trainerdata[i].addressentrys[j].value) downto 1 do
|
|
begin
|
|
case trainerdata[i].addressentrys[j].value[m] of
|
|
'0' : setbit(l,newbytes[k],0);
|
|
'1' : setbit(l,newbytes[k],1);
|
|
'*','?','x': ;
|
|
end;
|
|
|
|
inc(l);
|
|
if l>=8 then
|
|
begin
|
|
inc(k);
|
|
l:=0;
|
|
end;
|
|
end;
|
|
|
|
writeprocessmemory(processhandle,pointer(realaddress),@newbytes[0],bl,bytes);
|
|
setlength(newbytes,0);
|
|
end;
|
|
|
|
6 : begin //int64
|
|
newvalue6:=dword(trainerdata[i].addressentrys[j].valuei);
|
|
if trainerdata[i].addressentrys[j].frozendirection=0 then WriteProcessMemory(processhandle,pointer(realaddress),@newvalue6,8,bytes)
|
|
else
|
|
begin
|
|
ReadProcessMemory(processhandle,pointer(realaddress),@oldvalue6,8,bytes);
|
|
if trainerdata[i].addressentrys[j].frozendirection=1 then
|
|
begin
|
|
//allow decrease
|
|
if oldvalue6<newvalue6 then
|
|
trainerdata[i].addressentrys[j].valuei:=oldvalue6
|
|
else
|
|
WriteProcessMemory(processhandle,pointer(realaddress),@newvalue6,8,bytes)
|
|
end
|
|
else
|
|
begin
|
|
if oldvalue6>newvalue6 then
|
|
trainerdata[i].addressentrys[j].valuei:=oldvalue6
|
|
else
|
|
WriteProcessMemory(processhandle,pointer(realaddress),@newvalue6,8,bytes)
|
|
|
|
end;
|
|
|
|
end;
|
|
end;
|
|
|
|
7,8: begin //array of bytes , or array of char
|
|
writeprocessmemory(processhandle,pointer(realaddress),@trainerdata[i].addressentrys[j].valuea[0],trainerdata[i].addressentrys[j].valuelength,bytes);
|
|
end;
|
|
end;
|
|
VirtualProtectEx(processhandle, pointer(realaddress),1,original,original);
|
|
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TfrmMemoryTrainer.Button1Click(Sender: TObject);
|
|
begin
|
|
close;
|
|
end;
|
|
|
|
procedure TfrmMemoryTrainer.Button2Click(Sender: TObject);
|
|
begin
|
|
showmessage(aboutboxtext);
|
|
end;
|
|
|
|
procedure TfrmMemoryTrainer.Button3Click(Sender: TObject);
|
|
begin
|
|
if (sender is Tlabel2) then shellexecute(0,'open',pchar(tlabel2(sender).command),'','',sw_show);
|
|
if (sender is TImage2) then shellexecute(0,'open',pchar(timage2(sender).command),'','',sw_show);
|
|
if (sender is TButton2) then shellexecute(0,'open',pchar(tbutton2(sender).command),'','',sw_show);
|
|
end;
|
|
|
|
procedure TfrmMemoryTrainer.Timer2Timer(Sender: TObject);
|
|
begin
|
|
if reinitializedesired and (processhandle<>0) then
|
|
begin
|
|
//last time not all addresses got loaded successfull
|
|
reinterpretaddresses;
|
|
|
|
if reinitializedesired and symhandler.isloaded then symhandler.reinitialize;
|
|
end;
|
|
end;
|
|
|
|
procedure TfrmMemoryTrainer.Timer3Timer(Sender: TObject);
|
|
begin
|
|
//every 30 seconds reinterpret anyhow. (not really needed since dlls usually dont change address, but lets do it anyhow)
|
|
if reinitializedesired and symhandler.isloaded then
|
|
symhandler.reinitialize;
|
|
|
|
reinterpretaddresses;
|
|
end;
|
|
|
|
procedure TfrmMemoryTrainer.CheatClick(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
|
var t: tcheat;
|
|
m: twmhotkey;
|
|
begin
|
|
//sender is of type tcheat
|
|
t:=tcheat(sender);
|
|
|
|
//fake a hotkeypress
|
|
m.hotkey:=t.cheatnr;
|
|
|
|
hotkeyhandler(m);
|
|
end;
|
|
|
|
procedure TfrmMemoryTrainer.executecheat(sender: tobject);
|
|
var cheatnr: integer;
|
|
m: twmhotkey;
|
|
begin
|
|
if (sender is tbutton) then
|
|
cheatnr:=tbutton(sender).Tag;
|
|
|
|
if (sender is tlabel) then
|
|
cheatnr:=tlabel(sender).tag;
|
|
|
|
if (sender is timage) then
|
|
cheatnr:=tlabel(sender).tag;
|
|
|
|
cheatnr:=cheatnr;
|
|
m.HotKey:=cheatnr;
|
|
hotkeyhandler(m);
|
|
end; //onclick event
|
|
|
|
end.
|