【问题标题】:How to enumerate process' handles?如何枚举进程的句柄?
【发布时间】:2017-08-07 01:53:11
【问题描述】:

有什么方法可以在windows中枚举给定PID的进程,并获取他所有打开的句柄(锁定的文件等)的列表?

编辑:我不在乎语言。如果它在 .NET 中,我会很高兴,如果在 WinApi (C) 中,它不会受到伤害。如果在别的地方,我想我可以重写它:-)

【问题讨论】:

    标签: windows handles


    【解决方案1】:

    我进行了深入的谷歌搜索,发现了这个article。 本文给出了download source code的链接:

    我尝试了 NtSystemInfoTest.cpp 中的方法(下载的源代码),效果非常好。

    void ListHandles( DWORD processID, LPCTSTR lpFilter )
    

    代码有以下声明:

    // Written by Zoltan Csizmadia, zoltan_csizmadia@yahoo.com
    // For companies(Austin,TX): If you would like to get my resume, send an email.
    //
    // The source is free, but if you want to use it, mention my name and e-mail address
    //
    //////////////////////////////////////////////////////////////////////////////////////
    //
    

    希望对你有帮助。

    【讨论】:

    • 太棒了!这正是我所需要的(并且无法谷歌)。谢谢。 :-)
    • 不幸的是,虽然这有效,但它仍然需要调用 NtQuerySystemInformation,它返回 all 句柄,然后需要通过所需的 PID 对其进行迭代和过滤。据我所知,没有办法只向操作系统询问一个进程的句柄。
    【解决方案2】:

    如果您只想要一个工具,Sysinternals 的命令行“Handle”工具可以做到这一点。但是,如果您正在寻找代码解决方案,这对您没有帮助。

    【讨论】:

      【解决方案3】:

      Here is an example 使用来自 DDK 的 ZwQueryProcessInformation。 DDK 现在称为“WDK”,可通过 MSDN 获得。如果您没有 MSDN,显然,您也可以从 here 获得它。

      我没试过,我只是用谷歌搜索了你的问题。

      #include "ntdll.h"
      #include <stdlib.h>
      #include <stdio.h>
      #include "ntddk.h"
      
      #define DUPLICATE_SAME_ATTRIBUTES 0x00000004
      
      #pragma comment(lib,"ntdll.lib")
      
      BOOL EnablePrivilege(PCSTR name)
      {
      TOKEN_PRIVILEGES priv = {1, {0, 0, SE_PRIVILEGE_ENABLED}};
      LookupPrivilegeValue(0, name, &priv.Privileges[0].Luid);
      
      HANDLE hToken;
      OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken);
      
      AdjustTokenPrivileges(hToken, FALSE, &priv, sizeof priv, 0, 0);
      BOOL rv = GetLastError() == ERROR_SUCCESS;
      
      CloseHandle(hToken);
      return rv;
      }
      
      int main(int argc, char *argv[])
      {
      if (argc == 1) return 0;
      
      ULONG pid = strtoul(argv[1], 0, 0);
      
      EnablePrivilege(SE_DEBUG_NAME);
      
      HANDLE hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, pid);
      
      ULONG n = 0x1000;
      PULONG p = new ULONG[n];
      
      while (NT::ZwQuerySystemInformation(NT::SystemHandleInformation, p, n * sizeof *p, 0)
      == STATUS_INFO_LENGTH_MISMATCH)
      
      delete [] p, p = new ULONG[n *= 2];
      
      NT::PSYSTEM_HANDLE_INFORMATION h = NT::PSYSTEM_HANDLE_INFORMATION(p + 1);
      
      for (ULONG i = 0; i < *p; i++) {
      
      if (h[i].ProcessId == pid) {
      HANDLE hObject;
      
      if (NT::ZwDuplicateObject(hProcess, HANDLE(h[i].Handle), NtCurrentProcess(), &hObject,
      0, 0, DUPLICATE_SAME_ATTRIBUTES)
      != STATUS_SUCCESS) continue;
      
      NT::OBJECT_BASIC_INFORMATION obi;
      
      NT::ZwQueryObject(hObject, NT::ObjectBasicInformation, &obi, sizeof obi, &n);
      
      printf("%p %04hx %6lx %2x %3lx %3ld %4ld ",
      h[i].Object, h[i].Handle, h[i].GrantedAccess,
      int(h[i].Flags), obi.Attributes,
      obi.HandleCount - 1, obi.PointerCount - 2);
      
      n = obi.TypeInformationLength + 2;
      
      NT::POBJECT_TYPE_INFORMATION oti = NT::POBJECT_TYPE_INFORMATION(new CHAR[n]);
      
      NT::ZwQueryObject(hObject, NT::ObjectTypeInformation, oti, n, &n);
      
      printf("%-14.*ws ", oti[0].Name.Length / 2, oti[0].Name.Buffer);
      
      n = obi.NameInformationLength == 0
      ? MAX_PATH * sizeof (WCHAR) : obi.NameInformationLength;
      
      NT::POBJECT_NAME_INFORMATION oni = NT::POBJECT_NAME_INFORMATION(new CHAR[n]);
      
      NTSTATUS rv = NT::ZwQueryObject(hObject, NT::ObjectNameInformation, oni, n, &n);
      if (NT_SUCCESS(rv))
      printf("%.*ws", oni[0].Name.Length / 2, oni[0].Name.Buffer);
      
      printf("\n");
      
      CloseHandle(hObject);
      }
      }
      delete [] p;
      
      CloseHandle(hProcess);
      
      return 0;
      }
      

      【讨论】:

      • 好吧,我也用谷歌搜索过,但我无法下载 Vista 的 DDK :-( 所以我想,还有其他解决方案(来自 sysinternals 的 ProcessExplorer 根本没有链接 ntdll)
      • ProcessExplorer 不会静态链接到 ntdll,但会在运行时加载它。您可以通过依赖项找到它。
      • 如果您在使用 SYNC_READ 打开的管道上执行 ZwQueryObject(.. ObjectNameInformation..),您如何解决此解决方案?
      • @nothrow - 每个进程都隐式链接到 ntdll,它是 Windows 加载程序的一部分。这在 Mark Russinovich 的 Windows Internals 书中进行了讨论,请参阅第 3 章“图像加载器”。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多