win10 x64 r0枚举端口
2020-01-21 03:05:07 Author: bbs.pediy.com(查看原文) 阅读量:669 收藏

个人兴趣,想研究一下在r0枚举TCP/UDP端口,网上有代码是xp和win7的,试了一下不行,就简单研究了一下win10的,没啥技术含量,能逆出来相关结构体就行,实现了一个小demo,代码质量堪忧,不喜勿喷。

0x0环境

win10 x64
NtBuildNumber 17134

0x1原理

\Device\Nsi设备发送IOCTL_NSI_GETALLPARAM进行查询,r3分别有两个函数:GetTcpTable和GetUdpTable(位于Iphlpapi.dll里面),两个函数实现也是通过上述思路。
函数调用链:GetTcpTable/GetUdpTable --->(Iphlpapi.dll)GetTcpTableInternal/GetUdpTableInternal ---> (nsi.dll)NsiAllocateAndGetTable
在NsiAllocateAndGetTable中调用NtDeviceIoControlFile查询

该函数会查询两次,第一次获取连接数量,根据返回的连接数分配合适大小的内存,在第二查询时会将连接信息填充到buffer中,主要的内容就是对nsi.dll中NsiAllocateAndGetTable的逆向,并在r0实现。

0x2过程(以TCP为例,UDP仅有略微差异)

首先是控制码,在我的电脑上是0x12001B

#define IOCTL_NSI_GETALLPARAM 0x12001B

其次是传入NtDeviceIoControlFile的通用结构体buffer,0x70字节大小,下面是我的定义

typedef struct _NSI_PARAM
{
    ULONG_PTR UnknownParam1;    //0
    ULONG_PTR UnknownParam2;    //0
    ULONG_PTR UnknownParam3;    //NPI_MODULEID指针
    ULONG_PTR UnknownParam4;    //硬编码
    ULONG_PTR UnknownParam5;    //硬编码
    ULONG_PTR UnknownParam6;    //结构体1数组指针
    ULONG_PTR UnknownParam7;    //结构体1大小
    ULONG_PTR UnknownParam8;    //0
    ULONG_PTR UnknownParam9;    //0
    ULONG_PTR UnknownParam10;   //结构体2数组指针
    ULONG_PTR UnknownParam11;   //结构体2大小
    ULONG_PTR UnknownParam12;   //结构体3数组指针
    ULONG_PTR UnknownParam13;   //结构体3数组指针
    ULONG_PTR ConnCount;        //连接数
}NSI_PARAM, *PNSI_PARAM;

查询TCP时需要传入3个buffer,查询UDP传入两个,并且相关硬编码有所差异,NPI_MODULEID由上层函数GetTcpTableInternal传入,可以在ida中直接提取,NPI_MS_TCP_MODULEID
查询TCP时,NPI_MODULEID为NPI_MS_TCP_MODULEID。
NPI_MS_TCP_MODULEID

UCHAR NPI_MS_TCP_MODULEID[24] = {
    0x18,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
    0x03,0x4a,0x00,0xeb,0x1a,0x9b,0xd4,0x11,
    0x91,0x23,0x00,0x50,0x04,0x77,0x59,0xbc,
};

第一次查询时,只需要填写NSI_PARAM结构中的3,4,5三个域,查询成功ConnCount会得到TCP连接数,之后就是第二次查询,查询前需要分配内存。
NPI_MS_TCP_MODULEID
buffer大小需要在返回的连接数上加2

0x3r0实现

思路和r3发请求一致,效果:
demo
源码:

#include <wdm.h>
#include <intrin.h>

VOID MyUnload(PDRIVER_OBJECT pDriverObject);
#define ntohs(s) \
    (((s >> 8) & 0x00FF) | \
    ((s << 8) & 0xFF00))

typedef struct _NSI_PARAM
{
    ULONG_PTR UnknownParam1;
    ULONG_PTR UnknownParam2;
    ULONG_PTR UnknownParam3;
    ULONG_PTR UnknownParam4;
    ULONG_PTR UnknownParam5;
    ULONG_PTR UnknownParam6;
    ULONG_PTR UnknownParam7;
    ULONG_PTR UnknownParam8;
    ULONG_PTR UnknownParam9;
    ULONG_PTR UnknownParam10;
    ULONG_PTR UnknownParam11;
    ULONG_PTR UnknownParam12;
    ULONG_PTR UnknownParam13;
    ULONG_PTR ConnCount;
}NSI_PARAM, *PNSI_PARAM;

typedef struct _INTERNAL_UDP_TABLE_ENTRY
{
    USHORT Unknown1;
    USHORT Port;
    ULONG dwIP;
    UCHAR Unknown2[0x14];
}INTERNAL_UDP_TABLE_ENTRY, *PINTERNAL_UDP_TABLE_ENTRY;

typedef struct _INTERNAL_TCP_TABLE_SUBENTRY
{
    USHORT Unknown1;
    USHORT Port;
    ULONG dwIP;
    UCHAR Unknown2[20];
}INTERNAL_TCP_TABLE_SUBENTRY, *PINTERNAL_TCP_TABLE_SUBENTRY;

typedef struct _NSI_STATUS_ENTRY
{
    ULONG_PTR  dwState;
    ULONG_PTR Unknown1;
}NSI_STATUS_ENTRY, *PNSI_STATUS_ENTRY;

typedef struct _INTERNAL_TCP_TABLE_ENTRY
{
    INTERNAL_TCP_TABLE_SUBENTRY localEntry;
    INTERNAL_TCP_TABLE_SUBENTRY remoteEntry;

}INTERNAL_TCP_TABLE_ENTRY, *PINTERNAL_TCP_TABLE_ENTRY;

typedef struct _NSI_PROCESSID_INFO
{
    ULONG dwUdpProId;
    ULONG UnknownParam2;
    ULONG UnknownParam3;
    ULONG dwTcpProId;
    ULONG UnknownParam5;
    ULONG UnknownParam6;
    ULONG UnknownParam7;
    ULONG UnknownParam8;
}NSI_PROCESSID_INFO, *PNSI_PROCESSID_INFO;

#define IOCTL_NSI_GETALLPARAM 0x12001B

extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath)
{
    PIRP pIrp = NULL;
    KEVENT Event;
    NTSTATUS Statu;
    IO_STATUS_BLOCK StatusBlock;
    NSI_PARAM param = { 0, };
    PIO_STACK_LOCATION StackLocation = NULL;
    UCHAR NPI_MS_TCP_MODULEID[24] = {
        0x18,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
        0x03,0x4a,0x00,0xeb,0x1a,0x9b,0xd4,0x11,
        0x91,0x23,0x00,0x50,0x04,0x77,0x59,0xbc,
    };

    __debugbreak();

    pDriverObject->DriverUnload = MyUnload;

    KeInitializeEvent(&Event, NotificationEvent, FALSE);

    UNICODE_STRING DeviceName;
    RtlInitUnicodeString(&DeviceName, L"\\Device\\Nsi");
    PFILE_OBJECT FileObj;
    PDEVICE_OBJECT DevObj;

    Statu = IoGetDeviceObjectPointer(
        &DeviceName, 
        FILE_ALL_ACCESS,
        &FileObj, &DevObj
    );

    param.UnknownParam3 = (ULONG_PTR)&NPI_MS_TCP_MODULEID;
    param.UnknownParam4 = 0x3;//udp 0x1
    param.UnknownParam5 = 0x100000001;

    pIrp = IoBuildDeviceIoControlRequest(
        IOCTL_NSI_GETALLPARAM,
        DevObj,
        &param,0x70, 
        &param,0x70,
        FALSE,
        &Event,
        &StatusBlock
    );

    StackLocation = IoGetNextIrpStackLocation(pIrp);
    StackLocation->FileObject = FileObj;
    StackLocation->DeviceObject = DevObj;
    pIrp->RequestorMode = KernelMode;

    Statu = IoCallDriver(DevObj, pIrp);

    Statu = KeWaitForSingleObject(
            &Event,
            Executive,
            KernelMode,
            FALSE,
            0
        );

    ULONG_PTR Count = param.ConnCount + 2;

    PINTERNAL_TCP_TABLE_ENTRY pBuf1 = (PINTERNAL_TCP_TABLE_ENTRY)ExAllocatePoolWithTag(NonPagedPool, 0x38 * Count, 'MINL');
    PNSI_STATUS_ENTRY pBuf2 = (PNSI_STATUS_ENTRY)ExAllocatePoolWithTag(NonPagedPool, 0x10 * Count, 'MINL');
    PNSI_PROCESSID_INFO pBuf3 = (PNSI_PROCESSID_INFO)ExAllocatePoolWithTag(NonPagedPool, 0x20 * Count, 'MINL');

    RtlZeroMemory(pBuf1, 0x38 * Count);
    RtlZeroMemory(pBuf2, 0x10 * Count);
    RtlZeroMemory(pBuf3, 0x20 * Count);

    param.UnknownParam3 = (ULONG_PTR)&NPI_MS_TCP_MODULEID;
    param.UnknownParam4 = 0x3;
    param.UnknownParam5 = 0x100000001;
    param.UnknownParam6 = (ULONG_PTR)pBuf1;
    param.UnknownParam7 = 0x38;
    param.UnknownParam10 = (ULONG_PTR)pBuf2;
    param.UnknownParam11 = 0x10;
    param.UnknownParam12 = (ULONG_PTR)pBuf3;
    param.UnknownParam13 = 0x20;
    param.ConnCount = Count - 2;

    pIrp = IoBuildDeviceIoControlRequest(
        IOCTL_NSI_GETALLPARAM,
        DevObj,
        &param, 0x70,
        &param, 0x70,
        FALSE,
        &Event,
        &StatusBlock
    );

    StackLocation = IoGetNextIrpStackLocation(pIrp);
    StackLocation->FileObject = FileObj;
    StackLocation->DeviceObject = DevObj;
    pIrp->RequestorMode = KernelMode;

    Statu = IoCallDriver(DevObj, pIrp);

    Statu = KeWaitForSingleObject(
        &Event,
        Executive,
        KernelMode,
        FALSE,
        0
    );

    DbgPrint("TCP PORT");
    for (ULONG i = 0; i < param.ConnCount; i++)
    {
        DbgPrint("ip ---> %x\tport ---> %d pid ---> %d\n", pBuf1[i].localEntry.dwIP, ntohs(pBuf1[i].localEntry.Port), pBuf3[i].dwTcpProId);
    }

    UCHAR NPI_MS_UDP_MODULEID[24] =
    {
        0x18,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
        0x02,0x4a,0x00,0xeb,0x1a,0x9b,0xd4,0x11,
        0x91,0x23,0x00,0x50,0x04,0x77,0x59,0xbc,
    };

    memset(&param, 0x00, 0x70);
    param.UnknownParam3 = (ULONG_PTR)NPI_MS_UDP_MODULEID;
    param.UnknownParam4 = 0x1;
    param.UnknownParam5 = 0x100000001;

    pIrp = IoBuildDeviceIoControlRequest(
        IOCTL_NSI_GETALLPARAM,
        DevObj,
        &param, 0x70,
        &param, 0x70,
        FALSE,
        &Event,
        &StatusBlock
    );

    StackLocation = IoGetNextIrpStackLocation(pIrp);
    Statu = IoCallDriver(DevObj, pIrp);
    Statu = KeWaitForSingleObject(
        &Event,
        Executive,
        KernelMode,
        FALSE,
        0
    );

    Count = param.ConnCount + 2;
    PINTERNAL_UDP_TABLE_ENTRY pBuf4 = (PINTERNAL_UDP_TABLE_ENTRY)ExAllocatePoolWithTag(NonPagedPool, 0x1c * Count, 'MINL');
    PNSI_PROCESSID_INFO pBuf5 = (PNSI_PROCESSID_INFO)ExAllocatePoolWithTag(NonPagedPool, 0x20 * Count, 'MINL');

    memset(&param, 0x00, 0x70);
    param.UnknownParam3 = (ULONG_PTR)NPI_MS_UDP_MODULEID;
    param.UnknownParam4 = 0x1;
    param.UnknownParam5 = 0x100000001;

    param.UnknownParam6 = (ULONG_PTR)pBuf4;
    param.UnknownParam7 = 0x1c;

    param.UnknownParam12 = (ULONG_PTR)pBuf5;
    param.UnknownParam13 = 0x20;
    param.ConnCount = Count - 2;

    pIrp = IoBuildDeviceIoControlRequest(
        IOCTL_NSI_GETALLPARAM,
        DevObj,
        &param, 0x70,
        &param, 0x70,
        FALSE,
        &Event,
        &StatusBlock
    );
    StackLocation = IoGetNextIrpStackLocation(pIrp);

    Statu = IoCallDriver(DevObj, pIrp);

    Statu = KeWaitForSingleObject(
        &Event,
        Executive,
        KernelMode,
        FALSE,
        0
    );

    DbgPrint("UDP PORT");
    for (ULONG i = 0; i < param.ConnCount; i++)
    {
        DbgPrint("ip ---> %x\tport ---> %d\tpid ---> %d\n", pBuf4[i].dwIP, ntohs(pBuf4[i].Port), pBuf5[i].dwUdpProId);
    }

    ExFreePool(pBuf1);
    ExFreePool(pBuf2);
    ExFreePool(pBuf3);
    ExFreePool(pBuf4);
    ExFreePool(pBuf5);

    ObDereferenceObject(FileObj);
    return STATUS_SUCCESS;
}

VOID MyUnload(PDRIVER_OBJECT pDriverObject)
{
    DbgPrint("Unload!\n");
}

以上代码仅供参考!不做其他用途。

0x4顺便求个职

楼主大四,今年应届毕业,信安专业二进制方向,坐标成都,想找个安全研发岗(成都base),有招人需求的老板可以留一个联系方式投个简历,祝大家新年快乐(:

[2020元旦礼物]《看雪论坛精华17》发布!(补齐之前所有遗漏版本)!

最后于 8小时前 被Oday小斯编辑 ,原因:


文章来源: https://bbs.pediy.com/thread-257327.htm
如有侵权请联系:admin#unsafe.sh