Based EasyHook implement monitoring explorer Explorer file copy, delete, cut and other operations

I. Introduction

Recent himself in the study of a project need to implement monitoring of the explorer Explorer file operations, online to find some method ++ implementation Hook explorer file operations by C, because I used to use .NET development program, coupled with the C / C ++ base worse, it has been studying how to use .NET implementation, spent a week's time, finally realized the basic functionality through C # Hook Explorer file operations, here are some of the core content for your reference.

Two, EasyHook

1. Introduction

EasyHook is linked to a powerful engine, free open-source, 64-bit support, by calling .NET languages (such as C #, VB.NET), related to use and download the source code can refer to the official website: http : //easyhook.github.io/

2. remote injection

we here need to realize remote injection explorer program Hook Explorer features, so we must first look at EasyHook remote injection (remote Hooking) function, the official website there is a remote file monitoring tutorials, you can refer: http: //easyhook.github.io/tutorials/remotefilemonitor.html

briefly summarize: remote injection function realization involves two steps need to build two projects, one is to create an injection payload, which is the need to create injected into other processes library (.dll) file; the second is to create a main program to achieve the first step in generating the dll injected into other processes and monitoring capabilities.

A step used two major classes, and serverInterface InjectionEntryPoint (customizable class name), which realize a communication function between serverInterface dll and the main injection after the target process, need to inherit MarshalByRefObject class; InjectionEntryPoint for local installation and Hook Hook calling user-defined logic functions need to inherit EasyHook.IEntryPoint interfaces, constructors and including the Run method is successful, the Run method constructor parameter must be the same, these parameters can be passed at a remote main injection, number of parameters limit, can be customized according to specific needs. For example, I here main handle and process ID as parameters:
          // Constructors

public InjectionEntryPoint (EasyHook.RemoteHooking.IContext context, String channelName, passPID int, int passHandle)
        {
           _SERVER = EasyHook.RemoteHooking.IpcConnectClient <serverInterface> (channelName );
            _server.Ping ();
        }

  // the Run function
        public void the Run (EasyHook.RemoteHooking.IContext context, String channelName, passPID int, int passHandle)
        {

// implemented here after a local call users to install and hook hook function successfully self-defined functions

}

Step two is to create the main program, the main achievement function remote injection and monitor display parameters can be passed in accordance with the definition of a step when injected into the core the following code:

   // the using the Create The Server The FileMonitorIPC.ServiceInterface the IPC class AS A Singleton
        EasyHook.RemoteHooking.IpcCreateServer <FileMonitorHook.ServerInterface> (REF channelName, System.Runtime.Remoting.WellKnownObjectMode.Singleton);
        String injectionLibrary Path.Combine = ( Path.GetDirectoryName (System.Reflection.Assembly.GetExecutingAssembly () Location.) , "FileMonitorHook.dll"); //FileMonitorHook.dll step of generating a library file is referenced in a main program Engineering EasyHook.RemoteHooking .inject (targetPid, // ID of Process to Inject INTO
                    injectionLibrary, Library // 'bit to 32-Inject (IF' bit target IS-32)
                    injectionLibrary, Library // 'bit to 64-Inject (IF' bit target IS-64)
                    channelName, // The INTO Pass Parameters to Injected Library
                     passPID,
                    passHandle // these two steps for a custom parameter, according to the demand can be further increased ...
                );

three, IFileOperation interfaces

explorer WIN7 and above implementation file system operation skip the API layer but instead by the COM, the COM interface is IFileOperation.

For details on IFileOperation interface can refer to the Microsoft official document: https: //docs.microsoft.com/zh-cn/windows/desktop/api/shobjidl_core/nn-shobjidl_core-ifileoperation;

the Internet has great God uses C ++ implementation of the interface Hook IFileOperation may refer to: https: //blog.csdn.net/wzsy/article/details/17665311

for file operation monitoring function requires the following main Hook IFileOperation interface (C # shown):

copied: void CopyItems (
               IntPtr punkItems,
              IntPtr psiDestinationFolder);

deleted: void DeleteItems (
             IntPtr punkItems);

Cut: void MoveItems (
               IntPtr punkItems,
              IntPtr psiDestinationFolder);

Tested CopyItem, DeleteItem, MoveItem the singular can not be achieved hook, may be the explorer did not call these functions.

Four, EasyHook implement COM interfaces Hook

online about EasyHook official introduction and tutorial are based Hook API function, for example, to introduce COM interfaces Hook little, which also plagued a relatively long period of time, back in EasyHook github official homepage questions area to find a clue, plus some of their own research, be basically mastered the method of implement COM interfaces hook.

Implemented method comprises two main steps:

Step a guid according to define classes and interfaces of the COM interface itself belongs, the interface ID and class ID can be viewed by the specific name in c ++ header file name format as CLSID_IFileOperation, IID_IFileOperation. In C # is defined as follows:

 #region IFileOperation
        [the ComVisible (to true)]
        [the Guid ( "3ad05575-8857-4850-9277-11b85bdb8e09")]
        CLSID_IFileOperation class public
        {

// content of their class interfaces may be empty, only the position of the interface to facilitate subsequent determination by the API EasyHook
        }
        [the ComImport]
        [the Guid ( "947aab5f-0a5c-4c13-b4d6-4bf7836fc9f8")]
        [the InterfaceType (ComInterfaceType.InterfaceIsIUnknown )]
        public interface IID_IFileOperation
        {
            uint the Advise (IntPtr pfops, IntPtr The pdwCookie);
            void Unadvise (uint dwCookie);
            void SetOperationFlags (IntPtr dwOperationFlags);
            void SetProgressMessage (
              [the MarshalAs (UnmanagedType.LPWStr)] String pszMessage);
            void SetProgressDialog (
              [the MarshalAs (UnmanagedType.Interface)] object popd);
            void SetProperties(
              [MarshalAs(UnmanagedType.Interface)] object pproparray);
            void SetOwnerWindow(uint hwndParent);
            void ApplyPropertiesToItem(IntPtr psiItem);
            void ApplyPropertiesToItems(
              [MarshalAs(UnmanagedType.Interface)] object punkItems);
            void RenameItem(IntPtr psiItem,
              [MarshalAs(UnmanagedType.LPWStr)] string pszNewName,
               IntPtr pfopsItem);
            void RenameItems(
             IntPtr pUnkItems,
              [MarshalAs(UnmanagedType.LPWStr)] string pszNewName);
            void MoveItem(
              IntPtr psiItem,
               IntPtr psiDestinationFolder,
              [MarshalAs(UnmanagedType.LPWStr)] string pszNewName,
              IntPtr pfopsItem);
            void MoveItems(
               IntPtr punkItems,
              IntPtr psiDestinationFolder);
            void CopyItem(
              IntPtr psiItem,
               IntPtr psiDestinationFolder,
              [MarshalAs(UnmanagedType.LPWStr)] string pszCopyName,
              IntPtr pfopsItem);
            void CopyItems(
               IntPtr punkItems,
              IntPtr psiDestinationFolder);
            void DeleteItem(
              IntPtr psiItem,
               IntPtr pfopsItem);
            DeleteItems void (
             IntPtr punkItems);
            uint NewItem (
              IntPtr psiDestinationFolder,
              IntPtr dwFileAttributes,
              [the MarshalAs (UnmanagedType.LPWStr)] String pszName,
              [the MarshalAs (UnmanagedType.LPWStr)] String pszTemplateName,
              IntPtr pfopsItem);
            Long PerformOperations ();
            [return: the MarshalAs (UnmanagedType.Bool)]
            BOOL GetAnyOperationsAborted ();
        }
        #endregion

step two is determined by the position of the interface and to install the hook EasyHook API, copy the file to install hooks to monitor, for example, the main code is as follows:

   / * ** copy the files hook /
            = New new copyItemscom the COMClassInfo the COMClassInfo (typeof (CLSID_IFileOperation), typeof (IID_IFileOperation), "CopyItems"); //
            copyItemscom.Query ();
            var = CopyItemsHook EasyHook.LocalHook.Create (copyItemscom.MethodPointers [0], new new CopyItems_Delegate (CopyItemsHooked) , the this);
            // activate hook
            CopyItemsHook.ThreadACL.SetExclusiveACL (new Int32 [] {0 });

wherein CopyItems_Delegate copied file is a delegate function, defined as follows:
        [UnmanagedFunctionPointer (CallingConvention.StdCall, the CharSet = CharSet.Unicode, the SetLastError to false =)]
        public void CopyItems_Delegate the delegate (IID_IFileOperation Self, IntPtr punkItems,
           IntPtr psiDestinationFolder); // where the first interface instance parameters to be passed, in order to call the original can be copied in alternative copy function hook function, to achieve It does not affect the original purpose of the operation.

CopyItemsHooked for the successful execution Hook replacement copy function, the parameters and copy the files entrusted consistent function, which is the key to monitoring of file operations, the next section will focus on.

Fifth, file operations after Hook successfully replaced implement and analytic functions of

file operations after Hook success will perform new functions we replace such CopyItemsHooked previously described, in the function can be used to call the original function through the interface instance to perform the original operation, its function structure is as follows:

 public void CopyItemsHooked (IID_IFileOperation Self, IntPtr punkItems, IntPtr psiDestinationFolder)
        {
          self.CopyItems (punkItems, psiDestinationFolder); // perform primitive operations, calls may not achieve the object phrase to intercept file operations
        }

we want to implement file operations monitoring, it is necessary to carry out this function parses the incoming parameters, see Microsoft's official documentation can be found in the prototype CopyItems is: HRESULT CopyItems (IUnknown * punkItems, IShellItem * psiDestinationFolder);

which is punkItems IUnknown interface type, it may be IShellItemArray, IDataObject , a certain kind of IEnumShellItems or IPersistIDList, psiDestinationFolder is IShellItem interface type.

C # then we can get the information directly to the files it? I'm afraid not, at least I will not. There is also plagued some time back and finally thought of the solution of: .NET direct impossible to achieve resolve, C ++ always be right, relevant analytical method to be written in C ++, then the class library dll, then C # to call C ++ generated library is not on it.

It should acquire knowledge in C ++ C # class library that can be called, do not understand the students can refer to the article: https: //www.cnblogs.com/94cool/p/5772376.html

should be noted that the generated C ++ dll 32-bit and 64-bit to distinguish, can create two different platforms (Win32 and X64) dll file, to achieve compatibility purposes, as illustrated in FIG, I used the Unicode encoding code, so that the character set is configured to use Unicode character set.

Man of few words said on the code.

Get IShellItem interface file information Function:

LPWSTR the __stdcall GetDestFloderName (IShellItem * psiDestinationIntptr)

{

    IShellItem * psiDestinationFolder = (IShellItem *) (psiDestinationIntptr);
    LPWSTR lpDst = NULL;

    psiDestinationFolder-> GetDisplayName (SIGDN_FILESYSPATH, & lpDst);
    return lpDst;
}

obtain the replication shear file IUnknown interface functions file information (via IUnknown test copy, cut files interface IPersistIDList):
The __stdcall GetSrcFloderName LPWSTR (the IUnknown IUnknown *)

{
    IPersistIDList iPersistIDList * = NULL;
    the HRESULT HR = IUnknown-> the QueryInterface (IID_IPersistIDList, (void **) & iPersistIDList); // Find IPersistIDList interface via the interface IUnknown
    PIDLIST_ABSOLUTE abSourcePidl;
    HR = iPersistIDList-> GetIDList (& abSourcePidl);
    TCHAR tchPath [255];
    SHGetPathFromIDList (abSourcePidl, tchPath);
    return tchPath;

}

Further delete, rename files IUnknown interface are different, tested delete files IUnknown interface of the IDataObject, rename the file IUnknown interface IShellItemArray , implementations are similar (IDataObject file information analysis is relatively complex, previously the third link tutorial provides a corresponding analytic function), which are not listed in 8111.

Attach parsing library header files:

#include "stdafx.h"
#include <SHLOBJ.H>
#include <String>
#include <shellapi.h>
STD :: String the using;
the using STD :: wstring;
typedef WCHAR wpath [the MAX_PATH];
extern "C" _declspec (dllexport) LPWSTR the __stdcall GetDestFloderName (IShellItem * psiDestinationIntptr);
extern "C" _declspec (dllexport) LPWSTR the __stdcall GetSrcFloderName (the IUnknown * punkItems);
extern "C" _declspec (dllexport) LPWSTR __stdcall GetDeleteFileName (the IUnknown * punkItems);
extern "C" _declspec (dllexport) LPWSTR __stdcall GetRenameSrcFloderName (the IUnknown * punkItems)

after C ++ class library generate success, how to call in a C # program it ? C # DllImport used herein to call external functions dll (C ++ in C # LPWSTR directly correspond to the sting), part of the code as follows:

    // Call 64 dll
        [the DllImport ( "MyConvert64.dll", the EntryPoint = "GetDestFloderName", the CharSet = CharSet.

        [The DllImport ( "MyConvert64.dll", the EntryPoint = "GetSrcFloderName", the CharSet = CharSet.Unicode)]
        extern static IntPtr GetSrcFloderName64 (IntPtr psiIntptr);

 // call the 32-bit DLL
        [the DllImport ( "MyConvert32.dll", the EntryPoint = "GetDestFloderName ", the CharSet = CharSet.Unicode)]
        extern static String GetDestFloderName32 (IntPtr psiIntptr);
        [the DllImport (" MyConvert32.dll ", the EntryPoint =" GetSrcFloderName ", the CharSet = CharSet.Unicode)]

extern static IntPtr GetSrcFloderName32 (IntPtr psiIntptr);

where the function name can be customized, just to ensure consistency with the terms EntryPoint function name in the dll function. So how do you let the program automatically select different functions according to the median system do? Can be achieved:

  public static String GetDestFloderName (IntPtr psiIntptr)
        {
            ? return Environment.Is64BitOperatingSystem GetDestFloderName64 (psiIntptr): GetDestFloderName32 (psiIntptr);
        }
 public static IntPtr GetSrcFloderName (IntPtr psiIntptr)
        {
            return Environment.Is64BitOperatingSystem GetSrcFloderName64 (psiIntptr):? GetSrcFloderName32 (psiIntptr);
        }

so we can hook after the success of replace function using analytic functions written in C ++, and to copy files hook function as an example:

public void CopyItemsHooked (IID_IFileOperation Self, punkItems IntPtr,
              IntPtr psiDestinationFolder)
        {
            the try
            {
                String filename = GetDestFloderName (psiDestinationFolder); // call the function to get the analytical target folder information
                IntPtr srcintptr = GetSrcFloderName (punkItems); // here for a source file pointer is returned
                string ss = Marshal.PtrToStringUni (srcintptr); // can convert to string pointer information, note the Unicode encoding
                operationtag = "Copy File -messagesplit - "+ SS +" -messagesplit- "+ filename;
                self.CopyItems (punkItems, psiDestinationFolder); // perform original operations
                _server.ReportMessage (selfhandle," start -messagesplit- "+ operationtag); // copy is transmitted to the main program the operation information file

            }
            the catch (exception EE)
            {
                _server.ReportMessage (selfhandle, ee.ToString ()); // exception handling

            }
        }

six, file operations Hook effect

After completing Injection payload (that is, remote injection of dll) to create, create a main program according to the introduction above for remote injection and monitoring functions, explorer process ID can be obtained through the following code: Process.GetProcessesByName ( "explorer") [0] .Id; see section II or remote injection operation EasyHook official reference document. In explorer can realize the control to the main program file operations after completion of the remote operation of the injection, the effect shown below.

7 Conclusion

EasyHook does make Hook become Easy, gave me great help, thank the selfless dedication of the development team. The above code for my part in the actual project, ideographic first, not necessarily directly, writing this article is designed to allow readers to deepen their understanding of EasyHook, hoping to help.



Original link: https: //blog.csdn.net/weixin_42011520/article/details/84193237

Guess you like

Origin www.cnblogs.com/code1992/p/11374884.html