2

SysInternals の WinObj は、すべてのデバイス オブジェクトを一覧表示できます。

どのようにデバイスを一覧表示できるのだろうか。

私たちが読めるオープンソースはありますか?(またはコードスニペット)

知っておくべき最も重要な機能は何ですか?

4

6 に答える 6

6

WinObj は、NT システム コールNtOpenDirectoryObjectNtQueryDirectoryObject. ドライバーやカーネル コードは必要ありません。LoadLibraryこれらの NT 関数は/経由で読み込まれるため、インポートは表示されませんGetProcAddress

オブジェクトの名前空間全体を列挙する必要はありません。を使用したデバイス オブジェクトの呼び出しに関心がある場合はNtOpenDirectoryObject、返されたハンドルで"\Device"呼び出します。NtQueryDirectoryObject

于 2012-08-04T07:53:34.993 に答える
1

SysInternals の Web ページによると:

ネイティブ NT API は、ユーザー モード プログラムが名前空間を参照し、そこにあるオブジェクトの状態を照会できるようにするルーチンを提供しますが、インターフェイスは文書化されていません。

WinObj のインポート テーブル ( dumpbin /imports winobj.exe) を調べてみましたが、明らかな疑いはありません :-(

于 2011-03-01T15:03:43.807 に答える
1

user1575778 からの回答に従って、 NtOpenDirectoryObjectand NtQueryDirectoryObject(ユーザーモードからはZwOpenDirectoryObjectand とそれぞれ同じ) を使用ZwQueryDirectoryObjectして、オブジェクトマネージャーの名前空間内のオブジェクトを一覧表示できます。

NT Objects aka ntobjxobjmgr.hpp特にクラス(または) を見てください。これは、C++ クラスに適切にラップされた同じ機能を提供します。ユーティリティ全体はリベラル ライセンス (WTL 使用のため MIT と MS-PL の二重ライセンス) の下でオープン ソースであるため、ライセンス条項に準拠していれば、必要に応じてビットとピースを再利用できます。NtObjMgr::DirectoryDirectoryT

しかし、ここにあなたのユースケースだけを提供する簡単な C++ コードの例があります:

#include <Windows.h>
#include <tchar.h>
#include <cstdio>
#include <winternl.h>

NTSTATUS (NTAPI* NtOpenDirectoryObject)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES);
NTSTATUS (NTAPI* NtQueryDirectoryObject)(HANDLE, PVOID, ULONG, BOOLEAN, BOOLEAN, PULONG, PULONG);
VOID (NTAPI* RtlInitUnicodeString_)(PUNICODE_STRING, PCWSTR);
NTSTATUS (NTAPI* NtClose_)(HANDLE);

#define DIRECTORY_QUERY                 (0x0001)
#define DIRECTORY_TRAVERSE              (0x0002)

typedef struct _OBJECT_DIRECTORY_INFORMATION {
    UNICODE_STRING Name;
    UNICODE_STRING TypeName;
} OBJECT_DIRECTORY_INFORMATION, *POBJECT_DIRECTORY_INFORMATION;

#ifndef STATUS_SUCCESS
#define STATUS_SUCCESS                   ((NTSTATUS)0x00000000L) // ntsubauth
#endif // STATUS_SUCCESS
#ifndef STATUS_MORE_ENTRIES
#define STATUS_MORE_ENTRIES              ((NTSTATUS)0x00000105L)
#endif // STATUS_MORE_ENTRIES
#ifndef STATUS_NO_MORE_ENTRIES
#define STATUS_NO_MORE_ENTRIES           ((NTSTATUS)0x8000001AL)
#endif // STATUS_NO_MORE_ENTRIES

int PrintDevices()
{
    NTSTATUS ntStatus;
    OBJECT_ATTRIBUTES oa;
    UNICODE_STRING objname;
    HANDLE hDeviceDir = NULL;
    RtlInitUnicodeString_(&objname, L"\\Device");
    InitializeObjectAttributes(&oa, &objname, 0, NULL, NULL);
    ntStatus = NtOpenDirectoryObject(&hDeviceDir, DIRECTORY_QUERY | DIRECTORY_TRAVERSE, &oa);
    if(NT_SUCCESS(ntStatus))
    {
        size_t const bufSize = 0x10000;
        BYTE buf[bufSize] = {0};
        ULONG start = 0, idx = 0, bytes;
        BOOLEAN restart = TRUE;
        for(;;)
        {
            ntStatus = NtQueryDirectoryObject(hDeviceDir, PBYTE(buf), bufSize, FALSE, restart, &idx, &bytes);
            if(NT_SUCCESS(ntStatus))
            {
                POBJECT_DIRECTORY_INFORMATION const pdilist = reinterpret_cast<POBJECT_DIRECTORY_INFORMATION>(PBYTE(buf));
                for(ULONG i = 0; i < idx - start; i++)
                {
                    if(0 == wcsncmp(pdilist[i].TypeName.Buffer, L"Device", pdilist[i].TypeName.Length / sizeof(WCHAR)))
                    {
                        _tprintf(_T("%s\n"), pdilist[i].Name.Buffer);
                    }
                }
            }
            if(STATUS_MORE_ENTRIES == ntStatus)
            {
                start = idx;
                restart = FALSE;
                continue;
            }
            if((STATUS_SUCCESS == ntStatus) || (STATUS_NO_MORE_ENTRIES == ntStatus))
            {
                break;
            }
        }
        (void)NtClose_(hDeviceDir);
        return 0;
    }
    _tprintf(_T("Failed NtOpenDirectoryObject with 0x%08X"), ntStatus);
    return 1;
}

int _tmain(int /*argc*/, _TCHAR** /*argv*/)
{
    HMODULE hNtDll = ::GetModuleHandle(_T("ntdll.dll"));
    *(FARPROC*)&NtOpenDirectoryObject = ::GetProcAddress(hNtDll, "NtOpenDirectoryObject");
    *(FARPROC*)&NtQueryDirectoryObject = ::GetProcAddress(hNtDll, "NtQueryDirectoryObject");
    *(FARPROC*)&RtlInitUnicodeString_ = ::GetProcAddress(hNtDll, "RtlInitUnicodeString");
    *(FARPROC*)&NtClose_ = ::GetProcAddress(hNtDll, "NtClose");
    if (!NtOpenDirectoryObject || !NtQueryDirectoryObject || !RtlInitUnicodeString_ || !NtClose_)
    {
        _tprintf(_T("Failed to retrieve ntdll.dll function pointers\n"));
        return 1;
    }
    return PrintDevices();
}

いくつかの注意事項:これはサブディレクトリを掘り下げ、以外のタイプを一覧表示せずDevice、シンボリック リンクが存在する場合でも解決しません。これらの機能については、前述のユーティリティのソース コードを参照し、必要に応じて調整してください。winternl.h最近の Windows SDK で利用できるはずです。

関数RtlInitUnicodeString_NtClose_には、これらのネイティブ API 関数との衝突を避けるために、末尾にアンダースコアが付いています。これらの関数は で宣言されてwinternl.hいますが、__declspec(dllimport).

開示:私は ntobjx の作成者です。

于 2017-06-08T20:27:58.390 に答える
0

オブジェクトの名前空間の詳細を取得するには、Windows NT Undocumented API を使用する必要があります。これは、WinOBj がすべての結果を取得する方法がここで説明されているように、WinObj でも使用されます。これを行うにはドライバーが必要だと言っている人は、特定のページのこれらの行を読んでください。

「明らかな方法の 1 つは、ドライバーを使用することです。カーネル モードではすべてにアクセスできます。クライアント アプリは、独自のドライバーと通信することで必要な情報を取得できます。ただし、WinObj はドライバーを使用しません (これが、ドライバーを実行できる理由の 1 つです)。ただし、管理者権限がある場合は、部分的な結果ではなくすべてのオブジェクトが表示されます)。」

于 2014-09-26T09:53:16.113 に答える
0

NtOpenDirectoryObject と NtQueryDirectoryObject を使用して、特定のディレクトリ内のオブジェクト リストを列挙できます。

于 2012-07-23T09:25:55.747 に答える
-1

SetupDiCreateDeviceInfoList から開始し、他の関連関数を使用してすべてのデバイスを列挙できます。このようなものは使用するのが苦痛です。

于 2010-04-15T06:19:20.620 に答える