一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

Windows平臺(tái)內(nèi)核級文件訪問

 天蝎淚 2007-02-01

Windows平臺(tái)內(nèi)核級文件訪問


創(chuàng)建時(shí)間:2006-02-03
文章屬性:原創(chuàng)
文章提交:baiyuanfan (baiyuanfan_at_163.com)

Windows平臺(tái)內(nèi)核級文件訪問
作者:baiyuanfan (baiyuanfan@163.com)
日期:2.1,2006

1.背景
    在windows平臺(tái)下,應(yīng)用程序通常使用API函數(shù)來進(jìn)行文件訪問,創(chuàng)建,打開,讀寫文件。從kernel32的CreateFile/ReadFile/WriteFile函數(shù),到本地系統(tǒng)服務(wù),再到FileSystem及其FilterDriver,經(jīng)歷了很多層次。在每個(gè)層次上,都存在著安全防護(hù)軟件,病毒或者后門作監(jiān)視或者過濾的機(jī)會(huì)。作為安全產(chǎn)品開發(fā)者,我們需要比別人走得更遠(yuǎn),因此我們需要一個(gè)底層的“windows平臺(tái)內(nèi)核級文件訪問”的方法來確保我們能夠看到正確的干凈的文件系統(tǒng)。

2.用途
    直接的內(nèi)核級別文件訪問,在信息安全領(lǐng)域內(nèi)有廣泛的用途。用于入侵者的方面,可以讓他繞過殺毒軟件,IDS等安全保護(hù)系統(tǒng)的監(jiān)視。用于檢測者的方面,可以看到一個(gè)干凈的系統(tǒng),以此來查殺隱藏的后門或者rootkit。用于監(jiān)控者的方面,則可以了解最新的繞過監(jiān)控的技術(shù),可以根據(jù)來設(shè)計(jì)更新的監(jiān)控方案。

3.直接訪問FSD的內(nèi)核級別文件訪問
    FSD(FileSystemDriver)層是文件API函數(shù)經(jīng)過本地系統(tǒng)服務(wù)層(native API)最后到達(dá)的驅(qū)動(dòng)層次。如果我們可以模仿操作系統(tǒng),在我們自己的驅(qū)動(dòng)程序里直接向FSD發(fā)送IRP,就可以繞過那些native API 和win32 API了,也就可以繞過設(shè)置在這些層次上面的API鉤子等監(jiān)控措施。

3.1文件的Create和Open
    文件的Create和Open可以通過發(fā)送IRP_MJ_CREATE給FSD,或者調(diào)用IoCreateFile函數(shù)來完成。Create和Open的區(qū)別實(shí)際上在于IoCreateFile/IRP_MJ_CREATE的一個(gè)參數(shù)Disposition的取值。使用IoCreateFile函數(shù)的樣例代碼:

HANDLE openfile(WCHAR* name,ACCESS_MASK access,ULONG share)
{
    //return 0 for error.
    HANDLE hfile;
    IO_STATUS_BLOCK iosb;
    int stat;
    OBJECT_ATTRIBUTES oba;
    UNICODE_STRING nameus;
    ///
    if(KeGetCurrentIrql()>PASSIVE_LEVEL){return 0;}
    RtlInitUnicodeString(&nameus,name);
    InitializeObjectAttributes(&oba,&nameus,OBJ_KERNEL_HANDLE|OBJ_CASE_INSENSITIVE,0,0);
    stat=IoCreateFile(&hfile,access,&oba,&iosb,0,FILE_ATTRIBUTE_NORMAL,share,FILE_OPEN,0,0,0,0,0,0);
    if(!NT_SUCCESS(stat)){return 0;}
    return hfile;
}

HANDLE createnewfile(WCHAR* name,ACCESS_MASK access,ULONG share)
{
    //return 0 for error.
    HANDLE hfile;
    IO_STATUS_BLOCK iosb;
    int stat;
    OBJECT_ATTRIBUTES oba;
    UNICODE_STRING nameus;
    ///
    if(KeGetCurrentIrql()>PASSIVE_LEVEL){return 0;}
    RtlInitUnicodeString(&nameus,name);
    InitializeObjectAttributes(&oba,&nameus,OBJ_KERNEL_HANDLE|OBJ_CASE_INSENSITIVE,0,0);
    stat=IoCreateFile(&hfile,access,&oba,&iosb,0,//AllocationSize this set to 0 that when file opened it was zeroed.
        FILE_ATTRIBUTE_NORMAL,share,FILE_OVERWRITE_IF,0,0,0,0,0,0);
    if(!NT_SUCCESS(stat)){return 0;}
    return hfile;
}

    通過發(fā)送IRP_MJ_CREATE給FSD的方法與此類似,可以參考IFSDDK document的IRP_MJ_CREATE說明。不同于上面方法的是需要自己創(chuàng)建一個(gè)FILE_OBJECT,好于上面方法的是這種方法不需要一個(gè)HANDLE,HANDLE是線程依賴的,FileObject則是線程無關(guān)。

3.2文件的Read和Write
    我們通過給FSD發(fā)送IRP_MJ_READ來讀取文件,給FSD發(fā)送IRP_MJ_WRITE來改寫文件。
    如果我們是通過一個(gè)HANDLE來執(zhí)行(如使用IoCreateFile打開的文件),就要先用ObReferenceObjectByHandle函數(shù)來獲得這個(gè)Handle對應(yīng)的FileObject。我們只能給FileObject發(fā)送IRP。

stat=ObReferenceObjectByHandle(handle,GENERIC_READ,*IoFileObjectType,KernelMode,(PVOID*)&fileob,0);

    之后我們使用IoAllocateIrp分配一個(gè)IRP。根據(jù)FileObject->DeviceObject->Flags的值,我們判斷目標(biāo)文件系統(tǒng)使用什么樣的IO方式。

    if(fileob->DeviceObject->Flags & DO_BUFFERED_IO)
    {
        irp->AssociatedIrp.SystemBuffer=buffer;//buffered io
    }
    else if(fileob->DeviceObject->Flags & DO_DIRECT_IO)
    {
        mdl=IoAllocateMdl(buffer,count,0,0,0);
        MmBuildMdlForNonPagedPool(mdl);
        irp->MdlAddress=mdl;//direct io
    }
    else
    {
        irp->UserBuffer=buffer;//neither i/o, use kernel buffer
    }

    對每種不同的IO方式使用不同的地址傳遞方式。隨后我們填充IRP內(nèi)的各個(gè)參數(shù)域,就可以發(fā)送IRP了。以Read為例:

    irpsp->FileObject=fileob;
    irpsp->MajorFunction=IRP_MJ_READ;
    irpsp->MinorFunction=IRP_MN_NORMAL;//0
    irpsp->Parameters.Read.ByteOffset=offsetused;
    irpsp->Parameters.Read.Key=0;
    irpsp->Parameters.Read.Length=count;

    接著要考慮如果IRP不能及時(shí)完成,會(huì)異步的返回的情況,我們安裝一個(gè)CompletionRoutine,在CompletionRoutine里面設(shè)置一個(gè)事件為已激活,通知我們的主線程讀取或者寫入操作已經(jīng)完成。

IoSetCompletionRoutine(irp,IoCompletion,&event,1,1,1);

NTSTATUS
  IoCompletion(
    IN PDEVICE_OBJECT  DeviceObject,
    IN PIRP  Irp,
    IN PVOID  Context
    )
{
    KeSetEvent((PRKEVENT)Context, IO_DISK_INCREMENT, 0);
    return STATUS_MORE_PROCESSING_REQUIRED;
}

    現(xiàn)在可以發(fā)送IRP了。如果不采取特殊的措施的話,IRP發(fā)送目標(biāo)是FileObject對應(yīng)的DeviceObject。發(fā)送后,等待IRP的完成并且釋放資源,返回。

    stat=IoCallDriver(fileob->DeviceObject,irp);
    if(stat==STATUS_PENDING){
        KeWaitForSingleObject(&event, Executive,KernelMode,0,0);
        stat=irp->IoStatus.Status;
    }
    if(!NT_SUCCESS(stat))
    {
        IoFreeIrp(irp);
        if(mdl){IoFreeMdl(mdl);}//if DO_DIRECT_IO
        return -1;
    }
    stat=irp->IoStatus.Information;//bytes read
    IoFreeIrp(irp);
    if(mdl){IoFreeMdl(mdl);}//if DO_DIRECT_IO
    return stat;

3.3文件的Delete
    Delete實(shí)際上是通過向FSD發(fā)送IRP_MJ_SET_INFORMATION的IRP,并把IrpSp->Parameters.SetFile.FileInformationClass設(shè)置為FileDispositionInformation,用一個(gè)FILE_DISPOSITION_INFORMATION結(jié)構(gòu)填充buffer來執(zhí)行的。

    fdi.DeleteFile=TRUE;

    irpsp->MajorFunction=IRP_MJ_SET_INFORMATION;
    irpsp->Parameters.SetFile.Length = sizeof(FILE_DISPOSITION_INFORMATION);
    irpsp->Parameters.SetFile.FileInformationClass = FileDispositionInformation;
    irpsp->Parameters.SetFile.DeleteHandle = (HANDLE)handle;

3.4文件的Rename
    類似于Delete,Rename是向FSD發(fā)送IRP_MJ_SET_INFORMATION的IRP,把IrpSp->Parameters.SetFile.FileInformationClass設(shè)置為FileRenameInformation,填充buffer為FILE_RENAME_INFORMATION結(jié)構(gòu)。

    fri.ReplaceIfExists=TRUE;
    fri.RootDirectory=0;//Set fri.FileName to full path name.
    fri.FileNameLength=wcslen(filename)*2;
    wcscpy(fri.FileName,filename);//If the RootDirectory member is NULL, and the file is being moved to a different directory, this member specifies the full pathname to be assigned to the file.

    irpsp->MajorFunction=IRP_MJ_SET_INFORMATION;
    irpsp->Parameters.SetFile.Length = sizeof(FILE_FILE_RENAME_INFORMATION);
    irpsp->Parameters.SetFile.FileInformationClass = FileRenameInformation;


    綜上,于是我們可以在驅(qū)動(dòng)里面通過發(fā)送IRP來直接訪問文件系統(tǒng)了,繞過了native API 和win32 API層次。


4.繞過文件系統(tǒng)過濾驅(qū)動(dòng)和鉤子

    有了第三部分的內(nèi)容,我們目前可以直接給FSD發(fā)送請求操作文件。但是這還不夠,因?yàn)橛泻芏嗟臍⒍拒浖蛘弑O(jiān)視工具使用FSD Filter Driver或者FSD Hook的辦法來監(jiān)控文件操作。在今天這篇文章里我講一些原理性的東西,提供繞過FSD Filter Driver / FSD Hook的思路。

4.1對付文件系統(tǒng)過濾驅(qū)動(dòng)

    文件系統(tǒng)過濾驅(qū)動(dòng)Attach在正常的文件系統(tǒng)之上,監(jiān)視和過濾我們的文件訪問。文件系統(tǒng)驅(qū)動(dòng)棧就是由這一連串的Attach起來的過濾驅(qū)動(dòng)組成。我們可以用IoGetRelatedDeviceObject這個(gè)函數(shù)來獲得一個(gè)FileObject對應(yīng)的最底層的那個(gè)功能驅(qū)動(dòng)對象(FDO)。但是這樣雖然繞過了那些過濾驅(qū)動(dòng),卻同時(shí)也繞過了正常的FSD如Ntfs/Fastfat,因?yàn)檎5腇SD也是作為一個(gè)過濾驅(qū)動(dòng)存在的。磁盤文件對象的對應(yīng)的最底層的FDO是Ftdisk.sys,它已經(jīng)因?yàn)檫^于底層而不能處理我們投遞的IRP請求。
    其實(shí)正常的FSD信息存儲(chǔ)在一個(gè)Vpb結(jié)構(gòu)中,我們可以使用IoGetBaseFileSystemDeviceObject這個(gè)未公開的內(nèi)核函數(shù)來得到它。它就是我們發(fā)送IRP的目標(biāo)了。

4.2對付替換DispatchRoutine的FSD Hook

    這是一種常用的FSD Hook方式。我們需要得到原本的DispatchRoutine,向原本的DispatchRoutine發(fā)送我們的IRP。這里提供一個(gè)思路:我們可以讀取原本FSD驅(qū)動(dòng)的.INIT段或者.TEXT段,查找其DriverEntry函數(shù),在它的DriverEntry函數(shù)中肯定設(shè)置了自己的DriverObject的各個(gè)DispatchRoutine。在這個(gè)函數(shù)中我們就能找到我們想要的DispatchRoutine的地址。只需要使用特征碼搜索的方法就可以搜索到這個(gè)值。

4.3對付Inline Hook DispatchRoutine函數(shù)本身的FSD Hook

    這種Hook方法比較狠毒,但不是非常常見于安全產(chǎn)品中,一般應(yīng)用在木馬和rootkit上,比如我自己寫的rootkit。它沒有更改DriverObject里面的DispatchRoutine的函數(shù)指針,而是向函數(shù)開頭寫入?yún)R編指令的JMP來跳轉(zhuǎn)函數(shù)。對付它的基本思路就是讀取存在磁盤上的FSD的文件,加載到內(nèi)存一份干凈的備份,察看我們要調(diào)用的DispatchRoutine開頭的幾個(gè)字節(jié)和這個(gè)干凈備份是否一致。如果不一致,尤其是存在JMP,RET,INT3一類的匯編指令的時(shí)候,很可能就是存在了Inline Hook。(但要充分考慮重定位的情況。)如果存在Inline Hook,我們就把干凈的函數(shù)開頭拷貝過來覆蓋掉被感染的函數(shù)頭。然后在發(fā)送IRP,就不會(huì)被Inline Hook監(jiān)視或篡改了。

5.感謝
    感謝Vxk的支持和幫助。
    我的E-mail:baiyuanfan@163.com,安全和內(nèi)核愛好者。歡迎交流。

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    午夜色午夜视频之日本| 99一级特黄色性生活片| 成人亚洲国产精品一区不卡| 最新国产欧美精品91| 国产欧美亚洲精品自拍| 99一级特黄色性生活片| 欧美一区二区三区播放| 大屁股肥臀熟女一区二区视频| 99久久婷婷国产亚洲综合精品| 亚洲一区二区精品免费视频| 午夜精品国产一区在线观看| 国产白丝粉嫩av在线免费观看| 亚洲第一香蕉视频在线| 久久女同精品一区二区| 欧美日韩国产成人高潮| 欧美不雅视频午夜福利| 精品精品国产自在久久高清| 精品一区二区三区不卡少妇av| 永久福利盒子日韩日韩| 后入美臀少妇一区二区| 又色又爽又无遮挡的视频| 一级片黄色一区二区三区| 亚洲高清中文字幕一区二三区| 丰满少妇被粗大猛烈进出视频| 国产又大又猛又粗又长又爽| 精品少妇一区二区视频| 丝袜av一区二区三区四区五区 | 国产精品午夜福利免费阅读 | 国内精品偷拍视频久久| 欧美不卡一区二区在线视频| 欧美又大又黄刺激视频| 国产丝袜美女诱惑一区二区| 久久精品国产在热久久| 日本久久精品在线观看| 亚洲视频一级二级三级| 欧美黄色成人真人视频| 欧美精品中文字幕亚洲| 男女午夜在线免费观看视频| 日韩专区欧美中文字幕| 亚洲高清欧美中文字幕| 最新日韩精品一推荐日韩精品 |