2017年1月13日星期五

IPv6EnableFirewallHook.C

/*
文件名:IPv6EnableFirewallHook.C

这是一项过时的技术:Available on Microsoft Windows XP with Service Pack 2 (SP2) and Windows Server 2003 with Service Pack 1 (SP1).
而且编译平台只有:XP和2003,因为:只有这个有Tcpip6.lib。
运行平台,那你就测试吧!

不过,有时还是必不可少的技术。

前提条件:安装IPV6协议,
非正式的办法是加载并运行Tcpip6.SYS。
其中的一个检测办法是查看:sc query tcpip6是否运行。
否则本驱动启动失败,返回错误值2,找不到文件,这个文件肯定是Tcpip6.SYS,不信看这两个文件的导出依赖信息。
也就是说Tcpip6.SYS本身是存在的,但是默认没有安装,更不用说启动了。

made by correy
made at 2017.01.13.
homepage:http://correy.webs.com
*/

#include <ntifs.h>
#include <windef.h>
#include <ntddk.h>
#include <ntstrsafe.h>
#include <assert.h>
#include <ipexport.h>
#include <Ip6firewall.h> //编译版本不能超过:NTDDI_LONGHORN。

#pragma warning(disable:4100) //未引用的形参
#pragma warning(disable:4214) //整形以外的位域类型
#pragma warning(disable:4121) //封装要区分成员对齐方式
#pragma warning(disable:4189) //局部变量已初始化但不引用

KEVENT DisableCompleteEvent;// Event to indicate when the disable is complete

#define DATA_ALIGNMENT  4// Alignment for packet data


// Driver's FirewallHook function
IPv6Action
FirewallHook(
const IPv6Addr  *SourceAddress,
const IPv6Addr  *DestinationAddress,
uint  PayloadLength,
uchar  HeaderType,
const uchar  *HeaderData,
const void  *PacketContext,
uint  DataLength,
uint  InterfaceIndex,
IPv6Direction  Direction,
BOOLEAN  IsLoopBack
)
{
    const uchar *PacketData;
    IP6RouteEntry SourceRoute;
    IP6RouteEntry DestinationRoute;
    IP_STATUS Status;

    // Obtain a pointer to the packet data
    PacketData = IPv6ObtainPacketData(PacketContext, DataLength, DATA_ALIGNMENT);
    if (!PacketData)// Check result
    {
        return ActionDrop;// Drop the packet to be safe
    }

    // Get the source route information
    Status = IPv6GetBestRouteInfo(
        SourceAddress,
        0, // Global scope
        0, // No interface constraint
        &SourceRoute
        );
    if (Status != IP_SUCCESS)// Check result
    {
        return ActionDrop;// Drop the packet to be safe
    }

    // Get the destination route information
    Status = IPv6GetBestRouteInfo(
        DestinationAddress,
        0, // Global scope
        0, // No interface constraint
        &DestinationRoute
        );
    if (Status != IP_SUCCESS)// Check result
    {
        return ActionDrop;// Drop the packet to be safe
    }

    // Inspect the various data sources to determine
    // the action to be taken on the packet
    //...

        // If there is a reason why the packet should be dropped...
        //if (...)
        {
            // Drop the packet
            //return ActionDrop;
        }

    return ActionAccept;// Accept the packet
}


// Disable completion routine
VOID DisableComplete(VOID)
{
    KeSetEvent(&DisableCompleteEvent, 0, FALSE);// Set the disable complete event
}


DRIVER_UNLOAD Unload;
VOID Unload(__in PDRIVER_OBJECT DriverObject)
{
    KeInitializeEvent(&DisableCompleteEvent, NotificationEvent, FALSE);// Initialize the disable complete event
    IPv6DisableFirewallHook(DisableComplete);// Disable the firewall hook
    KeWaitForSingleObject(&DisableCompleteEvent, Executive, KernelMode, FALSE, NULL);// Wait for the disable complete event to be signaled
}


NTSTATUS DriverEntry(__in struct _DRIVER_OBJECT  * DriverObject, __in PUNICODE_STRING  RegistryPath)
{
    NTSTATUS status = STATUS_SUCCESS;

    //KdBreakPoint();
    __debugbreak();

    DriverObject->DriverUnload = Unload;

    status = IPv6EnableFirewallHook(FirewallHook);// Enable the FirewallHook callback function

    return status;
}

PacketFilterExtensionPtr.C

/*
文件名:PacketFilterExtensionPtr.C

说明:经常看到WDK的Hook Drivers,Filter-Hook Drivers,一直没有深入研究,直到今天。

参考:
1.WDK
2.http://newbiecoder.0ginr.com/blog/?p=550#comment-122368
3.开源防火墙NetDefender的IP过滤驱动模块
4.http://myblog-maurice.blogspot.jp/2012/02/sniffer.html

注意:
1.IpFilterDriver模块默认安装,但是没有运行。
2.或许是上面的原因,这个模块/功能会被删除/禁用掉。

made by correy
made at 2017.01.09.
homepage:http://correy.webs.com
*/

#include <ntifs.h>
#include <windef.h>
#include <ntddk.h>
#include <ntstrsafe.h>
#include <assert.h>
#include <Ntdddisk.h>

#include <ndis.h>
#include <Pfhook.h>

#include <intrin.h> //VS2012编译。
#include <immintrin.h>//VS2012编译。
//#include <mmintrin.h> //WDK 编译。
//#include <emmintrin.h>//WDK 编译。
//#include <xmmintrin.h>//WDK 编译。

#pragma warning(disable:4100) //未引用的形参
#pragma warning(disable:4214) //整形以外的位域类型
#pragma warning(disable:4121) //封装要区分成员对齐方式
#pragma warning(disable:4189) //局部变量已初始化但不引用


#define TAG 'test' test


PF_FORWARD_ACTION PacketFilterExtension(
    IN unsigned char  *PacketHeader,
    IN unsigned char  *Packet,
    IN unsigned int  PacketLength,
    IN unsigned int  RecvInterfaceIndex,
    IN unsigned int  SendInterfaceIndex,
    IN IPAddr  RecvLinkNextHop,
    IN IPAddr  SendLinkNextHop
    )
{
    return PF_FORWARD;
}


NTSTATUS StopIpFilter()
{
    NTSTATUS status = STATUS_SUCCESS;
    UNICODE_STRING IpFilterDriver = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\IpFilterDriver");//默认情况下,注册表已经存在,但是没有启动。
    UNICODE_STRING IpFilterDevice = RTL_CONSTANT_STRING(DD_IPFLTRDRVR_DEVICE_NAME);
    PDEVICE_OBJECT deviceObject;
    PFILE_OBJECT fileObject;
    PF_SET_EXTENSION_HOOK_INFO psehi = {0};
    KEVENT event;
    IO_STATUS_BLOCK ioStatusBlock;
    PIRP irp;

    status = IoGetDeviceObjectPointer(&IpFilterDevice, FILE_READ_ATTRIBUTES, &fileObject, &deviceObject);
    ASSERT(NT_SUCCESS(status));

    psehi.ExtensionPointer = NULL;

    KeInitializeEvent(&event, NotificationEvent, FALSE);

    irp = IoBuildDeviceIoControlRequest(IOCTL_PF_SET_EXTENSION_POINTER, deviceObject, &psehi, sizeof(PF_SET_EXTENSION_HOOK_INFO), NULL, 0, FALSE, &event, &ioStatusBlock);
    if (!irp)
    {
        ObDereferenceObject(fileObject);
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    status = IoCallDriver(deviceObject, irp);
    if (status == STATUS_PENDING)
    {
        KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
        status = ioStatusBlock.Status;
    }
    ASSERT(NT_SUCCESS(status));

    ObDereferenceObject(fileObject);

    status = ZwUnloadDriver(&IpFilterDriver);
    if (!NT_SUCCESS(status))
    {
        KdPrint(("ZwLoadDriver fail with 0x%x.\r\n", status));
        return status;
    }

    return status;
}


NTSTATUS StartIpFilter(PacketFilterExtensionPtr PacketFilter)
{
    NTSTATUS status = STATUS_SUCCESS;
    UNICODE_STRING IpFilterDriver = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\IpFilterDriver");//默认情况下,注册表已经存在,但是没有启动。
    UNICODE_STRING IpFilterDevice = RTL_CONSTANT_STRING(DD_IPFLTRDRVR_DEVICE_NAME);
    PDEVICE_OBJECT deviceObject;
    PFILE_OBJECT fileObject;
    PF_SET_EXTENSION_HOOK_INFO psehi = {0};
    KEVENT event;
    IO_STATUS_BLOCK ioStatusBlock;
    PIRP irp;

    status = ZwLoadDriver(&IpFilterDriver);
    if (!NT_SUCCESS(status))
    {
        KdPrint(("ZwLoadDriver fail with 0x%x.\r\n", status));
        return status;
    }

    status = IoGetDeviceObjectPointer(&IpFilterDevice, FILE_READ_ATTRIBUTES, &fileObject, &deviceObject);
    ASSERT(NT_SUCCESS(status));

    psehi.ExtensionPointer = PacketFilter;

    KeInitializeEvent(&event, NotificationEvent, FALSE);

    irp = IoBuildDeviceIoControlRequest(IOCTL_PF_SET_EXTENSION_POINTER, deviceObject, &psehi, sizeof(PF_SET_EXTENSION_HOOK_INFO), NULL, 0, FALSE, &event, &ioStatusBlock);
    if (!irp)
    {
        ObDereferenceObject(fileObject);
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    status = IoCallDriver(deviceObject, irp);
    if (status == STATUS_PENDING)
    {
        KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
        status = ioStatusBlock.Status;
    }
    ASSERT(NT_SUCCESS(status));

    ObDereferenceObject(fileObject);

    return status;
}


//DRIVER_UNLOAD Unload;
VOID Unload(__in PDRIVER_OBJECT DriverObject)
{
    StopIpFilter();
}


NTSTATUS DriverEntry(__in struct _DRIVER_OBJECT  * DriverObject, __in PUNICODE_STRING  RegistryPath)
{
    NTSTATUS status = STATUS_SUCCESS;

    //KdBreakPoint();
    __debugbreak();

    DriverObject->DriverUnload = Unload;

    status = StartIpFilter(PacketFilterExtension);
    if (!NT_SUCCESS(status))
    {
        KdPrint(("StartIpFilter fail with 0x%x.\r\n", status));
        return status;
    }

    return status;
}