Post Reply  Post Thread 
Pages (3): « First [1] 2 3 Next > Last »
Understanding how hooks work ?
Author Message
Mythar
Junior Member
**


Posts: 15
Group: Registered
Joined: Jul 2009
Status: Offline
Reputation: 0
Post: #1
Understanding how hooks work ?

Hi, tryed to get a hook up and running but failed, so now i got interested in how it actaly works hehe.

I looked through the codehook source etc. but found that it was pretty hard to figure out how the hook was set, so i wanted to try and make a "simple" sample.

Looking around the web, and translating some c++ code (c++ not my strong side).

Anyways this is what i came up with, not getting any errors but the hook dose not work.

Code:
Type
  TJMPCode = array[0..6] of Byte;

  TApiHookStruct = record
    ApiModuleName : PCHAR;
    ApiName       : PCHAR;
    ApiProc       : Pointer;
    ApiFiveByte   : TJMPCode;
    HookProc      : Pointer;
    HookFiveByte  : TJMPCode;
  End;

Const ZeroJMPCode : TJMPCode = (0, 0, 0, 0, 0, 0, 0);

var  gHook : TApiHookStruct;

procedure MakeJMPCode(Var lpJMPCode : TJMPCode; lpCodePoint : pointer);
Var
    temp : byte;
    wHiWord : WORD;
    wLoWord : WORD;
    wCS : WORD;
Begin
    wHiWord := HIWORD( DWORD(lpCodePoint) );
    wLoWord := LOWORD( DWORD(lpCodePoint) );

    asm
      push eax;
      push cs;
      pop  eax;
      mov  wCS, ax;
      pop  eax;
    end;

    lpJMPCode[0] := $ea;

    temp := LOBYTE(wLoWord);
    lpJMPCode[1] := temp;
    temp := HIBYTE(wLoWord);
    lpJMPCode[2] := temp;
    temp := LOBYTE(wHiWord);
    lpJMPCode[3] := temp;
    temp := HIBYTE(wHiWord);
    lpJMPCode[4] := temp;
    temp := LOBYTE(wCS);
    lpJMPCode[5] := temp;
    temp := HIBYTE(wCS);
    lpJMPCode[6] := temp;
End;

function Hook(Var ApiHook : TApiHookStruct) : boolean;
Var
  dwReserved : DWORD;
  dwTemp     : DWORD;
Begin
  Result := False;

  if not assigned(ApiHook.ApiProc) then
     ApiHook.ApiProc := GetProcAddress(GetModuleHandle(ApiHook.ApiModuleName), ApiHook.ApiName);

  if ApiHook.HookFiveByte[0] = 0 then
     MakeJMPCode(ApiHook.HookFiveByte, ApiHook.HookProc);

  if not VirtualProtect(ApiHook.ApiProc, 16, PAGE_READWRITE, @dwReserved) then exit;

  if IsBadWritePtr(ApiHook.ApiProc, 7) then
  Begin
     VirtualProtect(ApiHook.ApiProc, 16, dwReserved, @dwTemp);
     exit;
  End;

  move(ApiHook.HookFiveByte, ApiHook.ApiProc^, 7);

  if not VirtualProtect(ApiHook.ApiProc, 16, dwReserved, @dwTemp) then exit;

  Result := True;
End;

function UnHook(ApiHook : TApiHookStruct) : boolean;
Var
  dwReserved : DWORD;
  dwTemp     : DWORD;
Begin
  Result := False;

  if not assigned(ApiHook.ApiProc) then exit;

  if not VirtualProtect(ApiHook.ApiProc, 16, PAGE_READWRITE, @dwReserved) then exit;

  if IsBadWritePtr(ApiHook.ApiProc, 7) then
  Begin
     VirtualProtect(ApiHook.ApiProc, 16, dwReserved, @dwTemp);
     exit;
  End;

  move(ApiHook.ApiFiveByte, ApiHook.ApiProc^, 7);

  if not VirtualProtect(ApiHook.ApiProc, 16, dwReserved, @dwTemp) then exit;

  Result := True;
End;

procedure HookProc;
begin
  gHook.ApiModuleName := 'DInput8.dll';
  gHook.ApiName := 'DirectInput8Create';
  gHook.ApiProc := nil;
  gHook.ApiFiveByte := ZeroJMPCode;
  gHook.HookProc := @NewDirectInput8Create;
  gHook.HookFiveByte := ZeroJMPCode;
  Hook(gHook);
end;

procedure UnhookProc;
begin
  UnHook(gHook);
end;


Trying to figure out the "magic" behind CodeHook Smile

This post was last modified: 08-09-2009 05:53 AM by Mythar.

08-09-2009 05:51 AM
Find all posts by this user Quote this message in a reply
Qi
Administrator
*******


Posts: 46
Group: Administrators
Joined: Oct 2007
Status: Offline
Reputation: 0
Post: #2
RE: Understanding how hooks work ?

Hello Mythar,

You C++ code is a little same as the Raw Mode in CodeHook, though Raw Mode is a little more complicated. Your C++ is the very basic hook method.

CodeHook supports Raw Mode and Advance Mode.

In brief, Raw Mode is a method that simply redirect the target function to your hook function, so your hook function prototype should be exactly same as target, such as parameter count and types, calling conventions, etc.

Advance Mode is that CodeHook puts some bridge code between the target and hook function, so the hook function can has different prototype with target.

To understand how CodeHook works, it requires a lot of knowledge on Assembly language and knowing deeply how compiler generates code.

To help you to sort out your problem, I suggest,
1, You'd better read over the help document in CodeHook. Though there is no much details inside CodeHook, it will help you to understand how it works.
2, Paste your code that using CodeHook, include the target and hook function. The C++ code you pasted here makes no sense to CodeHook.
3, If you can read disassembly code, you can use Delphi debugger to disassembly the code generated by CodeHook, that will give you really intuitive understanding of how it works.

This post was last modified: 08-09-2009 08:42 PM by Qi.

08-09-2009 08:38 PM
Visit this users website Find all posts by this user Quote this message in a reply
Mythar
Junior Member
**


Posts: 15
Group: Registered
Joined: Jul 2009
Status: Offline
Reputation: 0
Post: #3
RE: Understanding how hooks work ?

The Code i tryed as a test :

Code:
unit Unit1;

interface

uses
  Windows,
  Messages,
  SysUtils,
  Classes,
  Graphics,
  Controls,
  Forms,
  Dialogs,
  StdCtrls,
  ComObj,
  DirectInput9,
  CodeHook,
  CodeHookIntf;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Memo: TMemo;
    Button3: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  gCodeHook: ICodeHook;
  gCodeHookHelper: ICodeHookHelper;


implementation

{$R *.DFM}

type
  keyBufferPtr=^keyBuffer;
  keyBuffer = array[0..255] of byte;

Var
  lDirectInput8Create: TCodeHookHandle;
  origDirectInput8Create: function(hinst: THandle; dwVersion: LongWord; const riidltf: TGUID; out ppvOut; punkOuter: IUnknown): HResult; stdcall;

  lCreateDevice: TCodeHookHandle;
  origCreateDevice: function(slf: pointer; const rguid: TGUID; out lplpDirectInputDevice: IDirectInputDevice8; pUnkOuter: IUnknown): HResult; stdcall;

  lGetDeviceState: TCodeHookHandle;
  origGetDeviceState: function(slf: pointer; const cbData: LongWord; lpvData: Pointer): HResult; stdcall;

Const
  OFFSET_CREATEDEVICE   = 12;
  OFFSET_GETDEVICESTATE = 36;

function GetInterfaceMethod(const intf; vmtOffset: dword): pointer;
begin
  result := pointer(pointer(dword(pointer(intf)^) + vmtOffset)^);
end;

function NewGetDeviceState(slf: pointer; const cbData: LongWord; lpvData: Pointer): HResult; stdcall;
var
  buf : keyBufferPtr;
begin
  Result := origGetDeviceState(slf,cbData,lpvData);
  buf := lpvData;
  buf^[DIK_UP] := 128;
end;

function NewCreateDevice(slf: pointer; const rguid: TGUID; out lplpDirectInputDevice: IDirectInputDevice8A; pUnkOuter: IUnknown): HResult; stdcall;
var
  funcAdr: pointer;
  lHookInfo: TCodeHookInfo;
begin
  Result := origCreateDevice(slf, rguid, lplpDirectInputDevice, pUnkOuter);

  if GUIDToString(rguid) = GUIDToString(GUID_SysKeyboard) then
  begin
    funcAdr := GetInterfaceMethod(lplpDirectInputDevice, OFFSET_GETDEVICESTATE);

    lGetDeviceState := GCodeHook.Hook(funcAdr, @NewGetDeviceState);
    GCodeHook.GetHookInfo(lGetDeviceState, @lHookInfo);
    @origGetDeviceState := lHookInfo.PreviousMethod;
  end;

end;

function NewDirectInput8Create(hinst: THandle; dwVersion: LongWord; const riidltf: TGUID; out ppvOut; punkOuter: IUnknown): HResult; stdcall;
var
  funcAdr: pointer;
  lHookInfo: TCodeHookInfo;
begin
  Result := origDirectInput8Create(hinst, dwVersion, riidltf, ppvOut, punkOuter);

  funcAdr := GetInterfaceMethod(ppvOut, OFFSET_CREATEDEVICE);

  lCreateDevice := GCodeHook.Hook(funcAdr, @NewCreateDevice);
  GCodeHook.GetHookInfo(lCreateDevice, @lHookInfo);
  @origCreateDevice := lHookInfo.PreviousMethod;
end;

procedure HookDirectInput8Create;
var
  funcAdr: pointer;
  lHookInfo: TCodeHookInfo;
begin
  funcAdr := GetProcAddress(GetModuleHandle('DInput8.dll'), 'DirectInput8Create');
  lDirectInput8Create := GCodeHook.Hook(funcAdr, @NewDirectInput8Create);
  GCodeHook.GetHookInfo(lDirectInput8Create, @lHookInfo);
  @origDirectInput8Create := lHookInfo.PreviousMethod;
end;

procedure UnHookDirectInput8Create;
Begin
  gCodeHookHelper.UnhookAll;
End;

procedure TForm1.FormCreate(Sender: TObject);
begin
  gCodeHook := GetCodeHookIntf;
  gCodeHook.GetCodeHookHelper(gCodeHookHelper);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  HookDirectInput8Create;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  UnHookDirectInput8Create;
end;

end.

08-09-2009 09:38 PM
Find all posts by this user Quote this message in a reply
Qi
Administrator
*******


Posts: 46
Group: Administrators
Joined: Oct 2007
Status: Offline
Reputation: 0
Post: #4
RE: Understanding how hooks work ?

Hello Mythar,

I've just done a quick test on your code and no problem was found.
But I didn't run the hooked function since I don't have DInput8.pas

By seeing your code, seems GetInterfaceMethod is problematic and it should be
result := pointer(ppointer(dword(ppointer(intf)^) + vmtOffset)^);
Could you give you try?

And what's the error information, and what's the stack trace?

08-09-2009 11:32 PM
Visit this users website Find all posts by this user Quote this message in a reply
Mythar
Junior Member
**


Posts: 15
Group: Registered
Joined: Jul 2009
Status: Offline
Reputation: 0
Post: #5
RE: Understanding how hooks work ?

Hi Qi, tryed to use ppointer, no change, not getting any errors, it just dont work.

Made a zip file with DInput9.pas (name dont matter its still ver 8), zip file contains the hole project.

Also inc. the Keyboard.exe from the DX SDK, for test.

This post was last modified: 08-20-2009 07:01 PM by Mythar.

08-10-2009 02:35 AM
Find all posts by this user Quote this message in a reply
Qi
Administrator
*******


Posts: 46
Group: Administrators
Joined: Oct 2007
Status: Offline
Reputation: 0
Post: #6
RE: Understanding how hooks work ?

Hello Mythar,

Can you debug it to see what happens in the hook function (NewDirectInput8Create)? Such like the return value from DX or the second hook?
According to my test, seems the hooking is correct, so there may be something wrong in the hook function.

08-10-2009 12:29 PM
Visit this users website Find all posts by this user Quote this message in a reply
Mythar
Junior Member
**


Posts: 15
Group: Registered
Joined: Jul 2009
Status: Offline
Reputation: 0
Post: #7
RE: Understanding how hooks work ?

Hi Qi,

The NewDirectInput8Create never gets called, its like the hook aint there.

Oh wait, im running Windows 7 rc x64, could that be the problem ?

(Your CodeHookTest sample dose seem to work tho)

Tryed running the Apihijack c++ code, that dose work on W7.

08-10-2009 08:07 PM
Find all posts by this user Quote this message in a reply
Qi
Administrator
*******


Posts: 46
Group: Administrators
Joined: Oct 2007
Status: Offline
Reputation: 0
Post: #8
RE: Understanding how hooks work ?

Hello Mythar,

Hmmm... I never have test on Windows 7, especially it's a 64 bits system.
I only test CodeHook on WinXP, 32 bits.

But I'm not sure when I can get a copy of Windows 7 to test on.

Sorry for that.

08-11-2009 11:48 AM
Visit this users website Find all posts by this user Quote this message in a reply
Mythar
Junior Member
**


Posts: 15
Group: Registered
Joined: Jul 2009
Status: Offline
Reputation: 0
Post: #9
RE: Understanding how hooks work ?

Hi Qi,

did some more cheking, it turns out that your hook dose work ... well sort of ...
If you call the hooked function with in the program that creates the hook, the hook works, BUT if another program calls the hooked function it dose not.

I tryed adding the following code:

Code:
procedure TForm1.Button3Click(Sender: TObject);
Var  IDirectInput : IDirectInput8;
begin
  DirectInput8Create(HInstance, DIRECTINPUT_VERSION, IDirectInput8, IDirectInput, nil);

  if assigned(IDirectInput) then
  Begin
    Debug.Lines.Add('IDirectInput was assigned');
    IDirectInput := nil;
  End;
end;


If you launch the hook be4 calling the above code, the DirectInput8Create, dose get redirected to the NewDirectInput8Create, however if another program calles DirectInput8Create, it dose not get redirected to the NewDirectInput8Create.

Its like W7 executes the program in a shell and dose not make the hook global.

hmm, the apihijack sample dose the hooking from a dll, we might have to launch you CodeHook from a dll too, to make it global ?

If W7 is launching the hook in a shell, using the CodeHook.pas and not the dll, the hook might only be "global" with in the "shell".
So might try to use the CodeHook dll insted, as that would kinda load the dll into the W7's global "stack" to make the hook global ?

Dose this make any sence ?

PS: I think you can still DL the W7 rc from MS if you want to try it out.

This post was last modified: 08-11-2009 07:40 PM by Mythar.

08-11-2009 07:39 PM
Find all posts by this user Quote this message in a reply
Qi
Administrator
*******


Posts: 46
Group: Administrators
Joined: Oct 2007
Status: Offline
Reputation: 0
Post: #10
RE: Understanding how hooks work ?

Hello Mythar,

It sounds like you want to hook code that in other process? Such as that your program is A, you want to hook application B (which is maybe a game, etc)?
If it is, then CodeHook can't work directly for it because it can only perform in-process hook.

However, if you don't want to support Win98 (i.e, your target OS is Win2K up), you can use CreateRemoteThread to easily inject your DLL to the target process and you can do the hook in the DLL.

A google of CreateRemoteThread can give you bunch of examples of how to use it to inject DLL. It's quite easy.

08-12-2009 01:18 PM
Visit this users website Find all posts by this user Quote this message in a reply
Pages (3): « First [1] 2 3 Next > Last »
Post Reply  Post Thread 

View a Printable Version
Send this Thread to a Friend
Subscribe to this Thread | Add Thread to Favorites

Forum Jump: