【问题标题】:calling PNtQuerySystemInformation from dll on a 64bit computer [closed]在 64 位计算机上从 dll 调用 PNtQuerySystemInformation [关闭]
【发布时间】:2017-03-28 05:57:34
【问题描述】:

以下程序从我的计算机中检索所有进程信息。通过dll调用同一个应用程序时,它无法检索系统进程信息。

// TestSysInternals.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <windows.h>
#include "ntdll.h"

#include <Winternl.h>

#define VISTA_FILETYPE  25
#define XP_FILETYPE 28



static PNtQuerySystemInformation NtQuerySystemInformation_dynamic = NULL;
static DWORD curPid = 0;
static int nFileHandleType; 
#define STATUS_INFO_LENGTH_MISMATCH 0xC0000004
int _tmain(int argc, _TCHAR* argv[])
{

    NtQuerySystemInformation_dynamic = (PNtQuerySystemInformation)GetProcAddress(GetModuleHandle(TEXT("ntdll.dll")), ("NtQuerySystemInformation"));
    //                                   (PNtQuerySystemInformation)GetProcAddress(GetModuleHandle(_T("ntdll.dll")),     _("NtQuerySystemInformation"));
    nFileHandleType = XP_FILETYPE;
    NTSTATUS status;
    DWORD size = sizeof(SYSTEM_HANDLE_INFORMATION);
    PSYSTEM_HANDLE_INFORMATION pSysHandleInformation = (PSYSTEM_HANDLE_INFORMATION)malloc(size);
    DWORD needed = 0;
    int nfound = 0;
    while (!NT_SUCCESS(status = NtQuerySystemInformation_dynamic(SystemHandleInformation, pSysHandleInformation, size, &needed)))
    {
        if (status != STATUS_INFO_LENGTH_MISMATCH
            || needed == 0)
        {
            //DBGLOG("==>Failed Status=%l(%#X) Needed=%lu", status, status, needed);
            goto CLEAN;// some other error
        }
        // The previously supplied buffer wasn't enough.
        size = needed + 1024;
        pSysHandleInformation = (PSYSTEM_HANDLE_INFORMATION)realloc(pSysHandleInformation, size);
    }
    DWORD i;
    for (i = 0; i < pSysHandleInformation->Count; i++)
    {
        DWORD handlePid = pSysHandleInformation->Handles[i].ProcessID;

    }


    CLEAN:
        free(pSysHandleInformation);
        return nfound;
    return 0;
}

头文件

#ifndef NT_DLL_H_INCLUDED
#define NT_DLL_H_INCLUDED
#include <Winternl.h>
#include <Windows.h>

typedef DWORD(WINAPI *PNtQuerySystemInformation)(DWORD, VOID*, DWORD, ULONG*);

typedef struct _SYSTEM_HANDLE
{
    DWORD   ProcessID;
    BYTE    HandleType;
    BYTE    HandleFlags;
    WORD    HandleNumber;
    DWORD   KernelAddress;
    DWORD   Flags;
} SYSTEM_HANDLE, *PSYSTEM_HANDLE;

typedef struct _SYSTEM_HANDLE_INFORMATION
{
    DWORD           Count;
    SYSTEM_HANDLE   Handles[1];
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;

#define NT_SUCCESS_K(Status) ((NTSTATUS)(Status) >= 0)
#define SystemHandleInformation (DWORD)0x10


#endif

当通过调试手表检查pSysHandleInformation-&gt;Handles 数组时,我可以看到以下信息。

根据图片,它为 processID 值提供了真实的进程 ID。但是,当我将相同的代码放入 dll 中时,processID 值会得到非常大的值,而这在我的电脑中确实不存在,以下是我通过 dll 运行相同代码时获得的进程 id 值的屏幕截图。我不知道为什么当通过 dll 运行相同的代码时应用程序的行为会有所不同。 非常感谢您对这种有线行为的任何想法。

【问题讨论】:

  • 为您的 dll 变体显示 minimal reproducible example
  • 失败 - 具体在哪里?在任何情况下,您的代码都非常无效并且包含错​​误。例如GetFileType(handle); - 你完全明白你在这里做什么吗?您如何定义 SYSTEM_HANDLE_INFORMATION 不可见。初始分配 sizeof(SYSTEM_HANDLE_INFORMATION) 有什么意义; ?... 并且需要 debug 自己的代码,而不仅仅是编写 fail
  • @DavidHeffernan,一会儿我会发一个代码示例,RbMm,这实际上是一个测试代码,if语句中的代码是我在成功检索进程ID后应该做的,但截至目前,进程 ID 没有正确检索,所以我只专注于这个测试代码的那部分。我编写了这个测试应用程序来测试这种有线行为。我删除了造成混淆的代码,头文件中定义了sys句柄信息,我已经更新了问题
  • 不要发布样本。发布minimal reproducible example。然后我们都会在同一个页面上。
  • 您对_SYSTEM_HANDLE 的定义是错误的——这是正确的_SYSTEM_HANDLE_TABLE_ENTRY_INFO,最好将_SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX 与其他信息类一起使用——SystemExtendedHandleInformation

标签: c++ winapi dll process sysinternals


【解决方案1】:

这个功能已经过时了,你应该在比 Win2000\XP 更新的任何东西上使用 GetSystemInfo。很难撕开遗留的 C 代码(这里没有 C++ 的任何内容),但是可以发现您使用 SystemHandleInformation 类,它没有记录,它是从哪里得到的?它应该通过 SystemProcessInformation。该信息可以通过 GetProcessMemoryInfo 来检索。

SystemProcessInformation 的结构将是相应的:

typedef struct _SYSTEM_PROCESS_INFORMATION {
    ULONG NextEntryOffset;
    BYTE Reserved1[52];
    PVOID Reserved2[3];
    HANDLE UniqueProcessId;
    PVOID Reserved3;
    ULONG HandleCount;
    BYTE Reserved4[4];
    PVOID Reserved5[11];
    SIZE_T PeakPagefileUsage;
    SIZE_T PrivatePageCount;
    LARGE_INTEGER Reserved6[6];
} SYSTEM_PROCESS_INFORMATION;  

要获取进程计数,请改用 GetProcessHandleCount。

【讨论】:

  • 这个功能绝对没有过时。和SYSTEM_PROCESS_INFORMATION 绝对与检索句柄列表无关
  • @RbMm,好吧,他使用旧 ntdll.h 中的定义。结构的“错误”(正如您评论的那样)定义实际上来自旧版本的微软代码。问题是,所有未记录的内容在_every_ 版本的 Windows 中可能会发生更改,恕不另行通知。虽然他们将 SystemProcessInformation 列为可用,但在文档中甚至没有提到 SystemHandleInformation。 NtQuerySystemInformation 的页面充斥着对应该用来代替 NtQuerySystemInformation 的函数的引用
  • 我不知道ntdll.h 是什么,但_SYSTEM_HANDLE 的定义绝对错误且不专业(仅查找DWORD KernelAddress; - 显然不是为在x64 中使用而设计的)。 ubject to change in_every_ version of Windows wihout notice - 但这直到 17 年才改变。而一些“记录”的api发生了变化。进程列表和句柄列表是绝对不同的东西。现在,我如何知道只有一种方式获取句柄列表 - 使用 System[Extended]HandleInformation 调用 NtQuerySystemInformation。没有记录?所以呢 ?但如果需要这些信息?
  • @Swift,你能给我举个例子来演示这个代码的用法吗?另外,是否有类似的方法可以使用您建议的这种新方法来获取处理程序属于单个进程。
  • 这是我发现SystemHandleInformationstackoverflow.com/questions/733384/…的用法,在第一个答案中,代码使用了与我相同的方法。这是一个参考表格 microsoft code.msdn.microsoft.com/windowsapps/CppFileHandle-03c8ea0b
猜你喜欢
  • 2011-12-21
  • 2011-12-22
  • 1970-01-01
  • 2011-08-08
  • 1970-01-01
  • 2013-06-11
  • 1970-01-01
  • 2011-01-28
  • 1970-01-01
相关资源
最近更新 更多