遇到某个文件无法删除,除了前一篇“打开”的占用之外,还有就是作为一个模块被占用。
ring3下的碎甲功能除了关闭打开的文件句柄之外,就是FreeLibrary作为模块打开的句柄。
GetProcModule.h
#ifndef GETPROCMODULE_H__
#define GETPROCMODULE_H__
void GetModuleByPid(DWORD dwPid, vector<string> & vData);
void GetPidByModule(const string& szPath, vector<PROCESSENTRY32>& vData);
#endif
GetProcModule.cpp
// GetProcModule.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
void GetModuleByPid(DWORD dwPid,vector<string> & vData)
{
HANDLE hProc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwPid);
if (hProc)
{
HMODULE hMod[1024];
DWORD cbNeeded;
CHAR szModName[MAX_PATH] = {0};
CHAR lPath[MAX_PATH] = {0};
// 获取进程模块
if (EnumProcessModules(hProc, hMod, sizeof(hMod), &cbNeeded))
{
//获得模块路径
for (int i = 0; i <= cbNeeded / sizeof(HMODULE); ++i)
{
if (GetModuleFileNameExA(hProc, hMod[i], szModName, sizeof(szModName)))
{
vData.push_back(szModName);
}
}
}
CloseHandle(hProc);
}
}
void GetPidByModule(const string& szPath, vector<PROCESSENTRY32>& vData)
{
DWORD ParentProcessID = -1;
PROCESSENTRY32 pe;
HANDLE hkz;
hkz = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
pe.dwSize = sizeof(PROCESSENTRY32);
if (Process32First(hkz, &pe))
{
do
{
vector<string> vModule;
GetModuleByPid(pe.th32ProcessID, vModule);
for (auto& str:vModule)
{
if (str == szPath)
{
vData.push_back(pe);
break;
}
}
} while (Process32Next(hkz, &pe));
}
}
最后还是不得不吐槽,当然是关于上一篇的利用ZwQuerySystemInformation枚举打开文件句柄,MSDN分明写着“is no longer available for use as of Windows 8. ”,可是我回家之后在win 8.1系统上dtll.dll也一样可以LoadLibrary得到函数指针,或许在windows 8.1微软又良心发现了,把它加回去了?
为了以防万一,我选择了NtQuerySystemInformation,搞过Ring0的容易误会,这个是Ring3那个,跟上面的Zw开头的函数是一样的,因为msdn上面说“ may be altered or unavailable in future versions of Windows.”,Zw是“一定不支持”,Nt是“可能失效”,起码还能多支持几个版本。
这一点我对微软越来越跟苹果一样,表示深深的鄙视,明显是信不过我们程序员,人家苹果程序员都是SB,开发难度低,难道你以为windows程序员也是这样吗?Linux太开发,Mac OS太封闭,windows恰好介于平衡点,于是上一轮PC战争中胜利。win8开始鲍尔默不相信开发者了,于是我们抛弃了他,如果win10继续延续这个路子,恐怕我就改成Ubuntu了,起码Linux世界尊重,我们程序员的智商。