看流星社区

 找回密码
 注册账号
查看: 1867|回复: 0

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

[复制链接]

该用户从未签到

发表于 2017-6-1 12:17:29 | 显示全部楼层 |阅读模式

原作者:Tesla.Angela
链接:http://www.m5home.com/bbs/thread-8896-1-1.html
众所周知在FILE_OBJECT.FileName的路径是不带盘符的,于是网上各种QUICK AND DIRTY的代码就干脆直接从FileName里取得“无头路径”。
这种恶心的做法自然是要不得的,现在分享一下从这个结构体里取完整路径的方法。区区40行代码(还包括空行和注释),即可支持XP到WIN10。

//通过FILE_OBJECT拿到文件名
{
    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上的获取进程全路径


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

点击按钮快速添加回复内容: 支持 高兴 激动 给力 加油 苦寻 生气 回帖 路过 感恩
您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

小黑屋|手机版|Archiver|看流星社区 |网站地图

GMT+8, 2024-3-19 14:54

Powered by Kanliuxing X3.4

© 2010-2019 kanliuxing.com

快速回复 返回顶部 返回列表