C # simple tutorial on Hook principle and EasyHook,

Source: Internet
Author: User

C # simple tutorial on Hook principle and EasyHook,
Preface

Before talking about C # Hook, let's talk about Hook Technology. I believe everyone has been familiar with plug-ins. Whether it's about modifying the game client or stealing passwords, how are they implemented?

In fact, Windows is based on the event-driven mechanism, and the entire system is implemented through message transmission. When a process responds (including responding to mouse and keyboard events), Windows will send a message queue to the application, the application then extracts messages from the message queue and sends them to the corresponding window for processing.

The Hook is a platform for Windows Message Processing Mechanism. Applications can set sub-processes on the top to monitor a message in a specified window, And the monitored window can be created by other processes. When a message arrives, process it before the target window processing function. The hook mechanism allows applications to intercept and process window messages or specific events.

Therefore, the Hook can process the message after the keyboard/mouse responds and before the window processes the message, such as listening to keyboard input and mouse clicking coordinates. Some Trojans Hook a specified process to listen to the content entered by the keyboard and steal the account password.

C # Hook

We know that C # runs on the. NET platform and dynamically runs based on CLR. Therefore, only encapsulated functions can be operated and memory data cannot be operated directly. In addition, common functions of C # Do not encapsulate Hook-related classes and methods. Therefore, if C # is used to implement Hook, you must call WindowsAPI for implementation.

WindowsAPI functions are unmanaged functions. You must follow these steps when calling them:

1. Find the DLL containing the called function, such as User32.dll and Kernel32.dll.

2. Load the DLL to the memory and specify the entry

3. Convert the required parameter to the existing type of C #, for example, the pointer corresponds to Intptr, And the handle corresponds to the int type.

4. Call Functions

The following functions are required in this document:

SetWindowsHookEx is used to install hooks

UnhookWindowsHookEx is used to uninstall a hook.

CallNextHookEx executes the next hook

For API details, refer to the official MSDN statement.

In C #, You need to declare this API function first:

[DllImport("user32.dll",CharSet=CharSet.Auto,CallingConvention=CallingConvention.StdCall)]public static extern int SetWindowsHookEx(int idHook, HookProc lpfn,IntPtr hInstance, int threadId);[DllImport("user32.dll",CharSet=CharSet.Auto,CallingConvention=CallingConvention.StdCall)]public static extern bool UnhookWindowsHookEx(int idHook);[DllImport("user32.dll",CharSet=CharSet.Auto,CallingConvention=CallingConvention.StdCall)]public static extern int CallNextHookEx(int idHook, int nCode,IntPtr wParam, IntPtr lParam);

After the statement is declared, you can call it. SetWindowsHookEx () installs the Hook Program defined by an application to the Hook linked list. The SetWindowsHookEx function always installs the Hook Child Program at the beginning of the Hook chain. When a specified Hook monitoring event occurs, the system calls the Hook child program starting with the Hook chain associated with the Hook. The Hook sub-process in each Hook chain determines whether to pass the event to the next Hook sub-process. The CallNextHookEx function must be called when the Hook sub-process transmits an event to the next Hook sub-process. After the hook is used, you need to call UnhookWindowsHookEx to uninstall it. Otherwise, the execution of other Hooks is easily affected, and too many hooks will affect the normal operation of the target process.

For more information about the detailed operation process of the instance, see: http://blog.csdn.net/ensoo/article/details/2045101 and https://www.cnblogs.com/ceoliujia/archive/2010/05/20/1740217.html

EasyHook

C # the function of calling WindowsAPI to Hook itself is greatly restricted, while C ++ is not restricted. Therefore, some smart people think of a smart method: C ++ encapsulates basic operations into libraries and is called by C #. Therefore, EasyHook is a great tool that is not only easy to use, but also open-source and free, and supports 64-bit versions.

Next we will use C # To operate EasyHook to implement a Demo and rewrite MessageBox.

First, create a WinForm project program and add a class library ClassLibrary1:

   

The WinForm program is used to obtain the target process and inject the target process. The steps are as follows:

1. obtain the relevant process based on the process ID and determine whether the process is 64-bit;

2. register the required DLL to GAC (Global Assembly Cache). The purpose of registering to GAC is to call EasyHook and our compiled DLL in the target process;

private bool RegGACAssembly() {     var dllName = "EasyHook.dll";     var dllPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, dllName);     if (!RuntimeEnvironment.FromGlobalAccessCache(Assembly.LoadFrom(dllPath)))     {         new System.EnterpriseServices.Internal.Publish().GacInstall(dllPath);         Thread.Sleep(100);     }   dllName = "ClassLibrary1.dll";     dllPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, dllName);     new System.EnterpriseServices.Internal.Publish().GacRemove(dllPath);     if (!RuntimeEnvironment.FromGlobalAccessCache(Assembly.LoadFrom(dllPath)))     {           new System.EnterpriseServices.Internal.Publish().GacInstall(dllPath);           Thread.Sleep(100);     }     return true;  } 

Note that you need to write your own class library DLL to add GAC, You need to perform a strong signature operation on the DLL, the operation method please refer to: https://docs.microsoft.com/zh-cn/dotnet/framework/app-domains/how-to-sign-an-assembly-with-a-strong-name

3. Inject the target process. Here the RemoteHooking. Inject () method of EasyHook must be used for injection:

Private static bool InstallHookInternal (int processId) {try {var parameter = new HookParameter {Msg = "the target process has been successfully injected", HostProcessId = RemoteHooking. getCurrentProcessId ()}; RemoteHooking. inject (processId, InjectionOptions. default, typeof (HookParameter ). assembly. location, typeof (HookParameter ). assembly. location, string. empty, parameter);} catch (Exception ex) {Debug. print (ex. toString (); return false;} return true ;}
The HookParameter class is a class defined in ClassLibrary1, including the message and process ID:
 [Serializable]    public class HookParameter    {        public string Msg { get; set; }        public int HostProcessId { get; set; }    }

At this step, we have completed the compilation of the main form code. Now we are writing the method for injecting DLL:

1. First introduce MessageBox related WindowsAPI:

# Region MessageBoxW [DllImport ("user32.dll", EntryPoint = "MessageBoxW", CharSet = CharSet. unicode)] public static extern IntPtr MessageBoxW (int hWnd, string text, string caption, uint type); [UnmanagedFunctionPointer (CallingConvention. stdCall, CharSet = CharSet. unicode)] delegate IntPtr DMessageBoxW (int hWnd, string text, string caption, uint type); static IntPtr MessageBoxW_Hooked (int hWnd, string text, string caption, uint type) {return MessageBoxW (hWnd, "injected-" + text, "injected-" + caption, type) ;}# endregion # region MessageBoxA [DllImport ("user32.dll ", entryPoint = "MessageBoxA", CharSet = CharSet. ansi)] public static extern IntPtr MessageBoxA (int hWnd, string text, string caption, uint type); [UnmanagedFunctionPointer (CallingConvention. stdCall, CharSet = CharSet. ansi)] delegate IntPtr DMessageBoxA (int hWnd, string text, string caption, uint type); static IntPtr MessageBoxA_Hooked (int hWnd, string text, string caption, uint type) {return MessageBoxA (hWnd, "injected-" + text, "injected-" + caption, type) ;}# endregion

Among them, MessageBoxA and MessageBoxW are used by Microsoft to distinguish the encoding types in different operating systems. Earlier Windows did not belong to the true 32-bit operating system, and the executed API functions belong to the ANSI Type, starting from Windows2000, it belongs to the Unicode type. In Windows, the MessageBox that is called will automatically distinguish the former and the latter based on the platform. We need to include both of them here.

DMessageBoxA and DMessageBoxW belong to the IntPtr type delegate, which is used to input the method we need to modify after the Hook function. Here we change the content and title of MessageBox, the prefix is marked with "injected.

2. After the definition is complete, we need to Hook the function. LocalHook is used here. getProcAddress ("user32.dll", "MessageBoxW") function. Obtain the address of the function in the actual memory using the specified DLL and function name. create () method, used to Create a local HOOK:

public void Run(            RemoteHooking.IContext context,            string channelName            , HookParameter parameter            )        {            try            {                MessageBoxWHook = LocalHook.Create(                    LocalHook.GetProcAddress("user32.dll", "MessageBoxW"),                    new DMessageBoxW(MessageBoxW_Hooked),                    this);                MessageBoxWHook.ThreadACL.SetExclusiveACL(new int[1]);                MessageBoxAHook = LocalHook.Create(                    LocalHook.GetProcAddress("user32.dll", "MessageBoxA"),                    new DMessageBoxW(MessageBoxA_Hooked),                    this);                MessageBoxAHook.ThreadACL.SetExclusiveACL(new int[1]);                 }            catch (Exception ex)            {                MessageBox.Show(ex.Message);                return;            }            try            {                while (true)                {                    Thread.Sleep(10);                }            }            catch            {            }        }

Among them, MessageBoxWHook and MessageBoxAHook are both LocalHook variables, MessageBoxAHook. ThreadACL. SetExclusiveACL (new int [1]); this code is used to add local hooks to the current thread for execution.

After running the function, let's check the Hook effect. Open a test form and pop up MessageBox. At this time, MessageBox has no title and the content is normal:

    

 

Next, we inject the target process, obtain the process ID, and click inject, prompting that the target process has been successfully injected:

 

    

 

Click the target process MessageBox, and you will find that the Hook has been successful, and the content and title have been changed:

 

    

 

So far, C # has called EasyHook to Hook the target process.

Postscript

From this practice, we can feel that C # is completely feasible to Hook the program. Although the memory and address cannot be operated directly, we can do this by operating WindowsAPI and using EasyHook, in particular, the latter greatly reduces the number of codes and the difficulty of using them.

However, EasyHook currently has very few Chinese documents, and I have encountered great difficulties in using it. The methods for Hook other functions have not been fully implemented. I hope to brainstorm and share ideas with you!

I have just studied Hook for a short time, and it is inevitable that there will be leakage in this article. Please comment and correct me.

Source code has been uploaded to Baidu Network Disk: Link: https://pan.baidu.com/s/1wyin9Ezn6AwFQlQxMenQeg password: dv9b

 

 

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.