C#代码屏蔽CTRL+ALT+DEL

来源:互联网 发布:算法模型电商 编辑:程序博客网 时间:2024/05/17 01:33
非常折腾的方法,就是为了不写驱动!

首先是挂起winlogon进程的类:
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace WindowsFormsApplication1
{
    class ProcessMgr
    {
        /// <summary>
          /// The process-specific access rights.
          /// </summary>
        [Flags]
        public enum ProcessAccess : uint
        {
            /// <summary>
               /// Required to terminate a process using TerminateProcess.
               /// </summary>
            Terminate = 0x1,
            /// <summary>
               /// Required to create a thread.
               /// </summary>
            CreateThread = 0x2,
            /// <summary>
               /// Undocumented.
               /// </summary>
            SetSessionId = 0x4,
            /// <summary>
               /// Required to perform an operation on the address space of a process (see VirtualProtectEx and WriteProcessMemory).
               /// </summary>
            VmOperation = 0x8,
            /// <summary>
               /// Required to read memory in a process using ReadProcessMemory.
               /// </summary>
            VmRead = 0x10,
            /// <summary>
               /// Required to write to memory in a process using WriteProcessMemory.
               /// </summary>
            VmWrite = 0x20,
            /// <summary>
               /// Required to duplicate a handle using DuplicateHandle.
               /// </summary>
            DupHandle = 0x40,
            /// <summary>
               /// Required to create a process.
               /// </summary>
            CreateProcess = 0x80,
            /// <summary>
               /// Required to set memory limits using SetProcessWorkingSetSize.
               /// </summary>
            SetQuota = 0x100,
            /// <summary>
               /// Required to set certain information about a process, such as its priority class (see SetPriorityClass).
               /// </summary>
            SetInformation = 0x200,
            /// <summary>
               /// Required to retrieve certain information about a process, such as its token, exit code, and priority class (see OpenProcessToken, GetExitCodeProcess, GetPriorityClass, and IsProcessInJob).
               /// </summary>
            QueryInformation = 0x400,
            /// <summary>
               /// Undocumented.
               /// </summary>
            SetPort = 0x800,
            /// <summary>
               /// Required to suspend or resume a process.
               /// </summary>
            SuspendResume = 0x800,
            /// <summary>
               /// Required to retrieve certain information about a process (see QueryFullProcessImageName). A handle that has the PROCESS_QUERY_INFORMATION access right is automatically granted PROCESS_QUERY_LIMITED_INFORMATION.
               /// </summary>
            QueryLimitedInformation = 0x1000,
            /// <summary>
               /// Required to wait for the process to terminate using the wait functions.
               /// </summary>
            Synchronize = 0x100000
        }
        [DllImport("ntdll.dll")]
        private static extern uint NtResumeProcess([In] IntPtr processHandle);
        [DllImport("ntdll.dll")]
        private static extern uint NtSuspendProcess([In] IntPtr processHandle);
        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern IntPtr OpenProcess(
        ProcessAccess desiredAccess,
        bool inheritHandle,
        int processId);
        [DllImport("kernel32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool CloseHandle([In] IntPtr handle);
        public static void SuspendProcess(int processId)
        {
            IntPtr hProc = IntPtr.Zero;
            try
            {
                // Gets the handle to the Process
                hProc = OpenProcess(ProcessAccess.SuspendResume, false, processId);
                if (hProc != IntPtr.Zero)
                    NtSuspendProcess(hProc);
            }
            finally
            {
                // Don't forget to close handle you created.
                if (hProc != IntPtr.Zero)
                    CloseHandle(hProc);
            }
        }
        public static void ResumeProcess(int processId)
        {
            IntPtr hProc = IntPtr.Zero;
            try
            {
                // Gets the handle to the Process
                hProc = OpenProcess(ProcessAccess.SuspendResume, false, processId);
                if (hProc != IntPtr.Zero)
                    NtResumeProcess(hProc);
            }
            finally
            {
                // Don't forget to close handle you created.
                if (hProc != IntPtr.Zero)
                    CloseHandle(hProc);
            }
        }
        public static void SuspendWinlogon()
        {
            Process[] processes = Process.GetProcesses();
            foreach (Process process in processes)
            {
                Console.WriteLine(process.ProcessName);
                if (process.ProcessName == "winlogon")
                {
                    SuspendProcess(process.Id);
                }
            }
        }
        public static void ResumeWinlogon()
        {
            Process[] processes = Process.GetProcesses();
            foreach (Process process in processes)
            {
                Console.WriteLine(process.ProcessName);
                if (process.ProcessName == "winlogon")
                {
                    ResumeProcess(process.Id);
                }
            }
        }
    }
}

然后是键盘钩子类:
using System;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    class MyHook
    {
        //消息函数的委托
        public delegate int HookProc(int nCode, int wParam, IntPtr lParam);
        static int hHook = 0;
        public const int WH_KEYBOARD_LL = 13;//底层键盘钩子
        HookProc KeyBoardHookProcedure;

        //按键信息结构
        [StructLayout(LayoutKind.Sequential)]
        public class KeyBoardHookStruct
        {
            public int vkCode;
            public int scanCode;
            public int flags;
            public int time;
            public int dwExtraInfo;
        }

        //安装钩子
        [DllImport("user32.dll")]
        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")]
        public static extern int CallNextHookEx(int idHook, int nCode, int wParam, IntPtr lParam);

        //返回当前线程 ID
        [DllImport("kernel32.dll")]
        public static extern int GetCurrentThreadId();

        //得到模块的句柄
        [DllImport("kernel32.dll")]
        public static extern IntPtr GetModuleHandle(string name);

        //安装钩子
        public void InsertHook()
        {
            if (hHook == 0)
            {
                KeyBoardHookProcedure = new HookProc(KeyBoardHookProc);
                hHook = SetWindowsHookEx(WH_KEYBOARD_LL,
                          KeyBoardHookProcedure,
                        GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName), 0);
                if (hHook == 0)
                {
                    UnHook();
                    throw new Exception("设置Hook失败!");
                }
            }
        }

        //卸载钩子
        public void UnHook()
        {
            bool retKeyboard = true;
            if (hHook != 0)
            {
                retKeyboard = UnhookWindowsHookEx(hHook);
                hHook = 0;
            }
            if (!retKeyboard) throw new Exception("卸载Hook失败!");
        }

        //按键消息的处理函数
        public static int KeyBoardHookProc(int nCode, int wParam, IntPtr lParam)
        {
            if (nCode >= 0)
            {
                KeyBoardHookStruct kbh = (KeyBoardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyBoardHookStruct));
                //添加自己的判断语句,如果符合要求的按键,就 return 1;
                //没有判断直接 return 1;那么就屏蔽所有按键除了ctrl+alt+del
                //屏蔽Ctrl+Esc

                if (kbh.vkCode == (int)Keys.Delete && (int)Control.ModifierKeys == (int)Keys.Control + (int)Keys.Alt)      //截获Ctrl+Alt+Delete
                {
                    //MessageBox.Show("截获Ctrl+Alt+Delete!");
                    ProcessMgr.SuspendWinlogon();
                    WinIoPort winIoPort = new WinIoPort();
                    winIoPort.KeyEscSend();
                    //Form1.keybd_event((byte)Keys.Escape, 0, 0, 0);
                    //Form1.keybd_event((byte)Keys.Escape, 0, 2, 0);
                    ProcessMgr.ResumeWinlogon();
                    return 1;
                }
                if ((kbh.vkCode == (int)Keys.Escape))
                {
                    //MessageBox.Show("ESC key hooked!");
                    //return 1;
                }
            }
            return CallNextHookEx(hHook, nCode, wParam, lParam);
        }
    }
}

最后是用WINIO向WIN10操作系统发送键盘扫描码,不能用keybd_event.:
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    unsafe class WinIoPort
    {
        [DllImport("user32.dll")]
        public static extern int MapVirtualKey(uint Ucode, uint uMapType);

        [DllImport("kernel32.dll")]
        private extern static IntPtr LoadLibrary(String DllName);

        [DllImport("kernel32.dll")]
        private extern static IntPtr GetProcAddress(IntPtr hModule, String ProcName);

        [DllImport("kernel32")]
        private extern static bool FreeLibrary(IntPtr hModule);

        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        private delegate bool InitializeWinIoType();

        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        private delegate bool GetPortValType(UInt16 PortAddr, UInt32* pPortVal, UInt16 Size);

        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        private delegate bool SetPortValType(UInt16 PortAddr, UInt32 PortVal, UInt16 Size);

        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        private delegate bool ShutdownWinIoType();

        public static IntPtr hMod;
        public WinIoPort()
        {
            IntPtr pFunc = default(IntPtr);
            // Check if this is a 32 bit or 64 bit system
            if (IntPtr.Size == 4)
                hMod = LoadLibrary("WinIo32.dll");
            else
                hMod = LoadLibrary("iEiIo64.dll");

            if (hMod == IntPtr.Zero)
            {
                MessageBox.Show("Can't find WinIo dll.\nMake sure the WinIo library files are located in the same directory as your executable file.", "DumpPort", MessageBoxButtons.OK, MessageBoxIcon.Error);
                throw new Exception();
            }
            if (IntPtr.Size == 4)
                pFunc = GetProcAddress(hMod, "InitializeWinIo");
            else
                pFunc = GetProcAddress(hMod, "InitializeiEiIo");

            if (pFunc != IntPtr.Zero)
            {
                InitializeWinIoType InitializeWinIo = (InitializeWinIoType)Marshal.GetDelegateForFunctionPointer(pFunc, typeof(InitializeWinIoType));
                bool Result = InitializeWinIo();

                if (!Result)
                {
                    MessageBox.Show("Error returned from InitializeWinIo.\nMake sure you are running with administrative privileges and that the WinIo library files are located in the same directory as your executable file.", "DumpPort", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    FreeLibrary(hMod);
                    throw new Exception();
                }
            }
        }
        bool SetPortVale(UInt16 PortAddr, UInt32 PortVal, UInt16 Size)
        {
            IntPtr pFunc = GetProcAddress(hMod, "SetPortVal");
            if (pFunc != IntPtr.Zero)
            {
                SetPortValType SetPortVal = (SetPortValType)Marshal.GetDelegateForFunctionPointer(pFunc, typeof(SetPortValType));

                // Call WinIo to set value
                bool Result = SetPortVal(PortAddr, PortVal, 1);

                if (Result)
                {
                    return true;
                }
            }
            MessageBox.Show("Error returned from SetPortVal", "DumpPort", MessageBoxButtons.OK, MessageBoxIcon.Error);
            return false;
        }

        bool GetPortVale(UInt16 PortAddr, UInt32* pPortVal, UInt16 Size)
        {
            IntPtr pFunc = GetProcAddress(hMod, "GetPortVal");
            if (pFunc != IntPtr.Zero)
            {
                GetPortValType GetPortVal = (GetPortValType)Marshal.GetDelegateForFunctionPointer(pFunc, typeof(GetPortValType));

                // Call WinIo to get value
                bool Result = GetPortVal(PortAddr, pPortVal, 1);

                if (Result)
                {
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// armand test
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        ///等待键盘缓冲区为空
        void KBCWait4IBE()
        {
            UInt32 dwVal = 0;
            do
            {
                bool flag = GetPortVale(0x64, &dwVal, 1);
            }
            while ((dwVal & 0x2) > 0);
        }
        /// 模拟键盘按下
        void MyKeyDown(UInt32 vKeyCoad)
        {
            KBCWait4IBE();
            SetPortVale(0x64, 0xD2, 1);// 发送命令
            KBCWait4IBE();
            //SetPortVal(KBC_KEY_DATA, 0x60, 1);// 写入按键信息----这里四条被我注释掉了,因为网路上的其他人都没有注释掉,我查了资料,亲测,去掉这四条才能用。
            //KBCWait4IBE();
            //SetPortVal(KBC_KEY_CMD, 0xD2, 1);// 发送键盘写入命令
            //KBCWait4IBE();
            SetPortVale(0x60, vKeyCoad, 1);// 写入按下键
        }
        /// 模拟键盘弹出
        void MyKeyUp(UInt32 vKeyCoad)
        {
            KBCWait4IBE();
            SetPortVale(0x64, 0xD2, 1);// 发送命令
            KBCWait4IBE();
            //SetPortVal(KBC_KEY_DATA, 0x60, 1);// 写入按键信息
            //KBCWait4IBE();
            //SetPortVal(KBC_KEY_CMD, 0xD2, 1);// 发送键盘写入命令
            //KBCWait4IBE();
            SetPortVale(0x60, (vKeyCoad | 0x80), 1);// 写入按下键
        }
        public void KeyEscSend()
        {
            MyKeyDown(0x01);
            MyKeyUp(0x01);
        }
    }
}
当然是有问题的方法。winlogon 画面还是要闪一下。winlogon就不应该屏蔽,这是微软给大家最后的救命机会,当你的程序挂了,又不想关机重启的时候。
而且,64位WINIO需要签名才能用,设备管理器里必须看到60/64端口是开出来的,真坑!不过我们做BIOS人不可能受此限制,做一个WMI和APP或是APPLICATION通信就可以了!
网上代码,如有雷同,纯属靠皮!:)
原创粉丝点击