سؤال

يمكن لـ Sysinternals WinObJ سرد جميع كائنات الجهاز.

أتساءل كيف يمكن أن تسرد الأجهزة.

هل هناك أي مصدر مفتوح يمكننا قراءته؟ (أو مقتطف رمز)

ما هي أهم وظيفة يجب أن أعرفها؟

هل كانت مفيدة؟

المحلول

يستخدم WinObj مكالمات نظام NT NtOpenDirectoryObject و NtQueryDirectoryObject. لا يوجد سائق أو رمز نواة مطلوب. لن ترى الواردات لأن وظائف NT هذه يتم تحميلها عبر LoadLibrary/GetProcAddress.

ليس عليك تعداد مساحة اسم الكائن بأكملها. إذا كنت مهتمًا بمكالمة كائنات الجهاز NtOpenDirectoryObject مع "\Device", ، ثم اتصل NtQueryDirectoryObject على المقبض الذي تم إرجاعه.

نصائح أخرى

بالنسبة الى صفحة الويب الخاصة بـ sysinternals:

يوفر API الأصلي NT إجراءات إجراءات تسمح لبرامج وضع المستخدم بتصفح مساحة الاسم والاستعلام عن حالة الكائنات الموجودة هناك ، ولكن الواجهات غير موثقة.

لقد حاولت النظر في جدول استيراد وينوبج (dumpbin /imports winobj.exe) ولكن لا يوجد مشتبه بهم واضحون :-(

يمكنك استخدام ntopendirectoryoBject و ntquerydirectoryoBject لتعداد قائمة الكائنات في دليل معين.

للحصول على تفاصيل مساحة اسم الكائن ، يجب عليك استخدام واجهة برمجة تطبيقات Windows NT غير الموثقة. يستخدم أيضًا WinObj كما هو موصوف هنا كيف يحصل وينوبج على جميع النتائج .. وبالنسبة لأولئك الذين يقولون إننا بحاجة إلى سائق للقيام بذلك من فضلك ، اقرأ هذه الخطوط على الصفحة المحددة.

"إحدى الطرق الواضحة هي استخدام برنامج تشغيل - في وضع kernel ، كل شيء يمكن الوصول إليه - حتى يتمكن تطبيق العميل من الحصول على المعلومات المطلوبة من خلال التواصل مع برنامج التشغيل الخاص به. بدون امتيازات المسؤول ، على الرغم من امتيازات المسؤول ، فإنه يظهر جميع الكائنات بدلاً من النتائج الجزئية). "

وفقا ل إجابة من user1575778 يمكنك استخدام NtOpenDirectoryObject و NtQueryDirectoryObject (والتي من وضع المستخدم مماثلة ل ZwOpenDirectoryObject و ZwQueryDirectoryObject على التوالي) لسرد الكائنات داخل مساحة اسم مدير الكائن.

القي نظرة على objmgr.hpp من كائنات NT AKA NTOBJX, ، على وجه الخصوص في الفصل NtObjMgr::Directory (أو DirectoryT). يوفر نفس الوظيفة ملفوفة بشكل جيد في فئة C ++. الأداة المساعدة بأكملها مفتوحة المصدر بموجب ترخيص ليبرالي (مرخصة مزدوجة بسبب استخدام WTL: MIT و MS-PL) ، لذلك يمكن إعادة استخدام القطع والقطع كما من فضلك ، شريطة أن تمتثل لشروط الترخيص.

ولكن إليك مثال رمز 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 ولن يحل الروابط الرمزية ، إن وجدت. بالنسبة لأي من هذه الميزات ، يرجى إلقاء نظرة على رمز المصدر الخاص بـ Attility المذكور أعلاه والضبط حسب الحاجة. winternl.h يجب أن يكون متاحًا في أي Windows SDK حديثًا.

وظائف RtlInitUnicodeString_ و NtClose_ احصل على سطح زائد لتجنب الاشتباكات مع وظائف API الأصلية هذه ، والتي يتم الإعلان عنها في winternl.h, ، لكن الاستخدام __declspec(dllimport).

إفشاء: أنا مؤلف NTOBJX.

يمكنك البدء مع setupdicreatedeviceinfolist واستخدام وظائف أخرى ذات صلة لتعداد جميع الأجهزة. هذه الأشياء مؤلمة للاستخدام.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top