|
到這里,下面將要給出的示例代碼之一的“安全密碼框”的原理也就基本上明了了。先關閉鍵盤中斷,然后采用輪詢的辦法獲得鍵盤輸入,在每一次輪詢中一旦取走了鍵盤數據立刻向鍵盤控制器發送&HD2指令清除上一次的按鍵信息,這樣就可以有效防止別的記錄器也采用輪詢的辦法來記錄鍵盤。同時,由于關閉了鍵盤中斷,Windows中所的程序都無法感知到鍵盤輸入,無論全局HOOK還是別的什么,統統失效。所以,這個密碼框的保護強度還是很不錯的。從鍵盤的角度說,QQ的鍵盤加密保護也是采用了類似的方法,不過又稍有不同。QQ的鍵盤加密技術并沒有關閉鍵盤中斷來輪詢,而是采用了另一個辦法:替換掉系統默認的鍵盤中斷處理程序,換成了QQ自己的鍵盤中斷處理,這個QQ的中斷程序并不會把鍵盤消息發送給Windows的上層服務,而是私自處理了這些消息,將用戶的鍵盤輸入加密,然后將密文直接傳遞給了QQ,因此任何位于上層的鍵盤記錄器都記錄不了QQ的密碼輸入啦。QQ2008早期版本的鍵盤加密驅動在取走鍵盤端口的數據后,同樣會有一個清空鍵盤輸入緩沖區的操作,讓別的程序即使輪詢也輪詢不了。但是那個版本的兼容性卻不太好,特別是導致使用USB鍵盤的用戶經常藍屏,騰訊后來改進了保護方式。在QQ2008的后期版本中,鍵盤加密的穩定性提高了,但是保護強度卻降低了,并且也沒有了清空輸入緩沖區的動作,而是改用另一個思路:通過不斷注入垃圾字符來對抗鍵盤記錄器。但是這樣的話使用普通輪詢的方法也可以截獲到用戶的輸入了,這也許是騰訊在保護強度和穩定性之間做出的一個折中。好啦,還有個問題,你用上述原理做了個安全密碼框,在密碼框中倒是可以輸入了,但是你關了程序以后,發現鍵盤失效啦,Windows所有程序都對鍵盤一點反應也沒有 - - 哈哈,剛才說啦,鍵盤中斷不是被關閉了嗎,Windows靠中斷來感知鍵盤,既然關掉了,當然鍵盤就不靈了,所以密碼框在實際制作的時候應該這樣:當密碼框獲得輸入焦點的時候才關閉鍵盤中斷,當密碼框失去焦點時應該立刻重新打開鍵盤中斷,當窗體失去焦點時也應該開中斷,當登錄完成或程序結束時都要打開中斷,不然別的程序就不能感知鍵盤了。另外,輪詢鍵盤端口得到的數據都是鍵盤掃描碼,你還需要轉換成虛擬鍵碼和對應的ASCII字符才行的。
說完了安全密碼框,現在也來說說利用這個原理怎么制作鍵盤記錄器,好在事物都是兩面的。我的思路是這樣:可以簡單輪詢,就是設置一個定時器,每30毫秒讀取一次鍵盤數據端口,就可以知道有沒有鍵被按下了。這個方法對大多數程序有效,對現在版本的QQ2008也有效(上面說過現在它的保護強度降低了嘛)。但是對于早期版本的QQ2008是無效的,因為那時的QQ鍵盤加密有個動作,就是取完了數據后會將鍵盤端口清零。而且鍵盤中斷的反應速度永遠比用輪詢的方法快(原因很明顯,中斷是由設備通知的,總是在“第一時間”被激活,而輪詢則不是),所以輪詢到的數據永遠是被QQ清空后的零。而且簡單輪詢還有個缺點,你需要自己來通過別的寄存器狀態識別輪詢到的是鍵盤數據還是鼠標數據。因為,你大概已經知道,在PS/2設備中,鍵盤控制器和鼠標控制器是共用的,而且它們的輸入緩沖區也是共用的,也就是說,鍵盤數據和鼠標數據是會混合在一起的,如果你只是簡單輪詢&H60端口的話,你就需要靠別的辦法來區分鍵盤和鼠標數據了(在示例代碼中,你將可以看到如何進行簡單輪詢)。現在我們使用一種改進的辦法來輪詢,它可以解決上述問題,并對早期版本的QQ2008也有效。思路是:首先關閉鍵盤中斷,這時候QQ密碼框也不會獲得任何輸入了,然后用輪詢的方法判斷鍵盤有沒有輸入。因為此時中斷已被關掉,再也不會有誰跟我們搶數據了,所以獲得的鍵盤輸入總是“第一手的”。在本文的開頭已經介紹了這個思路。下面的問題是,輪詢完畢后,怎樣讓QQ也能獲得輸入(注意此時鍵盤中斷已被關閉)?解決方法是打開中斷,然后利用上面的&HFE指令或者&HD2指令。我們可以在每次輪詢結束后,如果發現有按鍵消息,則打開鍵盤中斷,然后用&HFE指令讓鍵盤重發上一次的數據,或者用&HD2指令將我們輪詢到的數據塞回輸入緩沖區。注意實際測試時發現&HFE指令似乎不能再次激發鍵盤中斷,所以我用&HD2來將我們取走的數據重新塞回去,這個操作可以同時激發一次鍵盤中斷,由于此時中斷已經打開,中斷處理程序被激活,會取走我們塞回去的數據,這樣QQ或者其他任何程序都能接收到鍵盤輸入了。注意中斷處理程序取走的可是我們塞回去的數據哦,實際上我們想塞進去幾都可以,比如我輪詢到的是A鍵被按下,但是我完全可以欺騙系統是B鍵被按下。所以,這個思路還有另一個用途,修改實際按鍵,而且該修改是很底層的,足以欺騙鍵盤中斷處理程序和任何位于它上層的程序。好了,現在中斷處理程序已經處理完畢,系統已經收到了按鍵消息(如果是QQ密碼框,那么這個密碼框也收到了按鍵),注意它們都是在我們的程序之后(并且經過我們程序的同意)才收到這一消息的,因此可以認為,鍵盤已經被我們的程序從較底層給HOOK了,接下來,再次關閉鍵盤中斷,然后等待下一次輪詢。可以看到,在中斷關閉期間其它程序都得不到鍵盤消息,而中斷打開時我們的程序已經處理完鍵盤數據,所以可以保證我們的程序總在“最前面”得到按鍵信息。你可以設置一個定時器,然后輪訓間隔為30毫秒左右,時間不能太長,否則鍵盤記錄器反應很慢,也不能太短,否則太占系統資源。你要問了,按照這個思路的話,每一秒鐘鍵盤中斷都要打開關閉好多次,對性能有影響嗎?答案是肯定的,這個記錄器確實會在一定程度上降低鍵盤的反應速度,不過它的性能比我預想的要好得多,實際測試時,對性能并沒有太大影響,甚至不太感到它的存在 ^_^
|
|