I've got the following problem and i'm hoping you can help me. During the last days i tried to build an delphi injector that injects a speedhack dll in a program. But unfortunately it doesn't work.
The dll itself seems to work, because i'm able to inject it through MHS.
Here are the facts:
- Windows 7 OS, UAC Disabled
- MHS: MHS5.2009
- Embarcadero RAD Studio 2010 (Delphi 2010)
- The Program (Game) I want to inject in: http://www.virtualskipper-game.com/vsk5/
Now comes the code part:
Speedhack.dll
- Code: Select all
library speedhack;
uses
SysUtils,
Classes,
speedhackunit in 'speedhackunit.pas';
{$R *.res}
begin
acceleration := 500;
sleeptime := 1;
InitializeSpeedhack;
end.
speedhackunit.pas
- Code: Select all
unit speedhackunit;
interface
uses windows,classes;
type TAPIInfo = record
location: Pointer;
Original: Array [0..4] of byte;
Jump: Array [0..4] of byte;
end;
type TTick=class(TThread)
private
public
procedure Execute; override;
end;
procedure InitializeSpeedhack;
procedure StopSpeedhack;
procedure GetTime; stdcall;
//function GetTime:dword; stdcall;
function NewQueryPerformanceCounter(var output: int64):BOOl; stdcall;
var CETick: dword;
CETick64: int64;
Ticker: TTick;
PerformanceFrequency: int64;
PerformanceFrequencyMS: int64;
acceleration: single;
sleeptime: dword;
slow: boolean;
tickerstopped: boolean;
speedhackenabled: boolean;
timeGetTimeInfo:TAPiInfo;
getTickcountInfo: TAPIInfo;
QueryPerformanceCounterInfo: TAPIInfo;
winmmlib,kernel32lib: thandle;
implementation
procedure InitializeSpeedhack;
var op:dword;
begin
cetick:=gettickcount;
//change the gettickcount and timegettime functions so that they look at cetick
if ticker<>nil then
begin
ticker.Terminate;
stopspeedhack;
end;
ticker:=nil;
winmmlib:=LoadLibrary('winmm.dll');
if winmmlib<>0 then
begin
timeGetTimeInfo.location:=GetProcAddress(winmmlib,'timeGetTime');
if VirtualProtect(timeGetTimeInfo.location,5,PAGE_EXECUTE_READWRITE,op) then
begin
timeGetTimeInfo.jump[0]:=$e9;
pdword(@timeGetTimeInfo.jump[1])^:=dword(@GetTime)-dword(timeGetTimeInfo.location)-5;
try
asm
//store original
push edi
push esi
lea edi,timeGetTimeInfo.original[0]
mov esi,timeGetTimeInfo.location
movsd
movsb
//replace with jump
lea esi,timeGetTimeInfo.jump[0]
mov edi,timeGetTimeInfo.location
movsd
movsb
pop esi
pop edi
end;
except
end;
end;
end;
kernel32lib:=LoadLibrary('kernel32.dll');
if kernel32lib<>0 then
begin
//gettickcount
GetTickCountInfo.location:=GetProcAddress(kernel32lib,'GetTickCount');
if VirtualProtect(GetTickCountInfo.location,5,PAGE_EXECUTE_READWRITE,op) then
begin
GetTickCountInfo.jump[0]:=$e9;
pdword(@GetTickCountInfo.jump[1])^:=dword(@GetTime)-dword(GetTickCountInfo.location)-5;
try
asm
//store original
push edi
push esi
lea edi,GetTickCountInfo.original[0]
mov esi,GetTickCountInfo.location
movsd
movsb
//replace with jump
lea esi,GetTickCountInfo.jump[0]
mov edi,GetTickCountInfo.location
movsd
movsb
pop esi
pop edi
end;
except
end;
end;
//QueryPerformanceCounter
if QueryPerformanceFrequency(PerformanceFrequency) then
begin
QueryPerformanceCounter(CETick64);
PerformanceFrequencyMS:=PerformanceFrequency div 1000;
//there is a high performance counter
QueryPerformanceCounterInfo.location:=GetProcAddress(kernel32lib,'QueryPerformanceCounter');
if VirtualProtect(QueryPerformanceCounterInfo.location,5,PAGE_EXECUTE_READWRITE,op) then
begin
QueryPerformanceCounterInfo.jump[0]:=$e9;
pdword(@QueryPerformanceCounterInfo.jump[1])^:=dword(@NewQueryPerformanceCounter)-dword(QueryPerformanceCounterInfo.location)-5;
try
asm
//store original
push edi
push esi
lea edi,QueryPerformanceCounterInfo.original[0]
mov esi,QueryPerformanceCounterInfo.location
movsd
movsb
//replace with jump
lea esi,QueryPerformanceCounterInfo.jump[0]
mov edi,QueryPerformanceCounterInfo.location
movsd
movsb
pop esi
pop edi
end;
except
end;
end;
end;
end;
speedhackenabled:=true;
if ticker=nil then ticker:=TTick.Create(false);
end;
procedure StopSpeedhack;
begin
if not speedhackenabled then exit;
speedhackenableD:=false;
try
asm
lea esi,timeGetTimeInfo.original[0]
mov edi,timeGetTimeInfo.location
movsd
movsb
end;
except
end;
try
asm
lea esi,GetTickCountInfo.original[0]
mov edi,GetTickCountInfo.location
movsd
movsb
end;
except
end;
try
asm
lea esi,QueryPerformanceCounterInfo.original[0]
mov edi,QueryPerformanceCounterInfo.location
movsd
movsb
end;
except
end;
FreeLibrary(winmmlib);
FreeLibrary(kernel32lib);
winmmlib:=0;
kernel32lib:=0;
if ticker<>nil then ticker.terminate;
ticker:=nil;
end;
procedure GetTime; stdcall;
asm
mov eax,[CETick]
ret
end;
{function GetTime:dword; stdcall;
begin
result:=CETick;
end;}
function NewQueryPerformanceCounter(var output: int64):BOOl; stdcall;
begin
output:=cetick64;
result:=true;
end;
procedure TTick.Execute;
begin
tickerstopped:=false;
freeonterminate:=true;
priority:=tpTimeCritical; //if not a thread with higher priority will prevent the timer from running
while not terminated do
begin
inc(cetick64,trunc(acceleration*(PerformanceFrequency / (1000 / sleeptime))) );
inc(cetick,trunc(sleeptime*acceleration));
sleep(sleeptime);
end;
tickerstopped:=true;
end;
initialization
acceleration:=1.8;
sleeptime:=10;
InitializeSpeedhack;
end.
Now the Injection Tool:
- Code: Select all
program ProjectInject;
{$APPTYPE CONSOLE}
uses
SysUtils,
windows,
psapi,
tlhelp32,
inifiles,
speedhackunit in 'speedhackunit.pas', Messages, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TUI = class(tthread)
public
procedure execute; override;
end;
var
WName,PName,DName:string;
DLLLocation:string;
ProcessId:DWORD;
sui: tui;
procedure Tui.Execute;
begin
//
end;
procedure PhraseINI();
var
IniFile:TIniFile;
begin
if FileExists(GetCurrentDir + '\Injector.ini') then
begin
IniFile:=TIniFile.Create(GetCurrentDir + '\Injector.ini');
WName:=IniFile.ReadString('DLL Injector','Window','');
PName:=IniFile.ReadString('DLL Injector','Target','notepad.exe');
DName:=IniFile.ReadString('DLL Injector','DLL','MessageBox.dll');
end
else
begin
IniFile:=TIniFile.Create(GetCurrentDir + '\Injector.ini');
IniFile.WriteString('DLL Injector','Window','Untitled - Notepad');
IniFile.WriteString('DLL Injector','Target','notepad.exe');
IniFile.WriteString('DLL Injector','DLL','MessageBox.dll');
PhraseINI();
end;
end;
procedure GetPID();
var
TempSnapshot:THandle;
Process32:TProcessEntry32;
Name: HWND;
begin
Name := FindWindow('PName',nil);
ProcessId := GetWindowThreadProcessId(Name);
{while (ProcessId=0) do
begin
TempSnapshot:=CreateToolhelp32Snapshot(TH32CS_SNAPALL,0);
Process32First(TempSnapshot,Process32);
while Process32Next(TempSnapshot,Process32) do
begin
if Process32.szExeFile = PName then
ProcessId:=Process32.th32ProcessID;
end;
CloseHandle(TempSnapshot);
end;}
//ProcessId := 4728;
end;
procedure InjectDLL();
var
Process:THandle;
TempHandle:THandle;
AllocatedRegion:pointer;
Empty:DWORD;
NumberOfBytesWritten:Cardinal;
begin
Process:=OpenProcess(PROCESS_ALL_ACCESS,False,ProcessId);
AllocatedRegion:=VirtualAllocEx(Process,NIL,length(DLLLocation),MEM_COMMIT,PAGE_EXECUTE_READWRITE);
WriteProcessMemory(Process,AllocatedRegion,pchar(DLLLocation),length(DLLLocation),NumberOfBytesWritten);
if WName='' then
sleep(750)
else
while FindWindow(nil,pchar(WName))=0 do
sleep(10);
TempHandle:=CreateRemoteThread(Process,nil,0,GetProcAddress(GetModuleHandle('kernel32.dll'),'LoadLibraryA'),AllocatedRegion,0,Empty);
WaitForSingleObject(TempHandle,INFINITE);
CloseHandle(TempHandle);
end;
begin
PhraseINI();
Writeln('- DLL Injector -'+#$0A+#$0D+'----------------');
DLLLocation:=GetCurrentDir()+'\'+DName;
if not FileExists(DLLLocation) then
begin
Writeln('Unable to locate the DLL');
sleep(7000);
exitprocess(0);
end;
Writeln('Waiting for process: '+PName);
GetPID();
Writeln(' - Process found'+#$0A+#$0D);
Writeln('Injecting '+DName+' into '+PName);
InjectDLL();
Writeln(' - DLL injected');
sui:=tui.create(false);
acceleration := 500;
sleeptime := 1;
sleep(7000);
end.
Sorry for my bad english,
Sonic-Y3k