使用OllyDbg 分析 USB HID 裝置介面協議

來源:互聯網
上載者:User
使用OllyDbg 分析 USB HID 裝置介面協議
作者: Tase tase@163.com
關鍵字: OllyDbg,USB ,HID,Bus hound,

分析工具: OllyDbg,Bus hound
分析對象: 一個USB 介面飛行模擬器

目的:通過分析使用USB HID裝置的軟體,從中其主程式中“扣”HID 裝置資料協議,再根據這些協議自己實現USB HID的裝置,達到仿製原裝 HID資料擷取裝置的目的。

我有幸拿到了一款原裝的飛行類比軟體和介面裝置,這個模擬器是通過一個USB介面把遙控裝置上的資料擷取到PC,再通過軟體類比現實飛行,因為原裝裝置昂貴,因此打算DIY一套介面,便下手分析了一把!

這個模擬器軟體有兩部分組成,其一是類比軟體,其二是一個USB的資料擷取裝置,在拿到裝置前,我就猜想,它可能是HID(人體學裝置)DEVICE,現 在很多USB資料擷取裝置都是採用的HID協議的方法設計,這樣的話就可以實現在WINDOWS下免驅動安裝,並且可以通過windows內建的介面以客 戶態的方式訪問這些硬體介面。

經過測試,果然是HID裝置,使用Bushound5 匯流排觀察器,用它來捕捉匯流排上的USB裝置資料,HID裝置很簡單,花了兩個小時就基本弄清楚了它大部分的資料含義,因此很快就按照我理解的協議把裝置在 單片機開發板上實現了,插上我的裝置,模擬器軟體很快就識別了我的介面,但顯示各通道資料時,都是0,也就是說,它的系統檢測到了一個介面裝置,但這個設 備採樣的資料是錯誤的。

於是我又回到匯流排資料分析,找到我遺漏的2個bit,這個2個bit 是我沒有理解的,我猜想它是校正位,經過觀察,這個2個bit只和幾個位元組有關,但就是這2個bit花了我4天的時間,這幾天讓我學會Excel 中很多大多數人不知道的功能,學會了使用VBScript 寫宏,我甚至用到了MATLAB,我一直是用統計的方法尋找2bit的規律,但最終我失敗了。

山窮水盡,想到了Ollydbg 分析它主程式中的USB介面的協議,沒有想到,一個晚上,就解決了我的問題。
在Windows 下訪問HID 裝置可以有兩種方法,一是核態,也就是用驅動程式的方法訪問,這個方法非常複雜,我知道原理,但自己還沒有寫過這樣的驅動。二是客戶態,即應用程式通過調 用Windows提供的Hid 訪問函數就可以實現對HID裝置的訪問。如果我們截獲了這些函數的調用,那麼,距離我們要解決的目標就不遠了。

一般情況下,主程式識別USB HID外設的方法:首先調用HidD_GetHidGuid函數擷取HID裝置的類標識,調用SetupDiGetClassDevs函數查詢所有已安裝 的HID裝置,得到一個指向該HID裝置集合的控制代碼,調用SetupDiEnumDeviceInterface函數查詢HID裝置集中每一個裝置的介面 資訊,對每一個介面,調用SetupDiGetDeviceInterfaceDetail函數擷取其詳細的資訊,包括裝置名稱(頭四個位元組), CreateFile用此裝置名稱開啟裝置,調用SetupDiDestroyDeviceInfoList函數釋放裝置資訊集合;第二步,開啟裝置,擷取 裝置的屬性值以及裝置能力描述,調用CreaterFile函數開啟本裝置。調用HidD_GetAttributes函數,擷取USB裝置的有關屬性。 它包含了裝置的廠商ID、產品ID及產品的版本號碼等。可以根據這些資訊判斷該裝置是否為目標裝置,但我們關心的並不是這些,我們關心的是這個裝置開啟以後 的 ReadFile 操作,我們知道,Windows下的裝置都是當作檔案來讀寫的。

啟動OllyDbg 裝入模擬器軟體,下斷點 HidD_GetAttributes,CreateFile,這個函數是能把HID 的關鍵資訊擷取,例如廠商ID,產品ID,版本?等,在調試前,拔掉機器上所有不必要的USB裝置,這樣枚舉到的裝置會少些,你斷點的次數也會少很多。

因為前面用到了Bus Hound,很容易知道我們要關心的裝置的 VID 和 PID,這樣在斷點在HidD_GetAttributes, 之後,很容易得知哪個裝置是我們所關心的,在堆棧中記下裝置的字串路徑。在CreateFile函數斷點時,確認要開啟的裝置是否是我們關心的裝置?

我們關心的HID裝置開啟以後,就要關心 ReadFile 和 WriteFile了,下斷點 ReadFile ,不幸的是,這樣的斷點太多了! 想到一個問題,HID雖然是低速裝置,但重新整理時間也是10ms/幀,那麼一般的WINDOWS的定時器最多隻能精確到50ms,要想不丟幀讀取HID的設 備資料,一定會用到高精度的定時器——多媒體定時器。

用到了多媒體定時器,就肯定會用到下面的幾個函數 ,timeGetDevCaps,timeBeginPeriod,timeSetEvent ,遂下斷點在這函數,經過一番努力,果然找到了關鍵的ReadFile,讀完了HID的裝置資料後,幹什嗎? 按照常理,就該分析和校正了,果然,我分析的正確,正是如此,下面是破解當時擷取的關鍵彙編代碼,因為這篇文章是幾個月後寫的,所以有些內容只能靠回憶 了。

讀懂了這些代碼就完全弄明白了它的協議。

004417B2 . 8B0D D8CD9500 MOV ECX,DWORD PTR DS:[95CDD8] //取出CH1-CH4 的高位位元組
004417B8 . A3 00CE9500 MOV DWORD PTR DS:[95CE00],EAX
004417BD . 33D2 XOR EDX,EDX
004417BF . 8BC1 MOV EAX,ECX
004417C1 . 8A15 D7CD9500 MOV DL,BYTE PTR DS:[95CDD7] //取出CH1通道資料
004417C7 . 25 FF000000 AND EAX,0FF
004417CC . 8BF2 MOV ESI,EDX // 這裡要注意,儲存CH1的低8位元據,將來用來算校正位
004417CE . 8BD0 MOV EDX,EAX
004417D0 . 83E2 03 AND EDX,3 //用0x3 來掩碼 高位位元組,取出CH1的高2位
004417D3 . 33DB XOR EBX,EBX
004417D5 . C1E2 08 SHL EDX,8 //將CH1 的高2位左移 8位
004417D8 . 8A1D D6CD9500 MOV BL,BYTE PTR DS:[95CDD6] //取出CH2 的通道資料
004417DE . 8D9432 DC03000>LEA EDX,DWORD PTR DS:[EDX+ESI+3DC] //計算出 CH1 的最終資料,高2位+CH1的資料 + 常數3DC
004417E5 . 8915 E0CD9500 MOV DWORD PTR DS:[95CDE0],EDX //儲存CH1的資料
004417EB . 8BD0 MOV EDX,EAX
004417ED . 83E2 0C AND EDX,0C //取出CH2的高2位元遮罩
004417F0 . C1E2 06 SHL EDX,6 //計算出 CH2 的高2位
004417F3 . 8D941A DC03000>LEA EDX,DWORD PTR DS:[EDX+EBX+3DC] //計算出 CH2 的完整資料
004417FA . 33DB XOR EBX,EBX
004417FC . 8915 E4CD9500 MOV DWORD PTR DS:[95CDE4],EDX //儲存CH2 的資料
00441802 . 8BD0 MOV EDX,EAX
00441804 . 83E2 30 AND EDX,30 //取CH3 高位 的掩碼
00441807 . 8ADD MOV BL,CH //取CH3 低8位元據
00441809 . C1E2 04 SHL EDX,4 //高2位移位
0044180C . 25 C0000000 AND EAX,0C0 //取CH4 的高位元遮罩
00441811 . 8D8C1A DC03000>LEA ECX,DWORD PTR DS:[EDX+EBX+3DC] //計算出CH3 的完整資料
00441818 . 33D2 XOR EDX,EDX
0044181A . 8A15 D5CD9500 MOV DL,BYTE PTR DS:[95CDD5] //取CH4 低8位元據
00441820 . 890D E8CD9500 MOV DWORD PTR DS:[95CDE8],ECX //儲存CH3 的資料
00441826 . 8D8482 DC03000>LEA EAX,DWORD PTR DS:[EDX+EAX*4+3DC] //計算CH4 D 資料
0044182D . A3 ECCD9500 MOV DWORD PTR DS:[95CDEC],EAX //儲存CH4 的資料
00441832 . A1 DCCD9500 MOV EAX,DWORD PTR DS:[95CDDC] //取出CH5-CH8 的高位元據和標誌位元據
00441837 . A8 40 TEST AL,40 // 這個標誌的第6bit 是表示奇偶幀的
00441839 . 74 41 JE SHORT REFLEX.0044187C //如果是0 表示是偶數幀,那麼CH5,CH6 有效,GOTO 到0044187C
0044183B . 25 FF000000 AND EAX,0FF //否則 是奇數幀
00441840 . 33D2 XOR EDX,EDX
00441842 . 8A15 DBCD9500 MOV DL,BYTE PTR DS:[95CDDB] //取CH5的低8位元據
00441848 . 8BC8 MOV ECX,EAX
0044184A . 83E1 0C AND ECX,0C
0044184D . C1E1 06 SHL ECX,6
00441850 . 8D8C11 DC03000>LEA ECX,DWORD PTR DS:[ECX+EDX+3DC] //同上,計算出CH5 的完整資料
00441857 . 8BD0 MOV EDX,EAX
00441859 . 83E2 03 AND EDX,3 //取CH6 的高2位
0044185C . 890D F8CD9500 MOV DWORD PTR DS:[95CDF8],ECX //儲存CH5
00441862 . C1E2 08 SHL EDX,8
00441865 . 33C9 XOR ECX,ECX
00441867 . 8A0D DACD9500 MOV CL,BYTE PTR DS:[95CDDA] //取CH6 的低8位
0044186D . 8D940A DC03000>LEA EDX,DWORD PTR DS:[EDX+ECX+3DC] //計算出CH6 資料
00441874 . 8915 FCCD9500 MOV DWORD PTR DS:[95CDFC],EDX // 儲存CH6 資料
0044187A . EB 4A JMP SHORT REFLEX.004418C6
0044187C > 25 FF000000 AND EAX,0FF
00441881 . 33D2 XOR EDX,EDX
00441883 . 8A15 DBCD9500 MOV DL,BYTE PTR DS:[95CDDB]
00441889 . 8BC8 MOV ECX,EAX
0044188B . 83E1 0C AND ECX,0C
0044188E . C1E1 06 SHL ECX,6
00441891 . 8D8C11 DC03000>LEA ECX,DWORD PTR DS:[ECX+EDX+3DC]
00441898 . 8BD0 MOV EDX,EAX
0044189A . 890D F0CD9500 MOV DWORD PTR DS:[95CDF0],ECX
004418A0 . 83E2 03 AND EDX,3
004418A3 . 33C9 XOR ECX,ECX
004418A5 . 8A0D DACD9500 MOV CL,BYTE PTR DS:[95CDDA]
004418AB . C1E2 08 SHL EDX,8
004418AE . 8D940A DC03000>LEA EDX,DWORD PTR DS:[EDX+ECX+3DC]
004418B5 . 8BC8 MOV ECX,EAX
004418B7 . C1E9 07 SHR ECX,7 // 這裡也需要注意,這裡是取出標誌位的最高位,做判斷用的
004418BA . 8915 F4CD9500 MOV DWORD PTR DS:[95CDF4],EDX // 上面的部分是算出 7- 8 通道的資料並儲存
004418C0 . 890D 04CE9500 MOV DWORD PTR DS:[95CE04],ECX
004418C6 > 8BD0 MOV EDX,EAX //公用算2BIT 校正位的 部分 FLAG
004418C8 . 83F6 07 XOR ESI,7 //CH1 和 0X7 XOR ==> A
004418CB . 83E2 0F AND EDX,0F //標誌位取低4位 ==>B
004418CE . 03D6 ADD EDX,ESI //標誌位的低4位和A + B==>C
004418D0 . D1E2 SHL EDX,1 //C << 1 ==> D
004418D2 . 33D0 XOR EDX,EAX //D XOR FLAG ==> E
004418D4 . F6C2 30 TEST DL,30 //E & 0x30 ==>F 如果是 0 就成功了!
004418D7 . 74 3A JE SHORT REFLEX.00441913
004418D9 . A1 C4CD9500 MOV EAX,DWORD PTR DS:[95CDC4]
004418DE . 85C0 TEST EAX,EAX
004418E0 . 75 40 JNZ SHORT REFLEX.00441922
004418E2 . A1 08CE9500 MOV EAX,DWORD PTR DS:[95CE08]
004418E7 . C705 C4CD9500 >MOV DWORD PTR DS:[95CDC4],1
004418F1 . 50 PUSH EAX
004418F2 . EB 1D JMP SHORT REFLEX.00441911
004418F4 > 8B0D 08CE9500 MOV ECX,DWORD PTR DS:[95CE08]
004418FA . C705 C4CD9500 >MOV DWORD PTR DS:[95CDC4],1
00441904 . 8935 B8CD9500 MOV DWORD PTR DS:[95CDB8],ESI
0044190A . 8935 BCCD9500 MOV DWORD PTR DS:[95CDBC],ESI
00441910 . 51 PUSH ECX
00441911 > FFD5 CALL EBP
00441913 > A1 C4CD9500 MOV EAX,DWORD PTR DS:[95CDC4]
00441918 . 33F6 XOR ESI,ESI
0044191A . 3BC6 CMP EAX,ESI
0044191C .^0F84 61FEFFFF JE REFLEX.00441783
00441922 > 5F POP EDI
00441923 . 5E POP ESI
00441924 . 5D POP EBP
00441925 . 33C0 XOR EAX,EAX
00441927 . 5B POP EBX
00441928 . 59 POP ECX
00441929 . C2 0400 RETN 4

2Bit= ((((pPacket->byteCh1 ^ 0x07) + (CH_HID_REPORT[7] & 0x0F))<<1)&0x30)>>4;

當時困擾我4天的2BIT校正資料,其實用C語言一行就寫完了,興奮啊! 立刻將這個演算法寫進單片機的韌體,插上我自己DIY的HID模擬器裝置,OK,系統已經能正確的從我的裝置中採集資料了。
USB 協議破解成功!

這是我第一次使用OllyDbg 解決實際問題,愚昧之處還請各位前輩批評。

總結: 有時我們在解決一個難題的時候,往往在正面不能擷取進展時,不如從側面,後面下手,所謂殺豬捅屁股,各有各的殺法!
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.