寒江独钓-串口过滤

原创 2013年12月05日 21:07:05

直接上源码

注释什么的都在源码上:

因为没有  打印机  实现   下载程序   超级终端  可以看到

http://download.csdn.net/download/yfly13/863785


#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 //作者假设计算机上最多有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)
{
	//外面输入的是串口ID,这里会改写成字符串的形式
	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)//fileobj 这里无用
		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]);
	}
		KdPrint(("enter my unliad\n"));
}

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);
			//将请求发送到对应的真是设备,s_nextobj为真实设备保存地
            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;
    // 所有的分发函数都设置成一样的。

	KdPrint(("enter my driverentry\n"));
    for(i=0;i<IRP_MJ_MAXIMUM_FUNCTION;i++)
    {
        driver->MajorFunction[i] = ccpDispatch;
    }

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

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

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









C/C++ 实现文件透明加解密

    今日遇见一个开超市的朋友,真没想到在高校开超市一个月可以达到月净利润50K,相比起我们程序员的工资,真是不可同日而语,这个世道啊,真是做程序员不如经商开超市,我们高科技的从业者,真是造原子弹不...

寒江独钓 第三章 串口的过滤

3.1.1设备绑定API     根据设备的名字进行绑定: NTSTATUS IoAttachDevice{ IN PDEVICE_OBJECT SourceDevice, //...
  • bk8897
  • bk8897
  • 2014年11月24日 14:37
  • 411

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

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

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

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

windows7 《寒江独钓》传统键盘过滤驱动学习

本人驱动方面小白一枚,如果有什么不足之处与不正确之处还请各位大佬多多指正。 另外,本篇博客参考了以下博客,非常感谢原作者的分享!我在学习的时候真的受到了很大的帮助! IRP相关: http://...

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

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

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

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

寒江独钓-键盘过滤学习2修改IDT + IOAPIC重定位表截获PS2键盘中断

分析在源码上 直接上源码吧 读取出了扫描码  其实就知道了  按了哪些健了    一般按一下   有两个  扫描码   一个是 按下  一个是弹起 我将原来的源码改写可以输出  ASCI...
  • zcc1414
  • zcc1414
  • 2013年12月07日 14:40
  • 1322

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

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

寒江独钓-键盘过滤学习1传统型的键盘过滤

最顶层的设备对象是驱动  Kbdclass 生成的设备对象  中间层的设备对象是驱动i8042prt生成的设备对象 最底层的设备对象是驱动ACPI生成的设备对象 键盘过滤分为几种方式: 1 传统型...
  • zcc1414
  • zcc1414
  • 2013年12月07日 12:14
  • 947
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:寒江独钓-串口过滤
举报原因:
原因补充:

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