【问题标题】:NtDeviceIoControlFile (Query IP Address Entries) - STATUS_INVALID_DEVICE_REQUESTNtDeviceIoControlFile(查询 IP 地址条目)- STATUS_INVALID_DEVICE_REQUEST
【发布时间】:2018-03-17 12:20:54
【问题描述】:

任务

我正在尝试使用 NtDeviceIoControlFileIOCTL_TCP_QUERY_INFORMATION_EX 标志枚举当前的 ip 接口条目。

代码

NTSTATUS GetIPAddresses(HANDLE TcpFile, TDIEntityID InterfaceID, IPAddrEntry* Entries, ULONG NumEntries) {
    TCP_REQUEST_QUERY_INFORMATION_EX_WOW ReqWow64;

    IO_STATUS_BLOCK IOBlock = {0, 0};
    NTSTATUS Status = -1;

    ReqWow64.ID.toi_class = 0x200;
    ReqWow64.ID.toi_type = 0x100;
    ReqWow64.ID.toi_id = 0x102;
    ReqWow64.ID.toi_entity = InterfaceID;

    return NtDeviceIoControlFile(
        TcpFile, NULL, NULL, NULL, &IOBlock, IOCTL_TCP_QUERY_INFORMATION_EX,
        &ReqWow64, sizeof(ReqWow64), Entries, NumEntries * sizeof(IPAddrEntry));
}

this 页面上说我可以

  1. 获取有关特定 IP 实体的地址信息。

如果 IPSNMPInfo 结构的 ipsi_numaddr 成员返回 特定的 IP 实体是非零的,可以通过将 ID.toi_entity 成员设置为标识实体、将 ID.toi_class 设置为 INFO_CLASS_PROTOCOL、将 ID.toi_type 设置为 INFO_TYPE_PROVIDER 并将 ID.toi_id 设置为 IP_MIB_ADDRTABLE_ENTRY_ID 来检索 IPAddrEntry 结构的数组。在这种情况下,应该分配输出缓冲区来保存一个大小为数组的数组

sizeof(IPAddrEntry) * pIpSnmpInfoReturned->ipsi_numaddr

我在这里做过:

IPAddrEntry *AddrEntries = Crt::Allocate<IPAddrEntry *>(SnmpInfo.ipsi_numaddr * sizeof(IPAddrEntry));
if (!AddrEntries)
    return STATUS_NO_MEMORY;

但是,当我调用函数时:

NTSTATUS Status = GetIPAddresses(TcpFile, Interfaces[n], AddrEntries, SnmpInfo.ipsi_numaddr);

我得到以下 NTSTATUS -1073741808,十六进制等于 0xC0000010,计算结果为 STATUS_INVALID_DEVICE_REQUEST

TCP_REQUEST_QUERY_INFORMATION_EX_WOW 结构的声明

struct TCP_REQUEST_QUERY_INFORMATION_EX_WOW  {
    TDIObjectID     ID;
    ULONG           pad;
    UCHAR           Context[16];
};

问题

这个错误的原因是什么,我的代码哪里出了问题?

【问题讨论】:

  • 可能是由 TCP_REQUEST_QUERY_INFORMATION_EX_WOW 结构的错误声明引起的,将该声明添加到您的问题中可能是个好主意。 (我想您自己已经声明了这一点?Google 出现了空白。)
  • @HarryJohnston 更新了结构定义。
  • tdiinfo.h 中有一条评论暗示Context 可能需要在发送请求之前清零,您尝试过吗?
  • @HarryJohnston 是的,我已经尝试过了,但是没有任何区别。另外,顺便说一句(我昨晚应该发给你的电子邮件,问题是由于堆损坏,已经解决,抱歉)。
  • 别担心,很高兴听到你把它整理好了。

标签: c++ winapi tcp


【解决方案1】:
#include <iptypes.h>
#include <tdiinfo.h>
#include <tcpioctl.h>

NTSTATUS QueryTcp()
{
    NTSTATUS status;
#ifndef _WIN64

    struct TCP_REQUEST_QUERY_INFORMATION_EX_WOW 
    {
        TDIObjectID     ID;                     // object ID to query.
        ULONG           pad;                    // ! for wow64 only - Context must be aligned on 8 byte in 64bit windows
        uchar           Context[CONTEXT_SIZE];  // multi-request context. Zeroed
    };

    PVOID Wow;
    status = NtQueryInformationProcess(NtCurrentProcess(), ProcessWow64Information, &Wow, sizeof(Wow), 0);
    if (0 > status)
    {
        return status;
    }
#endif

    static const UNICODE_STRING ObjectName = RTL_CONSTANT_STRING(L"\\device\\tcp");
    static const OBJECT_ATTRIBUTES oa = { sizeof(oa), 0, const_cast<PUNICODE_STRING>(&ObjectName), OBJ_CASE_INSENSITIVE };

    HANDLE hFile;
    IO_STATUS_BLOCK iosb;
    status = NtOpenFile(&hFile, SYNCHRONIZE, 
        const_cast<POBJECT_ATTRIBUTES>(&oa), &iosb, FILE_SHARE_VALID_FLAGS, FILE_SYNCHRONOUS_IO_NONALERT);

    if (0 <= status)
    {
        PVOID InputBuffer;
        ULONG InputBufferLength;
        TDIObjectID* pID;
        PVOID Context;

#ifndef _WIN64
        if (Wow)
        {
            TCP_REQUEST_QUERY_INFORMATION_EX_WOW req = {
                { { GENERIC_ENTITY }, INFO_CLASS_GENERIC, INFO_TYPE_PROVIDER, ENTITY_LIST_ID }
            };

            InputBuffer = &req, InputBufferLength = sizeof(req), pID = &req.ID, Context = req.Context;
        }
        else
#endif
        {
            TCP_REQUEST_QUERY_INFORMATION_EX req = {
                { { GENERIC_ENTITY }, INFO_CLASS_GENERIC, INFO_TYPE_PROVIDER, ENTITY_LIST_ID }
            };

            InputBuffer = &req, InputBufferLength = sizeof(req), pID = &req.ID, Context = req.Context;
        }

        union {
            PVOID buf;
            TDIEntityID* pEntity;
        };

        volatile static UCHAR guz;

        PVOID stack = alloca(guz);

        ULONG cbAllocated = 0, cbNeed = 8 * sizeof(TDIEntityID);

        do 
        {
            if (cbAllocated < cbNeed)
            {
                cbAllocated = RtlPointerToOffset(buf = alloca(cbNeed - cbAllocated), stack);
            }

            // 1. Enumerate TDI Entities (INFO_CLASS_GENERIC, INFO_TYPE_PROVIDER, ENTITY_LIST_ID)

            if (0 <= (status = NtDeviceIoControlFile(hFile, 0, 0, 0, &iosb, 
                IOCTL_TCP_QUERY_INFORMATION_EX, InputBuffer, InputBufferLength, buf, cbAllocated)))
            {
                if (ULONG n = (ULONG)iosb.Information / sizeof(TDIEntityID))
                {
                    NTSTATUS s;

                    union {
                        ULONG type;
                        IPSNMPInfo snmp;
                        IFEntry ife;
                        IPInterfaceInfo ii;
                        BYTE iii_addr[sizeof(IPInterfaceInfo) + MAX_PHYSADDR_SIZE];
                        BYTE if_descr[sizeof(IFEntry) + MAX_ADAPTER_DESCRIPTION_LENGTH];
                    };

                    cbAllocated = 0;
                    stack = buf;
                    PVOID pv = 0;

                    do 
                    {
                        DbgPrint("***{ %08x, %08x }\n", pEntity->tei_entity, pEntity->tei_instance);

                        // set Specific Entity.
                        pID->toi_entity = *pEntity;

                        switch (pEntity->tei_entity)
                        {
                        case IF_ENTITY:
                            //3. Obtain MIB-II Information about an Interface Entity.
                            pID->toi_id = IF_MIB_STATS_ID;
                            pID->toi_class = INFO_CLASS_PROTOCOL;

                            s = NtDeviceIoControlFile(hFile, 0, 0, 0, &iosb, 
                                IOCTL_TCP_QUERY_INFORMATION_EX, 
                                InputBuffer, InputBufferLength, if_descr, sizeof(if_descr));

                            DbgPrint("#%u type=%u mtu=%u %.*S\n", ife.if_index, ife.if_type, ife.if_mtu,
                                ife.if_descrlen / sizeof(WCHAR), ife.if_descr);
                            break;

                        case CO_NL_ENTITY:
                        case CL_NL_ENTITY:
                            //4. Obtain MIB-II Information about a Particular IP Entity. 
                            pID->toi_id = IP_MIB_STATS_ID;
                            pID->toi_class = INFO_CLASS_PROTOCOL;

                            s = NtDeviceIoControlFile(hFile, 0, 0, 0, &iosb, 
                                IOCTL_TCP_QUERY_INFORMATION_EX, 
                                InputBuffer, InputBufferLength, &snmp, sizeof(snmp));

                            if (0 <= s)
                            {
                                if (snmp.ipsi_numaddr)
                                {
                                    cbNeed = snmp.ipsi_numaddr * sizeof(IPAddrEntry);

                                    if (cbAllocated < cbNeed)
                                    {
                                        cbAllocated = RtlPointerToOffset(pv = alloca(cbNeed - cbAllocated), stack);
                                    }

                                    // 5. Obtain Address Information about a Particular IP Entity
                                    pID->toi_id = IP_MIB_ADDRTABLE_ENTRY_ID;

                                    s = NtDeviceIoControlFile(hFile, 0, 0, 0, &iosb, 
                                        IOCTL_TCP_QUERY_INFORMATION_EX, 
                                        InputBuffer, InputBufferLength, pv, cbAllocated);

                                    if (0 <= s)
                                    {
                                        IPAddrEntry* pAddr = (IPAddrEntry*)pv;

                                        // 6. Obtain Interface Information about a Particular IP Address.
                                        pID->toi_id = IP_INTFC_INFO_ID;

                                        do 
                                        {
                                            char sz[16], mask[16];
                                            RtlIpv4AddressToStringA(&pAddr->iae_addr, sz);
                                            RtlIpv4AddressToStringA(&pAddr->iae_mask, mask);
                                            DbgPrint("[%s/%s]\n", sz, mask);

                                            // 6. Obtain Interface Information about a Particular IP Address.
                                            memcpy(Context, &pAddr->iae_addr, sizeof(pAddr->iae_addr));

                                            s = NtDeviceIoControlFile(hFile, 0, 0, 0, &iosb, 
                                                IOCTL_TCP_QUERY_INFORMATION_EX, 
                                                InputBuffer, InputBufferLength, &ii, sizeof(iii_addr));

                                            if (0 <= s)
                                            {
                                                if (ii.iii_addrlength)
                                                {
                                                    DbgPrint("addr=");
                                                    PBYTE pb = ii.iii_addr;
                                                    do 
                                                    {
                                                        DbgPrint("%02x", *pb++);
                                                    } while (--ii.iii_addrlength);
                                                    DbgPrint("\n");
                                                }
                                            }

                                        } while (pAddr++, --snmp.ipsi_numaddr);
                                    }
                                }
                            }
                            break;

                        case CO_TL_ENTITY:
                        case CL_TL_ENTITY:

                            //2. Obtain Type Information about a Specific TL Entity.
                            pID->toi_id = ENTITY_TYPE_ID;
                            pID->toi_class = INFO_CLASS_GENERIC;

                            s = NtDeviceIoControlFile(hFile, 0, 0, 0, &iosb, 
                                IOCTL_TCP_QUERY_INFORMATION_EX, 
                                InputBuffer, InputBufferLength, &type, sizeof(type));

                            if (0 <= s)
                            {
                                DbgPrint("type=%x\n", type);
                            }
                            break;
                        default:continue;
                        }

                        if (0 > s)
                        {
                            DbgPrint("error=%x { %08x, %08x }\n", s, pEntity->tei_entity, pEntity->tei_instance);
                        }

                    } while (pEntity++, --n);
                }
            }

            cbNeed += 8 * sizeof(TDIEntityID);

        } while (status == STATUS_BUFFER_OVERFLOW || status == STATUS_BUFFER_TOO_SMALL);

        NtClose(hFile);
    }

    return status;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-12-15
    • 1970-01-01
    • 1970-01-01
    • 2014-03-13
    • 1970-01-01
    • 1970-01-01
    • 2013-05-10
    相关资源
    最近更新 更多