打开被独占的文件方法Word格式.docx

上传人:b****7 文档编号:22135526 上传时间:2023-02-02 格式:DOCX 页数:17 大小:24.22KB
下载 相关 举报
打开被独占的文件方法Word格式.docx_第1页
第1页 / 共17页
打开被独占的文件方法Word格式.docx_第2页
第2页 / 共17页
打开被独占的文件方法Word格式.docx_第3页
第3页 / 共17页
打开被独占的文件方法Word格式.docx_第4页
第4页 / 共17页
打开被独占的文件方法Word格式.docx_第5页
第5页 / 共17页
点击查看更多>>
下载资源
资源描述

打开被独占的文件方法Word格式.docx

《打开被独占的文件方法Word格式.docx》由会员分享,可在线阅读,更多相关《打开被独占的文件方法Word格式.docx(17页珍藏版)》请在冰豆网上搜索。

打开被独占的文件方法Word格式.docx

这种方法不能用于许多情形,比如要在运行的系统中拷贝注册表文件,用这种方法就不会成功。

我们先来试着实现对系统中所有已打开文件的句柄的枚举。

为枚举句柄,每个句柄都由以下结构体描述:

typedefstruct_SYSTEM_HANDLE

{

ULONG 

uIdProcess;

UCHAR 

ObjectType;

Flags;

USHORT 

Handle;

POBJECT 

pObject;

ACCESS_MASKGrantedAccess;

}SYSTEM_HANDLE,*PSYSTEM_HANDLE;

这里的ObjectType域定义了句柄所属的对象类型。

这里我们又遇到了问题――File类型的ObjectType在Windows

2000、XP和2003下的取值各不相同,所以我们不得不动态的定义这个值。

为此我们用CreateFile来打开NUL设备,找到它的句柄并记下它的类型:

UCHARGetFileHandleType()

HANDLE 

hFile;

PSYSTEM_HANDLE_INFORMATIONInfo;

r;

Result=0;

hFile=CreateFile("

NUL"

GENERIC_READ,0,NULL,OPEN_EXISTING,0,0);

if(hFile!

=INVALID_HANDLE_VALUE)

Info=GetInfoTable(SystemHandleInformation);

if(Info)

for(r=0;

r<

Info->

uCount;

r++)

if(Info->

aSH[r].Handle==(USHORT)hFile&

&

aSH[r].uIdProcess==GetCurrentProcessId())

Result=Info->

aSH[r].ObjectType;

break;

}

}

HeapFree(hHeap,0,Info);

CloseHandle(hFile);

returnResult;

现在知道了句柄的类型我们就可以枚举系统中打开的文件了。

首先我们来用句柄获取打开文件的文件名:

typedefstruct_NM_INFO

FILE_NAME_INFORMATIONInfo;

WCHARName[MAX_PATH];

}NM_INFO,*PNM_INFO;

DWORDWINAPI

GetFileNameThread(PVOIDlpParameter)

PNM_INFO 

NmInfo=lpParameter;

IO_STATUS_BLOCKIoStatus;

intr;

NtQueryInformationFile(NmInfo->

hFile,&

IoStatus,&

NmInfo->

Info,

sizeof(NM_INFO)-sizeof(HANDLE),

FileNameInformation);

return0;

voidGetFileName(HANDLEhFile,PCHARTheName)

hThread;

PNM_INFOInfo=HeapAlloc(hHeap,0,sizeof(NM_INFO));

hFile=hFile;

hThread=CreateThread(NULL,0,GetFileNameThread,Info,0,NULL);

if(WaitForSingleObject(hThread,INFINITE)==WAIT_TIMEOUT)

TerminateThread(hThread,0);

CloseHandle(hThread);

memset(TheName,0,MAX_PATH);

WideCharToMultiByte(CP_ACP,0,Info->

Info.FileName,

Info.FileNameLength>

>

1,TheName,MAX_PATH,NULL,NULL);

现在来枚举打开的文件:

voidmain()

CHAR 

Name[MAX_PATH];

hProcess,hFile;

hHeap=GetProcessHeap();

ObFileType=GetFileHandleType();

aSH[r].ObjectType==ObFileType)

hProcess=OpenProcess(PROCESS_DUP_HANDLE,FALSE,

aSH[r].uIdProcess);

if(hProcess)

if(DuplicateHandle(hProcess,(HANDLE)Info->

aSH[r].Handle,

GetCurrentProcess(),&

hFile,0,FALSE,

DUPLICATE_SAME_ACCESS))

GetFileName(hFile,Name);

printf("

%s\n"

Name);

CloseHandle(hProcess);

现在对于文件的拷贝我们剩下的工作只是找到所需句柄后用ReadFile读取它。

这里一定要使用前面提到的机制,不可疏忽。

这种方法的优点是实现简单,但是其缺点更多,所以这个方法只适用于确定文件被那个进程占用。

打开被独占的文件方法

(二)--修改句柄访问权限

修改句柄访问权限

所有被占用的文件通常都可以用读属性(FILE_READ_ATTRIBUTES)打开,这样就可以读取文件的属性,取得它的大小,枚举NTSF

stream,但遗憾的是,ReadFile就不能成功调用了。

打开文件时各种访问属性的区别在哪里呢?

显然,打开文件时,系统会记录访问属性,之后会用这个属性与请求的访问作比较。

如果找到了系统保存这个属性的位置并修该掉它,那就不只可以读取,甚至可以写入任何已打开的文件。

在用户这一级别上我们并不是直接与文件打交道,而是通过它的句柄(这个句柄指向FileObject),而函数ReadFile/WriteFile调用ObReferenceObjectByHandle,并指明了相应的访问类型。

由此我们可以得出结论,访问权限保存在描述句柄的结构体里。

实际上,HANDLE_TABLE_ENTRY结构体包含有一个GrantedAccess域,这个域不是别的,就是句柄的访问权限。

遗憾的是,Microsoft的程序员们没有提供修改句柄访问权的API,所以我们不得不编写驱动自己来做这项工作。

我在《隐藏进程检测》一文中讲到过Windows2000和XP的句柄表结构体,我想补充的只有一点,就是Windows

2003中的句柄表与XP的完全一样。

与那篇文章不同,我们这里不需要枚举表中的句柄,而只需要找到某个具体的(已知的)句柄,我们不用管PspCidTable,而只操作自己进程的句柄表,表的指针位于进程的EPROCESS结构体里(2000下的偏移为0x128,XP下的为0x0C4)。

为了取得句柄结构体指针需要调用未导出函数ExpLookupHandleTableEntry,但我们不会去搜索它,因为在导出函数中没有对它的直接引用,搜索结果也很不可靠,除此之外我们此时还需要ExUnlockHandleTableEntry函数。

最好的办法就是编写自己的句柄表lookup函数。

考虑到Windows

2000与XP下句柄表的差异,我们将编写不同的函数。

首先是Windows2000下的:

PHANDLE_TABLE_ENTRY

Win2kLookupHandleTableEntry(

INPWIN2K_HANDLE_TABLEHandleTable,

INEXHANDLE 

Handle)

ULONGi,j,k;

i=(Handle.Index>

16)&

255;

j=(Handle.Index>

8) 

&

k=(Handle.Index) 

if(HandleTable->

Table[i])

Table[i][j])

return&

(HandleTable->

Table[i][j][k]);

returnNULL;

这段代码简单易懂。

因为句柄的值本身是个三维表的三个索引,所以我们只需其中的各个部分并查看表中相应的元素(当然如果存在的话)。

因为Windows

XP中的句柄表可以有一到三个级别,所以相应的lookup代码就要更为复杂一些:

XpLookupHandleTableEntry(

INPXP_HANDLE_TABLEHandleTable,

PHANDLE_TABLE_ENTRYEntry=NULL;

ULONGTableCode=HandleTable->

TableCode&

~TABLE_LEVEL_MASK;

p;

17)&

0x1FF;

9) 

switch(HandleTable->

TABLE_LEVEL_MASK)

case0:

Entry=&

((PHANDLE_TABLE_ENTRY)TableCode)[k];

case1:

if(((PVOID*)TableCode)[j])

((PHANDLE_TABLE_ENTRY*)TableCode)[j][k];

case2:

if(((PVOID*)TableCode)[i])

if(((PVOID**)TableCode)[i][j])

((PHANDLE_TABLE_ENTRY**)TableCode)[i][j][k];

returnEntry;

我们看到,这段代码中的句柄并不是ULONG型的值,而是EXHANDLE结构体:

typedefstruct_EXHANDLE

union

struct

ULONGTagBits:

02;

ULONGIndex 

:

30;

};

HANDLEGenericHandleOverlay;

}EXHANDLE,*PEXHANDLE;

我们看到,句柄不知包含了表的索引,还包含了一个2bit的标志。

您可能已经察觉到,一个句柄可以有着几种不同的意义,这一点与这样一个事实有关,那就是并非句柄中所有的位都被使用到(依赖于在表中的级别)。

这是Windows

XP最具个性的特点。

现在我们就可以获取句柄表中所需的元素了,该编写为句柄设置所需访问属性的函数了:

BOOLEANSetHandleAccess(

INHANDLE 

Handle,

INACCESS_MASKGrantedAccess

PHANDLE_TABLE 

ObjectTable=*(PHANDLE_TABLE

*)RVATOVA(PsGetCurrentProcess(),ObjectTableOffset);

PHANDLE_TABLE_ENTRYEntry;

EXHANDLE 

ExHandle;

ExHandle.GenericHandleOverlay=Handle;

Entry=ExLookupHandleTableEntry(ObjectTable,ExHandle);

if(Entry)Entry->

GrantedAccess=GrantedAccess;

returnEntry>

0;

现在编写驱动,设置句柄的访问属性,通过DeviceIoControl向驱动传递句柄。

代码如下:

NTSTATUSDriverIoControl(

INPDEVICE_OBJECTDeviceObject,

INPIRPIrp)

PIO_STACK_LOCATIONpisl 

=IoGetCurrentIrpStackLocation(Irp);

NTSTATUS 

status 

=STATUS_UNSUCCESSFUL;

BuffSize=

pisl->

Parameters.DeviceIoControl.InputBufferLength;

PUCHAR 

pBuff 

=Irp->

AssociatedIrp.SystemBuffer;

ACCESS_MASK 

GrantedAccess;

Irp->

IoStatus.Information=0;

switch(pisl->

Parameters.DeviceIoControl.IoControlCode)

caseIOCTL1:

if(pBuff&

BuffSize>

=sizeof(HANDLE)+

sizeof(ACCESS_MASK))

Handle 

=*(HANDLE*)pBuff;

GrantedAccess=*(ACCESS_MASK*)(pB

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > PPT模板 > 动态背景

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1