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;
}


 

 

 

 

 

 

 

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 Eric 的頭像
    Eric

    一個小小工程師的心情抒發天地

    Eric 發表在 痞客邦 留言(0) 人氣()