Click here to Skip to main content
15,887,596 members
Please Sign up or sign in to vote.
1.00/5 (2 votes)
See more:
Hello everyone,
I try to hook a thread of Notepad with C#, but it was not working. My code is:
C#
using System;
using System.Diagnostics;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.IO;

namespace ConsoleAppCSharp
{
    class Program
    {
        private const int WH_KEYBOARD_LL = 13;
        private const int WM_KEYDOWN = 0x0100;
        private static LowLevelKeyboardProc _proc = HookCallback;
        private static IntPtr _hookID = IntPtr.Zero;

        [DllImport("user32.dll", SetLastError = true)]
        static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

        [DllImport("user32.dll", SetLastError = true)]
        static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
        static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr SetWindowsHookEx(int idHook,
            LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool UnhookWindowsHookEx(IntPtr hhk);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
            IntPtr wParam, IntPtr lParam);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr GetModuleHandle(string lpModuleName);

        [DllImport("kernel32.dll")]
        static extern IntPtr GetConsoleWindow();

        [DllImport("user32.dll")]
        static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

        [DllImport("user32.dll", SetLastError = true)]
        static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

        static void Main(string[] args)
        {
            IntPtr hwnd1 = FindWindow("Notepad", "Untitled - Notepad");
            //MessageBox.Show(hwnd1.ToString("X"));
            IntPtr hwnd2 = FindWindowEx(hwnd1, IntPtr.Zero, "Edit", "");
            //MessageBox.Show(hwnd2.ToString("X"));
            //IntPtr send = SendMessage(hwnd2, 0x0102, 0x74, 0);
            uint lpdwProcessId = 0;
            uint pID = GetWindowThreadProcessId(hwnd2, out lpdwProcessId);
            //MessageBox.Show(pID.ToString("X"));
            
            _hookID = SetHook(_proc, lpdwProcessId);
            Application.Run();
            UnhookWindowsHookEx(_hookID);
        }

        private static IntPtr SetHook(LowLevelKeyboardProc proc, uint lpdwProcessId)
        {
            using (Process curProcess = Process.GetCurrentProcess())
            using (ProcessModule curModule = curProcess.MainModule)
            {
                return SetWindowsHookEx(WH_KEYBOARD_LL, proc,
                    GetModuleHandle(curModule.ModuleName), lpdwProcessId);
            }
        }

        private delegate IntPtr LowLevelKeyboardProc(
            int nCode, IntPtr wParam, IntPtr lParam);

        private static IntPtr HookCallback(
            int nCode, IntPtr wParam, IntPtr lParam)
        {
            if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
            {
                int vkCode = Marshal.ReadInt32(lParam);
                Console.WriteLine((Keys)vkCode);
                StreamWriter sw = new StreamWriter(Application.StartupPath + @"\logHook.txt", true);
                sw.Write((Keys)vkCode);
                sw.Close();
            }
            return CallNextHookEx(_hookID, nCode, wParam, lParam);
        }
    }
}

How to fix it. Thanks.

What I have tried:

I write this code and compile it. But it not works.
Posted
Updated 12-Apr-21 6:26am

1 solution

It doesn't work because .NET doesn't support the exports required to inject a managed code .DLL into another process. You would also have to inject the .NET CLR into the target process to get the managed code to execute.

You can get away with making a global (system-wide) keyboard hook, but not one that targets a specific process.

Also, any anti-virus software would see this hook injection as hostile and quarantine the process setting the hook.

This can be done, just not the way you think. The code you inject has to be in a .DLL and written in a language like C or C++, not a managed language like C# or VB.NET. However, the setting up the injection CAN be written in C#.

See this for an example: C# Inject a Dll into a Process (w/ CreateRemoteThread) | coding.vision[^]
 
Share this answer
 
Comments
Volga_ 12-Apr-21 14:36pm    
Thanks. My vote 5.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
Top Experts
Last 24hrsThis month


CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900