获取文件对象的名称

获取文件对象的名称

 

一.取文件对象名称

我们可以使用函数ObQueryNameString 来查询获取文件对象(FILE_OBJECT )的名称。由于文件对象有专门的名称查询函数IopQueryName ,所以ObQueryNameString 在内部会直接调用这个函数来查询文件对象名。

 

我们还有另外一种方法比较“直接”地获得文件对象名称。我们知道:文件对象名包括驱动器名和文件路径名。

FILE_OBJECT 结构中有一个成员FileName ,它只包括文件路径名(注意:不包括驱动器名)。

FILE_OBJECT 结构中另外有一个成员DeviceObject ,它是指向DEVICE_OBJECT 的设备对象。该设备就是包含该文件的驱动器设备对象。我们可以调用ObQueryNameString 查询获取此设备对象的名称。但是设备名称的格式是这样的://Device//HarddiskvolumeX X 为数字),并不是常见的C/D/E... 驱动器名格式。这是因为我们说的驱动器名其实是上面这些设备对象的符号链接(Symbolic link) 名,我们可以通过IoVolumeDeviceToDosName (在XP/2003 等下使用,在NT/2000 下使用RtlVolumeDeviceToDosName )来将设备名称转成驱动器名。

 

但是若直接使用ObQueryNameString 查询文件对象的话,返回的名称就是设备名称和文路径名,如:/Device/HarddiskVolume1/WINDOWS/system32/smss.exe

 

此时我们是没有设备对象,所以就没有办法调用IoVolumeDeviceToDosName 来转化了,此时该怎么办?有一个比较笨的方法,就是调用ZwOpenSymbolcLink 对象对所有A~Z 字母进行打开链接对象,并调用ZwQuerySymbilicLink 来获得对应的设备对象名,并将这个设备名与上面的ObQueyNameString 返回的设备名进行比较,以此来确定驱动器名。见下面的代码片段:

 

    

RtlInitUnicodeString(&SymbolicLink, L"//??//C:");

LinkTarget.MaximumLength = 200;

LinkTarget.Buffer = ExAllocatePoolWithTag(NonPagedPool, 200, 'test');

for (c = 'A'; c <='Z'; c++)

{

     SymbolicLink.Buffer[4] = c;

     InitializeObjectAttributes(&oa, &SymbolicLink, OBJ_KERNEL_HANDLE, 0, NULL);

     Status = ZwOpenSymbolicLinkObject(&LinkHandle, GENERIC_READ, &oa);

     if (Status != STATUS_SUCCESS)

          continue;    

     Status = ZwQuerySymbolicLinkObject(LinkHandle, &LinkTarget, NULL);

     //LinkTarget 返回的就是设备名称

     ZwClose(LinkHandle);

     if (Status == STATUS_SUCCESS)

     {

          RetLength = LinkTarget.Length;

          if (RtlCompareMemory(LinkTarget.Buffer, ObjectNameInfo->Name.Buffer, RetLength) == RetLength)

          break; //ObjectNameInfo ObQueryName 返回的文件对象名

     }

}

 

ExFreePoolWithTag(LinkTarget.Buffer, 'test');

 

 

二.引申:获取进程的主程序名

首先说一下每个进程的映像名称,这不是进程对象名。在_EPROCESS 结构中有一个ImageFileName 得成员(在XPSP3 下偏移为174H, 它是一个16 个字节的数组,它就是进程的映像名称,当有名称超过15 位是就截取前15 个字节,最后一个字节为NULL

 

当需要知道进程的主程序名时,我们通过下面的关系获得该进程对应的文件对象 : EPROCESS-> SectionObject ->Segment->controlArea->FilePointer ,只有一点要注意: SectionObject Segment 结构为 _SEGMENT ,而不是 _SEGMENT_OBJECT ,这个常常搞错。

 

例如:下例就是返回进程对象对应的文件对象的过程:

VOID NTAPI GetFilePointer(PULONG ProcessObject, PULONG *FileObject)

{

     ULONG Section, Segment ,ControlArea;

     *FileObject = NULL;

     if (ProcessObject)

         Section = *(PULONG)((PCHAR)ProcessObject + 0x138);

     else

         return; 

    

     if (Section)

         Segment = *(PULONG)((PCHAR)Section + 0x14);

     else

         return;

    

     if (Segment)

         ControlArea = *(PULONG)((PCHAR)Segment + 0x0);

     else

         return;

    

     if (ControlArea)

         *FileObject = *(PULONG *)((PCHAR)ControlArea + 0x24);

}

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值