Windows內核驅動程序靜態逆向之套路方法

2020-12-10 酷扯兒

編者按:這是一篇講解Windows內核驅動逆向分析之套路方法的好文,可以幫助大家奠定逆向分析木馬驅動文件的基礎,具有很強的指導性。通過此文,理清思路,掌握固定模式的逆向分析套路,方便大家按圖索驥。

文中作者(安全客)舉例分析的是一個非常簡單標準的驅動;下圖是我用Ghidra9.1分析mimikatz.sys,這個驅動要複雜一些,但總體思路是一樣的。

文章很長,希望你能認真地看完,也不枉我的一番心血。

文章來源:安全客

一、工作流程:

1、跟隨DriverEntry的第一個參數,即驅動程序對象,直至找到指示MajorFunction表的偏移量。

2、在MajorFunction[0xe]處查找偏移量,標記DeviceIoControl IRP Handler。

3、跟隨這個函數的第二個參數PIRP,直至找到PIRP->Tail +0x40,將其標記為CurrentStackLocation。

4、從CurrentStackLocation查找偏移量+0x18,這就是我們想尋找的IOCTL。

在很多情況下,我們會跳過第3步和第4步,並藉助反編譯器進行一連串的DWORD比較。如果為了方便,我們往往會尋找對IofCompleteRequest的調用,然後從調用向上滾動,以查找DWORD比較。

二、概述

多年來,許多惡意組織紛紛致力於針對Windows內核模式軟體驅動程序進行攻擊,特別是針對第三方發布的驅動程序開展攻擊。在這些漏洞中,一個比較常見和有據可查的就是CAPCOM.sys任意函數執行、Win32k.sys本地特權提升以及EternalBlue池損壞漏洞。攻擊者在驅動程序中得到了一些新的攻擊維度,無論是通過傳統的漏洞利用原語,還是濫用合法的驅動程序功能,這些都無法在用戶模式中實現。

隨著Windows安全性的不斷發展,研究內核模式驅動程序中的漏洞利用對於我們的攻防技術而言變得越來越重要。為了輔助分析這些漏洞,我認為比較重要的一件事是,我們需要在研究中探尋內核漏洞,並找到一些值得關注並且可以濫用的功能。

在本文中,我將首先介紹驅動程序的工作原理,說明所需的先驗知識,隨後將進入反彙編領域,逐步查找潛在的易受攻擊的內部函數。

目標識別與選擇

通常情況下,我們要首先分析的,就是基礎工作站和伺服器映像上到底加載了哪些驅動程序。如果我們能在這些核心驅動程序中發現漏洞,那麼其影響將會比較廣泛。同時,這也在對抗過程中帶來了一個好處,也就是不需要再投放和加載新的驅動程序,從而降低被發現的概率。為此,我將手動查看註冊表中的驅動程序(HKLM\System\ControlSetServices,其中Type為0x1,ImagePath包含*.sys的條目),或使用類似於DriverQuery的工具通過C2來運行。

在選擇目標時,我們需要考慮綜合因素,因為沒有某一種特定類型的驅動程序是比較容易受到攻擊的。儘管如此,但我們傾向於將目標放在由安全廠商發布的驅動程序、由主板廠商發布的任何內容以及性能監控軟體。並且,我們傾向於忽略掉微軟的驅動程序,因為我們通常沒有太多的時間對其進行深入研究。

三、驅動內部原理分析

如果大家以前沒有開發過內核模式軟體驅動程序,那麼可能會發現,它看起來要比實際複雜得多。在開始進行逆向之前,必須首先了解三個重要概念:DriverEntry、IRP Handler和IOCTL。

3.1DriverEntry

與C/C++語言中的main()函數非常相似,驅動程序必須指定入口點DriverEntry。

DriverEntry要負責很多工作,例如創建設備對象、創建用於與驅動程序和核心函數(IRP Handler、卸載函數、回調例程等)進行通信的符號連結。

DriverEntry首先使用到IoCreateDevice()或IoCreateDeviceSecure()的調用來創建設備對象,後者通常用於將安全描述符應用於設備對象,以限制對本地管理員和NT AUTHORITYSYSTEM的訪問。

接下來,DriveEntry將IoCreateSymbolicLink()與先前創建的設備對象一起使用,以建立符號連結,該連結將允許用戶模式進程與驅動程序進行通信。

其代碼如下:

NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath) {

UNREFERENCED_PARAMETER(RegistryPath);

NTSTATUS status;

// Create the device object

UNICODE_STRING devName = RTL_CONSTANT_STRING(L"\Device\MyDevice");

PDEVICE_OBJECT DeviceObject;

NTSTATUS status = IoCreateDevice(DriverObject, 0, &devName, FILE_DEVICE_UNKNOWN, 0, FALSE, &DeviceObject);

if (!NT_SUCCESS(status)) {

KdPrint(("Failed to create device object");

return status;

}

// Create the symbolic link

UNICODE_STRING symLink = RTL_CONSTANT_STRING(L"\??\MySymlink");

status = IoCreateSymbolicLink(&symLink, &devName);

if (!NT_SUCCESS(status)) {

KdPrint(("Failed to create symbolic link"));

IoDeleteDevice(DeviceObject);

return status;

}

return status;

}

最後,DriverEntry還定義了IRP Handler的函數。

3.2IRP Handler

中斷請求包(IRP)本質上只是驅動程序的一條指令。這些數據包允許驅動程序通過提供函數所需的相關信息來執行特定的主要函數。主要函數的代碼較多,但其中最常見的是IRP_MJ_CREATE、IRP_MJ_CLOSE和IRP_MJ_DEVICE_CONTROL。

這些與用戶模式函數相關:

IRP_MJ_CREATE → CreateFileIRP_MJ_CLOSE → CloseFileIRP_MJ_DEVICE_CONTROL → DeviceIoControl

在用戶模式下執行以下代碼時,驅動程序將收到具有主要函數代碼IRP_MJ_CREATE的IRP,並將執行MyCreateCloseFunction函數:

hDevice = CreateFile(L"\\.\MyDevice", GENERIC_WRITE|GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

在幾乎所有情況下,對我們來說最重要的主要函數是IRP_MJ_DEVICE_CONTROL,該函數用於發送請求,以從用戶模式執行特定的內部函數。這些請求中包括一個IO控制代碼,該代碼負責通知驅動程序具體的操作,還包含一個向驅動程序發送數據和從驅動程序接收數據的緩衝區。

3.3IOCTL

IO控制代碼(IOCTL)是我們的主要搜尋目標,因為其中包含我們需要知道的很多重要細節。它是以DWORD表示,每一個32位都表示有關請求的詳細信息,包括設備類型、需要的訪問、函數代碼和傳輸類型。微軟提供了一個可視化的圖表來分解這些欄位:

1、傳輸類型:定義將數據傳遞到驅動程序的方式,具體的類型可以是METHOD_BUFFERED、METHOD_IN_DIRECT、METHOD_OUT_DIRECT或METHOD_NEITHER。

2、函數代碼:驅動程序要執行的內部函數。這部分應該是以0x800開始,但實際上我們會發現,很多都是從0x0開始的。其中的自定義位(Custom bit)用於定義廠商分配的值。

3、設備類型:在IoCreateDevice(Secure)()指定的驅動程序設備對象類型。在Wdm.h和Ntddk.h中,定義了許多設備類型,但對於軟體驅動程序而言,最常見的一種就是FILE_DEVICE_UNKNOWN (0x22)。其中的通用位(Common bit)用於定義廠商分配的值。

驅動程序標頭定義示例如下:

#define MYDRIVER_IOCTL_DOSOMETHING CTL_CODE(0x8000, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)

我們完全可以自行對這些值進行解碼,但如果大家覺得解碼過程過於繁瑣,可以使用OSR的在線解碼器。並且,我們發現!ioctldecode Windbg擴展可能對這一過程非常有幫助。當我們編寫與目標驅動程序接口的應用程式時,這些細節將尤為重要。在反彙編程序中,它們仍然會以十六進位表示。

3.4 組合

我知道,上述的過程可能太過複雜。但是,我們可以對其進行簡化,並類比於發送網絡數據包的過程來對其進行分析。我們可以使用所需的任何細節來構造數據包,然後將其發送到伺服器進行處理,使用該數據包執行某些操作。而對於伺服器端,要不然會忽略我們的數據包,要不然會返回一些結果。接下來,我們對IOCTL的發送和處理方式進行簡化並說明:

1、用戶模式應用程式獲取符號連結上的句柄。

2、用戶模式應用程式使用DeviceIoControl()將所需的IOCTL和輸入/輸出緩衝區發送到符號連結。

3、符號連結指向驅動程序的設備對象,並允許驅動程序接收用戶模式應用程式的數據包(IRP)。

4、驅動程序看到該數據包來自DeviceIoControl(),因此將其傳遞給已定義的內部函數MyCtlFunction()。

5、MyCtlFunction()將函數代碼0x800映射到內部函數SomeFunction()。

6、SomeFunction()執行。

7、IRP已經完成,其狀態以及驅動程序在用戶模式應用程式中提供的輸出緩衝區中包含的為用戶提供的所有內容都將傳回給用戶。

注意:在這裡我們並不是說IRP已經完成,但需要關注的是,一旦SomeFunction()執行,上述時間就可以發生,並且將得到函數返回的狀態代碼,這表明操作的結束。

四、驅動程序反編譯

現在,我們已經對需要探尋的關鍵結構有了一定了解,是時候開始深入研究目標驅動程序了。我們會清晰展現出如何在Ghidra中執行此操作,IDA中的方法與之完全相同。

一旦我們將要定位的驅動程序下載到我們的分析環境中,就應該開始尋找IRP Handler,該處理程序會使我們明確潛在的關鍵函數。

4.1 設置

由於Ghidra中並沒有包含太多分析驅動程序所需的符號,所以我們需要找到一種方法,以某種方式將其進行導入。幸運的是,感謝0x6d696368(Mich)此前所做的研究工作,幫助我們簡化了這一過程。

Ghidra支持Ghidra數據類型存檔(GDT)格式的數據類型,這些數據類型是打包的二進位文件,其中包含從所選標頭衍生出的符號,這些符號可能是自定義的,也可能是微軟提供的。有關這些文件的文檔並不多,並且確實需要進行一些手工修改,但幸運的是,Mich已經完成了這部分工作。

我們在他的GitHub項目中找到了針對Ntddk.h和Wdm.h的預編譯GDT,即ntddk_64.gdt。我們需要在運行Ghidra的系統上下載該文件。

要導入並開始使用GDT文件,我們需要打開要分析的驅動程序,單擊「Data Type Manager」的下拉箭頭,然後選擇「Open File Archive」。

然後,選擇先前下載的ntddk_64.gdt文件並打開。

在「Data Type Manager」窗口中,目前有一個新的條目「ntddk_64」。右鍵單擊該條目,然後選擇「Apply Function Data Types」,隨後將會更新反編譯器,並且可以看到許多函數籤名的變化。

4.2 查找DriverEntry

現在,我們已經對數據類型進行了排序,接下來需要確定驅動程序對象。這個過程相對簡單,因為它是DriverEntry的第一個參數。首先,在Ghidra中打開驅動程序,並進行初始的自動分析。在「Symbol Tree」窗口下,展開「Exports」項目,就可以找到有一個名為entry的函數。

注意:在某些情況下,可能還會有一個GsDriverEntry函數,看起來像是對兩個未命名函數的調用。這是開發人員使用/GS編譯器標誌並設置棧Cookie的結果。其中的一個函數是真正的驅動程序入口,因此我們需要檢查其中較長的一個函數。

4.3 查找IRP Handler

我們需要查找的第一個內容是驅動程序對象的一系列偏移量。這些都與nt!_DRIVER_OBJECT結構的屬性有關。其中,我們最感興趣的一個是MajorFunction表(+0x70)。

使用我們新應用的符號,就變得容易很多。因為我們知道,DriverEntry的第一個參數是指向驅動程序對象的指針,所以我們可以在反編譯器中單擊該參數,然後按CTRL+L來調出數據類型選擇器,搜索PDRIVER_OBJECT,然後單擊「OK」,這樣將更改參數的類型以對應其真實類型。

注意:我希望將參數名稱更改為DriverObject,以在執行該函數時為我提供一些幫助。要執行此操作,需要單擊參數,然後按「L」,然後輸入要使用的名稱。

現在,我們就有了適當的類型,是時候開始尋找MajorFunction表的偏移量了。有時候,我們可能會在DriverEntry函數中看到這個權限,但有時可以看到驅動程序對象作為參數傳遞給另一個內部函數。

接下來,我們查找DriverObject變量的出現。使用滑鼠可以輕鬆完成查找工作,只需要在變量上單擊滑鼠滾輪,反編譯器中就可以突出顯示該變量的所有實例。在我們使用的示例中,沒有看到對驅動程序對象的偏移量的引用,但發現它被傳遞到另一個函數。

我們跳到FUN_00011060這個函數,然後將第一個參數重新輸入到PDRIVER_OBJECT中,因為我們知道DriverEntry將其作為唯一參數顯示。

然後,再次開始從DriverObject變量中搜索對偏移量的引用。我們正在尋找的是:

在vanilla Ghidra中,我們將這些視圖視為DriverObject的詳細偏移量,但由於我們已經應用了NTDDK數據類型,因此現在它變得更為整潔。現在,我們已經找到了標記了MajorFunction表的DriverObject偏移量,索引的位置是(0, 2, 0xe)?這些偏移量都是在WDM標頭(wdm.h)中定義,代表IRP主要函數代碼。

在我們的示例中,驅動程序處理3個主要函數代碼:IRP_MJ_CREATE、IRP_MJ_CLOSE和IRP_MJ_DEVICE_CONTROL。其中,前兩個我們並不關注,但第三個IRP_MJ_DEVICE_CONTROL非常關鍵,因為在該偏移量(0x104bc)處定義的函數使用了DeviceIoControl及其包含的I/O控制代碼(IOCTL)來處理從用戶模式發出的請求。

接下來,讓我們深入研究該函數。我們查看MajorFunction[0xe]的偏移量,將會看到驅動程序中偏移量為0x104bc的函數。該函數的第二個參數以及所有設備I/O控制IRP Handler是指向IRP的指針。我們可以再次使用CTLR+L,將第二個參數重新命名為PIRP(或者其他自定義名稱)。

IRP結構非常複雜,即使有了我們新的類型定義,也無法弄清楚所有內容。在其中,我們首先要尋找的是IOCTL。這部分在反編譯器中將以DWORD來表示,但我們需要知道它們將分配給哪個變量。為了弄明白這一點,我們要依靠我們的老朋友:WinDbg。

我們可以看到,IRP的第一個偏移量是IRP->Tail + 0x40。

接下來,我們深入研究一下IRP結構。

我們可以看到Tail是從偏移量+0x78開始,但是0x40位元組又是什麼呢?藉助WinDbg,我們可以看到CurrentStackLocation是位於Irp->Tail偏移量+0x40的位置,但僅僅顯示為一個指針。

微軟似乎暗示,這是指向_IO_STACK_LOCATION結構的指針。因此,在反編譯器中,我們可以將lVar2重命名為CurrentStackLocation。

在這個新變量之後,我們希望找到對偏移量+0x18(即IOCTL)的引用。

如果希望,還可以將該變量重命名為便於識別的名稱。

現在,我們已經找到了包含IOCTL的變量,我們看到,它與一系列DWORD進行了比較。

這些比較是驅動程序檢查這些IOCTL是否屬於其可以處理的範圍。在每次比較之後,可能會發生內部函數調用。當特定的IOCTL從用戶模式發送到驅動程序時,將會執行這些操作。在上面的示例中,驅動程序收到IOCTL 0x8000204c時,將執行FUN_0000944c(某些類型的列印函數)和FUN_000100d0。

五、函數逆向

既然我們已經知道驅動程序收到IOCTL時哪些函數會在內部執行,我們就可以開始逆向這些函數,以找到有趣的功能。由於各個驅動程序之間的差異很大,因此我們的分析中就沒有包含這部分內容。

在這裡,我的常用思路是,在這些函數中查找有趣的API調用,確定輸入所需的內容,然後使用簡單的用戶模式客戶端(根據目標來複製並修改的通用模板)來發送IRP。在分析EDR驅動程序時,我還希望了解它們具體的功能,例如進程對象處理程序回調。在此過程中,我找到了一些不錯的驅動程序漏洞,可以激發出我們的一些靈感。

需要注意的一件重要事情,特別是在使用Ghidra時,需要注意這個變量聲明:

如果我們在WinDbg中查看此內容,我們可以發現,在這個偏移量的位置是指向MasterIrp的指針。

實際上,我們看到的是與IRP->SystemBuffer的併集,該變量實際上是METHOD_BUFFERED數據結構。這也就是為什麼我們經常會看到它作為參數傳遞給內部函數的原因。在對內部函數進行逆向的過程中,請確保將其視為輸入/輸出緩衝區。

假期的時間充裕,總是能做很多事情!

相關焦點

  • 詳解Windows滲透測試工具Mimikatz的內核驅動
    而驅動程序為我們提供了一種通過用戶模式應用程式來調用這些函數的方法,我們也將在本文的後面部分進行深入探討。 三、加載Mimidrv要使用Mimikatz驅動程序,第一步可以使用命令!+,該命令會從用戶模式啟動驅動程序,並請求為當前令牌分配SeLoadDriverPrivilege。
  • Linux內核學習:簡單的字符設備驅動
    Linux內核設備驅動架構如下圖所示,Linux內核針對上述3類設備抽象出來一套完整的驅動框架和API接口,以便驅動開發者在編寫某類設備驅動時可重複使用。字符設備是以字節為單位的I/O傳輸,這種字符流的傳輸率通常比較低。
  • Windows 10 變身開發者利器:內置 Linux 內核,人人可用,像安裝驅動...
    微軟的開發者博客剛剛公布 [1] ,下一個 Windows10 版本,不僅自帶 Linux 內核,而且還會通過 Windows Update 安裝方式更新,簡單得就像安裝驅動程序一樣。比如直接使用 GNU Linux 的命令行工具,各種程式語言諸如 Python、Ruby 的解釋器,甚至像 XWindow 這樣的圖形應用程式。當然,微軟指出 WSL 主要是面向應用程式的開發者,而不是日常的桌面環境。
  • 通過逆向PCHunter驅動學習64位 windows內核之 精準定位
    首先感謝下PCHunter的作者提供了這麼優秀且還是免費的內核工具。
  • Linux 內核學習:環境搭建和內核編譯
    作為桌面系統,當對於windows而言,linux還是有許多不方便的,即使是最近幾年非常火的ubuntu,號稱可以替換windows的發行版,在日常使用的軟體方面,還是有不小的差距;再者,我們在工作中常常還是需要開發windows程序,而家裡更不合適了,家裡人基本上都用慣了windows,總不能強迫他們去用不懂的linux系統吧。
  • 如何在Windows中更新驅動程序
    如果要修復計算機的錯誤硬體,可能需要更換其驅動程序。以下是如何在Windows 10上更新設備驅動程序。驅動程序是一小塊軟體,可幫助您的PC與某個硬體進行通信。您的滑鼠,鍵盤,印表機和其他設備都有驅動程序,每隔一段時間,這些驅動程序可能需要更新來修復某些問題,引入新功能或提高性能。但是,一般情況下,您不需要經常更新驅動程序。如果您的硬體按預期工作,最好讓它成為現實,因為新驅動程序可能會引入問題並修復它們。但是,如果您遇到特定硬體問題 - 或者您知道某個驅動程序存在需要修復的安全漏洞 - 更新它可能是個好主意。
  • 2020 年的 Linux 內核仍為 Macintosh II 修復驅動
    Linux 內核正在對其驅動程序進行一些修復和改進工作,以更好地支持 Macintosh II 系統上的 Apple Desktop Bus(蘋果桌面總線)。隔一段時間就能看到 Linux 內核驅動對 Apple PowerBook 100 系列產品支持的改進。
  • 改善Linux內核實時性方法的研究與實現
    但是內核中仍有大量的不可搶佔區域, 如由自旋鎖spinlock保護的臨界區,以及一些失效搶佔的臨界區。另一個影響Linux實時性的因素就是關中斷,同步操作中使用的關中斷指令增大了中斷延遲,這樣很多由中斷驅動的實時任務得不到及時的執行,系統的實時性能得不到保障。因此提高Linux的可搶佔性,改進其中斷機制有利於改善內核的實時性。
  • checkra1n win 版僅差驅動,續籤已修復
    按照目前信息來看,checkra1n需要一個內核驅動(非常複雜代碼)才能在 Windows運行,因此它並不會很快出現,但 Linux 很快發布,另!續籤插件已修復。 windows 運行 checkra1n,相當的複雜,況且內核驅動是的問題。
  • 關鍵的Windows內核數據結構一覽(上)
    這些例程被驅動用來執行特定進程上下文的行為,主要是訪問進程的用戶模式虛擬地址空間。Windows中具體的功能如附加和分離一個線程到進程以及線程懸掛都是基於APC實現。APC有3種類型:用戶模式;普通內核模式;特殊內核模式。 KAPC表示了異步過程調用(APC)結構體,它包含一個指向驅動支持的例程的指針。
  • Linux 內核的測試和調試(6)
    runltp 腳本默認情況下會測試下面的子系統:文件系統壓力測試磁碟 IO 測試內存管理壓力測試IPC(進程間通信)測試調度器測試命令的功能性驗證測試系統調用功能驗證測試LTP-DDT 是一個基於 LTP 的測試應用(LCTT:就是 LTP 的閹割版麼),
  • Linux 系統內核的調試
    儘管缺乏一種內置的調試內核的有效方法,但是 Linux 系統在內核發展的過程中也逐漸形成了一些監視內核代碼和錯誤跟蹤的技術。同時,許多的補丁程序應運而生,它們為標準內核附加了內核調試的支持。儘管這些補丁有些並不被 Linux 官方組織認可,但他們確實功能完善,十分強大。調試內核問題時,利用這些工具與方法跟蹤內核執行情況,並查看其內存和數據結構將是非常有用的。
  • Windows USB 驅動程序接口及傳輸方式
    Windows USB 驅動程序接口系統中的USB的驅動程序完成許多的工作。實際上對於一些HID的USB設 備,象鍵盤,滑鼠和遊戲操縱杆之類的設備可以自動的被系統識別並且支持.而除此之外的設備就需要自己寫一個驅動程序來完成硬體和軟體之間的聯繫。在核心模 式(kernel mode)下,驅動程序用IOCTL來組織和操作一些由其他部分發過來的要求和命令。
  • 一個XP使用者眼中的Windows 7-Windows 7,XP ——快科技(驅動之家...
    安裝過程大概花了40分鐘,windows 7自帶我電腦所有硬體的驅動,所以安裝完後即可使用。這是windows 7給我的硬體的評分:2、Windows Media Player 12這沒有什麼可說的,windows肯定會自帶自己的媒體播放工具。同時,Windows media center也包含在程序裡。3、自帶截圖工具
  • 新手——win32程序的半生(CreateProcess)
    1、靜態分析:IDA PRO2、動態分析:Ollydbg/X32dbg/windbg3、ARK工具:PCHunter
  • 超40個Windows驅動存漏洞,被利用後重裝系統也無法解決問題
    據外媒報導,在拉斯維加斯舉行的DEF CON 27安全會議上,來自固件和硬體安全公司Eclypsium的研究人員表示,他們在來自不同供應商的四十多個驅動程序中發現了高風險漏洞。這些漏洞可能會允許攻擊者獲得系統最高權限,並用一種前所未見的方式隱藏其惡意軟體。
  • 基於Linux平臺下的FPGA的ARM驅動開發方法
    為此,本文以S3C2410上使用Altera公司的EP2S30F67214為例,系統地介紹了在Linux系統環境下的FPGA的驅動方法。1基本原理Linux下的設備驅動程序通常是一個存在於應用程式和實際設備間的軟體層。
  • linux字符設備驅動基本框架
    2.驅動程序的框架在理解設備框架之前,首先要知道驅動程序主要做了以下幾件事1.將此內核驅動模塊加載到內核中2.從內核中將驅動模塊卸載3.聲明遵循的開源協議2.1 Linux下的設備Linux下分成三大類設備:字符設備:字符設備是能夠像字節流一樣被訪問的設備。一般來說對硬體的IO操作可歸結為字符設備。
  • 索尼為PS5 DualSense手柄推出官方Linux驅動程序
    作為一個聖誕驚喜,索尼為 PS5 標配的 DualSense 手柄發布了官方的 Linux 內核驅動程序。據悉,在該人機互動(hid-playstation)設備驅動通過認可之後,玩家將能夠在 USB 和藍牙模式下調用 DualSense 手柄的各項功能,以及在 Linux 平臺上支持其它 PlayStation 硬體。索尼表示,該 Linux 官方手柄驅動支持所有關鍵功能,以及 LED、燈條、運動傳感器、觸摸板、電量、以及振動器。
  • 學術論文分享-Java企業應用程式靜態分析
    這也體現了本篇論文關注的是那些被現有靜態分析框架所忽視的,但是在企業應用程式中大量存在的「Frameworks and Caches」(框架和緩存)的靜態分析方法。1.什麼是靜態分析在介紹論文之前,我先來介紹一下什麼是靜態分析:靜態分析就是在不運行程序的情況下對源碼進行詞法分析、語法分析、控制流、數據流、指針分析等,來檢測程序是否滿足規範性和安全性等。