天天看點

通過File Reference Number擷取檔案全路徑(c++)

//管理者方式運作

#include<windows.h>
#include<winternl.h>
#include<iostream>

using namespace std;

//首先進行函數類型的定義

typedef NTSTATUS (NTAPI* NTCREATEFILE)(
	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
);
	
typedef NTSTATUS (NTAPI* NTQUERYINFORMATIONFILE)(
    HANDLE handle,
    PIO_STATUS_BLOCK io,
    PVOID ptr,
    ULONG len,
    FILE_INFORMATION_CLASS FileInformationClass
);

typedef NTSTATUS (NTAPI* NTCLOSE)(
	IN HANDLE Handle
);

//volume_handle為使用CreateFile獲得的卷句柄
void get_path_from_frn(HANDLE &volume_handle,DWORDLONG frn)
{
//Nt函數的導出

	HMODULE hmodule=NULL;
    hmodule=LoadLibrary("ntdll.dll");
    if(hmodule) cout<<"載入ntdll.dll成功"<<endl<<endl;
    
    NTCREATEFILE NtCreateFile=NULL;
    NtCreateFile=(NTCREATEFILE)GetProcAddress(hmodule,"NtCreateFile");
    if(NtCreateFile) cout<<"導出NtCreateFile函數成功"<<endl<<endl;
    
    NTQUERYINFORMATIONFILE NtQueryInformationFile=NULL;
    NtQueryInformationFile=(NTQUERYINFORMATIONFILE)GetProcAddress(hmodule,"NtQueryInformationFile");
    if(NtQueryInformationFile) cout<<"導出NtQueryInformationFile函數成功"<<endl<<endl;
    
    NTCLOSE NtClose=NULL;
    NtClose=(NTCLOSE)GetProcAddress(hmodule,"NtClose");
    if(NtClose) cout<<"導出NtClose函數成功"<<endl<<endl;

//各種所需變量的定義
	
	UNICODE_STRING us_id;//UNICODE_STRING型的檔案ID
    OBJECT_ATTRIBUTES oa;
    IO_STATUS_BLOCK isb;
    LARGE_INTEGER id;//檔案ID
	HANDLE file_handle=NULL;//frn所訓示的檔案的句柄
	
	id.QuadPart=frn;//檔案ID指派為frn
        
    us_id.Buffer=(WCHAR*)&id;//建立UNICODE型的檔案ID
    us_id.Length=8;
    us_id.MaximumLength=8;
    	
	oa.ObjectName=&us_id;//指派OBJECT_ATTRIBUTES結構體
	oa.Length=sizeof(OBJECT_ATTRIBUTES);
	oa.RootDirectory=volume_handle;
	oa.Attributes=OBJ_CASE_INSENSITIVE;
	oa.SecurityDescriptor=NULL;
	oa.SecurityQualityOfService=NULL;
	 
//使用NtCreateFile函數通過檔案ID獲得目标檔案的句柄
   
	ULONG status=NtCreateFile
	(
	    &file_handle,
	    FILE_GENERIC_READ,
		&oa,
		&isb,
		NULL,
	    FILE_ATTRIBUTE_NORMAL,
		FILE_SHARE_READ|FILE_SHARE_WRITE,
		FILE_OPEN,
		FILE_OPEN_BY_FILE_ID,
		NULL,
		0
	);
	
	if(0==status)
	{
		FILE_NAME_INFORMATION* name_info=(FILE_NAME_INFORMATION*)malloc(512);

//利用剛剛得到的句柄通過NtQueryInformationFile函數獲得路徑資訊		

        status=NtQueryInformationFile
		(
		    file_handle,
		    &isb,
		    name_info,
	    	512,
		    FileNameInformation
		);
		
        if(0==status)
		{
        	char path_buf[260]={0};
            int path_size=(*name_info).FileNameLength;
            //寬字元轉為char型
            WideCharToMultiByte(CP_OEMCP,0,(*name_info).FileName,path_size/2,path_buf,path_size,NULL,NULL);
            cout<<"路徑:"<<"C:"<<path_buf<<endl<<endl;
        }
            
        free(name_info);
		NtClose(file_handle);//關閉目标檔案句柄
	}
    
	CloseHandle(volume_handle);//關閉卷句柄
}

bool get_handle(LPCSTR volume_name,HANDLE &volume_handle)
{
	volume_handle=CreateFile(volume_name,GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL);
	if(volume_handle==INVALID_HANDLE_VALUE) return false;
	return true;
}

int main()
{
	HANDLE volume_handle=NULL;
	if(get_handle("\\\\.\\c:",volume_handle))
	{
		get_path_from_frn(volume_handle,17451448556075090);
	}
	system("pause");
	
	return 0;
}
           
測試圖
           
通過File Reference Number擷取檔案全路徑(c++)