Windows 7及以后版本的网络模块较从前发生了很大变化,事实上在Windows 下netstat.exe调用Iphlpapi.dll导出的InternalGetTcpTable2函数实现对所有打开端口的列举. InternalGetTcpTable2随后调用由nsi.dll导出的NsiAllocateAndGetTable 函数,nsi.dll则调用NsiEnumerateObjectsAllParametersEx向nsiproxy.sys发送Irp最终转入内核.而nsiproxy.sys又只是对netio.sys的简单封装,它最终调用了netio.sys导出的内核服务例程.
DriverEntry.h
#pragma once
#include<ntifs.h>
#include<windef.h>
extern POBJECT_TYPE* IoDeviceObjectType, * IoDriverObjectType;
PDRIVER_OBJECT pNsiDrvObj = 0;
PDRIVER_DISPATCH oldNsiDeviceIoControl = 0;
typedef struct _HP_CONTEXT
{
PIO_COMPLETION_ROUTINE oldIocomplete;
PVOID oldCtx;
BOOLEAN bShouldInvolve;
PKPROCESS pcb;
} HP_CONTEXT, * PHP_CONTEXT;
typedef struct _INTERNAL_TCP_TABLE_SUBENTRY
{
char bytesfill0[2];
USHORT Port;
DWORD dwIP;
char bytesfill[20];
} INTERNAL_TCP_TABLE_SUBENTRY, * PINTERNAL_TCP_TABLE_SUBENTRY;
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_STATUS_ENTRY
{
char bytesfill[12];
} NSI_STATUS_ENTRY, * PNSI_STATUS_ENTRY;
//typedef struct _NSI_PARAM
//{
// DWORD UnknownParam1;
// DWORD UnknownParam2;
// DWORD UnknownParam3; //NPI_MODULEID指针
// DWORD UnknownParam4; //硬编码
// DWORD UnknownParam5; //硬编码
// DWORD UnknownParam6; //结构体1数组指针
// PVOID lpMem; //结构体1大小
// DWORD UnknownParam8;
// DWORD UnknownParam9;
// DWORD UnknownParam10; //结构体2数组指针
// PNSI_STATUS_ENTRY lpStatus; //结构体2大小
// DWORD UnknownParam12; //结构体3数组指针
// DWORD UnknownParam13; //结构体3数组指针
// DWORD UnknownParam14;
// DWORD TcpConnCount;
//
//} NSI_PARAM, * PNSI_PARAM;
typedef struct _NSI_PARAM
{
ULONG_PTR UnknownParam1; //0
ULONG_PTR UnknownParam2; //0
ULONG_PTR UnknownParam3; //NPI_MODULEID指针
ULONG_PTR UnknownParam4; //硬编码
ULONG_PTR UnknownParam5; //硬编码
PVOID lpMem; //结构体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;
NTSTATUS ObReferenceObjectByName(
IN PUNICODE_STRING ObjectName,
IN ULONG Attributes,
IN PACCESS_STATE AccessState OPTIONAL,
IN ACCESS_MASK DesiredAccess OPTIONAL,
IN POBJECT_TYPE ObjectType,
IN KPROCESSOR_MODE AccessMode,
IN OUT PVOID ParseContext OPTIONAL,
OUT PVOID* Object
);
DriverEntry.c
#include"DriverEntry.h"
#include<stdio.h>
#define HTONS(a) (((0xFF&a)<<8) + ((0xFF00&a)>>8))
#define IOCTL_NSI_GETALLPARAM 0x12001B
#define POOLTAG 'buff'
static long htonl(long value)
{
return (((value & 0xff000000) >> 24) | ((value & 0x00ff0000) >> 8) | ((value & 0x0000ff00) << 8) | ((value & 0x000000ff) << 24));
}
PCHAR GetIP(unsigned int ipAddr) {
static char pIp[20];
unsigned int nIpAddr = htonl(ipAddr);
sprintf(pIp, "%d.%d.%d.%d",
(nIpAddr >> 24) & 0xFF,
(nIpAddr >> 16) & 0xFF,
(nIpAddr >> 8) & 0xFF,
(nIpAddr) & 0xFF);
return pIp;
}
NTSTATUS MyCompletion(PDEVICE_OBJECT DeviceObject,PIRP Irp,PVOID Context)
{
//PIO_STACK_LOCATION irpspNext = IoGetCurrentIrpStackLocation(Irp);
PIO_STACK_LOCATION irpspNext = IoGetNextIrpStackLocation(Irp);
PHP_CONTEXT pCtx = Context;
PNSI_PARAM nsiParam;
BOOLEAN bShouldInvolve = FALSE;
UNREFERENCED_PARAMETER(DeviceObject);
if (NT_SUCCESS(Irp->IoStatus.Status))
{
nsiParam = Irp->UserBuffer;
if (MmIsAddressValid(nsiParam->lpMem))
{
if ((nsiParam->UnknownParam7 == 0x38))
{
KAPC_STATE apcstate;
//PNSI_STATUS_ENTRY pStatusEntry = (PNSI_STATUS_ENTRY)nsiParam->lpStatus;
PINTERNAL_TCP_TABLE_ENTRY pTcpEntry = (PINTERNAL_TCP_TABLE_ENTRY)nsiParam->lpMem;
ULONG_PTR nItemCnt = nsiParam->ConnCount;
KeStackAttachProcess(pCtx->pcb, &apcstate);
char localIp[20];
char remoteIp[20];
for (int i = 0; i < nItemCnt; i++)
{
strncpy(localIp, GetIP(pTcpEntry[i].localEntry.dwIP), 20);
strncpy(remoteIp, GetIP(pTcpEntry[i].remoteEntry.dwIP), 20);
DbgPrint("localIp:%s\t\tPort:%d\t\tremoteIp:%s\t\tPort:%d", localIp, HTONS(pTcpEntry[i].localEntry.Port), remoteIp, HTONS(pTcpEntry[i].remoteEntry.Port));
}
KeUnstackDetachProcess(&apcstate);
}
}
}
irpspNext->Context = pCtx->oldCtx;
irpspNext->CompletionRoutine = pCtx->oldIocomplete;
bShouldInvolve = pCtx->bShouldInvolve;
ExFreePoolWithTag(Context, POOLTAG);
DbgPrint("return success\n");
if (Irp->PendingReturned) {
IoMarkIrpPending(Irp);
}
return STATUS_SUCCESS;
//if (bShouldInvolve && irpspNext->CompletionRoutine != NULL)
//{
// DbgPrint("return pld CompletionRoutine\n");
// return irpspNext->CompletionRoutine(DeviceObject, Irp, irpspNext->Context);
//}
//else
//{
// DbgPrint("return success\n");
// if(Irp->PendingReturned) {
// IoMarkIrpPending(Irp);
// }
// return STATUS_SUCCESS;
//}
}
NTSTATUS HPUnload(IN PDRIVER_OBJECT DriverObject)
{
LARGE_INTEGER waittime;
waittime.QuadPart = -50 * 1000 * 1000;
InterlockedExchangePointer((PVOID)(&(pNsiDrvObj->MajorFunction[IRP_MJ_DEVICE_CONTROL])), (PVOID)oldNsiDeviceIoControl);
KeDelayExecutionThread(KernelMode, 0, &waittime);
UNICODE_STRING DeleteSymName;
PDEVICE_OBJECT deviceObject = DriverObject->DeviceObject;
RtlInitUnicodeString(&DeleteSymName, L"\\DosDevices\\HookNsi");
//删除符号对象
IoDeleteSymbolicLink(&DeleteSymName);
if (deviceObject != NULL) {
IoDeleteDevice(deviceObject);
}
ObDereferenceObject(pNsiDrvObj);
return STATUS_SUCCESS;
}
NTSTATUS MyDeviceControl(PDEVICE_OBJECT DeviceObject,PIRP Irp)
{
ULONG uIoControlCode;
PIO_STACK_LOCATION irpStack;
NTSTATUS status;
irpStack = IoGetCurrentIrpStackLocation(Irp);
uIoControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
if (IOCTL_NSI_GETALLPARAM == uIoControlCode)
{
if (irpStack->Parameters.DeviceIoControl.InputBufferLength == sizeof(NSI_PARAM))
{
PHP_CONTEXT ctx = (HP_CONTEXT*)ExAllocatePoolWithTag(NonPagedPool, sizeof(HP_CONTEXT),POOLTAG);
if (ctx == NULL) {
DbgPrint("Failed to ExAllocatePoolfor ctx!");
status = STATUS_INSUFFICIENT_RESOURCES;
return status;
}
else {
RtlZeroMemory(ctx, sizeof(HP_CONTEXT));
}
ctx->oldIocomplete = irpStack->CompletionRoutine;
ctx->oldCtx = irpStack->Context;
irpStack->CompletionRoutine = MyCompletion;
irpStack->Context = ctx;
ctx->pcb = IoGetCurrentProcess();
if ((irpStack->Control & SL_INVOKE_ON_SUCCESS) == SL_INVOKE_ON_SUCCESS) {
ctx->bShouldInvolve = TRUE;
}
else {
ctx->bShouldInvolve = FALSE;
}
irpStack->Control |= SL_INVOKE_ON_SUCCESS;
}
}
status = oldNsiDeviceIoControl(DeviceObject, Irp);
return status;
}
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath)
{
NTSTATUS status=STATUS_SUCCESS;
UNICODE_STRING uniNsiDrvName;
UNICODE_STRING DeviceName;
UNICODE_STRING SymbolicLinkName;
DEVICE_OBJECT* pDeviceObj = NULL;
NTSTATUS nStatus = STATUS_SUCCESS;
UNICODE_STRING DeleteSymName;
RtlInitUnicodeString(&DeleteSymName, L"\\DosDevices\\HookNsi");
//删除符号对象
IoDeleteSymbolicLink(&DeleteSymName);
UNREFERENCED_PARAMETER(RegistryPath);
RtlInitUnicodeString(&DeviceName, L"\\Device\\IOCTLHookNsi");
RtlInitUnicodeString(&SymbolicLinkName, L"\\DosDevices\\HookNsi");
nStatus = IoCreateDevice(DriverObject,
0,
&DeviceName,
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN,
TRUE,
&pDeviceObj);
if (!NT_SUCCESS(nStatus)) {
DbgPrint("IoCreateDevice failed!");
return nStatus;
}
nStatus = IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName);
if (!NT_SUCCESS(nStatus)) {
DbgPrint("IoCreateSymbolicLink failed!");
IoDeleteDevice(pDeviceObj);
return nStatus;
}
//初始化派遣函数
DriverObject->DriverUnload = HPUnload;
RtlInitUnicodeString(&uniNsiDrvName, L"\\Driver\\nsiproxy");
status = ObReferenceObjectByName(
&uniNsiDrvName,
OBJ_CASE_INSENSITIVE,
NULL,
FILE_ALL_ACCESS,
*IoDriverObjectType,
KernelMode,
NULL,
&pNsiDrvObj);
if (!NT_SUCCESS(status))
{
DbgPrint("ObReferenceObjectByName failed,err:%d", status);
return STATUS_SUCCESS;
}
else
{
oldNsiDeviceIoControl = pNsiDrvObj->MajorFunction[IRP_MJ_DEVICE_CONTROL];
InterlockedExchangePointer((PVOID) (&(pNsiDrvObj->MajorFunction[IRP_MJ_DEVICE_CONTROL])), (PVOID)MyDeviceControl);
}
return STATUS_SUCCESS;
}