3环与0环通信-代码

admin 2023年12月26日08:09:45评论21 views字数 6421阅读21分24秒阅读模式

3环与0环通信-代码

前言

在前面我们已经说了,在内核开发时,消息被封装成IRP,我们在写代码之前,先看一下IRP结构体的组成:

kd> dt _IRP
ntdll!_IRP
   +0x000 Type             : Int2B //I/O请求类型(IRP_MJ_CREATE等等)
   +0x002 Size             : Uint2B
   +0x008 MdlAddress       : Ptr64 _MDL  //指向用户缓冲区的MDL类型的指针 
   +0x010 Flags            : Uint4B //I/O需要进行的操作类型
   +0x018 AssociatedIrp    : <unnamed-tag> //指向系统缓冲区的指针
   +0x020 ThreadListEntry  : _LIST_ENTRY
   +0x030 IoStatus         : _IO_STATUS_BLOCK //保存IRP状态和信息
   +0x040 RequestorMode    : Char //来自于内核请求还是用户层请求
   +0x041 PendingReturned  : UChar
   +0x042 StackCount       : Char 
   +0x043 CurrentLocation  : Char
   +0x044 Cancel           : UChar //设置取消IRP
   +0x045 CancelIrql       : UChar
   +0x046 ApcEnvironment   : Char
   +0x047 AllocationFlags  : UChar
   +0x048 UserIosb         : Ptr64 _IO_STATUS_BLOCK
   +0x050 UserEvent        : Ptr64 _KEVENT
   +0x058 Overlay          : <unnamed-tag>
   +0x068 CancelRoutine    : Ptr64     void 
   +0x070 UserBuffer       : Ptr64 Void
   +0x078 Tail             : <unnamed-tag>


相关函数说明

01

IoCreateDevice

3环与0环通信-代码
NTSTATUS IoCreateDevice(
  _In_        PDRIVER_OBJECT    DriverObject, 
  _In_        ULONG             DeviceExtensionSize,
  _In_opt_    PUNICODE_STRING   DeviceName,
  _In_        DEVICE_TYPE       DeviceType,
  _In_        ULONG             DeviceCharacteristics,
  _In_        BOOLEAN           Exclusive,
  _Out_       PDEVICE_OBJECT    *DeviceObject
);
  • PDRIVER_OBJECT DriverObject: 指向驱动程序对象的指针。这是操作系统传递给驱动程序的 DriverEntry 函数的一个参数,表示正在加载的驱动程序。
  • ULONG DeviceExtensionSize: 用于指定与设备对象关联的扩展的字节数。这是在创建设备对象时分配的额外内存大小。通常用于保存与设备关联的自定义数据结构。如果不需要额外的扩展,可以将其设置为 0。
  • PUNICODE_STRING DeviceName: 指定设备对象的名称,是一个 Unicode 字符串。这个参数是可选的,如果为 NULL,系统会自动分配一个唯一的设备名称。
  • DEVICE_TYPE DeviceType: 指定设备对象的类型。可以是以下常见的设备类型之一:
  • FILE_DEVICE_UNKNOWN: 未知设备类型。
  • FILE_DEVICE_BEEP: 蜂鸣器设备。
  • FILE_DEVICE_CD_ROM: CD-ROM 设备。
  • FILE_DEVICE_CONTROLLER: 控制器设备。
  • 等等,具体取决于设备的性质。
  • ULONG DeviceCharacteristics: 指定设备对象的特性。这通常是一个标志位的组合,表示设备对象的一些属性。例如,可以设置 FILE_DEVICE_SECURE_OPEN 表示设备支持安全打开。
  • BOOLEAN Exclusive: 一个布尔值,表示是否独占性创建设备对象。如果为 TRUE,则只有一个进程能够打开设备对象。如果为 FALSE,则可以同时由多个进程打开。
  • PDEVICE_OBJECT *DeviceObject: 一个指向 DEVICE_OBJECT 结构的指针,该结构表示创建的设备对象。这是 IoCreateDevice 函数的输出参数。


0环驱动代码


#include<ntddk.h>
#include<ntstatus.h>

#define DEVICE_NAME L"\Device\MyDevice"
#define SYMBOLICLINE_NAME L"\??\MyTestDriver" //ring3用CreateFile打开设备时,用"\\.\MyTestDriver"//相当于起的别名

#define OPER1 CTL_CODE(FILE_DEVICE_UNKNOWN,0x800/*0-0x7FF保留*/,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define OPER2 CTL_CODE(FILE_DEVICE_UNKNOWN,0x900,METHOD_BUFFERED,FILE_ANY_ACCESS)

//实现卸载函数和派遣函数
VOID DriverUnload(PDRIVER_OBJECT pdriver)
{
DbgPrint("EXIT!");

}
NTSTATUS IrpCreateProc(PDEVICE_OBJECT pDeviceObject/*设备信息*/, PIRP pIrp/*参数信息*/)
{
DbgPrint("DispatchCreate ... n");
pIrp->IoStatus.Status = STATUS_SUCCESS;//getlasterror()得到的就是这个值
pIrp->IoStatus.Information = 0;//返回给3环多少数据,没有填0
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS IrpCloseProc(PDEVICE_OBJECT pdriver, PIRP pIrp)
{
DbgPrint("DispatchClose ... n");
pIrp->IoStatus.Status = STATUS_SUCCESS;
pIrp->IoStatus.Information = 0;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
// 参数pIrp:I / O 管理器在接受到应用层的设备读写请求后, 将请求封装为一个IRP请求(包含IRP 头部和IO_STACK_LOCATION)
NTSTATUS IrpDeviceContrlProc(PDEVICE_OBJECT pdriver, PIRP pIrp)
{
NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
PIO_STACK_LOCATION pIrpStack;
ULONG uIoControlCode;
PVOID pIoBuffer;
ULONG uInLength;
ULONG uOutLength;
ULONG uRead;
ULONG uWrite;

//设置临时变量的值
uRead = 0;
uWrite = 0x12345678;

// 设置临时变量的值
pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
// 获取控制码
uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
// 获取缓冲区地址(输入和输出的缓冲区都是一个)
pIoBuffer = pIrp->AssociatedIrp.SystemBuffer;
// Ring3 发送数据的长度
uInLength = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
// Ring0 发送数据的长度
uOutLength = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;

switch (uIoControlCode)
{
case OPER1:
{
DbgPrint("IrpDeviceControlProc -> OPER1 ... n");

pIrp->IoStatus.Information = 0;
status = STATUS_SUCCESS;
break;
}
case OPER2:
{
DbgPrint("IrpDeviceControlProc -> OPER2 接收字节数:%d n", uInLength);
DbgPrint("IrpDeviceControlProc -> OPER2 输出字节数:%d n", uOutLength);
// 读取缓冲区
memcpy(&uRead, pIoBuffer, 4);
DbgPrint("IrpDeviceControlProc -> OPER2 ... %x n", uRead);
// 写入缓冲区
memcpy(&pIoBuffer, &uWrite, 4);
// 设置状态,返回两字节
pIrp->IoStatus.Information = 2;
status = STATUS_SUCCESS;
break;
}
}

// 设置返回状态
pIrp->IoStatus.Status = status;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return status;
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pdriver, PUNICODE_STRING reg_path)
{
DbgPrint("Welcome Driver,rn");

NTSTATUS status = 0;
ULONG uIndex = 0;
UNICODE_STRING DeviceName;
UNICODE_STRING SymbolicLinkName;
PDEVICE_OBJECT pDeviceObject = NULL;
NTSTATUS nStatus;

// 创建设备
RtlInitUnicodeString(&DeviceName, DEVICE_NAME);

//创建设备
status = IoCreateDevice(pdriver, 0, &DeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDeviceObject);
if (status != STATUS_SUCCESS)
{
DbgPrint("创建设备失败! rn");
return status;
}

//设置交互数据方式
pDeviceObject->Flags |= DO_BUFFERED_IO;

//创建符号链接名称,就是给该设备在三环起个能用的别名
RtlInitUnicodeString(&SymbolicLinkName, SYMBOLICLINE_NAME);

//创建符号链接
status = IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName);
if (status != STATUS_SUCCESS)
{
DbgPrint("创建符号链接失败!rn");
IoDeleteDevice(pDeviceObject);
return status;
}

//设置派遣函数和卸载函数
pdriver->MajorFunction[IRP_MJ_CREATE] = IrpCreateProc;
pdriver->MajorFunction[IRP_MJ_CLOSE] = IrpCloseProc;
pdriver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IrpDeviceContrlProc;
pdriver->DriverUnload = DriverUnload;
return STATUS_SUCCESS;

}


3环代码

#include "stdafx.h"
#include <windows.h>
#include <winioctl.h>

#define IN_BUFFER_MAXLENGTH 0x10 //输入缓存最大长度
#define OUT_BUFFER_MAXLENGTH 0x10 //输出缓存最大长度
#define OPER1 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define OPER2 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x900, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define SYMBOLICLINK_NAME "\\.\MyTestDriver"

HANDLE g_hDevice; //驱动句柄

/***************************************************************************/
//打开驱动服务句柄
//打开三环链接名:\\.\Driver
/***************************************************************************/
BOOL Open(PCHAR pLinkName)
{
TCHAR szBuffer[10] = {0};
//在3环获取驱动程序
g_hDevice = CreateFile(pLinkName, GENERIC_READ|GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
DWORD err = GetLastError();
sprintf(szBuffer, "%dn", err);
if(g_hDevice != INVALID_HANDLE_VALUE)
return TRUE;
else
return FALSE;
}

/***************************************************************************/
//与驱动通信的函数
/***************************************************************************/
BOOL IoControl(DWORD dwIoCode, PVOID InBuff, DWORD InBuffLen, PVOID OutBuff, DWORD OutBuffLen)
{
DWORD dw;
//驱动句柄/操作码/输入缓冲区地址/输入缓冲区长度/输出缓冲区地址/输出缓冲区长度/返回长度/指向OVERLAPPED 此处为NULL
DeviceIoControl(g_hDevice, dwIoCode, InBuff, InBuffLen, OutBuff, OutBuffLen, &dw, NULL);
return TRUE;
}

int main()
{
DWORD dwInBuffer = 0x11223344;
TCHAR szOutBuffer[OUT_BUFFER_MAXLENGTH] = {0};

//1. 通过符号链接,打开设备
Open(SYMBOLICLINK_NAME);
//2. 测试通信
IoControl(OPER2, &dwInBuffer, IN_BUFFER_MAXLENGTH, szOutBuffer, OUT_BUFFER_MAXLENGTH);

printf("%s", szOutBuffer);
//3. 关闭设备
CloseHandle(g_hDevice);

getchar();
return 0;
}


问题

当3环代码运行之后,将设备关闭之后,如果不卸载驱动,就再运行一次会蓝屏。

但是卸载之后,在注册运行驱动,就会失败,不知道是为什么?

3环与0环通信-代码

原文始发于微信公众号(loochSec):3环与0环通信-代码

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年12月26日08:09:45
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   3环与0环通信-代码http://cn-sec.com/archives/2231218.html

发表评论

匿名网友 填写信息