Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Hooking Programs 3

Status
Not open for further replies.

BobbaFet

Programmer
Feb 25, 2001
903
NL
Hi all,

Thanks for reading my question:

I've got 2 questions for you:
Is there a way to detect one program hooking into another?
Is there a way to prevent this?

Thing is, I'm one of the administrators of a quite popular gaming league and we are having real big problems with cheaters. I've written an application which detects all the changed files and which can be forced to be used, but still the mayority of the programs work through hooking into memory of the game and changing it to preform features otherwise not available. Now if I can detect this from happening as the game has to be launched from my program with CreateProcess I can easily terminate the game as well. So this will be quite useful.

[bobafett] BobbaFet [bobafett]

Everyone has a right to my opinion.
E-mail me at caswegkamp@hotmail.com Great Delphi Websites faq102-5352
 
Or is there perhaps a way to hide the process of the game from the process list?

[bobafett] BobbaFet [bobafett]

Everyone has a right to my opinion.
E-mail me at caswegkamp@hotmail.com Great Delphi Websites faq102-5352
 
Hey BobbaFet
I can recommend you to fight fire with fire heh. Install your own hook for your application when it starts. What you need is Debug hook (see WH_DEBUG). Once it's installed it allows you to control the calls of hooks installed for a specific application. Debug hook is always the first one that is called and in order to prevent calling any other hook (or a specific type of hooks) the callback function should return a non zero value.
Can't provide you with a code snippet at the moment, may be a lil bit later.

HTH
--- McMerfy
 
Thanks allot man, really appreciate it! I'm going to dig straight into it!

[bobafett] BobbaFet [bobafett]

Everyone has a right to my opinion.
E-mail me at caswegkamp@hotmail.com
Great Delphi Websites faq102-5352
 
If you got the time, could you show me that code snippet, because I can't get it to work.

Appreciate it,

[bobafett] BobbaFet [bobafett]
 
Hey BobbaFet.

There you go. Explanations are below the code.

Code:
interface
...
type
  _DEBUGHOOKINFO = record
    idThread : DWORD;
    idThreadInstaller :DWORD;
    lParam   : Longint;
    wParam   : Longint;
    code     : Integer;
  end;
  DEBUGHOOKINFO = _DEBUGHOOKINFO;
  PDEBUGHOOKINFO = ^DEBUGHOOKINFO;
...
// in your application create a function
function DebugHookProc(nCode: Integer; wParam: Longint; lParam: Longint): Longint; stdcall;
...
implementation
...
function DebugHookProc(nCode: Integer; wParam: Longint; lParam: Longint): Longint; stdcall
var
  DHI : PDEBUGHOOKINFO;
begin
  Result := -1;
  DHI := PDEBUGHOOKINFO(lParam);
  case nCode of
   WH_DEBUG:
   begin
     if (DHI^.idThreadInstaller = GetCurrentThreadId())then
      Result := CallNextHookEx(Form1.AppDebugHook, DHI^.code, DHI^.wParam, DHI^.lParam);
   end
 end;
end;
...
// now somewere in FormCreate handler (for example)
procedure TForm1.FormCreate(Sender: TObject);
begin
// AppDebugHook: HHOOK  - is a private member of a form
  AppDebugHook := SetWindowsHookEx(WH_DEBUG, @DebugHookProc, 0, GetCurrentThreadId());
  if (AppDebugHook = 0)then ShowMessage('Hook install failed');
end;
...
// and in FormClose we remove our hook
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
...  
  UnhookWindowsHookEx(AppDebugHook);
...
end;
You don't need to create DLL that contain hook procedures since you install hook for your own application. In this sample DebugHookProc will block any hook except for other DEBUG hooks installed by your application.

Have you any questions, feel free to aks. Cheers.

--- McMerfy
 
Hi, McMerfy!

Thnx allot, you're help is awesome! If I could award you more then 1 star I would :D

Greetz!

[bobafett] BobbaFet [bobafett]

Everyone has a right to my opinion.
E-mail me at caswegkamp@hotmail.com
Great Delphi Websites faq102-5352
 
Just to make sure, I'm using Delphi 7 and the code would initially not work, so to make it work I added this:

Code:
  private
    AppDebugHook: HHOOK;

That is correct right?

[bobafett] BobbaFet [bobafett]

Everyone has a right to my opinion.
E-mail me at caswegkamp@hotmail.com
Great Delphi Websites faq102-5352
 
If I can bother you some more :)

This is the code that I use to launch the game, now this in itself works fine, but I cannot get the hook to install because the game is still loading when the hook code is executed, is there a way to determine when it is fully loaded ???

Code:
function RunExecutable (const FileName : String; WaitForIt : boolean) :DWORD;
var StartupInfo: TStartupInfo; ProcessInfo: TProcessInformation; errMsg: pChar;
begin
  Result := STILL_ACTIVE;
  GetStartupInfo(StartupInfo);
  if CreateProcess(nil, PChar(FileName), nil, nil, IsConsole,
            NORMAL_PRIORITY_CLASS, nil, nil, StartupInfo, ProcessInfo)then
  begin
    try
      if (not WaitForIt)
      or (WaitForSingleObject(ProcessInfo.hProcess,INFINITE) = WAIT_OBJECT_0) then
        GetExitCodeProcess(ProcessInfo.hProcess, Result);
      finally
        CloseHandle(ProcessInfo.hThread);
        CloseHandle(ProcessInfo.hProcess);
      end;
  end
  else
  begin
    if FormatMessage (Format_Message_Allocate_Buffer
    or Format_Message_From_System, nil, GetLastError, 0, @errMsg, 0, nil) <> 0 then
    begin
      try
        raise Exception.Create ('CreateProcess failed with error "' + String (errMsg) + '".');
      finally
        LocalFree (Cardinal (errMsg));
      end;
    end;
  end;
end;

[bobafett] BobbaFet [bobafett]

Everyone has a right to my opinion.
E-mail me at caswegkamp@hotmail.com
Great Delphi Websites faq102-5352
 
Can you modify the code of the game? Or is that only the launching program that you can modify?

--- McMerfy
 
It is only the launching of the game, the game itself is already fully compiled, should you want to know, the game's name is Ghost Recon. Maybe you have heard of it.

[bobafett] BobbaFet [bobafett]

Everyone has a right to my opinion.
E-mail me at caswegkamp@hotmail.com
Great Delphi Websites faq102-5352
 
Hmmm something strange is going on. I use that code above because itll give me the process information which is copied to a global variable of TProcessInformation. But no matter what I try, namely:

Code:
procedure TForm1.SetNewHook(MyProcess: Cardinal);
begin
if (AppDebugHook <> 0) then
        UnhookWindowsHookEx(AppDebugHook);

AppDebugHook := SetWindowsHookEx(WH_DEBUG, @DebugHookProc, 0, MyProcess);
if (AppDebugHook = 0) then 
          ShowMessage('Hook Install Failed');
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
SetNewHook(GlobalProcInfo.dwProcessId); {or}
SetNewHook(GlobalProcInfo.dwThreadId); {or}
SetNewHook(GlobalProcInfo.hProcess); {or}
SetNewHook(GlobalProcInfo.hThread); 
end;

All of them return the "Hook Install Failed" message. Even though I wait for Ghost Recon to be fully loaded before attempting to set the hook manually by button click. What am I doing wrong here?

[bobafett] BobbaFet [bobafett]

Everyone has a right to my opinion.
E-mail me at caswegkamp@hotmail.com
Great Delphi Websites faq102-5352
 
Hmmm my mistake. Thought that you're protecting your own app. So we'll need a DLL for hook 'injection'.
1. Here's the unit that is to be used in your app and DLL module.
Code:
unit UShared;

interface
uses Windows, Messages;

const
  MemShareName = 'SharedData.mem';
  MessageName  = 'WM_HOOKEVENT';
type
  TMemoryData = packed record
{    WMMessage   : Cardinal;} // ignore this one
{    hTraceWnd   : HWND;}     // ignore this one
{    hMainWnd    : HWND;}     // ignore this one
    MyThreadID  : Cardinal;
    hDebugHook  : HHOOK;
    hMouseHook  : HHOOK;
  end;
  PMemoryData = ^TMemoryData;

  _DEBUGHOOKINFO = record
    idThread : DWORD;
    idThreadInstaller :DWORD;
    lParam   : Longint;
    wParam   : Longint;
    code     : Integer;
  end;
  DEBUGHOOKINFO = _DEBUGHOOKINFO;
  PDEBUGHOOKINFO = ^DEBUGHOOKINFO;

  THookProc = function (Code : Integer; wParam : WPARAM; lParam: LPARAM):LRESULT of object; stdcall;

function CreateOrOpenMemShare():Boolean;
function CloseMemShare():Boolean;

var
  hMappedFile    : Cardinal = 0;
  MappingExists  : Boolean  = False;
  SharedData     : PMemoryData = nil; // this will be used
// for the data exchange between the DLL and application

implementation

function CreateOrOpenMemShare():Boolean;
var
  NewlyCreated : Boolean;
begin
  Result := False;
  hMappedFile := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, SizeOf(TMemoryData), pChar(MemShareName));
  if (hMappedFile <> 0) then
  begin
    NewlyCreated := (GetLastError <> ERROR_ALREADY_EXISTS);
    SharedData := MapViewOfFile(hMappedFile, FILE_MAP_ALL_ACCESS, 0, 0, 0);
    Result := Assigned(SharedData);
    MappingExists := Result;
    if (Result and NewlyCreated) then
     FillChar(SharedData^, SizeOf(TMemoryData), 0);
  end;
end;

function CloseMemShare():Boolean;
begin
  Result := True;
  if MappingExists then
   UnmapViewOfFile(SharedData);
  if (hMappedFile <> 0) then
   CloseHandle(hMappedFile);
  MappingExists := False;
end;

end.
2. DLL module code (sample, feel free to modify it)
Code:
library HooksLib;
uses
  SysUtils, Messages, Windows, UShared;

function ADebugProc(nCode : Integer; wParam : WPARAM; lParam: LPARAM):LRESULT;stdcall;
var
  DHI : PDEBUGHOOKINFO;
begin
  Result := -1;
  DHI := PDEBUGHOOKINFO(lParam);
  case nCode of
   WH_DEBUG:
   begin
     if (DHI^.idThread = SharedData^.MyThreadID)then
      Result := CallNextHookEx(SharedData^.hDebugHook, DHI^.code, DHI^.wParam, DHI^.lParam);
   end
 end;
end;

exports
  ADebugProc    index 1 name 'ADebugProc'{,
  AMouseProc    index 2 name 'AMouseProc'};


{$R *.RES}

procedure LibraryProg(Reason: Integer);
begin
 case Reason of
   DLL_PROCESS_ATTACH  : CreateOrOpenMemShare();
   DLL_PROCESS_DETACH  : CloseMemShare();
 end;
end;

begin
  DLLProc := @LibraryProg;
  LibraryProg(DLL_PROCESS_ATTACH);
end.
3. Now how to install from hook from your application.
Code:
unit ...;

interface

uses ..., UShared;

{const
  WM_HOOKEVENT   = WM_USER + 300;}

type
  Tfr... = class(TForm)
  ...
  end;

  function SetHooks(): Boolean;
  procedure RemoveHooks();

var
  fr...: Tfr...;
  AHooksLibrary : Cardinal;

implementation

function SetHooks(): Boolean;
var
  AHookProc   : THookProc;
  TrackProcessID: Cardinal;
begin
  Result := False;
  AHooksLibrary := LoadLibrary('HooksLib.dll');
  if (AHooksLibrary = 0) then
  begin
    ShowMessage('Library not found');
    Exit;
  end;
  AHookProc := nil;
  @AHookProc := GetProcAddress(AHooksLibrary, 'ADebugProc');
  if (Assigned(@AHookProc)) then
  begin
    SharedData^.hDebugHook := SetWindowsHookEx(WH_DEBUG, @AHookProc, AHooksLibrary, GameThreadID {0});
// Game ThreadID is obtained from  PROCESS_INFORMATION structure after CreateProcess.
    Result := True;
  end
  else
  begin
    FreeLibrary(AHooksLibrary);
    AHooksLibrary := 0;
    ShowMessage('Failed to setup hook');
    Exit;
  end;
end;

procedure RemoveHooks();
begin
  UnHookWindowsHookEx(SharedData^.hDebugHook);
  FreeLibrary(AHooksLibrary);
  AHooksLibrary := 0;
end;

procedure Tfr....Button1Click(Sender: TObject);
begin
  if SetHooks() then
   ShowMessage('ok');
end;

procedure Tfr....Button2Click(Sender: TObject);
begin
  RemoveHooks();
end;
Damn, I hope this would help. Cheers.

--- McMerfy
 
Man, I'm sorry for my poor explanation, but thank you for being so kind to write all this code for me! And I'm sure that all of the fair playing gaming community will greatly appreciate all your efforts too! Should you want to see our community, here's a link to it! :-D
Thank you so much again,

[bobafett] BobbaFet [bobafett]

Everyone has a right to my opinion.
E-mail me at caswegkamp@hotmail.com
Great Delphi Websites faq102-5352
 
Man I've really put in the effort and I just cannot get this code to work, I keep getting access violations and I cant find where the problem lies.

[bobafett] BobbaFet [bobafett]

Everyone has a right to my opinion.
E-mail me at caswegkamp@hotmail.com
Great Delphi Websites faq102-5352
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top