个人兴趣,想研究一下在r0枚举TCP/UDP端口,网上有代码是xp和win7的,试了一下不行,就简单研究了一下win10的,没啥技术含量,能逆出来相关结构体就行,实现了一个小demo,代码质量堪忧,不喜勿喷。
win10 x64
NtBuildNumber 17134
给\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实现。
首先是控制码,在我的电脑上是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。
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连接数,之后就是第二次查询,查询前需要分配内存。
buffer大小需要在返回的连接数上加2
思路和r3发请求一致,效果:
源码:
#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, ¶m,0x70, ¶m,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, ¶m, 0x70, ¶m, 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(¶m, 0x00, 0x70); param.UnknownParam3 = (ULONG_PTR)NPI_MS_UDP_MODULEID; param.UnknownParam4 = 0x1; param.UnknownParam5 = 0x100000001; pIrp = IoBuildDeviceIoControlRequest( IOCTL_NSI_GETALLPARAM, DevObj, ¶m, 0x70, ¶m, 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(¶m, 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, ¶m, 0x70, ¶m, 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"); }
以上代码仅供参考!不做其他用途。
楼主大四,今年应届毕业,信安专业二进制方向,坐标成都,想找个安全研发岗(成都base),有招人需求的老板可以留一个联系方式投个简历,祝大家新年快乐(:
[2020元旦礼物]《看雪论坛精华17》发布!(补齐之前所有遗漏版本)!
最后于 8小时前 被Oday小斯编辑 ,原因: