First Step
In order to realize our concept, we have to find a way to hook QueryPerformanceCounter every time Half-Life calls it.
C++ users also could use ForceLibrary (I was thinking about porting Forcelibary into a DLL, untill System game me told me about madshi).
There might be more(elegant) ways to hook the function but i actually chose this.
If you want to take a deeper look at hooks you should click here.
Now Back to MadShi:
The headers we need from Madshi is MadhookCode.pas There are two functions we need: 1.CreateProcessEx and 2.HookCode. In order to make a global hook, we have to write our little cheat in two seperated parts: a DLL with the hooking function and a Executable witch injects you DLL onto a target.
Coding Part
In this part I will post the entire Source and than I will describe it step for step:
In the Loader:
uses....MadHookCode......
procedure TForm1.FormShow(Sender: TObject);
var curpath: String;
begin
Curpath:=ExtractFilePath(Application.ExeName);
CreateProcessEx(PChar('E:\CounterStrike'), PChar('-console -game cstrike'), nil, nil, false, 0, nil, nil, si, pi, PChar(Curpath+'MySpeedhack.dll'));
end;
This is basically all you need in your Loader, the rest is up to you to design....
Now the the DLL:
uses ....Windows,MadHookCode......
var NextQuerryPerform: function(var lpPerformancecount: Int64): longbool; stdcall;
Speedon:bool=FALSE;
ls:bool=FALSE;
function myQuerryPerform(var lpPerformancecount: Int64): longbool; stdcall;
begin
result:=NextQuerryPerform(lpPerformancecount);
if (GetAsyncKeyState(VK_CAPITAL)<0) and (ls=FALSE) Then
begin
ls:=TRUE;
if speedon=TRUE then speedon:=FALSE
else speedon:=TRUE;
end
else if not GetAsyncKeyState(VK_CAPITAL)<0 Then
ls:=FALSE;
if speedon=TRUE Then
lpPerformancecount:=lpPerformancecount*2;
end;
begin
HookCode(@QueryPerformanceCounter,@myQuerryPerform,@NextQuerryPerform) ;
end.
Okay and now to the details:
In our Loader we have......
uses....MadHookCode......
Uses is a expression similar to C++'s #include <> in the upper line we simply tell the compiler that we want to use MadhookCode.pas a "header" file with constants and functions...etc.
procedure TForm1.FormShow(Sender: TObject);
This is one of the "prefabricated" procedures of delphi, similar to C++'s mfc class events. FormShow is the standart name for the procedue for the pre-Dialoge showing.
var curpath: pChar;
Here we declare a private variable of the current procedure, its similar to c's char curpath;
begin......end
Now this is similar to C's brackets "{" and "}" which defines the beginning and the end of the current Proc/loop/if,casestatement..
Curpath:=ExtractFilePath(Application.ExeName)
This Statement assigns curpath to the current DirectoryFullPath of the loader. (where the dll file is also stored) we will need this in the next statement.
CreateProcessEx(PChar('E:\CounterStrike'), PChar('-console -game cstrike'), nil, nil, false, 0, nil, nil, si, pi, PChar(Curpath+'MySpeedhack.dll'));
Now this is our main loader-function, so lets take a closer look at it:
function CreateProcessEx (applicationName, commandLine : pchar;
processAttr, threadAttr : PSecurityAttributes;
inheritHandles : bool;
creationFlags : dword;
environment : pointer;
currentDirectory : pchar;
const startupInfo : TStartupInfo;
var processInfo : TProcessInformation;
loadLibrary : pchar ) : bool; stdcall;
as we see this function is very likely the WindowsFunction CreateProcess the only difference is that CreateProcessEx contains the additional " loadLibrary: pchar ", which specifies the dll, we want to inject.
After CreateProcessEx has been executed, it starts the specified application, but patching it in a way that the app behaves like would have a Loadlibrary call right in its first line.
Okay, that was the Loader, now to the Dll:
var NextQuerryPerform: function(var lpPerformancecount: Int64): longbool; stdcall;
Here we declare a buf-function with the same variables as the Original function. This Function is called in the callback function.
function myQuerryPerform(var lpPerformancecount: Int64): longbool; stdcall;
begin
result:=NextQuerryPerform(lpPerformancecount);
if (GetAsyncKeyState(VK_CAPITAL)<0) and (ls=FALSE) Then
begin
ls:=TRUE;
if speedon=TRUE then speedon:=FALSE
else speedon:=TRUE;
end
else if not GetAsyncKeyState(VK_CAPITAL)<0 Then
ls:=FALSE;
if speedon=TRUE Then
lpPerformancecount:=lpPerformancecount*2;
end;
And now this is the function we let it "replace" instead of the Original function
First we call the original Function in
result:=NextQuerryPerform(lpPerformancecount);
Than there is our simple Key Trigger to turn the speedhack on and off.
And at last, if the speedhack is on(speedon=TRUE)
we change pPerformancecount by double its speed in:
lpPerformancecount:=lpPerformancecount*2;
Now here we go, the last thing we have to do is using MadCodehook's function HookCode to hook the Process QueryProformanceCount :
HookCode(@QueryPerformanceCounter,@myQuerryPerform,@NextQuerryPerform) ;
a "@" indicates a Pointer.
last thing I wanted to mention:
With this method you are also able to hook GetProcAddress or LoadLibrary for example to inject your OpenGl functions...
as it is discribed here
Credit
Coder-original author