? ? 最近因?yàn)榕老x(chóng)登錄的網(wǎng)站加了密碼控件,嘗試了很多方法都不能破解(該控件屏蔽了虛擬軟鍵盤),尋找資料中發(fā)現(xiàn)了winIo這么工具,十幾年前的東西了,它的官網(wǎng)貌似也處于游離狀態(tài),使用中也出現(xiàn)了很多問(wèn)題,便以此mark一下。
? ? 最開(kāi)始從這里獲取到了winIo32實(shí)現(xiàn)驅(qū)動(dòng)級(jí)鍵盤事件,但使用的是JNative(目前只支持32位),同時(shí)winIO32在64位的OS下運(yùn)行有問(wèn)題(本人測(cè)試過(guò),可能過(guò)程中有沒(méi)考慮到的原因,此文略過(guò)),所以采用winIo64+JNA來(lái)實(shí)現(xiàn)鍵盤的驅(qū)動(dòng)級(jí)模擬。
? ? 在開(kāi)始前,先申明一下所需要的環(huán)境和設(shè)備(本文主要在window7 64位環(huán)境下測(cè)試):
1.WinIo64.dll 和 WinIo64.sys(下載請(qǐng)見(jiàn)上面winIo32實(shí)現(xiàn)驅(qū)動(dòng)級(jí)鍵盤事件的附件key文件夾)
2.因?yàn)閃inIo庫(kù)允許Windows應(yīng)用程序中直接對(duì)I/O端口和物理內(nèi)存進(jìn)行存取操作,目前從網(wǎng)上找到的資料winio能模擬PS/2鍵盤輸入(串口鍵盤),但USB設(shè)備的模擬暫時(shí)資料不詳,所以此次以PS/2鍵盤模擬為例(必須鏈接PS/2鍵盤,否者模擬無(wú)效)。
3.WinIo64.sys簽名:64位版本的Windows只加載設(shè)備驅(qū)動(dòng)程序,這些驅(qū)動(dòng)程序由一個(gè)公共CA簽發(fā)的代碼簽名證書簽署,如Verisign、Thawte等。WinIo64 除非獲得了代碼簽名證書,否則系統(tǒng)不能部署在生產(chǎn)機(jī)器上。
? ? a.開(kāi)啟測(cè)試模式
????????? ?1)管理員模式運(yùn)行cmd
????????? ?2)在命令行輸入:bcdedit /set TESTSIGNING ON
????? ? ? ?3)重啟電腦,桌面右下角會(huì)出現(xiàn)測(cè)試模式。
? ? b.完成winIO64的簽名認(rèn)證:
???????????1.打開(kāi) WinIO64.sys的屬性框,翻到“數(shù)字簽名”選項(xiàng)卡,點(diǎn)擊“詳細(xì)信息”
????????????2.在新出來(lái)的對(duì)話框中點(diǎn)擊“查看證書”
????????????3.在又新出來(lái)的對(duì)話框中點(diǎn)擊“安裝證書”
????????????4.點(diǎn)擊“下一步”,然后選擇“將所有的證書放入下列存儲(chǔ)”
????????????5.點(diǎn)擊瀏覽,選擇“受信任的根證書發(fā)布機(jī)構(gòu)”
4.需要jna相關(guān)的jar,自行下載。本示例jdk:1.8 64位。
接下來(lái),貼出代碼:
????
import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.KeyEvent;
import java.util.HashMap;
import java.util.Map;import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.ie.InternetExplorerDriver;import com.sun.jna.Native;
import com.sun.jna.win32.StdCallLibrary;public class Selenium {private Robot robot = null;//此處用robot去移動(dòng)鼠標(biāo),可忽略public static final int CONTROL_PORT = 0x64;public static final int DATA_PORT = 0x60;public static final Map<String,Integer> map=new HashMap();public Selenium(){try {robot = new Robot();} catch (AWTException e) {e.printStackTrace();}} static{map.put("0", KeyEvent.VK_0);map.put("1", KeyEvent.VK_1);map.put("2", KeyEvent.VK_2);map.put("3", KeyEvent.VK_3);map.put("4", KeyEvent.VK_4);map.put("5", KeyEvent.VK_5);map.put("6", KeyEvent.VK_6);map.put("7", KeyEvent.VK_7);map.put("8", KeyEvent.VK_8);map.put("9", KeyEvent.VK_9);map.put("a", KeyEvent.VK_A);map.put("b", KeyEvent.VK_B);map.put("c", KeyEvent.VK_C);map.put("d", KeyEvent.VK_D);map.put("e", KeyEvent.VK_E);map.put("f", KeyEvent.VK_F);map.put("g", KeyEvent.VK_G);map.put("h", KeyEvent.VK_H);map.put("i", KeyEvent.VK_I);map.put("j", KeyEvent.VK_J);map.put("k", KeyEvent.VK_K);map.put("l", KeyEvent.VK_L);map.put("m", KeyEvent.VK_M);map.put("n", KeyEvent.VK_N);map.put("o", KeyEvent.VK_O);map.put("p", KeyEvent.VK_P);map.put("q", KeyEvent.VK_Q);map.put("r", KeyEvent.VK_R);map.put("s", KeyEvent.VK_S);map.put("t", KeyEvent.VK_T);map.put("u", KeyEvent.VK_U);map.put("v", KeyEvent.VK_V);map.put("w", KeyEvent.VK_W);map.put("x", KeyEvent.VK_X);map.put("y", KeyEvent.VK_Y);map.put("z", KeyEvent.VK_Z);map.put("Tab", KeyEvent.VK_TAB);map.put("Space", KeyEvent.VK_SPACE);map.put("Shift", KeyEvent.VK_SHIFT);map.put("Cntl", KeyEvent.VK_CONTROL);map.put("Alt", KeyEvent.VK_ALT);map.put("F1",KeyEvent.VK_F1);map.put("F2",KeyEvent.VK_F2);map.put("F3",KeyEvent.VK_F3);map.put("F4",KeyEvent.VK_F4);map.put("F5",KeyEvent.VK_F5);map.put("F6",KeyEvent.VK_F6);map.put("F7",KeyEvent.VK_F7);map.put("F8",KeyEvent.VK_F8);map.put("F9",KeyEvent.VK_F9);map.put("F10",KeyEvent.VK_F10);map.put("F11",KeyEvent.VK_F11);map.put("F12",KeyEvent.VK_F12);}//使用User32庫(kù)里面鍵位值轉(zhuǎn)換public interface User32 extends StdCallLibrary{User32 Instance = (User32)Native.loadLibrary("User32",User32.class);int MapVirtualKeyA(int key, int type);}//此處是winIo使用關(guān)鍵public interface WinIo extends StdCallLibrary{WinIo Instance = (WinIo)Native.loadLibrary("WinIo64",WinIo.class); boolean InitializeWinIo();boolean GetPortVal(int portAddr, int pPortVal, int size);boolean SetPortVal(int portAddr, int portVal, int size) ;void ShutdownWinIo();}//將虛擬鍵位值轉(zhuǎn)成掃描碼public static int toScanCode(String key){try {return User32.Instance.MapVirtualKeyA(map.get(key).intValue(),0);} catch (Exception e) {return 0;}}public static void KBCWait4IBE() throws Exception{int val=0;do {if(!WinIo.Instance.GetPortVal(CONTROL_PORT,val, 1)){System.err.println("Cannot get the Port");}} while ((0x2&val)>0); }public static void KeyDown(int key) throws Exception{KBCWait4IBE();WinIo.Instance.SetPortVal(WinIOAPI.CONTROL_PORT,0xD2,1);KBCWait4IBE();WinIo.Instance.SetPortVal(WinIOAPI.DATA_PORT,key,1);}public static void KeyUp(int key) throws Exception{KBCWait4IBE();WinIo.Instance.SetPortVal(WinIOAPI.CONTROL_PORT,0xD2,1);KBCWait4IBE();WinIo.Instance.SetPortVal(WinIOAPI.DATA_PORT,(key|0x80),1); }public void mouseDemo() throws InterruptedException{robot.mouseMove(500, 290);Thread.sleep(650);robot.mousePress(KeyEvent.BUTTON1_MASK);Thread.sleep(150);robot.mouseRelease(KeyEvent.BUTTON1_MASK);Thread.sleep(999);System.out.println("鼠標(biāo)點(diǎn)擊完畢");}public static void main(String[] args) throws Exception{ //System.setProperty("webdriver.ie.driver", "D:/IEDriverServer.exe");//WebDriver dr = new InternetExplorerDriver();// 打開(kāi)網(wǎng)站//dr.get("https://www.hao123.com");// 獲取源代碼//System.out.println("--"+dr.getPageSource());//Selenium se = new Selenium();//se.mouseDemo();System.out.println("winIO64初始化是否成功:"+WinIo.Instance.InitializeWinIo());//此處應(yīng)該有判斷,只有初始化成功才可繼續(xù)往下走,否者直接終止Thread.sleep(1000);String s="helloworld";for (int i = 0; i < s.length(); i++) {KeyDown(toScanCode(""+s.charAt(i)));Thread.sleep(10);KeyUp(toScanCode(""+s.charAt(i)));Thread.sleep(200);}WinIo.Instance.ShutdownWinIo();// 關(guān)閉//System.out.println(dr.getPageSource());//Thread.sleep(20000); //dr.quit();
}
}
說(shuō)明:代碼中有使用selenium工具,一種自動(dòng)化網(wǎng)頁(yè)測(cè)試的工具,可自行注釋掉,不影響執(zhí)行,關(guān)于代碼中scancode可以自行查找相關(guān)資料。
關(guān)于代碼中如果winIO64初始化失敗的問(wèn)題,首先檢查2個(gè)winio的文件路徑是否正確,我習(xí)慣放在jdk的java/bin下,其次執(zhí)行這段代碼必須是管理員的權(quán)限,用IDE的童靴請(qǐng)自行用管理員啟動(dòng)IDE。
結(jié)語(yǔ):
本方法僅適用于個(gè)人需求,對(duì)于上生產(chǎn)環(huán)境使用作用不大,而且涉及的問(wèn)題較多,主要是得有ps/2鍵盤。
2018-05-16 add:無(wú)意中發(fā)現(xiàn)筆記本上的鍵盤就是PS/2,呵呵呵呵呵!!!
總結(jié)
以上是生活随笔為你收集整理的WinIo64驱动级别的键盘模拟(java)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。