初步認識MDL

我們知道,系統中一些重要的表項如SSDT是隻讀的,如果我們強行對其進行修改就會造成BSOD的嚴重後果。當然這種保護方式很容易被繞過,我們曾 經介紹了通過修改cr0來禁用WP(Write Protect,寫保護)位的方法,現在再介紹一種不需要使用匯編的方法,就是MDL。

MDL的全稱是Memory Descriptor List,即內存描述符表。我們可以通過MDL描述一塊內存區域,在MDL中包含了該內存區域的起始地址、擁有者進程、字節數量、標記等信息,如下所示:
typedef struct _MDL
{
    struct _MDL  *Next;
    CSHORT       Size;
    CSHORT       MdlFlags;
    struct _EPROCESS *Process;
    PVOID          MappedSystemVa;
    PVOID          StartVa;
    ULONG         ByteCount;
    ULONG   ByteOffset;
} MDL, *PMDL;

 

 

我們先來看一段在SSDT HOOK中常見的代碼,如下所示:
PMDL MDSystemCall;
PVOID *MappedSCT;

MDSystemCall = MmCreateMdl(NULL, KeServiceDescriptorTable.ServiceTableBase, KeServiceDescriptorTable.NumberOfServices*4);
if(!MDSystemCall)
{
    return STATUS_UNSUCCESSFUL;
}
MmBuildMdlForNonPagedPool(MDSystemCall);
MDSystemCall->MdlFlags |= MDL_MAPPED_TO_SYSTEM_VA;
MappedSCT = MmMapLockedPages(MDSystemCall, KernelMode);
HookOn( ZwTerminateProcess, New_ZwTerminateProcess);

其中KeServiceDescriptorTable描述的是SSDT,其中ServiceTableBase標明瞭SSDT的起始地址,因此我 們通過MmCreateMdl函數創建一個MDL,它剛好把SSDT這塊內存包含在內,有人可能會問,它的長度爲啥是 “KeServiceDescriptorTable.NumberOfServices*4”字節呢?很簡單,因爲指針的長度是4個字節。

後面的代碼首先從不分頁的內存池中Build MDL,然後添加一個MDL_MAPPED_TO_SYSTEM_VA標記以便允許寫入該內存區域;然後我們將這塊內存鎖起來,現在可以就開始HOOK SSDT了,直到關閉HOOK後纔將其釋放。從這裏就可以看出,這種方式明顯沒有修改cr0的方法好,呵呵呵呵。

不過這種方法的應用範圍比較廣,控制精度也較好,精確地指定了要修改哪一塊內存的標記,兩者方法算是各有千秋吧,誰喜歡用哪一種都可以。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章