close
這一整個月都在開始邊學寫Driver,除了每天BlueScreen之外,
還有更多的是只要一個細節沒處理好就葛屁的莫名其妙了,
而這一個月的心得就是.... 這玩意真的心不細的人不要來碰,
而且入門真的不容易,學習曲線真的是很難呈正成長的那種。
這邊主要是要教如何透過Kernel實現以下幾個功能:
1>打開文件
2>讀取文件
3>創建文件
4>寫入文件
Transfer:
KernelCopyFile(L"\??\C:\888.exe", L"\??\C:\567.exe");
Be careful:
1. How is the file read?
Readoffset.quadpart = 0 This is a read file location. If the read file is large, you can pass this parameter.
2, zwclose (hfile2); finally do not close the handle
//內核拷貝
NTSTATUS KernelCopyFile(PWCHAR defile_path, PWCHAR sourcefile_path)
{
NTSTATUS status = STATUS_SUCCESS;//定義一個返回值
HANDLE hFile1 = NULL; //定義一個handle
UNICODE_STRING sourcefilepath = { 0 };//原始文件位置
OBJECT_ATTRIBUTES obja1 = { 0 }; //原始文件參數
IO_STATUS_BLOCK iostack1 = { 0 };//舊文件操作紀錄
//Step1.打開原始文件並且初始化
RtlInitUnicodeString(&sourcefilepath, sourcefile_path);//初始化一個文件路徑
InitializeObjectAttributes
(
&obja1,
&sourcefilepath,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL
);//初始化
//Step2.打開原始文件->向IO發起請求
//參數1: file handle
//參數2: 訪問的權限
//參數3: &iostack1 會記錄這一次操作的一些訊息
//參數4: FILE_SHARE_READ 共享讀, FILE_SHARE_WRITE 共享寫
status = ZwOpenFile(&hFile1, GENERIC_ALL, &obja1, &iostack1, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_NONALERT);
//Step3.判斷文件是不是成功
if (!NT_SUCCESS(status))
{
DbgPrint(("[E]>Open source file failed:%x \n", status));
return status;
}
//Step4.查詢文件大小
FILE_STANDARD_INFORMATION fbi = { 0 }; //這個是要判斷取得的文件大小用的
//查詢文件的訊息
status = ZwQueryInformationFile
(
hFile1,
&iostack1,
&fbi,
sizeof(FILE_STANDARD_INFORMATION),
FileStandardInformation
);
if (!NT_SUCCESS(status))//如果失敗了
{
DbgPrint(("[E]>QueryInformationFile source file failed:%x \n", status));
ZwClose(hFile1);//關閉文件
return status;
}
/************************************************************************/
/* 基本上到這邊文件查詢就算是成功了 */
/************************************************************************/
//Step5.要申請一個緩衝區的大小
PVOID fileBuffer = NULL; //定義一個文件的緩衝區
// 申請緩衝區
// 申請緩衝區大小,這裡就是上面取得的文件的大小
fileBuffer = ExAllocatePool(NonPagedPool, fbi.EndOfFile.QuadPart);
if (!fileBuffer)//如果不成功
{
DbgPrint(("[E]>AllocateBuffer Failed\n"));
ZwClose(hFile1);//關閉文件
return status;
}
// 清空緩衝區
RtlZeroMemory(fileBuffer, fbi.EndOfFile.QuadPart);
// 開始讀!
LARGE_INTEGER readoffset = { 0 };
// 從0開始讀的意思是整個讀入,如果你想要從0x1000 ,那就填0x1000
readoffset.QuadPart = 0;
//讀文件
//參數1: file handle
//參數2: NULL表示讀事件,異步讀
//參數3: NULL means reading event, read asynchronous reading
//參數4: &iostack1 裡面有請求的基本訊息,請求的長度...結果..etc
//參數5: fbi.EndOfFile.QuadPart 是緩衝區的長度
//參數6: 從哪裡開始讀文件, readoffset 這裡是從0開始讀
//最後一個參數Key,一般來說傳NULL
status = ZwReadFile(hFile1, NULL, NULL, NULL,
&iostack1,
fileBuffer,
fbi.EndOfFile.QuadPart,
&readoffset,
NULL);
if (!fileBuffer)
{
//讀取失敗
DbgPrint(("[E]>ReadFile Failed:%x\n",status));
ZwClose(hFile1);
ExFreePool(fileBuffer);
return status;
}
DbgPrint(("[E]>-----------IoInfo------%d \n", iostack1.Information));
ZwClose(hFile1);//我們把文件關掉,因為文件內容已經讀到了,並且放在緩衝區內
//Step6.創建新文件
HANDLE hFile2 = NULL;
UNICODE_STRING defilepath = { 0 };
OBJECT_ATTRIBUTES obja2 = { 0 }; //新文件參數
IO_STATUS_BLOCK iostack2 = { 0 };//新聞見IO操作紀錄
RtlInitUnicodeString(&defilepath, defile_path);//新文件路徑
//初始化文件描述
InitializeObjectAttributes(&obja2, &defilepath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL, NULL);
//ZwCreateFile內的參數:
//這邊是創建文件
//ULONG CreateDisposition =>如果文件存在的話 = 替換,不存在的話=創建
//ZwCreateFile可以創建新文件,也可以打開設備,可以打開任何東西
//参数1:&hfile2 handle
//参数2:訪問權限 GENERIC_ALL是全部權限的意思
//参数3:&obja2文件訊息的描述
//参数4:iostack2 IO操作的紀錄
//参数5:一個指針 提前申請文件的大小,這邊先設置NULL,不設置大小先創建
//参数6:FILE_ATTRIBUTE_NORMAL 文件的描述
//参数7:FILE_SHARE_WRITE
//参数8:這個參數比較重要,如果文件存在怎麼辦?? FILE_SUPERSEDE 這個代表文件存在就用新創建的文件替換
//参数9:FILE_SYNCHRONOUS_IO_NONALERT和ZwOpenFile一樣
//参数10:NULL 用到網路通訊,本例用不到,設置NULL ,打開TCP UDP設備的時候會用到這個參數
//参数11: 0 用到網路通訊,本例用不到, 設置為NULL ,打開TCP UDP設備的時候會用到這個參數
status = ZwCreateFile(&hFile2, GENERIC_ALL, &obja2, &iostack2, NULL, FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_WRITE,
FILE_SUPERSEDE,
FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
if (!NT_SUCCESS(status))
{
DbgPrint(("[E]>Create File Failed:%x\n", status));
ExFreePool(fileBuffer);
return status;
}
/************************************************************************/
/* 文件到這邊就已經算是創建成功了 */
/************************************************************************/
//Step7.將資料寫進去
LARGE_INTEGER writeoffset = { 0 };
//從哪裡開始寫文件,這裡的意思是從0開始寫
writeoffset.QuadPart = 0;
/// <寫入文件>
/// ZwWriteFile
/// 參數1:hfile2 FileHandle
/// 參數2:NULL 事件
/// 參數3:NULL 是否APC異步寫
/// 參數4:NULL
/// 參數5:&iostack2
/// 參數6:filebuffe 內存中的文件
/// 參數7:fbi.EndOfFile.QuadPart文件的長度
/// 參數8:writeoffset.QuadPart 準備從哪裡開始寫
/// 參數9:NULL
status = ZwWriteFile(hFile2, NULL, NULL, NULL, &iostack2, fileBuffer, fbi.EndOfFile.QuadPart,
&writeoffset, NULL);
if (!NT_SUCCESS(status))
{
//失敗的化去關閉文件和釋放BUFFER
DbgPrint(("[E]>Write File Failed:%x\n", status));
ExFreePool(fileBuffer);
ZwClose(hFile2);
return status;
}
//印出實際寫入的一些訊息
DbgPrint(("[E]>----------Write------%d\n", iostack2.Information));
//Free memory & handle
ExFreePool(fileBuffer);
//如果不關閉的話,文建會被系統鎖住,該文件就不能刪除也不能運行
ZwClose(hFile2);
return status;
}
全站熱搜
留言列表