??斗地主捕鱼电竞提现秒到 广告位招租 - 15元/月全站展示
??支付宝搜索579087183领大额红包 ??伍彩集团官网直营彩票
??好待遇→招代理 ??伍彩集团官网直营彩票
??络茄网 广告位招租 - 15元/月全站展示
回顾过滤器原理

转载   土匪猿   2018-11-11   浏览量:14


win驱动下过滤器原理:
简单说就是电脑一般真实设备只有一个,像键盘,但有的说一个电脑有多个键盘。多个键盘分别是多个不同的真实物体。
而真实设备对应多个设备对象。多个设备共同组成一个设备栈。不能的设备对应不同的设备对象。如键盘与鼠标是不同的设备对象。设备对象上层是驱动对象。每个设备对象只有唯一的驱动对象。驱动对象有多个设备对象。如一个驱动对象有键盘,鼠标设备对象。一般通信是用户层调用api去访问相应的设备。而调用api底层是调用驱动。也就是发请求给驱动。这个请求一般叫做irp包,然后这个包给设备对象。因为一个真实设备有多个设备对象。因此这个包从设备对象栈第一个开始一直发。直到发给真实设备。在设备栈中的设备对象可以不是同一个驱动对象。比如过滤器驱动创建的设备对象。如果这个设备对象把这个包不往下发也就是不给真实设备。就达到了过滤的作用。
那这些设备对象怎么与真实设备对象关联的呢,就是通过api把一个驱动对象创建的设备对象附加到真实设备对象上。
结构图
回顾过滤器原理
简单代码引用独钓寒江书的源码串口过滤


///
/// @file       comcap.c
/// @author crazy_chu
/// @date       2008-6-18
/// 

#include <ntddk.h>
#define NTSTRSAFE_LIB
#include <ntstrsafe.h>

#ifndef SetFlag
#define SetFlag(_F,_SF)       ((_F) |= (_SF))
#endif
#ifndef ClearFlag
#define ClearFlag(_F,_SF)     ((_F) &= ~(_SF))
#endif
#define CCP_MAX_COM_ID 32

// 过滤设备和真实设备
static PDEVICE_OBJECT s_fltobj[CCP_MAX_COM_ID] = { 0 };
static PDEVICE_OBJECT s_nextobj[CCP_MAX_COM_ID] = { 0 };

// 打开一个端口设备
PDEVICE_OBJECT ccpOpenCom(ULONG id,NTSTATUS *status)
{
    UNICODE_STRING name_str;
    static WCHAR name[32] = { 0 };
    PFILE_OBJECT fileobj = NULL;
    PDEVICE_OBJECT devobj = NULL;

    // 输入字符串。
    memset(name,0,sizeof(WCHAR)*32);
    RtlStringCchPrintfW(
        name,32,
        L"\\Device\\Serial%d",id);
    RtlInitUnicodeString(&name_str,name);

    // 打开设备对象
    *status = IoGetDeviceObjectPointer(&name_str, FILE_ALL_ACCESS, &fileobj, &devobj);
    if (*status == STATUS_SUCCESS)
        ObDereferenceObject(fileobj);

    return devobj;
}

NTSTATUS
ccpAttachDevice(
                PDRIVER_OBJECT driver, 
                PDEVICE_OBJECT oldobj,
                PDEVICE_OBJECT *fltobj, 
                PDEVICE_OBJECT *next)
{
    NTSTATUS status;
    PDEVICE_OBJECT topdev = NULL;

    // 生成设备,然后绑定之。
    status = IoCreateDevice(driver,
                            0,
                            NULL,
                            oldobj->DeviceType,
                            0,
                            FALSE,
                            fltobj);

    if (status != STATUS_SUCCESS)
        return status;

    // 拷贝重要标志位。
    if(oldobj->Flags & DO_BUFFERED_IO)
        (*fltobj)->Flags |= DO_BUFFERED_IO;
    if(oldobj->Flags & DO_DIRECT_IO)
        (*fltobj)->Flags |= DO_DIRECT_IO;
    if(oldobj->Flags & DO_BUFFERED_IO)
        (*fltobj)->Flags |= DO_BUFFERED_IO;
    if(oldobj->Characteristics & FILE_DEVICE_SECURE_OPEN)
        (*fltobj)->Characteristics |= FILE_DEVICE_SECURE_OPEN;
    (*fltobj)->Flags |=  DO_POWER_PAGABLE;
    // 绑定一个设备到另一个设备上
    topdev = IoAttachDeviceToDeviceStack(*fltobj,oldobj);
    if (topdev == NULL)
    {
        // 如果绑定失败了,销毁设备,重新来过。
        IoDeleteDevice(*fltobj);
        *fltobj = NULL;
        status = STATUS_UNSUCCESSFUL;
        return status;
    }
    *next = topdev;

    // 设置这个设备已经启动。
    (*fltobj)->Flags = (*fltobj)->Flags & ~DO_DEVICE_INITIALIZING;
    return STATUS_SUCCESS;
}

// 这个函数绑定所有的串口。
void ccpAttachAllComs(PDRIVER_OBJECT driver)
{
    ULONG i;
    PDEVICE_OBJECT com_ob;
    NTSTATUS status;
    for(i = 0;i<CCP_MAX_COM_ID;i++)
    {
        // 获得object引用。
        com_ob = ccpOpenCom(i,&status);
        if(com_ob == NULL)
            continue;
        // 在这里绑定。并不管绑定是否成功。
        ccpAttachDevice(driver,com_ob,&s_fltobj[i],&s_nextobj[i]);
        // 取消object引用。
    }
}

#define  DELAY_ONE_MICROSECOND  (-10)
#define  DELAY_ONE_MILLISECOND (DELAY_ONE_MICROSECOND*1000)
#define  DELAY_ONE_SECOND (DELAY_ONE_MILLISECOND*1000)

void ccpUnload(PDRIVER_OBJECT drv)
{
    ULONG i;
    LARGE_INTEGER interval;

    // 首先解除绑定
    for(i=0;i<CCP_MAX_COM_ID;i++)
    {
        if(s_nextobj[i] != NULL)
            IoDetachDevice(s_nextobj[i]);
    }

    // 睡眠5秒。等待所有irp处理结束
    interval.QuadPart = (5*1000 * DELAY_ONE_MILLISECOND);       
    KeDelayExecutionThread(KernelMode,FALSE,&interval);

    // 删除这些设备
    for(i=0;i<CCP_MAX_COM_ID;i++)
    {
        if(s_fltobj[i] != NULL)
            IoDeleteDevice(s_fltobj[i]);
    }
}

NTSTATUS ccpDispatch(PDEVICE_OBJECT device,PIRP irp)
{
    PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation(irp);
    NTSTATUS status;
    ULONG i,j;

    // 首先得知道发送给了哪个设备。设备一共最多CCP_MAX_COM_ID
    // 个,是前面的代码保存好的,都在s_fltobj中。
    for(i=0;i<CCP_MAX_COM_ID;i++)
    {
        if(s_fltobj[i] == device)
        {           
            // 所有电源操作,全部直接放过。
            if(irpsp->MajorFunction == IRP_MJ_POWER)
            {
                // 直接发送,然后返回说已经被处理了。
                PoStartNextPowerIrp(irp);
                IoSkipCurrentIrpStackLocation(irp);
                return PoCallDriver(s_nextobj[i],irp);
            }
            // 此外我们只过滤写请求。写请求的话,获得缓冲区以及其长度。
            // 然后打印一下。
            if(irpsp->MajorFunction == IRP_MJ_WRITE)
            {
                // 如果是写,先获得长度
                ULONG len = irpsp->Parameters.Write.Length;
                // 然后获得缓冲区
                PUCHAR buf = NULL;
                if(irp->MdlAddress != NULL)
                    buf = 
                    (PUCHAR)
                    MmGetSystemAddressForMdlSafe(irp->MdlAddress,NormalPagePriority);
                else
                    buf = (PUCHAR)irp->UserBuffer;
                if(buf == NULL)
                    buf = (PUCHAR)irp->AssociatedIrp.SystemBuffer;

                // 打印内容
                for(j=0;j<len;++j)
                {
                    DbgPrint("comcap: Send Data: %2x\r\n",
                        buf[j]);
                }
            }

            // 这些请求直接下发执行即可。我们并不禁止或者改变它。
            IoSkipCurrentIrpStackLocation(irp);
            return IoCallDriver(s_nextobj[i],irp);
        }
    }

    // 如果根本就不在被绑定的设备中,那是有问题的,直接返回参数错误。
    irp->IoStatus.Information = 0;
    irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
    IoCompleteRequest(irp,IO_NO_INCREMENT);
    return STATUS_SUCCESS;  
}

NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
{
    size_t i;
    // 所有的分发函数都设置成一样的。
    for(i=0;i<IRP_MJ_MAXIMUM_FUNCTION;i++)
    {
        driver->MajorFunction[i] = ccpDispatch;
    }

    // 支持动态卸载。
    driver->DriverUnload = ccpUnload;

    // 绑定所有的串口。
    ccpAttachAllComs(driver);

    // 直接返回成功即可。
    return STATUS_SUCCESS;
}

转载自://blog.51cto.com/haidragon/2315568

招聘 不方便扫码就复制添加关注:程序员招聘谷,微信号:jobs1024



Fishhook原理 源码解读)
用到技术利用dyld相关接口,我们可以注册image装载的监听方法:externvoid_dyld_register_func_for_add_image(void(func)(conststructmach_headermh,intptr_tvmaddr_slide));调用_dyld_register_func_for_add_image注册监听方法后,当前已经装载的image(动态库等)会立
Bindshell原理
原理很简单就是创建一个进程打开一个终端然后标准输入输出句柄重定位到一个网络端口c版win系统#include<winsock2.h>#pragmacomment(lib,"Ws2_32.lib")int_tmain(intargc,TCHAR*argv[]){//1.初始化一个sock服务WSADATAstWSA;WSAStartup(0x0202,&stWSA);SOCKET
C语言中可变参数的函数,va_start和va_end的使用及原理介绍
C语言中可变参数的函数,va_start和va_end的使用及原理介绍。在以前的一篇帖子FormatMessageBox详解中曾使用到va_start和va_end这两个宏,但对它们也只是泛泛的了解。介绍这两个宏之前先看一下C中传递函数的参数时的用法和原理:
winsdk回顾
今天想用sdk写一个pe查看器时,打开vs时有点懵。特意简单写下快速回忆1。首先winsdk是一个消息驱动的系统所以所有事情都是通过消息机制所有东西都有自己对应的消息宏2。所有资源对应有资源文件像菜单资源,对话框资源图片资源(字符串也是资源)等win中有一个专门的.rc文件保存所有资源通过资源---id对应起来还有一个.h文件就保存所有id通过id--×××数对应3。winsdk中没有对象的概念不是
智能指针的原理及其应用
所谓智能指针就是自动化管理指针所指向的动态资源的释放。那么智能指针的引用是为了解决哪些问题呢?代码中经?;嵬羰头哦俚淖试?,引用智能指针可用于动态资源管理,资源分配即初始化,定义一个类来封装资源的分配和释放,在构造函数中完成资源的分配和初始化,在析构函数完成资源的清理,可以保证资源的正确初始化和释放。智能指针的原理:智能指针是一个类,这个类的构造函数中传入一个普通指针,析构函数中释放传入的指
DCOM(分布式组件对象模型)原理浅析(一)
&nbsp;&nbsp;&nbsp;(分布式组件对象模型)是一系列微软的概念和程序接口,利用这个接口,客户端程序对象能够请求来自网络中另一台计算机上的服务器程序对象。DCOM基于组件对象模型(COM),COM提供了一套允许同一台计算机上的客户端和服务器之间进行通信的接口(运行在Windows95或者其后的版本上)。&nbsp;&nbsp;&nbsp;DCOM(分布式组件对象模型,分布式组
TCP、UDP原理
现在Internet上流行的协议是TCP/IP协议,对应着Internet上一些常见的服务。这些常见的服务可以分为使用TCP端口(面向连接)和使用UDP端口(面向无连接)两种。说到TCP和UDP,首先要明白“连接”和“无连接”的含义。TCP(TransmissionControlProtocol,传输控制协议)是基于连接的协议,也就是说,在正式收发数据前,必须和对方建立可靠的连接。一个TCP连
TCP和UDP的原理、区别
现在Internet上流行的协议是TCP/IP协议,对应着Internet上一些常见的服务。这些常见的服务可以分为使用TCP端口(面向连接)和使用UDP端口(面向无连接)两种。说到TCP和UDP,首先要明白“连接”和“无连接”的含义。TCP(TransmissionControlProtocol,传输控制协议)是基于连接的协议,也就是说,在正式收发数据前,必须和对方建立可靠的连接。一个TCP连
代码函数名提取与shell 回顾
&nbsp;&nbsp;#include&nbsp;&lt;stdlib.h&gt;#include&nbsp;&lt;stdio.h&gt;int&nbsp;main(){&nbsp;FILE&nbsp;*in;&nbsp;FILE&nbsp;*out;&nbsp;&nbsp;char&nbsp;c;&nbsp;&nbsp;&nbsp;int&nbsp;count=0;&nbsp
位图与布隆过滤器
给40亿个不重复的无符号整数,没排过序。给一个无符号整数,如何快速判断一个数是否在这40亿个数中。这个问题怎么解决呢?【位图方法】:位图(BitMap)是用一个数组中的每个数据的每个二进制位表示一个数是否存在。1表示存在,0表示不存在。相当于把数组分成很多块的空间,每一块是32个比特位。原来32个比特位放一个数据,现在一个位就可以放一个数据。16GB/32=0.5GB=512MB。#ifndef