您的位置:首页 > 移动开发 > Objective-C

从FILE_OBJECT里获取完整NT路径和DOS路径

2016-11-29 20:02 211 查看
原作者: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 的获取

可以看我的另一篇文章

NT5/NT6上的获取进程全路径
http://blog.csdn.net/zhuhuibeishadiao/article/details/51136650  

也可以参考以下链接 第八个男人 很难访问 赶紧备份下

链接:http://www.debugman.com/archiver/tid/4223 (我的第八个男人啊~~~)

论坛 › Native Code 综合讨论 › EPROCESS获取FileObject

JeTus 发表于 2010-1-2 13:44:07

EPROCESS获取FileObject

1,通过PsGetCurrentProcess获取EPROCESS,EPROCESS->SectionObject->Segment->ControlArea->FileObject,不过貌似wdk的EPROCESS被定义成了KPROCESS,这个EPROCESS的结构就不一样了;

2,通过获取process的Handle,然后调用ObReferenceObjectByHandle, ObjectType 填写IoFileObjectType,然后获取其FileObject;

目前只想到上面两种方法,不知道还有没有其他更简单点的办法。

PS:用的框架是文件过滤驱动。

先谢谢了

JeTus 发表于 2010-1-2 14:18:26

写了验证一下,第二个方法好像行不通,不知道是不是process的handle不能用IoFileObjectType来获取FileObject。

第一个方法因为没有wdk定义的结构体,暂时不想使用哪个方法。

MJ0011 发表于 2010-1-2 15:05:29

ZwQueryInformationProcess, ZwCreateFile , ObReferenceObjectByHandle

JeTus 发表于 2010-1-2 16:49:20

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

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息