获取文件对象的名称

获取文件对象的名称

一.取文件对象名称

我们可以使用函数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; //ObjectNameInfoObQueryName 返回的文件对象名

}

}

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

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值