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

Win64編程編程

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

這裏打算寫寫關於64位驅動編程的內容,固然大部份內容都是從網上搜集過來的,而後聚集到一塊兒好用來學習.安全

 

  1. 準備

 

雙機調試, 加載驅動工具,debgview工具, win10重啓後禁用驅動簽名. 重啓後加載驅動函數

雙機調試:工具

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

執行下面命令測試

64系統開始有個驅動簽名機制,沒有經過微軟簽名的驅動沒法加載, 咱們調試時須要禁用它.網站

開機按f8後有個禁用驅動簽名啓動選項, 選擇它啓動便可.spa

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

     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中 反彙編便可:

 

編寫代碼以下 :

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

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;

 

}

  

 

測試結果:

 

相關文章
相關標籤/搜索