Windows下挂钩nsiproxy.sys模块获取网络连接信息

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值