論文關鍵字: 內核 攔截 活動進程鏈表 系統服務派遣表 線程調度鏈 驅動程序簡介
論文摘要:資訊對抗是目前發展的一個重要的方向,爲了更好的防禦,必須去深入的瞭解敵人進攻的招式。資訊對抗促使資訊技術飛速的發展。下面我選取了資訊對抗技術的中一個很小一角關於windows內核級病毒隱藏技術和反病毒偵測技術作爲議題詳細討論。
1.爲什麼選驅動程序
驅動程序是執行在系統信任的Ring0下在代碼,她擁有對系統任何軟件和硬件的訪問權限。這意味着內核驅動可以訪問所有的系統資源,可以讀取所有的內存空間,而且也被允許執行CPU的特權指令,如,讀取CPU控制寄存器的當前值等。而處於用戶模式下的程序如果試圖從內核空間中讀取一個字節或者試圖執行像MOV EAX,CR3這樣的彙編指令都會被立即終止掉。不過,這種強大的底線是驅動程序的一個很小的錯誤就會讓整個系統崩潰。所以對隱藏和反隱藏技術來說都提供了一個極好的環境。但是又對攻擊者和反查殺者提出了更高的技術要求。
2.入口例程DriverEntry
DriverEntry是內核模式驅動程序主入口點常用的名字,她的作用和main,WinMain,是一樣的。
extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{...}
DriverEntry的第一個參數是一個指針,指向一個剛被初始化的驅動程序對象,該對象就代表你的驅動程序,DriverEntry的第二個參數是設備服務鍵的鍵名。DriverEntry函數返回一個NTSTATUS值。NTSTATUS實際就是一個長整型,但你應該使用NTSTATUS定義該函數的返回值而不是LONG,這樣代碼的可讀性會更好。大部分內核模式支援例程都返回NTSTATUS狀態代碼,你可以在DDK頭檔案NTSTATUS.H中找到NTSTATUS的代碼列表。
DriverEntry的作用主要就是創建設備對象,建立設備對象的符號連結,設定好各個類型的回調函數等。
例如:
extern "C"
NTSTATUS
DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
DriverObject->DriverUnload = DriverUnload; <--1
DriverObject->DriverExtension->AddDevice = AddDevice;
DriverObject->DriverStartIo = StartIo;
DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp; <--2
DriverObject->MajorFunction[IRP_MJ_POWER] = DispatchPower;
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = DispatchWmi;
...
}
在WDM中透過設定AddDevice回調函數來創建設備對象。在NT驅動中在DriverEntry例程中創建設備對象和符號連結。
例如:
RtlInitUnicodeString (&deviceNameUnicodeString, deviceNameBuffer); //初始化設備名字
//創建設備
ntStatus = IoCreateDevice (DriverObject,
0,
&deviceNameUnicodeString,
##DeviceId,
0,
FALSE,
&deviceObject
);
if ( NT_SUCCESS ( ntStatus ) ) {
RtlInitUnicodeString (&deviceLinkUnicodeString, deviceLinkBuffer); //初始化符號連結名字
//創建符號連結
ntStatus = IoCreateSymbolicLink (&deviceLinkUnicodeString, &deviceNameUnicodeString);
if ( !NT_SUCCESS ( ntStatus ) ) {
IoDeleteDevice (deviceObject); //如果創建符號連結失敗,刪除設備
return ntStatus;
}
}
建立符號連結的作用就是暴露一個給應用程序的接口,應用程序可以透過CreateFile API開啟連結符號,得到一個語柄,和我們的驅動程序進行交互操作。
ad例程
雖然各個驅動程序的Unload例程不盡相同,但是它大致執行下列工作:
釋放屬於驅動程序的任何硬件。
從Win32的名字空間移除符號連接名。
這個動作可以調用IoDeleteSymbolicLink來實現。
使用IoDeleteDevice移除設備對象。
釋放驅動程序持有的任何緩衝池等。
VOID DriverUnload ( IN PDRIVER_OBJECT pDriverObject )
{
PDEVICE_OBJECT pNextObj;
// 循環每一個驅動過程控制的設備
pNextObj = pDriverObject->DeviceObject;
while (pNextObj != NULL)
{
//從設備對象中取出設備Extension
PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)extObj->DeviceExtension;
// 取出符號連接名
UNICODE_STRING pLinkName = pDevExt->ustrSymLinkName;
IoDeleteSymbolicLink(&pLinkName); //刪除符號連接名
IoDeleteDevice(pNextObj); // 刪除設備
pNextObj = pNextObj->NextDevice;
}
}
4. 派遣例程
Win2000的I/O請求是包驅動的,當一個I/O請求開始,I/O器先創建一個IRP去跟蹤這個請求,另外,它存儲一個功能代碼在IRP的I/O堆棧區的MajorField域中來唯一的標識請求的類型。MajorField域是被I/O管理器用來索引驅動程序對象的MajorFunction表,這個表包含一個指向一個特殊I/O請求的派遣例程的功能指針,如果驅動