<span id="7ztzv"></span>
<sub id="7ztzv"></sub>

<span id="7ztzv"></span><form id="7ztzv"></form>

<span id="7ztzv"></span>

        <address id="7ztzv"></address>

            PS2鍵盤保護的另一種方法

            By Mix	
            mix#ph4nt0m.org
            
            	
                為了保障用戶輸入帳號密碼的安全性,各種安全控件、密碼保險箱產品比比皆是,衍生
            出了很多保護鍵盤的方法。就筆者了解的,糾結到系統底層國內的資料大部分都是落在了直
            接I/O端口讀寫上,再往上一點就是IDT中斷了,本文將逐步探討和中斷有關的攻防技術,這
            也是筆者一次學習和小結的過程。
            
            
            一、基礎知識
            
                有不少內容其實大學的課程里面都有,只是當時聽講的時候大都覺得枯燥無味,剛走出
            大學校門時更是覺得那時候學的那些東西在實際工作中幾乎完全用不到,但是在深入學習和
            研究過程中才發現原來那些東西居然真的需要被了解和掌握。
            
                所謂中斷,就是指在CPU執行過程中出現了某些突發事件時,CPU需要停止當前程序轉去
            處理突發事件,處理完成后返回原處繼續之前的工作。那么系統中每個中斷對應的哪段處理
            代碼(即中斷門),就需要一份對應的表以供查找,這個表被稱為中斷描述符表Interrupt 
            Descriptor Table(即IDT)。
            
                對于IDT的存放和使用,按照程序員的邏輯來說就是在一片連續內存中依次存放著0xFF
            個P2C_IDTENTRY結構,結構描述如下:
            
            --code-------------------------------------------------------------------------
            typedef struct P2C_IDT_ENTRY_ {
            		P2C_U16 offset_low;//中斷門所在地址的底位
            		P2C_U16 selector;
            		P2C_U8 reserved;
            		P2C_U8 type:4;
            		P2C_U8 always0:1;
            		P2C_U8 dpl:2;
            		P2C_U8 present:1;
            		P2C_U16 offset_high; //中斷門所在地址的高位
            } P2C_IDTENTRY, *PP2C_IDTENTRY;
            -------------------------------------------------------------------------------
            
                在WindowsXP默認的IDT中,第0x93個結構就是被用來描述鍵盤的中斷門。思維迅猛的讀
            者肯定會刨根問底了:“那為什么第0x93是描述鍵盤的呢?”
            
                因為在硬件設備和CPU之間還有個銜接設備,叫中斷控制器,專門負責管理IDT的填充、
            查找和修改。請允許粘貼一段關于中斷控制器的精確描述:
            
            -------------------------------------------------------------------------------
                中斷控制器經歷了PIC(Programmable Interrupt Controller,可編程中斷控制器)和
            APIC(Advanced Programmable Interrupt Controller,高級可編程中斷控制器)兩個階段。
            
                而APIC 又由兩部分組成,一個稱為LAPIC(Local APIC,本地高級中斷控制器),一個
            稱為IOAPIC(I/O APCI,I/O 高級中斷控制器)
            -------------------------------------------------------------------------------
            
                現在的電腦基本都是使用APIC來管理中斷了,更準確的說是通過IOAPIC的控制就可以把
            鍵盤中斷定位到第0x93號中斷上去。這里還有個硬件IRQ的知識點,著急的同學請自行百度,
            不著急的同學暫時先理解為一個硬件設備對應一個IRQ資源,比如鍵盤默認被分配到IRQ1,
            在設備管理器的鍵盤驅動資源屬性頁里面可以找得到,鍵盤對應的I/O端口號60、64也可以
            在這里被找到。
            
            
            二、常見技術方法
            
                有了第一章的基本知識,就來看下常見的兩種PS2鍵盤中斷攻防技術。因為這兩種方法
            網上都有代碼,而且《寒江獨釣-內核安全編程》一書中也有不少說明,所以這里只是簡單
            描述。另外,筆者的測試代碼也是基于此書隨帶代碼進行的修改,在這里表示感謝。
            
                *替換0x93中斷門處理函數地址
            
                既然IDT中有保存中斷門的入口地址,那么直接修改掉這個值后,當新的鍵盤中斷產生,
            CPU將跳轉到新的中斷門處理函數去執行鍵盤鍵值的捕獲和傳遞,這樣就改變了原系統執行
            流程。
            
                *IOAPIC重定位中斷號
                
                前面說了系統中有0xFF個中斷描述結構,這其中總會有預留的、空閑的、沒用的,搶一
            個過來耍耍唄。然后通過IOAPIC修改鍵盤硬件IRQ和第0x93個中斷描述結構的對應關系,指
            到剛搶過來的那個中斷描述結構,從而改變了原有的系統流程,達到保護或攻擊的目的。
            
                著重說下第二種方法,對IOAPIC高級中斷控制器的理解貼段文字來描述:
            
            -------------------------------------------------------------------------------    
                IOAPIC重定位表表示每個IRQ被重定位到哪個中斷處理函數。這個表一共有24項,每一
            項用兩個IOAPIC寄存器來存取(64位)。
            
                這個表的寄存器偏移從0x10開始,一直到0x3f為止,一共48個。IRQ1對應的表項所在的
            寄存器偏移為0x12和0x13,而中斷號保存在0x12寄存器的底8位(1個字節),修改這個字節
            就可以替換成其他中斷號了。
            -------------------------------------------------------------------------------
            
                這樣的描述有編程經驗的讀者應該很容易理解,不理解的可以這樣來理解:實際上,根
            據Intel的規范標準,IOAPIC設備就是82093AA芯片,搞過單片機吧?一堆堆的引腳還記得吧?
            實際編程中,82093的這些引腳被系統映射到了內存地址0xfec00000上(形成了一張表),
            對這個內存地址進行賦值(及修改表內內容)就能夠完成對芯片的控制。參照intel-82093-
            apic.pdf規范標準第3.2.4節內容結合上面的描述,可以得出兩條結論:
            
            1、表內偏移12-13h(IOREDTBL1)的內容,就是用來控制鍵盤IRQ1和鍵盤中斷的對應關系;
            2、表內偏移12-13h的數據內容中,第7:0(及0到7)底8位就是存放的對應中斷號;
            
                在默認情況下,12-13h低8位讀出來的值是0x93,連貫起來看整個過程:
            
                
                上述兩種常見攻防方法,就是在第2步和第3步上做了手腳,改變了原有流程。躲懶貼段
            代碼來補充個說明,經過這兩種方法處理過后,都可以這樣寫中斷門的測試代碼:
            
            --code-------------------------------------------------------------------------
            __declspec(naked) p2cInterruptProc()
            {
            	__asm
            	{
            		pushad					// 保存所有的通用寄存器
            		pushfd					// 保存標志寄存器
            		call p2cUserFilter			//調一個我們自己的函數。
            		//這個函數將實現一些我們自己的功能,例如讀鍵盤I/O端口
            		popfd					// 恢復標志寄存器
            		popad					// 恢復通用寄存器
            		jmp	g_p2c_old		// 跳到原來的中斷服務程序
            	}
            }
            -------------------------------------------------------------------------------
            
            	
            三、另一種方法的技術細節
            
                哎,鋪墊來鋪墊去,終于寫到這里了,其實這種方法已經有商業級應用產品在使用了,
            但國內資料中應該都還沒有說過,所以在這里科普一下,希望不要被BS和丟雞蛋,呵呵。
            
            3.1 理論知識之PIC和APIC
            
                雖然已經是APIC的時代了,但是基本上計算機中PIC和APIC是共存的,基本結構如下圖
            所示:
            
               
                可見APIC和PIC都可以接收中斷,并提交給CPU核心處理,只是中斷必須先經過APIC才能
            到PIC,而且PIC的中斷請求只交給CPU第一個核心處理。
            
                為了規范使用,MP spec為PIC和APIC共存的平臺規定了三種模式:PIC mode、Virtual 
            Wire Mode、Symmetric I/O Mode。其中開啟了Virtual Wire Mode模式后的中斷處理流程,
            可用下圖來描述:
            
                
                注意圖中虛線的路線,中斷產生以后只通過8259A直接進入了CPU1核進行處理,完全撇
            開了I/O APIC的中斷管理。也就是說,在這種模式下根本就不會執行之前的鍵盤中斷常規流
            程,0x93號中斷門派遣地址修改和IOAPIC重定向IRQ和中斷號的關聯,都不會影響到中斷的
            產生和處理過程,完全啟用一條新的執行路線來完成對鍵盤中斷的處理。
            
                而且,在這種模式下的另一個好處是,可以無視多核CPU的存在,因為8259A只對CPU1核
            負責,其他核心都不參與這個中斷的處理過程。這兩個明顯特點對于鍵盤保護來說,無疑是
            好處大大的。
            
            3.2 設置允許Virtual Wire Mode模式
            
                根據資料顯示,82093AA芯片的管腳必須配置成ExtINT模式才能夠打開使用Virtual Wire 
            Mode模式,這是標準規范。還記得前面說的82093AA芯片在物理內存0xfec00000上那表內偏
            移12-13h的數據內容嗎,前面只說了末尾的8位,看看其他位是干什么的。
            
                第10:8位(也就是8到11位),名為Delivery Mode (DELMOD)—R/W,如果設置為111則
            表示管腳使用ExtINT模式,詳細英文描述如下:
            
            -------------------------------------------------------------------------------
            111 ExtINT Deliver the signal to the INTR signal of all processor cores listed 
            in the destination as an interrupt that originated in an externally connected 
            (8259A-compatible) interrupt controller. The INTA cycle that corresponds to this 
            ExtINT delivery is routed to the external controller that is expected to supply 
            the vector. A Delivery Mode of "ExtINT" requires an edge trigger mode.
            -------------------------------------------------------------------------------
            
                編程修改鍵盤資源IRQ1所對應的0xfec00012-0xfec00013h內容的第8到第11位,將值改
            為111啟用ExtINT,就成功開啟了Virtual Wire Mode模式。接下來,再看對PIC的處理,也
            就是需要對8259A芯片進行激活操作。
            
            3.3 8259A芯片編程
            
                和之前說的82093AA芯片略有不同,對這個芯片的控制和操作,是通過I/O端口讀寫來完
            成的。先來看看8259A長啥樣子:
            
                
                現在,有沒有回到了大學的感覺,沒錯!這就是大學里面經常做單片機實驗啊搞來搞去
            的那類東西,只不過原來是在模擬環境下編程,現在換到計算機上來了,淚奔……參考了些
            資料,有了下面的代碼:
            
            --code-------------------------------------------------------------------------
            g_idle_id--;//事先搶的一個空閑IDT號
            
            //關中斷
            __asm cli
            
            // 發送 ICW1 : 使用 ICW4,級聯工作
            __asm mov al , 0x11
            __asm out 0x20 , al
            __asm out 0xa0 , al
            // 發送 ICW2,中斷起始號從g_idle_id開始(第一片)及g_idle_id+8開始(第二片)
            __asm mov al , g_idle_id
            __asm out 0x21 , al
            g_idle_id += 8;
            __asm mov al , g_idle_id
            __asm out 0xa1 , al
            // 發送 ICW3
            __asm mov al , 0x4
            __asm out 0x21 , al
            __asm mov al , 0x2
            __asm out 0xa1 , al
            // 發送 ICW4
            __asm mov al , 0x1
            __asm out 0x21 , al
            __asm out 0xa1 , al
            // 設置中斷屏蔽位 OCW1 ,屏蔽所有中斷請求
            __asm mov al , 0xff
            __asm out 0x21 , al
            __asm out 0xa1 , al
            
            //許可鍵盤中斷,也只許可處理此中斷
            __asm mov al , 0xfd
            __asm out 0x21 , al
            //開中斷
            __asm sti
            
            g_idle_id -= 8;
            g_idle_id++;
            -------------------------------------------------------------------------------
            
                其中的g_idle_id是搶過來用的一個新注冊的IDT項,需要注意的是這個g_idle_id的值
            的16進制個位數需要等于9!
            
                如圖3.3所示8259A的16個引腳對應IRQ0~IRQ15,而這16個IRQ資源需要對應到16個IDT結
            構上去(雖然只需要用其中的一個,及鍵盤的),而且起始的IDT號16進制個位數需要是8,
            也就是IRQ0對應8、IRQ1對應9依次類推,鍵盤剛好被默認分配IRQ1,對應的是9。
            
                但是為什么起始的ID值需要滿足16進制個位數為8呢?可能英文資料里面有說明,懶得
            看了也懶得驗證了……和這個經驗值相關的一段中文描述如下:
            
            -------------------------------------------------------------------------------
                在BIOS初始化PIC的時候,IRQ0~IRQ7被分配了0x8~0xF的中斷號,然而當CPU轉到保護模
            式下工作的時候,0x8~0xF的中斷號卻被CPU用來處理錯誤!一點不奇怪,CPU是Intel生產的,
            而計算機卻是由IBM生產的,兩家公司沒有協調好:(。
            -------------------------------------------------------------------------------
            
                至此,經過3.2和3.3節的編程設置,就能夠實現3.1節中描述的工作流程。
                
            
            四、后記
            
                通過IDA調試和文中所帶的關鍵代碼,就能夠驗證這個鍵盤保護技術的可行性,但是要
            做到商業應用,還要經歷很多磨難,比如接收到中斷請求后的處理應該怎么做。而且,這種
            技術也無法對抗直接I\O端口讀寫的鍵盤嗅探,還需要考慮使用虛擬按鍵加擾等等。
            
                另外對于8259A的控制,筆者沒有找到方法從芯片內讀出之前已設置的中斷號,如果真
            是沒有這樣的功能,那對鍵盤保護來說這又會是一個優點。最后,由于對這塊內容研究的時
            間不長,文中欠缺之處還請包涵和指教。
            
            
            五、參考文獻
            
            《Microsoft Windows Internals》
            《Linux設備驅動開發詳解》
            《intel-82093-apic》
            《intel-8259a-pic》
            《Interrupt in Linux(硬件篇)》
            《保護模式下的8259A芯片編程及中斷處理探究》
            《寒江獨釣-內核安全編程》
            
            附件下載
            -EOF-
            
            <span id="7ztzv"></span>
            <sub id="7ztzv"></sub>

            <span id="7ztzv"></span><form id="7ztzv"></form>

            <span id="7ztzv"></span>

                  <address id="7ztzv"></address>

                      亚洲欧美在线