Windows 64位驅動編程基礎與win64 ssdt


 

 

 

 

Win64編程

32位系統逐漸淘汰,轉到64位編程相當重要. 但苦於64位驅動編程網上的資料比較雜亂

這里打算寫寫關於64位驅動編程的內容,當然大部分內容都是從網上搜集過來的,然后匯集到一起好用來學習.

 

  1. 准備

 

雙機調試, 加載驅動工具,debgview工具, win10重啟后禁用驅動簽名. 重啟后加載驅動

雙機調試:

在win7虛擬機關機狀態添加一個基於命名管道的串口,然后設置另一端時應用程序,然后

執行下面命令

64系統開始有個驅動簽名機制,沒有通過微軟簽名的驅動無法加載, 我們調試時需要禁用它.

開機按f8后有個禁用驅動簽名啟動選項, 選擇它啟動即可.

bcdedit /dbgsettings serial baudrate:115200 debugport:1    (最后的1表示虛擬機中設置的com1)

     bcdedit /copy {current} /d debug     (記住這里返回的id號,下面用到)

            bcdedit /displayorder {current} {ID}    這里的ID設置為第2條命令返回的id

            bcdedit /debug {ID} ON              這里的ID設置為第2條命令返回的id

重啟即可.

 

2.代碼

對於ULONG 在64編譯時自動轉為ULONG64

如果是ULONG_PTR 則編譯器自動幫我們轉換

無類型指針使用PVOID64.

通過KdPrint打印時, %x不用而用%p .

從xp到windows7 64位      像EPROCESS等結構體也有變化,通過windbg可以查看比較.

 

對於驅動代碼來說, 因為那些數據類型都有2個版本:以32結尾和以64結尾,它通過在不同環境編譯時自動轉到目標類型

 

3.Patchguard

說白了,就是微軟為了讓系統更安全, 不能隨隨便便就能hook和inline,不能隨隨便便就能通過修改EPROCESS來隱藏進程.  

這家伙每隔一段時間對系統關鍵文件,內存區域進行CRC校驗,發現不對立刻進行0x109藍屏.

而且它自己藏在內存中不好通過解決它來繞過patchguard.

https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/bug-check-0x109---critical-structure-corruption

上面的網站有列出的被其保護的內容.

 

  4. 64位ssdt表的查找

在32位系統中我們可以通過已導出的結構體名直接操作, 或者搜素函數KeAddSystemServiceTable, 或者通過windbg查看.

但是在64位系統中並沒有導出這個結構. 所以需要通過其他方式找到他.

思路1  (這個思路參考黑客防線2011合訂本下半年第7頁)

通過讀取C0000082寄存器 獲得KiSystemCall64函數的地址, 因為這個函數沒有導出,故通過這種方式.. (相當佩服作者底層知識功底)

在往下搜索0x500個字節左右就能得到KeServiceDescriptorTable地址

在windbg中查看:

而且KeServiceDescriptorTable的特征碼是4c8d15

    KeServiceDescriptorTableShadow的特征碼是4c8d1d

 

 

 

查找思路是, 將ntoskrnl.exe拖到ida,隨便找到一個內核函數,比如ZwCreateFile: 

 

 

所以在KiSystemServiceRepeat 里面就能看到 在加載好符號的windbg中 反匯編即可:

 

編寫代碼如下 :

ULONGLONG GetKeSeviceDescriptorTable64()

{

    PUCHAR startSearchAddress = (PUCHAR)__readmsr(0xC0000082);

    PUCHAR endSearchAddress = startSearchAddress + 0x500;

    PUCHAR i = 0;

    UCHAR b1 = 0, b2 = 0, b3 = 0;

    ULONG temp = 0;

    ULONGLONG addr = 0;

    for ( i = startSearchAddress; i < endSearchAddress; i++)

    {

         if (MmIsAddressValid(i) && MmIsAddressValid(i + 1) && MmIsAddressValid(i + 2))

         {

             b1 = *i;

             b2 = *(i + 1);

             b3 = *(i + 2);

             if (b1 == 0x4c && b2 == 0x8d && b3 == 0x15)

             {

                  memcpy(&temp, i + 3, 4);

                  addr = (ULONGLONG)temp + (ULONGLONG)i + 7;//加上指令長度

                  KdPrint(("find ssdt is %p\n", addr));

                  return addr;

             }

         }

    }

    KdPrint(("find ssdt error\n"));

    return 0;

}

  

 

測試結果:

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM