從FILE_OBJECT裡獲取完整NT路徑和DOS路徑
阿新 • • 發佈:2018-11-10
原作者:Tesla.Angela
連結:http://www.m5home.com/bbs/thread-8896-1-1.html
眾所周知在FILE_OBJECT.FileName的路徑是不帶碟符的,於是網上各種QUICK AND DIRTY的程式碼就乾脆直接從FileName裡取得“無頭路徑”。
這種噁心的做法自然是要不得的,現在分享一下從這個結構體裡取完整路徑的方法。區區40行程式碼(還包括空行和註釋),即可支援XP到WIN10。
本帖隱藏的內容
- //通過FILE_OBJECT拿到檔名
- BOOLEAN QueryFileObjectNtName(PFILE_OBJECT pFileObject, PWCHAR *OutputBufferFreeByCaller)
- {
- NTSTATUS status;
- ULONG returnedLength;
- BOOLEAN foundCompleteName = FALSE;
- PUNICODE_STRING pObjectName = NULL;
- status = ObQueryNameString(pFileObject, (POBJECT_NAME_INFORMATION)pObjectName, 0, &returnedLength );
- if(status == STATUS_INFO_LENGTH_MISMATCH)
- {
- pObjectName = ExAllocatePoolWithTag(PagedPool, returnedLength, 'XXOO');
- status = ObQueryNameString(pFileObject, (POBJECT_NAME_INFORMATION)pObjectName, returnedLength, &returnedLength );
- if(NT_SUCCESS(status))
- {
- *OutputBufferFreeByCaller = ExAllocatePool(PagedPool,pObjectName->Length+2);
- RtlZeroMemory(*OutputBufferFreeByCaller,pObjectName->Length+2);
- memcpy(*OutputBufferFreeByCaller,pObjectName->Buffer,pObjectName->Length);
- foundCompleteName = TRUE;
- }
- ExFreePoolWithTag(pObjectName, 'XXOO');
- }
- return foundCompleteName;
- }
-
- //通過FILE_OBJECT拿到檔名
- BOOLEAN QueryFileObjectDosName(PFILE_OBJECT pFileObject, PWCHAR *OutputBufferFreeByCaller)
- {
- UNICODE_STRING volumeDosName = {0};
- //初始化輸出路徑
- *OutputBufferFreeByCaller = ExAllocatePool(PagedPool, pFileObject->FileName.Length+32);
- RtlZeroMemory(*OutputBufferFreeByCaller, pFileObject->FileName.Length+32);
- //取得碟符DOS名
- RtlInitEmptyUnicodeString(&volumeDosName,NULL,0);
- if(!NT_SUCCESS(IoVolumeDeviceToDosName(pFileObject->DeviceObject, &volumeDosName)))
- return FALSE;
- memcpy(*OutputBufferFreeByCaller, volumeDosName.Buffer, volumeDosName.Length);
- //連線檔名
- memcpy((PUCHAR)*OutputBufferFreeByCaller + volumeDosName.Length, pFileObject->FileName.Buffer, pFileObject->FileName.Length);
- return TRUE;
- }
不知道啥時候這段程式碼會出現在某些“大牛”的工程裡然後標為“原創”。哈哈。
最後補充一下:這個pFileObject 的獲取
可以看我的另一篇文章
http://blog.csdn.net/zhuhuibeishadiao/article/details/51136650
也可以參考以下連結 第八個男人 很難訪問 趕緊備份下
連結:http://www.debugman.com/archiver/tid/4223 (我的第八個男人啊~~~)
論壇 › Native Code 綜合討論 › EPROCESS獲取FileObject
EPROCESS獲取FileObject
1,通過PsGetCurrentProcess獲取EPROCESS,EPROCESS->SectionObject->Segment->ControlArea->FileObject,不過貌似wdk的EPROCESS被定義成了KPROCESS,這個EPROCESS的結構就不一樣了;2,通過獲取process的Handle,然後呼叫ObReferenceObjectByHandle, ObjectType 填寫IoFileObjectType,然後獲取其FileObject;
目前只想到上面兩種方法,不知道還有沒有其他更簡單點的辦法。
PS:用的框架是檔案過濾驅動。
先謝謝了 寫了驗證一下,第二個方法好像行不通,不知道是不是process的handle不能用IoFileObjectType來獲取FileObject。
第一個方法因為沒有wdk定義的結構體,暫時不想使用哪個方法。 ZwQueryInformationProcess, ZwCreateFile , ObReferenceObjectByHandle 謝謝MJ。
網上找的一段程式碼,貼出來留給後面的同學看看。
// 注: 當函式返回TRUE時,引數pImageName所指向的 PANSI_STRING 物件需要用RtlFreeAnsiString()釋放。
// 否則,標記為 "Strg" 的記憶體池會產生洩露。
typedef NTSTATUS (*QUERY_INFO_PROCESS) (
__in HANDLE ProcessHandle,
__in PROCESSINFOCLASS ProcessInformationClass,
__out_bcount(ProcessInformationLength) PVOID ProcessInformation,
__in ULONG ProcessInformationLength,
__out_opt PULONG ReturnLength
);
QUERY_INFO_PROCESS ZwQueryInformationProcess;
#define ProcessImageFileName 27
BOOLEAN GetProcessImageName(PANSI_STRING pImageName)
{
KIRQL CurIRQL ;
NTSTATUS status;
ULONG returnedLength;
ULONG bufferLength;
PVOID buffer;
PUNICODE_STRING imageName;
BOOLEAN bRet = FALSE ;
PAGED_CODE(); // this eliminates the possibility of the IDLE Thread/Process
CurIRQL = KeGetCurrentIrql() ;
DbgPrint ("Current IRQL is %d\\r\\n", CurIRQL) ;
if (PASSIVE_LEVEL != CurIRQL)
{
return FALSE ;
}
try
{
if ( ! MmIsAddressValid (pImageName))
{
return FALSE ;
}
pImageName->Length = 0 ;
pImageName->MaximumLength = 0 ;
pImageName->Buffer = NULL ;
}
except (EXCEPTION_EXECUTE_HANDLER)
{
return FALSE ;
}
if (NULL == ZwQueryInformationProcess) {
UNICODE_STRING routineName;
RtlInitUnicodeString(&routineName, L"ZwQueryInformationProcess");
ZwQueryInformationProcess =
(QUERY_INFO_PROCESS) MmGetSystemRoutineAddress(&routineName);
if (NULL == ZwQueryInformationProcess) {
DbgPrint("Cannot resolve ZwQueryInformationProcess\\n");
return FALSE ;
}
}
//
// Step one - get the size we need
//
status = ZwQueryInformationProcess( NtCurrentProcess(),
ProcessImageFileName,
NULL, // buffer
0, // buffer size
&returnedLength);
if (STATUS_INFO_LENGTH_MISMATCH != status) {
return FALSE;
}
//
// Is the passed-in buffer going to be big enough for us?
// This function returns a single contguous buffer model...
//
bufferLength = returnedLength - sizeof(UNICODE_STRING);
//
// If we get here, the buffer IS going to be big enough for us, so
// let's allocate some storage.
//
buffer = ExAllocatePoolWithTag(PagedPool, returnedLength, 'ipgD');
if (NULL == buffer) {
return FALSE ;
}
try
{
//
// Now lets go get the data
//
status = ZwQueryInformationProcess( NtCurrentProcess(),
ProcessImageFileName,
buffer,
returnedLength,
&returnedLength);
if (NT_SUCCESS(status)) {
//
// Ah, we got what we needed
//
imageName = (PUNICODE_STRING) buffer;
// RtlCopyUnicodeString(ProcessImageName, imageName);
//RtlZeroMemory (pBuffer, cbBuffer) ;
//if (((size_t)-1) != wcstombs (pBuffer, imageName->Buffer, cbBuffer))
//{
// bRet = TRUE ;
//}
//KdPrint (("Current ProcessImageFileName: \\"%s\\"\\r\\n", pBuffer)) ;
if (STATUS_SUCCESS != RtlUnicodeStringToAnsiString (pImageName, imageName, TRUE))
{
bRet = FALSE ;
KdPrint (("Current ProcessImageFileName: Unknow\\r\\n")) ;
}
else
{
bRet = TRUE ;
KdPrint (("Current ProcessImageFileName: \\"%s\\"\\r\\n", pImageName->Buffer)) ;
}
}
}
except (EXCEPTION_EXECUTE_HANDLER)
{
bRet = FALSE ;
}
//
// free our buffer
//
ExFreePool(buffer);
//
// And tell the caller what happened.
//
return bRet ;
}