前言:
任何編碼的東西必須充分的了解規則!
我試探性的搜索了下關(guān)于這個(gè)native api的相關(guān)的問(wèn)題,很郁悶的發(fā)現,這些問(wèn)題90%都是沒(méi)有真正理解了這個(gè)函數導致的!
有的人連函數干嘛的都不知道就著(zhù)急的寫(xiě)驅動(dòng),真是不可一世!所謂兼收并蓄為的是厚積薄發(fā),其間如履薄冰。說(shuō)的很貼切!
對此我一直支持achills師傅的思想!搞明白了最基本的和必須的東西,一切后續的東西迎刃而解!
這個(gè)文章我沒(méi)有過(guò)多的寫(xiě)什么東西,因為很多東西都文檔化了,只需要我們認真而且真正從本質(zhì)上串一遍,完全的理解了它就可以了!而且有些東西也沒(méi)有必 要再寫(xiě)了,比如HOOK SSDT inline hook等,現在缺的不是怎么實(shí)現一個(gè)代碼的流程,缺的是兩個(gè)東西:一個(gè)是思路,一個(gè)是準確性。
原型:
NTSYSAPI
NTSTATUS
NTAPI
ZwCreateFile(
OUT PHANDLE FileHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PLARGE_INTEGER AllocationSize OPTIONAL,
IN ULONG FileAttributes,
IN ULONG ShareAccess,
IN ULONG CreateDisposition,
IN ULONG CreateOptions,
IN PVOID EaBuffer OPTIONAL,
IN ULONG EaLength
);
參數理解:
OUT-
FileHandle--------這是一個(gè)指向一個(gè)變量的指針,用來(lái)最后存放file object handle的
IoStatusBlock-----這個(gè)也是個(gè)指針變量,指向一個(gè)叫做IO_STATUS_BLOCK的結構體,最后函數返回的時(shí)候,這個(gè)結構體的成員 里面要填充一些值,具體的呢就是完成狀態(tài),請求操作的一些信息,最重要的一個(gè)成員就是Information成員,他顯示了函數對文件的處理方式,他的值 可能是下面的幾個(gè):
FILE_SUPERSEDED(替代)
FILE_OPENED(打開(kāi))
FILE_CREATED(創(chuàng )建)
FILE_OVERWRITTEN(重寫(xiě))
FILE_EXISTS(存在)
FILE_DOES_NOT_EXIST(文件不存在)
再看下這個(gè)IO_STATUS_BLOCK的具體結構:
typedef struct _IO_STATUS_BLOCK {
union {
NTSTATUS Status;
PVOID Pointer;
} DUMMYUNIONNAME;
ULONG_PTR Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
通過(guò)上述的兩個(gè)輸出的參數我們可以看到,這個(gè)ZwCreateFile函數就是返回創(chuàng )建好的文件對象的句柄,然后返回一個(gè)期間處理的方式。
IN-
DesiredAccess----這個(gè)參數指定一個(gè)訪(fǎng)問(wèn)權限,大概有以下的權限:
FILE_ANY_ACCESS 0x0000 // any type
FILE_READ_ACCESS 0x0001 // file & pipe
FILE_READ_DATA 0x0001 // file & pipe
FILE_LIST_DIRECTORY 0x0001 // directory
FILE_WRITE_ACCESS 0x0002 // file & pipe
FILE_WRITE_DATA 0x0002 // file & pipe
FILE_ADD_FILE 0x0002 // directory
FILE_APPEND_DATA 0x0004 // file
FILE_ADD_SUBDIRECTORY 0x0004 // directory
FILE_CREATE_PIPE_INSTANCE 0x0004 // named pipe
FILE_READ_EA 0x0008 // file & directory
FILE_WRITE_EA 0x0010 // file & directory
FILE_EXECUTE 0x0020 // file
FILE_TRAVERSE 0x0020 // directory
FILE_DELETE_CHILD 0x0040 // directory
FILE_READ_ATTRIBUTES 0x0080 // all types
FILE_WRITE_ATTRIBUTES 0x0100 // all types
FILE_ALL_ACCESS // All of the preceding +
STANDARD_RIGHTS_ALL
最后一個(gè)權限最大
這里面要注意的是范圍問(wèn)題,有的值只適合目錄,有的只適合管道,有的只適合命名管道,有的同時(shí)適用,想下這個(gè)地方可以做什么文章
ObjectAttributes---指向下面這個(gè)結構的一個(gè)變量,就是來(lái)表明文件對象的屬性的。
typedef struct _OBJECT_ATTRIBUTES {
ULONG Length;
HANDLE RootDirectory;
PUNICODE_STRING ObjectName;
ULONG Attributes;
PVOID SecurityDescriptor; /* type SECURITY_DESCRIPTOR */
PVOID SecurityQualityOfService; /* type SECURITY_QUALITY_OF_SERVICE */
} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;
這個(gè)結構是針對很多對象的,不光是針對文件對象的,所以OBJ_PERMANENT(永久), OBJ_EXCLUSIVE(互斥),
and OBJ_OPENLINK這三個(gè)實(shí)際上對于文件對象來(lái)說(shuō)始終是無(wú)效的,為什么?
不能設置那三個(gè),那可以設置些什么呢?呼呼
AllocationSize---這是個(gè)可選的參數,他是指定初始化文件需要的內存字節數的,所以可向而知,他只有在真正的涉及到文件創(chuàng )建的時(shí)候才有意義,也就是說(shuō)創(chuàng )建,重寫(xiě),替換這些操作的時(shí)候。指向一個(gè)LARGE_INTEGER:
typedef union _LARGE_INTEGER {
_ANONYMOUS_STRUCT struct
{
ULONG LowPart;
LONG HighPart;
} DUMMYSTRUCTNAME;
struct
{
ULONG LowPart;
LONG HighPart;
} u;
#endif //MIDL_PASS
LONGLONG QuadPart;
} LARGE_INTEGER, *PLARGE_INTEGER;
這個(gè)結構體在內核結構里面很常見(jiàn),呼呼,,支持到64位,看情況設置。不過(guò)我至今沒(méi)有明白QuadPart這個(gè)是干嘛的!
FileAttributes---這個(gè)參數指定文件的屬性,剛才是文件對象的屬性??梢允且韵碌模?br> FILE_ATTRIBUTE_READONLY
FILE_ATTRIBUTE_HIDDEN
FILE_ATTRIBUTE_SYSTEM
FILE_ATTRIBUTE_DIRECTORY
FILE_ATTRIBUTE_ARCHIVE
FILE_ATTRIBUTE_NORMAL
FILE_ATTRIBUTE_TEMPORARY
FILE_ATTRIBUTE_SPARSE_FILE
FILE_ATTRIBUTE_REPARSE_POINT
FILE_ATTRIBUTE_COMPRESSED
FILE_ATTRIBUTE_OFFLINE
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED
FILE_ATTRIBUTE_ENCRYPTED
ShareAccess---指定共享的權限,以下三種的組合:
FILE_SHARE_READ
FILE_SHARE_WRITE
FILE_SHARE_DELETE
CreateDisposition---這個(gè)參數指定要對文件干嘛,呼呼,可以是下面的值:
FILE_SUPERSEDE
FILE_OPEN
FILE_CREATE
FILE_OPEN_IF
FILE_OVERWRITE
FILE_OVERWRITE_IF
CreateOptions---這個(gè)參數指定創(chuàng )建或者打開(kāi)文件的時(shí)候做的一些事情,可以是以下的組合:
FILE_DIRECTORY_FILE
FILE_WRITE_THROUGH
FILE_SEQUENTIAL_ONLY
FILE_NO_INTERMEDIATE_BUFFERING
FILE_SYNCHRONOUS_IO_ALERT
FILE_SYNCHRONOUS_IO_NONALERT
FILE_NON_DIRECTORY_FILE
FILE_CREATE_TREE_CONNECTION
FILE_COMPLETE_IF_OPLOCKED
FILE_NO_EA_KNOWLEDGE
FILE_OPEN_FOR_RECOVERY
FILE_RANDOM_ACCESS
FILE_DELETE_ON_CLOSE
FILE_OPEN_BY_FILE_ID
FILE_OPEN_FOR_BACKUP_INTENT
FILE_NO_COMPRESSION
FILE_RESERVE_OPFILTER
FILE_OPEN_REPARSE_POINT
FILE_OPEN_NO_RECALL
FILE_OPEN_FOR_FREE_SPACE_QUERY
這個(gè)我不太清楚,概念有點(diǎn)模糊
EaBuffer---這個(gè)是個(gè)可選的參數,用來(lái)存放一些擴展的屬性
EaLength---存放擴展屬性的字節大小
有個(gè)疑問(wèn),這個(gè)擴展屬性什么時(shí)候用呢?(TDI里面常用這個(gè))
更詳細的參數的理解參考
http://xiaomaier.bokee.com/3439967.html
返回值理解:
如果成功,返回STATUS_SUCCESS
如果失敗,返回
STATUS_ACCESS_DENIED,
STATUS_OBJECT_NAME_NOT_FOUND, STATUS_OBJECT_NAME_COLLISION,
STATUS_OBJECT_NAME_INVALID, STATUS_SHARING_VIOLATION, STATUS_NOT_A_DIRECTORY, or
STATUS_FILE_IS_A_DIRECTORY.
說(shuō)明:
1.與這個(gè)native api相關(guān)的r3api是CreateFile
2.DDK里面對這個(gè)函數有詳細的說(shuō)明
擴展:
1.與CreateFile這個(gè)api的異同。
同:
(1)功能基本相同,都是可以打開(kāi)或者創(chuàng )建一個(gè)文件對象,包括文件,磁盤(pán),卷,管道,串口,油槽等
(2)都是返回一個(gè)文件句柄
異:
(1)在vista及以上的版本,CreateFile做了擴展,加上了事務(wù)性文件系統
HANDLE WINAPI CreateFileTransacted(
__in LPCTSTR lpFileName,
__in DWORD dwDesiredAccess,
__in DWORD dwShareMode,
__in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes,
__in DWORD dwCreationDisposition,
__in DWORD dwFlagsAndAttributes,
__in_opt HANDLE hTemplateFile,
__in HANDLE hTransaction,
__in_opt PUSHORT pusMiniVersion,
PVOID pExtendedParameter
);
但是ZwCreateFile還是那樣
(2)HANDLE WINAPI CreateFile(
__in LPCTSTR lpFileName,
__in DWORD dwDesiredAccess,
__in DWORD dwShareMode,//////////////////////
__in LPSECURITY_ATTRIBUTES lpSecurityAttributes,
__in DWORD dwCreationDisposition,
__in DWORD dwFlagsAndAttributes,
__in HANDLE hTemplateFile
);
NTSYSAPI
NTSTATUS
NTAPI
ZwCreateFile(
OUT PHANDLE FileHandle,
IN ACCESS_MASK DesiredAccess,////////////
IN POBJECT_ATTRIBUTES ObjectAttributes,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PLARGE_INTEGER AllocationSize OPTIONAL,
IN ULONG FileAttributes,
IN ULONG ShareAccess,///////////
IN ULONG CreateDisposition,//////////////////////////
IN ULONG CreateOptions,
IN PVOID EaBuffer OPTIONAL,
IN ULONG EaLength
);
2.內核里與ZwCreateFile功能相似的還有一個(gè)函數IoCreateFile
NTSTATUS IoCreateFile
(
OUT PHANDLE FileHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PLARGE_INTEGER AllocationSize OPTIONAL,
IN ULONG FileAttributes,
IN ULONG ShareAccess,
IN ULONG Disposition,
IN ULONG CreateOptions,
IN PVOID EaBuffer OPTIONAL, I
N ULONG EaLength,
IN CREATE_FILE_TYPE CreateFileType,
IN PVOID ExtraCreateParameters OPTIONAL,
IN ULONG Options
) ;
windbg看下,其實(shí)ZwCreateFile內部調用了IoCreateFile
至于這兩個(gè)函數的區別可以參考combojiang的http://hi.baidu.com/combojiang/blog/item/cd6269de55ce235eccbf1adb.html
IoCreateFile內部還調用了一個(gè)allmul函數,這個(gè)函數是用來(lái)做int64的移位的,具體的參考
http://hi.baidu.com/combojiang/blog/item/29411c5c6841ae45fbf2c088.html
據說(shuō)IoCreateFile函數更優(yōu)良一些,IceSword就調用了這個(gè)函數來(lái)打開(kāi)ntoskrnl。exe的
3.hook ZwCreateFile是很簡(jiǎn)單的,,hook SSDT就可以了!考慮個(gè)問(wèn)題:
ZwCreateFile是創(chuàng )建文件的,那么如果我們hook之后比如函數變成了my_ZwCreateFile(),這個(gè)時(shí)候我們還想調用ZwCreateFile創(chuàng )建文件的話(huà),就會(huì )出錯,還想再創(chuàng )建文件,怎么辦?
這個(gè)得做個(gè)線(xiàn)程模式的切換。
詳細的可以參考http://www.cnblogs.com/jokerfox/archive/2009/04/14/1435819.html
4.ZwCreateFile是運行在PASSIVE_LEVEL上的。那么比如要調用這個(gè)函數的程序必須運行在DISPATCH_LEVEL呢?怎么調用?
http://xuyingpin.blogbus.com/logs/10845127.html
http://xuyingpin.blogbus.com/logs/11152569.html
最簡(jiǎn)單的使用方法:
BOOL testCreateFile(IN PUNICODE_STRING filename)
{
HANDLE hFile=NULL;
NTSTATUS status;
IO_STATUS_BLOCK isb;
OBJECT_ATTRIBUTES oa;
InitializeObjectAttributes(&oa,filename,OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE,NULL,NULL);
status=ZwCreateFile(&hFile,GENERIC_ALL,&oa,&isb,NULL,FILE_ATTRIBUTE_NORMAL,FILE_SHARE_READ,FILE_CREATE,FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,NULL,0);
if(NT_SUCCESS(status))
{
status=STATUS_SUCCESS;
}
else
{
status=isb.Status;
}
DbgPrint("hFile=%08X",hFile);
if(hFile)
{
ZwClose(hFile);
}
return status;
hook ZwCreateFile的思路:
1.hook SSDT
NTSTATUS NewZwCreateFile(OUT PHANDLE FileHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PLARGE_INTEGER AllocationSize OPTIONAL,
IN ULONG FileAttributes,
IN ULONG ShareAccess,
IN ULONG CreateDisposition,
IN ULONG CreateOptions,
IN PVOID EaBuffer OPTIONAL,
IN ULONG EaLength) {
NTSTATUS ntS = (NTSTATUS) NULL;
DbgPrint("ZwCreateFile called\n");
ntS = ((ZWCREATEFILE)(OldZwCreateFile)) (
FileHandle,
DesiredAccess,
ObjectAttributes,
IoStatusBlock,
AllocationSize,
FileAttributes,
ShareAccess,
CreateDisposition,
CreateOptions,
EaBuffer,
EaLength);
return(ntS);
}
http://dev.csdn.net/article/36/36751.shtm
http://www.zeroplace.cn/article.asp?id=138
2.通過(guò)調試寄存器hook
http://www.xfocus.net/articles/200709/950.html
3.inline hook
http://hackbase.com/tech/2009-05-11/52690.html系列
總結:
我們站在一個(gè)稍微高的地方來(lái)看一些東西
任何用戶(hù)態(tài)或核心態(tài)的函數CreateFile或者內核態(tài)的ZwCreateFile等都是為了獲得handle,為進(jìn)一步的訪(fǎng)問(wèn)做準備。而在獲得 handle的過(guò)程中,調用者需要提供DesiredAccess和ShareAccess等選項。如果文件已經(jīng)被另一個(gè)調用者以排他方式打開(kāi),這時(shí)候的 訪(fǎng)問(wèn)就會(huì )失敗。
那么我們可以這么想一個(gè)問(wèn)題,如果我們精通一種驗證機制,或者說(shuō)構造一種驗證機制的話(huà),那么訪(fǎng)問(wèn)不需要這么復雜就可以實(shí)現,這就是邪惡的繞過(guò)技術(shù)!那么針對我剛才說(shuō)的話(huà),具體的可以參考這么幾種技術(shù):
搜索句柄表,關(guān)閉句柄
DKOM
區域映射
I/O
我還不清楚這里面的研究空間有多大,反正我見(jiàn)好多人都是怎么xx了,怎么繞過(guò)什么了,怎么投機了一下過(guò)了什么保護了,其實(shí)從個(gè)人需求來(lái)看,確實(shí)是一個(gè)突破,若從全局來(lái)看,根本是牽一發(fā)不動(dòng)全身的!