【问题标题】:GetFinalPathByHandle returns the same path for all handles returned by NtQuerySystemInformationGetFinalPathByHandle 为 NtQuerySystemInformation 返回的所有句柄返回相同的路径
【发布时间】:2014-10-21 13:18:35
【问题描述】:

我想检索操作系统中进程访问的所有文件路径。 检索进程列表并且这些进程具有正确的句柄值。所以现在我想使用GetFinalPathNameByHandle 函数来获取这些文件的路径,但是所有记录的路径变量都是相同的。伙计们,我需要帮助。

源代码在这里:http://pastebin.com/nU26Vcsd 或者如果无法访问 pastebin 则在这里 http://hastebin.com/wahudogawa.avrasm

第 66 行是我需要帮助的地方。测试进程的每个文件处理程序的路径都相同,并且等于执行该程序的路径(而不是进程启动文件夹)。

我将其运行为:testprogram.exe | grep 5231,其中 5231 是我需要的进程的 PID。

结果如下:

PID: 5231        FileHandlePid: 44       The final path is: \Device\HarddiskVolume4\KillFileHandle\C++\Debug

虽然那些应该是这样的:

PID: 5231        FileHandlePid: 44       The final path is: \Device\HarddiskVolume2\Users\username\AppData\Roaming\testapp

如果我的预期结果有误,请纠正我。


最新添加:

感谢@Raymond Chen cmets,我正在努力前进并使用 DuplicateHandle() 功能。到目前为止,我已经更新了代码(现在是硬编码的 pid,抱歉),添加了 HandleValueTemp,试图将它传递给 DuplicateHandle。输出更改为不可打印的字符。

for (i = 0; i < hCount; ++i)
if ((hFirstEntry[i].ObjectType == 28))
{
    HANDLE TargetHandleValueTemp = (HANDLE)hFirstEntry[i].HandleValue;
    HANDLE SourceProcHandleTemp = OpenProcess(PROCESS_DUP_HANDLE, FALSE, hFirstEntry[i].OwnerPid);

    if (!DuplicateHandle(SourceProcHandleTemp, (HANDLE)hFirstEntry[i].HandleValue, GetCurrentProcess(), &TargetHandleValueTemp, 0, FALSE, DUPLICATE_SAME_ACCESS))
    {
        cout << "Error in DuplicateHandle"
    }

    CloseHandle(SourceProcHandleTemp);
    TCHAR Path[MAX_PATH];
    DWORD dwret = GetFinalPathNameByHandle(TargetHandleValueTemp, Path, MAX_PATH, 0);
    _tprintf(TEXT("PID: %d\tFileHandle: %d\tThe final path is: %s\n"), hFirstEntry[i].OwnerPid, TargetHandleValueTemp, Path);
    CloseHandle(TargetHandleValueTemp);
}

不时深入挖掘并查看 cmets。也许这段代码对这里的其他人有用。

【问题讨论】:

  • 未记录的 API 未记录。此外,句柄也不是那样工作的。
  • "这是假设您需要删除的所有文件都归执行删除的进程所有。"此外,强制关闭句柄可能会导致数据损坏和其他“不可能”的错误。您正在以长期痛苦为代价来创造短期缓解。另外,请在此处而不是在外部站点上包含代码。
  • "如果任何文件属于另一个进程,您将需要使用 DuplicateHandle() 的额外步骤。"但在这种情况下,您不会试图强制关闭手柄。此外,最好有一个调试或单元测试钩子,这样被测试的应用程序可以显式地提供句柄,而不是让你去寻找它。这样,您就可以避免使用未记录的 API。
  • 您没有从 GetFinalPathByName 检查错误。
  • 很快找到了原因。看起来在 Windows 8.1 中,文件的 SystemHandleInformation ObjectType 应该是 30,而不是像以前版本中的 28。现在有效

标签: c++ windows kernel ntdll


【解决方案1】:

感谢@RaymondChen 和@HarryJohnston cmets 我能够得到工作结果。我把它留在这里以防其他人需要它。代码有点糟糕,但进一步的格式取决于你。请记住在测试时将 OwnerPid in loop 更新为您自己的。

#include <Windows.h>
#include <stdio.h>
#include <string.h>
#include <tchar.h>
#include <iostream>

#define START_ALLOC                 0x1000
#define STATUS_INFO_LENGTH_MISMATCH 0xC0000004
#define SystemHandleInformation     0x10

typedef long(__stdcall *NtQSI)(
ULONG  SystemInformationClass,
PVOID  SystemInformation,
ULONG  SystemInformationLength,
PULONG ReturnLength
);

typedef struct _SYSTEM_HANDLE_ENTRY {
ULONG  OwnerPid;
BYTE   ObjectType;
BYTE   HandleFlags;
USHORT HandleValue;
PVOID  ObjectPointer;
ACCESS_MASK  AccessMask;
} SYSTEM_HANDLE_ENTRY, *PSYSTEM_HANDLE_ENTRY;

int main()
{
HMODULE hNtDll = NULL;
NtQSI   pNtQSI = NULL;
PVOID   pMem = NULL;
ULONG   allocSize = START_ALLOC;
ULONG   retVal = 0;
// --------------------------------
ULONG   hCount = 0;
PSYSTEM_HANDLE_ENTRY hFirstEntry = NULL;
// --------------------------------
ULONG   i;

hNtDll = LoadLibraryA("NTDLL.dll");

if (!hNtDll)
    return 1;

pNtQSI = (NtQSI)GetProcAddress(hNtDll, "NtQuerySystemInformation");

if (!pNtQSI) {
    FreeLibrary(hNtDll);
    return 2;
}

pMem = malloc(allocSize);

while (pNtQSI(SystemHandleInformation, pMem, allocSize, &retVal)
    == STATUS_INFO_LENGTH_MISMATCH) {
    pMem = realloc(pMem, allocSize *= 2);
}

hCount = *(ULONG*)pMem;
hFirstEntry = (PSYSTEM_HANDLE_ENTRY)((PBYTE)pMem + 4);

for (i = 0; i < hCount; ++i)
if ((hFirstEntry[i].ObjectType == 30) && (hFirstEntry[i].OwnerPid == 5628))
{
    HANDLE TargetHandleValueTemp = (HANDLE)hFirstEntry[i].HandleValue;
    HANDLE SourceProcHandleTemp = OpenProcess(PROCESS_DUP_HANDLE, FALSE, hFirstEntry[i].OwnerPid);

    if (!DuplicateHandle(SourceProcHandleTemp, (HANDLE)hFirstEntry[i].HandleValue, GetCurrentProcess(), &TargetHandleValueTemp, 0, FALSE, DUPLICATE_SAME_ACCESS))
    {
        TargetHandleValueTemp = (HANDLE)hFirstEntry[i].HandleValue;
    }

    CloseHandle(SourceProcHandleTemp);
    TCHAR Path[MAX_PATH];
    DWORD dwret = GetFinalPathNameByHandle(TargetHandleValueTemp, Path, MAX_PATH, 0);
    _tprintf(TEXT("PID: %d\tFileHandle: %d\tThe final path is: %s\n"), hFirstEntry[i].OwnerPid, TargetHandleValueTemp, Path);
    CloseHandle(TargetHandleValueTemp);
}

free(pMem);
FreeLibrary(hNtDll);
}

【讨论】:

    猜你喜欢
    • 2018-02-20
    • 2015-09-15
    • 1970-01-01
    • 2020-11-27
    • 2013-04-26
    • 1970-01-01
    • 1970-01-01
    • 2011-12-20
    • 1970-01-01
    相关资源
    最近更新 更多