寒江独钓-Windows内核安全编程笔记-第3章代码和笔记

原创 2015年07月10日 13:24:19

第3章代码 

// #include 
#include 
#define NTSTRSAFE_LIB
#include 

#define  CPP_MAX_COM_ID 32
#define     DELAY_ONE_MICROSECOND (-10)
#define     DELAY_ONE_MILLISECOND (DELAY_ONE_MICROSECOND*1000)
#define     DELAY_ONE_SECOND (DELAY_ONE_MILLISECOND*1000)
static PDEVICE_OBJECT s_fltobj[CPP_MAX_COM_ID] = {0};
static PDEVICE_OBJECT s_nextobj[CPP_MAX_COM_ID] = {0};


NTSTATUS ccpAttachDevice(
    PDRIVER_OBJECT driver
    , PDEVICE_OBJECT oldobj
    , PDEVICE_OBJECT *fltobj
    , PDEVICE_OBJECT *next)
{
    NTSTATUS status;
    PDEVICE_OBJECT topdev = NULL;
    // IoCreateDevice 创建设备对象
    // driver 驱动程序对象 , oldobj->DeviceType设备的类型
    // fltobj指向接收DEVICE_OBJECT结构体的指针
    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 & FILE_DEVICE_SECURE_OPEN)
    {
        (*fltobj)->Characteristics |= FILE_DEVICE_SECURE_OPEN;
    }
    (*fltobj)->Flags |= DO_POWER_PAGABLE;
    // 将调用方的设备对象附加到设备对象链中的最高层,并返回之前在设备对象链中最高的设备对象。
    // fltobj需要附着的源设备对象, oldobj附着到的目标设备对象
    // 把fltobj放到oldobj所在的链的顶端
    topdev = IoAttachDeviceToDeviceStack (*fltobj, oldobj);
    if (NULL == topdev)
    {
        // 从系统中删除一个设备对象fltobj
        // VOID IoDeleteDevice(
        //     _In_ PDEVICE_OBJECT DeviceObject
        //     );
        //     DeviceObject 要删除的设备对象指针
        IoDeleteDevice (*fltobj);
        *fltobj = NULL;
        status = STATUS_UNSUCCESSFUL;
        return status;
    }
    *next = topdev;

    (*fltobj)->Flags = (*fltobj)->Flags & ~DO_DEVICE_INITIALIZING;
    return STATUS_SUCCESS;
}

PDEVICE_OBJECT cppOpenCom(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);
    // 获取命名对象
    // IoGetDeviceObjectPointer返回一个指向命名对象设备堆栈顶部的对象指针和
    // 相应的文件对象指针
    // The IoGetDeviceObjectPointer routine returns a pointer to the top object 
    // in the named device object's stack and a pointer to the corresponding file object, 
    // if the requested access to the objects can be granted.
    *status = IoGetDeviceObjectPointer(&name_str, FILE_ALL_ACCESS, &fileobj, &devobj);
    if (*status == STATUS_SUCCESS)
    {
        // 解除引用。
        // ObDereferenceObject检查给定对象的引用计
        // The ObDereferenceObject routine decrements the given object's reference count
        // and performs retention checks.
        ObDereferenceObject(fileobj);
    }
    return devobj;
}




void cppAttachAllCom(PDRIVER_OBJECT driver)
{
    ULONG i;
    PDEVICE_OBJECT com_ob;
    NTSTATUS status;
    for (i = 0; i < CPP_MAX_COM_ID; ++i)
    {
        com_ob = cppOpenCom (i, &status);
        if (NULL == com_ob)
        {
            continue;
        }
        ccpAttachDevice(driver, com_ob, &s_fltobj[i], &s_nextobj[i]);
    }
}

NTSTATUS ccpDispatch(PDEVICE_OBJECT device, PIRP irp)
{
    PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation (irp);
    NTSTATUS status;
    ULONG i, j;
    for (i = 0; i < CPP_MAX_COM_ID; ++i)
    {
        if (device == s_fltobj[i])
        {
            if (irpsp->MajorFunction == IRP_MJ_POWER)
            {
                // The PoStartNextPowerIrp routine signals the power manager that 
                // the driver is ready to handle the next power IRP.
                // (Windows Server 2003, Windows XP, and Windows 2000 only.)
                PoStartNextPowerIrp (irp);
                // The IoSkipCurrentIrpStackLocation macro modifies the system's
                // IO_STACK_LOCATION array pointer, so that when the current
                // driver calls the next-lower driver, that driver receives
                // the same IO_STACK_LOCATION structure that
                // the current driver received.
                IoSkipCurrentIrpStackLocation (irp);
                // The PoCallDriver routine passes a power IRP to the next-lower 
                // driver in the device stack. 
                // (Windows Server 2003, Windows XP, and Windows 2000 only.)
                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)
                {
                    // The MmGetSystemAddressForMdlSafe macro returns a 
                    // nonpaged system-space virtual address for the buffer that
                    // the specified MDL describes.
                    buf = (PUCHAR)MmGetSystemAddressForMdlSafe(
                        irp->MdlAddress, NormalPagePriority);
                }
                else
                {
                    buf = (PUCHAR)irp->UserBuffer;
                }
                if (NULL == buf)
                {
                    buf = (PUCHAR)irp->AssociatedIrp.SystemBuffer;
                }

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

            IoSkipCurrentIrpStackLocation (irp);
            // The IoCallDriver routine sends an IRP to the driver associated with
            // a specified device object.
            // 发送irp给s_nextobj[i]
            return IoCallDriver (s_nextobj[i], irp);
        }
    }
    irp->IoStatus.Information = 0;
    irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
    // The IoCompleteRequest routine indicates that the caller has completed all processing
    // for a given I/O request and is returning the given IRP to the I/O manager.
    // 调用者已完成所有处理对于一个给定的I / O请求和返回给定的irp到I / O管理器。
    IoCompleteRequest(irp, IO_NO_INCREMENT);
    return STATUS_SUCCESS;
}


void ccpUnload(PDRIVER_OBJECT drv)
{
    ULONG i;
    LARGE_INTEGER interval;
    for (i = 0; i < CPP_MAX_COM_ID; ++i)
    {
        if (NULL != s_nextobj[i])
        {
            // The IoDetachDevice routine releases an attachment between the caller's 
            // device object and a lower driver's device object.
            // 从设备链上删除 s_nextobj[i]
            // s_nextobj[i] 下层堆栈上的设备对象  
            IoDetachDevice (s_nextobj[i]);
        }
    }
    interval.QuadPart = 5*1000*DELAY_ONE_MILLISECOND;
    // The KeDelayExecutionThread routine puts the current thread into an alertable or
    // nonalertable wait state for a specified interval.
    // 延时
    KeDelayExecutionThread (KernelMode, FALSE, &interval);
    for (i = 0; i < CPP_MAX_COM_ID; ++i)
    {
        if (NULL != s_fltobj[i])
        {
            IoDeleteDevice (s_fltobj[i]);
        }
    }
}

NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
{
    size_t i;
#if DBG
    _asm int 3;
#endif
    for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; ++i)
    {             
        driver->MajorFunction[i] = ccpDispatch;
    }

    driver->DriverUnload = ccpUnload ;
    cppAttachAllCom (driver);
    return STATUS_SUCCESS;
}


相关文章推荐

<寒江独钓>Windows内核安全编程__具有还原功能的磁盘卷过滤驱动

磁盘过滤驱动的概念 1.设备过滤和类过滤 在之前的文章里,我们已经介绍过滤的概念,所谓过滤技术就是在本来已有的设备栈中加入自己的一个设备。由于Windows向任何一个设备发送IRP请求都会首先发送...
  • aksnzhy
  • aksnzhy
  • 2011年10月27日 19:33
  • 5758

<寒江独钓>Windows内核安全编程__键盘过滤之内核级Hook(二)

Windows内核安全编程__键盘过滤内核级Hook(二) 如果不想让键盘过滤驱动程序或回调函数首先获得按键,则必须比端口驱动更加底层一些。 早期版本的QQ反盗号驱动的原理是这样的:用户要输入密码...
  • aksnzhy
  • aksnzhy
  • 2011年10月17日 09:57
  • 3171

<寒江独钓>Windows内核安全编程__传统键盘过滤程序

技术原理 1.预备知识 何为符号链接?符号链接其实就是设备的一个“别名”。在应用程序中想要访问设备一般要通过符号链接来完成,而不是设备名本身。 ZwCreateFile是很重要的函数。同名的函数...
  • aksnzhy
  • aksnzhy
  • 2011年10月13日 12:15
  • 3900

<寒江独钓>Windows内核安全编程__Ramdisk源码解读

这篇文章来介绍一下WDK中提供的一个案例源码--Ramdisk虚拟磁盘。这个例子实现了一个非分页内存做的磁盘储存空间,并将其以一个独立磁盘的形式暴露给用户,用户可以将它格式化成一个Windows能够使...
  • aksnzhy
  • aksnzhy
  • 2011年10月20日 11:58
  • 3435

<寒江独钓>Windows内核安全编程__键盘过滤之内核级Hook(一)

Hook分发函数 前一篇文章讲述了进行键盘过滤,截取用户输入的方法。本篇文章开始更加深入地讨论键盘的过滤与反过滤对抗。无论是过滤还是饭过滤,原理都是过滤,取胜的关键在于谁第一个得到信息。 一种方发...
  • aksnzhy
  • aksnzhy
  • 2011年10月14日 20:03
  • 4560

寒江独钓-windows内核安全编程源码

  • 2010年07月21日 08:45
  • 1.16MB
  • 下载

寒江独钓-Windows内核安全编程.part1

  • 2012年01月07日 00:37
  • 57.22MB
  • 下载

<寒江独钓>学习笔记 -- 第四章 Hook分发函数 过滤键盘输入

转载请注明出处:http://blog.csdn.net/lup7in/article/details/7015497 最近在学习windows内核编程,下面是《寒江独钓》第四章hook分发函数过滤...
  • lup7in
  • lup7in
  • 2011年11月26日 21:44
  • 1780

寒江独钓-Windows内核安全编程.part3

  • 2012年03月06日 22:43
  • 28.61MB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:寒江独钓-Windows内核安全编程笔记-第3章代码和笔记
举报原因:
原因补充:

(最多只允许输入30个字)