Hook when any file is closed

c++ / delphi package - dll injection and api hooking
Post Reply
andrewc
Posts: 5
Joined: Mon Jun 28, 2004 9:25 am

Hook when any file is closed

Post by andrewc »

I want to find out when any file on the machine is closed.

These shell change notifiers don't seem to work very well so I am thinking about hooking the CloseHandle API.

Am I going about this the right way ?

Also is there any way to find out if a THandle is a file handle and if so how to get the filename from it.

Another thing, what happens if someone else's program also hooks the same API ?

Thanks for any help.
Claes
Posts: 52
Joined: Thu Apr 22, 2004 10:52 pm
Location: Denmark

Post by Claes »

I did a silimar thing this way: Hook CreateFile, build a list of Handles to files created and then hook CloseHandle, see if the Handle of CloseHandle is in your list. I can post my code, if you are interested?
andrewc
Posts: 5
Joined: Mon Jun 28, 2004 9:25 am

Post by andrewc »

I have just come to the same conclusion. Hook all versions of CreateFile and keep a list of Handles. Then hook CloseHandle and if its in my list I send IPC to my app with the filename. I have a working test program now.

My big worry is that I assume CloseHandle will be used rather a lot for many things so will it slow the system down to be scanning my list of handles every time it gets called ?

It would be interesting to see your code.

Also what happens of some other app decides to try and hook these API calls also ?
Claes
Posts: 52
Joined: Thu Apr 22, 2004 10:52 pm
Location: Denmark

Post by Claes »

My hook isn't systemwide, I hook only ONE specific app. So I don't know about overhead, although I think you may be right that IS quite an overhead! And you may experience a systemlockups, as your app will prolly use CreateFile too. Also, my code only hooks CreateFileA. For a systemwide hook, you may need to hook CreateFileW as well. Anyhow, here is the code - I hope you find it useful.

Code: Select all

library Hook;

uses
  Windows,
  Classes,
  SysUtils,
  madCodeHook,
  madStrings,
  HookInit;

{$R *.res}

var
  CreateFileNext: function(lpFileName: PAnsiChar; dwDesiredAccess, dwShareMode: DWORD;
    lpSecurityAttributes: PSecurityAttributes; dwCreationDisposition, dwFlagsAndAttributes: DWORD;
    hTemplateFile: THandle): DWORD; stdcall;
  CloseHandleNext: function(hObject: THandle): BOOL; stdcall;

function CreateFileCallback(lpFileName: PAnsiChar; dwDesiredAccess, dwShareMode: DWORD;
  lpSecurityAttributes: PSecurityAttributes; dwCreationDisposition, dwFlagsAndAttributes: DWORD;
  hTemplateFile: THandle): DWORD; stdcall;
begin
  Result :=
    CreateFileNext(lpFileName,
                   dwDesiredAccess,
                   dwShareMode,
                   lpSecurityAttributes,
                   dwCreationDisposition,
                   dwFlagsAndAttributes,
                   hTemplateFile);

  if not Closing then
    if IsTextEqual(ExtractFilePath(lpFileName), SaveDir) then
      if Files.IndexOfObject(TObject(Result)) < 0 then
        Files.AddObject(lpFileName, TObject(Result));
end;

function CloseHandleCallback(hObject: THandle): BOOL; stdcall;
var
  I: Integer;
begin
  if not Closing then
  begin
    I := Files.IndexOfObject(TObject(hObject));
    if I >= 0 then
    begin
      StrPCopy(MessageBuf.FileName, Files.Strings[I]);
      MessageBuf.FileHandle := DWORD(Files.Objects[I]);
      Files.Delete(I);
      SendIpcMessage(DLLName, @MessageBuf, SizeOf(MessageBuf));
    end;
  end;

  Result := CloseHandleNext(hObject);
end;

begin
  HookAPI('kernel32.dll', 'CreateFileA', @CreateFileCallback, @CreateFileNext);
  HookAPI('kernel32.dll', 'CloseHandle', @CloseHandleCallback, @CloseHandleNext);
end.
I use an initialization unit, that sets the global var Closing. Without this variable, the code will crash when you exit the targetapp. This unit is also responsible for creating and freeing the list of files.

Code: Select all

unit HookInit;

interface

uses
  Windows, Classes, SysUtils, AnotherUnit;

type
  TMessageBuf = record
    FileName: array [0..MAX_PATH] of Char;
    FileHandle: DWORD;
  end;

const
  DLLName = 'Hook.dll';
  
var
  Files: TStringList;
  MessageBuf: TMessageBuf;
  SaveDir: string;
  Closing: Boolean;

implementation

initialization
  Closing := False;
  Files := TStringList.Create;
  SaveDir := IncludeTrailingPathDelimiter(AnotherUnit.GetDir);

finalization
  Closing := True;
  Files.Free;

end.
madshi
Site Admin
Posts: 10754
Joined: Sun Mar 21, 2004 5:25 pm

Post by madshi »

When hooking APIs like CreateFile + CloseHandle system wide you have to very careful with what you do. Performance might be a problem, if your hook callback functions do too much work. The hook itself should not be a problem, though. Please make sure that you follow all hooking rules (see madCodeHook documentation). Also don't transport each and every call via SendIpcMessage. madCodeHook's IPC message functions do work, but they're not the fasting thing on earth.
Post Reply