自動填密碼你們可能都不莫生,最有名的應該是 按鍵精靈 只要是一個能夠輸入的地方均可以能過按鍵精靈來完成輸入.我今天要講的是使用 winio/winring0來完成相似的功能安全
若是要自動填充密碼方式基本上有 消息級的模擬 和 驅動級的模擬,服務器
消息級的模擬如 C# 直接使用 SendKeys 就能夠完成 API下可使用 SendMessage完成 即有了這個神器爲何還要用三方?測試
答案:如今一些網都使用了ActiveX安全插件,如網銀,支付寶,等,還有咱們上一次說到的 翼支付和手機支付 它們基本上屏蔽了 SendMessage 有些就算可使用可是不能獲得正確的加密數據.還有更可氣的是 在服務器遠程操做中手動輸入都不能輸入密碼.ui
驅動級的就是硬盤的模擬 模擬鍵盤,大牛們能夠直接操做 I/O 我這裏講的是使用三方類庫來完成,加密
第一個是 winIO 在XP時候我一直使用它,但到了 win7+64位模式下使用有點小問題,winIO 64位下驅動數字簽名有點問題不能直接運行,須要將 win7轉到測試模式下,安裝數字證書而用程序還要在測試模式使用,若是是本身有能夠湊合着,若是是給客戶去使用,客戶絕對會說你腦殘,我運行個程序還要調這調那,固然是不肯意了.spa
我如今就以 32位模式下來演示如何使用 winIO,首先是下載winIO 最新版本爲 3.0 網官下載地址 http://www.internals.com/插件
解壓後,獲得上圖所示的文件 這個地方有用的 就是最後4個文件其它的是源文件和例子幫助文件之類的,debug
跟據系統的不一樣來使用不一樣的文件 若是是 32位的就使用32結尾的兩個.呵呵 直接把這兩個放到你開發目錄下的 bin/release 或 bin/debug下面就好了code
而後就是調用blog
public class WinIO { public const int KBC_KEY_CMD = 0x64;//輸入鍵盤按下消息的端口 public const int KBC_KEY_DATA = 0x60;//輸入鍵盤彈起消息的端口 [DllImport("WinIo32.dll")] public static extern bool InitializeWinIo(); [DllImport("WinIo32.dll")] public static extern bool GetPortVal(IntPtr wPortAddr, out int pdwPortVal, byte bSize); [DllImport("WinIo32.dll")] public static extern bool SetPortVal(uint wPortAddr, IntPtr dwPortVal, byte bSize); [DllImport("WinIo32.dll")] public static extern byte MapPhysToLin(byte pbPhysAddr, uint dwPhysSize, IntPtr PhysicalMemoryHandle); [DllImport("WinIo32.dll")] public static extern bool UnmapPhysicalMemory(IntPtr PhysicalMemoryHandle, byte pbLinAddr); [DllImport("WinIo32.dll")] public static extern bool GetPhysLong(IntPtr pbPhysAddr, byte pdwPhysVal); [DllImport("WinIo32.dll")] public static extern bool SetPhysLong(IntPtr pbPhysAddr, byte dwPhysVal); [DllImport("WinIo32.dll")] public static extern void ShutdownWinIo(); [DllImport("user32.dll")] public static extern int MapVirtualKey(uint Ucode, uint uMapType); private WinIO() { IsInitialize = true; } public static void Initialize() { if (InitializeWinIo()) { KBCWait4IBE(); IsInitialize = true; } } public static void Shutdown() { if (IsInitialize) ShutdownWinIo(); IsInitialize = false; } private static bool IsInitialize { get; set; } ///等待鍵盤緩衝區爲空 private static void KBCWait4IBE() { int dwVal = 0; do { bool flag = GetPortVal((IntPtr)0x64, out dwVal, 1); } while ((dwVal & 0x2) > 0); } /// 模擬鍵盤標按下 public static void KeyDown(Keys vKeyCoad) { if (!IsInitialize) return; int btScancode = 0; btScancode = MapVirtualKey((uint)vKeyCoad, 0); KBCWait4IBE(); SetPortVal(KBC_KEY_CMD, (IntPtr)0xD2, 1); KBCWait4IBE(); SetPortVal(KBC_KEY_DATA, (IntPtr)0x60, 1); KBCWait4IBE(); SetPortVal(KBC_KEY_CMD, (IntPtr)0xD2, 1); KBCWait4IBE(); SetPortVal(KBC_KEY_DATA, (IntPtr)btScancode, 1); } /// 模擬鍵盤彈出 public static void KeyUp(Keys vKeyCoad) { if (!IsInitialize) return; int btScancode = 0; btScancode = MapVirtualKey((uint)vKeyCoad, 0); KBCWait4IBE(); SetPortVal(KBC_KEY_CMD, (IntPtr)0xD2, 1); KBCWait4IBE(); SetPortVal(KBC_KEY_DATA, (IntPtr)0x60, 1); KBCWait4IBE(); SetPortVal(KBC_KEY_CMD, (IntPtr)0xD2, 1); KBCWait4IBE(); SetPortVal(KBC_KEY_DATA, (IntPtr)(btScancode | 0x80), 1); } }
上面這個類也是網上搜出來的,感受前輩們的分享.此處只模擬了鍵盤的 按下和彈起
使用實例
String pass = "123456"; foreach (char chr in pass) { WinIO.KeyDown((Keys)chr); Thread.CurrentThread.Join(100); WinIO.KeyUp((Keys)chr); Thread.CurrentThread.Join(100); } Thread.CurrentThread.Join(100); WinIO.Shutdown();
這個地方按下的時候,稍停下,彈起也同樣
這樣的話 winIO 的調用就完成了
另外一個神器就是 WinRing0 這個是一個開源的項目,能夠通殺 32 64位系統, 不須要爲驅動安裝數字簽名,自從發現了這個之後,我全部的須要自動填密碼的項目都使用了它
雖然說開源,可是這個在網上的使用文檔仍是比較少,有的都是自帶的一些文檔和使用實例沒有特殊意義的例子,說實話,這項目的找了很久才找到下載地址,你們如須要就留個郵箱,
我看到後就發給你
咱們打開 release目錄,
複製相關的文件到你的工做開發目錄下.
source\sample\Cs\OpenLibSys.cs 找到這個cs文件,這個是官方的全部的功能的封裝,包括 I/O PCI CPU 等操做.把它加到咱們的工程項目中
新建一個類 WinRing 代碼以下
using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Text; using OpenLibSys; class WinRing { public enum Key { ABSOLUTE = 0x8000, LEFTDOWN = 2, LEFTUP = 4, MIDDLEDOWN = 0x20, MIDDLEUP = 0x40, MOVE = 1, RIGHTDOWN = 8, RIGHTUP = 0x10, VIRTUALDESK = 0x4000, VK_A = 0x41, VK_ADD = 0x6b, VK_B = 0x42, VK_BACK = 8, VK_C = 0x43, VK_CANCEL = 3, VK_CAPITAL = 20, VK_CLEAR = 12, VK_CONTROL = 0x11, VK_D = 0x44, VK_DECIMAL = 110, VK_DELETE = 0x2e, VK_DIVIDE = 0x6f, VK_DOWN = 40, VK_E = 0x45, VK_END = 0x23, VK_ESCAPE = 0x1b, VK_EXECUTE = 0x2b, VK_F = 70, VK_F1 = 0x70, VK_F10 = 0x79, VK_F11 = 0x7a, VK_F12 = 0x7b, VK_F2 = 0x71, VK_F3 = 0x72, VK_F4 = 0x73, VK_F5 = 0x74, VK_F6 = 0x75, VK_F7 = 0x76, VK_F8 = 0x77, VK_F9 = 120, VK_G = 0x47, VK_H = 0x48, VK_HELP = 0x2f, VK_HOME = 0x24, VK_I = 0x49, VK_INSERT = 0x2d, VK_J = 0x4a, VK_K = 0x4b, VK_L = 0x4c, VK_LBUTTON = 1, VK_LEFT = 0x25, VK_M = 0x4d, VK_MBUTTON = 4, VK_MENU = 0x12, VK_N = 0x4e, VK_NEXT = 0x22, VK_NULTIPLY = 0x6a, VK_NUM0 = 0x30, VK_NUM1 = 0x31, VK_NUM2 = 50, VK_NUM3 = 0x33, VK_NUM4 = 0x34, VK_NUM5 = 0x35, VK_NUM6 = 0x36, VK_NUM7 = 0x37, VK_NUM8 = 0x38, VK_NUM9 = 0x39, VK_NUMLOCK = 0x90, VK_NUMPAD0 = 0x60, VK_NUMPAD1 = 0x61, VK_NUMPAD2 = 0x62, VK_NUMPAD3 = 0x63, VK_NUMPAD4 = 100, VK_NUMPAD5 = 0x65, VK_NUMPAD6 = 0x66, VK_NUMPAD7 = 0x67, VK_NUMPAD8 = 0x68, VK_NUMPAD9 = 0x69, VK_O = 0x4f, VK_P = 80, VK_PAUSE = 0x13, VK_PRINT = 0x2a, VK_PRIOR = 0x21, VK_Q = 0x51, VK_R = 0x52, VK_RBUTTON = 2, VK_RETURN = 13, VK_RIGHT = 0x27, VK_S = 0x53, VK_SCROLL = 0x91, VK_SELECT = 0x29, VK_SEPARATOR = 0x6c, VK_SHIFT = 0x10, VK_SNAPSHOT = 0x2c, VK_SPACE = 0x20, VK_SUBTRACT = 0x6d, VK_T = 0x54, VK_TAB = 9, VK_U = 0x55, VK_UP = 0x26, VK_V = 0x56, VK_W = 0x57, VK_X = 0x58, VK_Y = 0x59, VK_Z = 90, WHEEL = 0x800, XDOWN = 0x80, XUP = 0x100 } static OpenLibSys.Ols ols = null; [DllImport("user32.dll")] public static extern int MapVirtualKey(uint Ucode, uint uMapType); public static Boolean init() { ols = new OpenLibSys.Ols(); return ols.GetStatus() == (uint)Ols.Status.NO_ERROR; } private static void KBCWait4IBE() { byte dwVal = 0; do { ols.ReadIoPortByteEx(0x64, ref dwVal); } while ((dwVal & 0x2) > 0); } public static void KeyDown(Char ch) { int btScancode = MapVirtualKey((uint)(Key)ch, 0); KBCWait4IBE(); ols.WriteIoPortByte(0x64, 0xd2); KBCWait4IBE(); ols.WriteIoPortByte(0x60, (byte)btScancode); } public static void KeyUp(Char ch) { int btScancode = MapVirtualKey((uint)(Key)ch, 0); KBCWait4IBE(); ols.WriteIoPortByte(0x64, 0xd2); KBCWait4IBE(); ols.WriteIoPortByte(0x60, (byte)(btScancode | 0x80)); } }
也只是模擬了 按下和彈起 如下爲調用方式
String pwd = "123456"; foreach (char chr in pwd) { WinRing.init(); WinRing.KeyDown(chr); Thread.Sleep(100); WinRing.KeyUp(chr); } Thread.CurrentThread.Join(100);
到此 這兩個類庫的使用就介紹完了,可是在真正項目中可能會遇到各類問題,這就需咱們的經驗和處理問題的能力了.
注:這兩個類庫有一個通病就是不支持 USB鍵盤的模擬.估計是我沒有研究出來吧
--幸福海