目錄api
操做 |
---|
建立文件/文件夾 |
讀/寫 |
拷貝 |
移動 |
刪除 |
屬性訪問與設置 |
文件路徑表示表格:數組
表示層 | 文件路徑表示方法 |
---|---|
Ring3 | L"C:\HelloWorld.txt" |
Ring0 | L"\??\C:\HelloWorld.txt" |
其中兩個 ****是表明一個.表明的是轉義字符.異步
內核層的兩個??實際上是符號連接.表明的是是
\device\harddiskvolume3函數
內核中的文件路徑完整表達是: ** L"\device\harddiskvolume3\HelloWorld.txt**設計
Ring3跟Ring0的其它路徑.如設備對象.(符號連接)3d
表示層 | 路徑表示 |
---|---|
Ring3設備名 | L"\\.\xxx符號名,或者 \\?\xxx符號名 |
Ring0設備名稱 | L"\device\xxx |
Ring0符號鏈接名 | L"\dosDevices\xxx符號鏈接名 或者\??\xxx符號鏈接 |
方法名 | 做用 |
---|---|
ZwCreateFile | 建立文件或者文件夾 |
ZwWriteFile | 寫文件 |
ZwReadFile | 讀文件 |
ZwQueryInfomationFile | 查詢文件 |
ZwQueryFullAttributeFile | 查詢文件 |
ZwSetInfomationFile | 設置文件信息,設置文件大小,設置文件訪問日期.設置屬性隱藏文件.重命名.刪除.對應IRP = Irp_mj_Set_Information. |
ZwClose | 關閉文件句柄 |
ZwQueryDirectoryFile | 枚舉文件跟目錄 |
如ZwCreateFile指針
NTSTATUS ZwCreateFile( __out PHANDLE FileHandle, 文件句柄 __in ACCESS_MASK DesiredAccess, 建立權限 __in POBJECT_ATTRIBUTES ObjectAttributes,文件路徑.這裏放文件瞭解那個 __out PIO_STATUS_BLOCK IoStatusBlock, __in_opt PLARGE_INTEGER AllocationSize, __in ULONG FileAttributes, __in ULONG ShareAccess, 文件是建立仍是打開 __in ULONG CreateDisposition, __in ULONG CreateOptions, __in_opt PVOID EaBuffer, __in ULONG EaLength );
NTSTATUS ZwReadFile( IN HANDLE FileHandle, 文件句柄 IN HANDLE Event OPTIONAL, 異步過程調用 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,異步過程 IN PVOID ApcContext OPTIONAL, 異步過程調用 OUT PIO_STATUS_BLOCK IoStatusBlock, 讀寫的IO狀態 OUT PVOID Buffer, 讀寫的Buffer IN ULONG Length, 讀寫的長度 IN PLARGE_INTEGER ByteOffset OPTIONAL, 讀寫的偏移 IN PULONG Key OPTIONAL );
查詢文件類型code
NTSTATUS ZwQueryInformationFile( IN HANDLE FileHandle, 文件句柄 OUT PIO_STATUS_BLOCK IoStatusBlock, IO狀態 OUT PVOID FileInformation, 根據參數四.傳出的一個結構體樂行 IN ULONG Length, 查詢文件類型的長度 IN FILE_INFORMATION_CLASS FileInformationClass 查詢的文件的類型, 你查詢的信息是個結構體.這裏放什麼上面就放這個信息結構體的大小. );
上面這個函數簡單來講就是 你參數4傳入一個枚舉類型.表示你想查詢什麼類型信息. 而後查詢的信息經過參數3. FileInformation傳出. 你參數4傳入的是什麼枚舉.他就會返回查詢的結構體給參數三.
僞代碼:orm
ZwQueryInfomationFile(hfile,&Iostatus,&FileInformatin,sizeof(FileInforMation),FileBaseicInfoMation
具體信息查詢WDK幫助文檔便可.對象
設置文件信息
NTSTATUS ZwSetInformationFile( IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PVOID FileInformation, IN ULONG Length, IN FILE_INFORMATION_CLASS FileInformationClass 文件的類型 );
跟查詢文件相反.只不過須要咱們傳入信息.
好比: 下面就是刪除文件
FILE_DISPOSITION_INFORMATION FileInformation; ZwSetInformationFile(hfile,&ioStatus,&FileInformation,sizeof(FileInformation),FileDispositionInformation);
爲何說這個.由於在上面文件操做.若是你查詢Wdk文檔的話.會看到不一樣的結構體定義.
如:
typedef struct _FILE_RENAME_INFORMATION { BOOLEAN ReplaceIfExists; HANDLE RootDirectory; ULONG FileNameLength; WCHAR FileName[1]; } FILE_RENAME_INFORMATION, *PFILE_RENAME_INFORMATION;
更更名字的結構體.
能夠看到第三個參數 跟第四個參數. 爲何這樣定義.
這樣定義表明這個結構體利用數組能夠溢出的原理.設計的一個邊長結構體.
他這個數組的大小根據第三個參數決定.
其他的兩種就很簡單了
struct stack { int value char szBuffer[100] }
這種類型.咱們的szBuffer就是佔你給定的大小.
指針類型
struct point { int value char *pszBuffer }
這種類型則是指針定義.pszBuffer指向一塊地址.
#include <ntddk.h> #include <wdm.h> #include <ntdef.h> #include <ntstrsafe.h> #define DEVICENAME L"" #define SYMBOLICLINKENAME L"" DRIVER_UNLOAD DriverUnload; //函數聲明 NTSTATUS NtDeleteFile(const WCHAR *FileNmae);//刪除文件的第一種方式. NTSTATUS NtCreateFile(UNICODE_STRING ustr); NTSTATUS NtCreateFile(UNICODE_STRING ustr) { //建立文件 /* #define InitializeObjectAttributes( p, n, a, r, s ) { \ (p)->Length = sizeof( OBJECT_ATTRIBUTES ); \ (p)->RootDirectory = r; \ (p)->Attributes = a; \ (p)->ObjectName = n; \ (p)->SecurityDescriptor = s; \ (p)->SecurityQualityOfService = NULL; \ } */ NTSTATUS NtStatus = 0; HANDLE hFile; IO_STATUS_BLOCK io_Status = { 0 }; OBJECT_ATTRIBUTES ObjAttus = { 0 }; InitializeObjectAttributes(&ObjAttus, //初始化ObjAttus結構. &ustr, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); NtStatus = ZwCreateFile(&hFile, GENERIC_WRITE, &ObjAttus, &io_Status, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_ALERT | FILE_NON_DIRECTORY_FILE, NULL, 0); if (NT_SUCCESS(NtStatus)) { //建立成功了 ZwClose(hFile); } return NtStatus; } void DriverUnload(DRIVER_OBJECT *DriverObject) { UNICODE_STRING ustr; RtlUnicodeStringInit(&ustr,L"Driver UnLoad"); DbgPrint("%wZ",&ustr); } NTSTATUS DriverEntry(PDRIVER_OBJECT PdriverObject, PUNICODE_STRING RegistryPath) { //建立設備對象 UNICODE_STRING uPrintString = { 0 }; UNICODE_STRING uPathName = { 0 }; NTSTATUS NtStatus; PdriverObject->DriverUnload = DriverUnload; RtlUnicodeStringInit(&uPrintString, L"啓動驅動安裝"); DbgPrint("%wZ", &uPrintString); RtlUnicodeStringInit(&uPathName, L"\\??\\c:\\1.txt");//初始化字符串路徑 NtStatus = NtCreateFile(uPathName); if (NT_SUCCESS(NtStatus)) { DbgPrint("建立文件成功"); } return STATUS_UNSUCCESSFUL; }
建立完畢截圖:
下面只提供核心接口代碼.直接添加到DLL DriverEntry中便可.
傳參的uPathName = L"\\??\\c:\\IBinary\\"
NTSTATUS IBinaryNtCreateDirectory(UNICODE_STRING uPathName) { NTSTATUS ntStatus; HANDLE hFile; OBJECT_ATTRIBUTES objAttus = { 0 }; IO_STATUS_BLOCK ioStatus = { 0 }; //初始化文件屬性結構體 InitializeObjectAttributes(&objAttus, &uPathName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); ntStatus = ZwCreateFile(&hFile, GENERIC_READ | GENERIC_WRITE, &objAttus, &ioStatus, NULL, FILE_ATTRIBUTE_DIRECTORY, //注意這個屬性.咱們設置建立文件 FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN_IF, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, //表示建立的是目錄,而且是同步執行 NULL, 0); if (NT_SUCCESS(ntStatus)) { ZwClose(hFile); } return ntStatus; }
原理: 使用ZwCreateFile打開文件.獲取文件句柄.而後使用ZwWriteFile寫文件便可.
uPathName = "\\??\\C:\\1.txt"
NTSTATUS IBinaryNtWriteFile(UNICODE_STRING uPathName) { //首先打開文件,而後寫入文件. OBJECT_ATTRIBUTES objAttri = { 0 }; NTSTATUS ntStatus; HANDLE hFile; IO_STATUS_BLOCK ioStatus = { 0 }; PVOID pWriteBuffer = NULL; KdBreakPoint(); InitializeObjectAttributes(&objAttri, &uPathName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, 0); ntStatus = ZwCreateFile(&hFile, GENERIC_WRITE | GENERIC_WRITE, &objAttri, &ioStatus, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN,//注意此標誌,打開文件文件不存在則失敗. FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); if (!NT_SUCCESS(ntStatus)) { return ntStatus; } //開始寫文件 pWriteBuffer = ExAllocatePoolWithTag(PagedPool, 0x20, "niBI"); if (pWriteBuffer == NULL) { DbgPrint("寫文件分配內存出錯"); ZwClose(hFile); return STATUS_INSUFFICIENT_RESOURCES; } RtlZeroMemory(pWriteBuffer, 0x20); RtlCopyMemory(pWriteBuffer, L"HelloIBinary", wcslen(L"HelloIBinary")); ntStatus = ZwWriteFile(hFile, NULL, NULL, NULL, &ioStatus, pWriteBuffer, 0x20, NULL, NULL); if (!NT_SUCCESS(ntStatus)) { ZwClose(hFile); return STATUS_INSUFFICIENT_RESOURCES; } ZwClose(hFile); ExFreePoolWithTag(pWriteBuffer, "niBI"); return ntStatus; }
在拷貝字符串的時候我拷貝的是寬字符.因此顯示如上圖.在咱們讀文件以前.我稍微修改一下.這裏就不在貼出代碼了.
內核中讀寫文件實際上是同樣的.打開一個文件.讀取數據便可.
代碼以下:
uPathName = L"\\??\\c:\\1.txt
傳入了緩衝區.只須要往緩衝區中讀取數據便可.
NTSTATUS IBinaryNtReadFile(PVOID pszBuffer, UNICODE_STRING uPathName) { OBJECT_ATTRIBUTES objAttri = { 0 }; NTSTATUS ntStaus; HANDLE hFile; IO_STATUS_BLOCK ioStatus = { 0 }; PVOID pReadBuffer = NULL; if (NULL == pszBuffer) return STATUS_INTEGER_DIVIDE_BY_ZERO; //打開文件讀取文件. InitializeObjectAttributes(&objAttri, &uPathName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, 0); ntStaus = ZwCreateFile(&hFile, GENERIC_READ | GENERIC_WRITE, &objAttri, &ioStatus, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, NULL); if (!NT_SUCCESS(ntStaus)) { ZwClose(hFile); if (NULL != pReadBuffer) ExFreePoolWithTag(pReadBuffer, "niBI"); return STATUS_INTEGER_DIVIDE_BY_ZERO; } //讀取文件 pReadBuffer = ExAllocatePoolWithTag(PagedPool, 100, "niBI"); if (NULL == pReadBuffer) return STATUS_INTEGER_DIVIDE_BY_ZERO; ntStaus = ZwReadFile(hFile, NULL, NULL, NULL, &ioStatus, pReadBuffer, 100, NULL, NULL); if (!NT_SUCCESS(ntStaus)) { ZwClose(hFile); if (NULL != pReadBuffer) ExFreePoolWithTag(pReadBuffer, "niBI"); return STATUS_INTEGER_DIVIDE_BY_ZERO; } //將讀取的內容拷貝到傳入的緩衝區. RtlCopyMemory(pszBuffer, pReadBuffer, 100); ZwClose(hFile); if (NULL != pReadBuffer) ExFreePoolWithTag(pReadBuffer, "niBI"); return ntStaus; }
內核中能夠刪除文件.有兩種方式.第一種調用 ZwDeleteFile.你須要包含一個 <ntifs.h>頭文件.
可是我包含以後出錯.就沒再深究.本身聲明瞭一下.
uDeletePathName = L"\\??\\c:\\1.txt"
#include <ntddk.h> #include <wdm.h> #include <ntdef.h> #include <ntstrsafe.h> NTSTATUS ZwDeleteFile( IN POBJECT_ATTRIBUTES ObjectAttributes); //函數聲明 NTSTATUS IBinaryNtZwDeleteFile(UNICODE_STRING uDeletePathName) { OBJECT_ATTRIBUTES obAttri = { 0 }; //初始化源文件路徑而且打開 InitializeObjectAttributes(&obAttri, &uDeletePathName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL ); return ZwDeleteFile(&obAttri); }
這種方式刪除文件.可是可能刪除失敗.好比文件被獨佔打開等等.我沒有進行嘗試.在虛擬機中我就算 打開 1.txt這個文件.當我要刪除這個文件的時候同樣刪除成功.
這種刪除方式更加厲害. 好比上面咱們說的文件可能由於各類因素刪除失敗.因此採用這種方法. 這種方法是使用 內核中的 ZwSetInformationFile設置文件信息從而進行刪除的.
代碼以下:
NTSTATUS IBinaryNtSetInformationFileDeleteFile(UNICODE_STRING uDeletePathName) { //刪除文件的第二種方式 /* 思路: 1.初始化文件路徑 2.使用讀寫方式打開文件. 以共享模式打開. 3.若是是拒絕,則以另外一種方式打開文件.而且設置這個文件的信息. 4.設置成功以後就能夠刪除了. */ OBJECT_ATTRIBUTES objAttri; NTSTATUS ntStatus; HANDLE hFile; IO_STATUS_BLOCK ioStatus; FILE_DISPOSITION_INFORMATION IBdelPostion = { 0 }; //經過ZwSetInformationFile刪除.須要這個結構體 __try { InitializeObjectAttributes(&objAttri, &uDeletePathName, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL ); ntStatus = ZwCreateFile(&hFile, DELETE | FILE_WRITE_DATA | SYNCHRONIZE, //注意權限,以刪除權限.寫權限. &objAttri, &ioStatus, NULL, FILE_ATTRIBUTE_NORMAL, //文件的屬性是默認 FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,//文件的共享模式 刪除 讀寫 FILE_OPEN, //文件的打開方式是 打開.若是不存在則返回失敗. FILE_SYNCHRONOUS_IO_NONALERT | FILE_DELETE_ON_CLOSE, //文件的應用選項,若是是FILE_DELETE_ON_CLOSE則使用ZwClose關閉文件句柄的時候刪除這個文件 NULL, 0 ); if (!NT_SUCCESS(ntStatus)) { //若是不成功,判斷文件是否拒絕訪問.是的話咱們就設置爲能夠訪問.而且進行刪除. if (STATUS_ACCESS_DENIED == ntStatus) { ntStatus = ZwCreateFile(&hFile, SYNCHRONIZE | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,//刪除權限失敗就以讀寫模式 &objAttri, &ioStatus, NULL, FILE_ATTRIBUTE_NORMAL, //文件的屬性爲默認 FILE_SHARE_DELETE | FILE_SHARE_WRITE | FILE_SHARE_READ,//文件的共享屬性爲 讀寫刪除 FILE_OPEN, //文件的打開方式爲 打開,不存在則失敗 FILE_SYNCHRONOUS_IO_NONALERT, //文件的應用選項. NULL, 0 ); //若是打開成功了.則設置這個文件的信息 if (NT_SUCCESS(ntStatus)) { FILE_BASIC_INFORMATION IBFileBasic = { 0 };// /* 使用ZwQueryInformationfile遍歷文件的信息.這裏遍歷的是文件的基本信息 */ ntStatus = ZwQueryInformationFile( hFile, &ioStatus, &IBFileBasic, sizeof(IBFileBasic), FileBasicInformation ); //遍歷失敗.輸出打印信息 if (!NT_SUCCESS(ntStatus)) DbgPrint("刪除文件失敗,遍歷文件信息出錯 文件名= %wZ", &uDeletePathName); //設置文件的基本信息 IBFileBasic.FileAttributes = FILE_ATTRIBUTE_NORMAL; //設置屬性爲默認屬性 ntStatus = ZwSetInformationFile( hFile, &ioStatus, &IBFileBasic, sizeof(IBFileBasic), FileBasicInformation); //將個人FileBasic基本屬性設置到這個文件中 if (!NT_SUCCESS(ntStatus)) DbgPrint("刪除文件失敗,設置文件信息出錯"); //若是成功關閉文件句柄. ZwClose(hFile); //從新打開這個設置信息後的文件. ntStatus = ZwCreateFile(&hFile, SYNCHRONIZE | FILE_WRITE_DATA | DELETE, &objAttri, &ioStatus, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT | FILE_DELETE_ON_CLOSE, NULL, 0); } if (!NT_SUCCESS(ntStatus)) DbgPrint("打開文件失敗,刪除失敗"); } } //進行強制刪除文件 經過 ZwSetInformationFile IBdelPostion.DeleteFile = TRUE; //此標誌設置爲TRUE便可刪除 ntStatus = ZwSetInformationFile(hFile, &ioStatus, &IBdelPostion, sizeof(IBdelPostion), FileDispositionInformation); if (!NT_SUCCESS(ntStatus)) { ZwClose(hFile); DbgPrint("刪除文件失敗,設置文件信息出錯"); return ntStatus; } ZwClose(hFile); } __except (1) { DbgPrint("刪除文件出現異常"); } return ntStatus; }