有方法读取一个已被其他进程打开且dwSharemode = 0的文件吗?

有方法读取一个已被其他进程打开且dwSharemode = 0的文件吗?

 

最近有项目要打开一个已被其他进程打开,且其dwShareMode=0,即其它进程不得共享打开。该如何做呢?久思不得其解,于是去bbs.pediy.com询问[1],网友给出的方法是:

 

1)         干掉原句柄,比较常用的手段有杀死原进程,远程关闭句柄,创建远程线程调用CloseHandle

2)         复制原句柄,打开进程用DuplicateHandle复制一份即可使用

3)         如果使用驱动的话,直接下发IRP读文件内容即可,缺点是也许需要硬编码 

 

 

我选用了第二种方法,果然能解决问题。但是中间也遇到了一些问题,本文来说说这中间遇到的问题。

 

既然是使用DuplicateHandle,那么必须知道原进程的PID,和文件在该进程中的句柄Handle。

所以程序的思路是先遍历系统中所有进程,然后或则进程中文件句柄,接着使用文件句柄获得文件名称——这样便可以得到PID和Handle了。

 

一.       遍历系统所有进程

可以使用多种方法遍历系统中所有进程,一般使用ZwQuerySystemInformation(SystemProcessesAndThreadsInformation)或者CreateToolhelp32Snapshot来实现。

 

二.       遍历句柄

句柄的遍历使用ZwQuerySystemInformation(SystemHandleInformation),该函数列出所有进程的所有句柄,然后使用TSYSTEM_HANDLE_INFORMATION结构体中的ProcessId来过滤出指定进程的句柄。

 

这里的句柄是各种类型。可以通过TSYSTEM_HANDLE_INFORMATION结构体中的ObjectTypeNumber来判断句柄类型。在程序中我使用File=28硬编码,因为我发现在Win7和XP下是成立的,

 

但是有网友[3]讨论说不是所有的系统都是这样的,于是我尝试遍历系统中所有的类型对象(type object),方法是使用ZwQueryObject(ObjectAllTypesInformation)。本想通过序号实时找出当前系统中的类型值,但是遗憾是序号值不对。

 

补充:这个index值应该是OBJECT_TYPE对象中的INDEX字段:


三.       根据文件句柄获取文件名

只有获得句柄对应的文件名,通过比较才能知道是否是想要的文件句柄,所以当务之急是获得文件名。但是得先通过调用OpenProcess和DuplicateHandle来复制一个句柄。然后再使用下面两类方法中的一种:

 

1.      使用ZwQueryInformationFile

该函数返回一个TFILE_NAME_INFORMATION结构,这个结构包括文件的名称,但是不包括驱动器名,所以需要通过其他方法(见下)获得驱动器名,将上述两者相连方可获得整个文件名了。

 

这个方法有个问题,在某些进程(如qq.exe)在调用ZwQueryInformationFile时会使调用程序“死掉”。难道qq这些程序有什么保护方法,不让复制的句柄来使用ZwQueryInformationFile?

 

2.      使用GetMappedFileName

这种方法使用CreateFileMapping、MapViewOfFile和GetMappedFileName获得文件名——同样没有驱动器名,所以也得通过其他方法(见下)获得驱动器名。

这种方法也有缺陷,不能调用CreateFileMapping打开没有访问权限目录中的文件。

 

3.      获得驱动器名

有两种方法获得驱动器名:

1)  GetFileInformationByHandle和GetLogicalDriveStringsA比较

2)  GetLogicalDriveStrings和QueryDosDevice比较

GetFileInformationByHandle也会使程序“死掉”,所以慎用。

 

四.       大功告成

知道了进程pid和句柄值,就可以通过复制句柄的方法访问文件了——这其实在前面已经这么做过一次了——获得文件名不正是复制句柄来实现的吗?

 

不过,在使用文件指针访问文件(如调用ReadFile和WriteFile)时要注意:因为原句柄和复制句柄共享一个文件指针,所以可能会造成指针位置的混乱。

 

五.       参考文献

1.      http://bbs.pediy.com/showthread.php?t=198566

2.      有关遍历进程中句柄的方法总结http://blog.sina.com.cn/s/blog_58e7a03b01014c9e.html

3.      http://bbs.pediy.com/showthread.php?t=179951

4.      [Delphi]从handle获得文件名 

http://cndkervip.blog.163.com/blog/static/32546863200772311416631/

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Creating Windows CreateMDIWindow CreateWindow CreateWindowEx RegisterClass RegisterClassEx UnregisterClass Message Processing BroadcastSystemMessage CallNextHookEx CallWindowProc DefFrameProc DefMDIChildProc DefWindowProc DispatchMessage GetMessage GetMessageExtraInfo GetMessagePos GetMessageTime GetQueueStatus InSendMessage PeekMessage PostMessage PostQuitMessage PostThreadMessage RegisterWindowMessage ReplyMessage SendMessage SendMessageCallback SendMessageTimeout SendNotifyMessage SetMessageExtraInfo SetWindowsHookEx TranslateMessage UnhookWindowsHookEx WaitMessage Window Information AnyPopup ChildWindowFromPoint ChildWindowFromPointEx EnableWindow EnumChildWindows EnumPropsEx EnumThreadWindows EnumWindows FindWindow FindWindowEx GetClassInfoEx GetClassLong GetClassName GetClientRect GetDesktopWindow GetFocus GetForegroundWindow GetNextWindow GetParent GetProp GetTopWindow GetWindow GetWindowLong GetWindowRect GetWindowText GetWindowTextLength IsChild IsIconic IsWindow IsWindowEnabled IsWindowUnicode IsWindowVisible IsZoomed RemoveProp SetActiveWindow SetClassLong SetFocus SetForegroundWindow SetParent SetProp SetWindowLong SetWindowText WindowFromPoint Processes and Threads CreateEvent CreateMutex CreateProcess CreateSemaphore CreateThread DeleteCriticalSection DuplicateHandle EnterCriticalSection ExitProcess ExitThread GetCurrentProcess GetCurrentProcessId GetCurrentThread GetCurrentThreadId GetExitCodeProcess GetExitCodeThread GetPriorityClass GetThreadPriority GetWindowThreadProcessId InitializeCriticalSection InterlockedDecrement InterlockedExchange InterlockedIncrement LeaveCriticalSection OpenEvent OpenMutex OpenProcess OpenSemaphore PulseEvent ReleaseMutex ReleaseSemaphore ResetEvent ResumeThread SetEvent SetPr
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值