首页
社区
课程
招聘
通过驱动接触win内核
发表于: 2022-12-9 22:29 17879

通过驱动接触win内核

2022-12-9 22:29
17879

整个结构会很复杂,比如处理IRP部分:
2girpeg

模型中我们最需要关注这三个概念:
pimpmypid_winkernel_device_objects_model

DRIVER_OBJECT包含许多驱动程序标准例程的入口点的存储。同样重要的是要注意这一点:当 I/O 管理器处理 IRP 时,它会将当前驱动程序的DRIVER_OBJECT内存地址提供给名为 DriverEntry 的主函数。更详细的描述参考链接1。

了解一些重要的结构能帮助我们快速构建需要的payload

它是 Input/Output Request Packet 的简称,在WDM.H定义了标准的NT结构。如下:

我们重点关注两个元素:

该结构体有上面提到的 CurrentStackLocation指定,其结构可以从这查看https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ns-wdm-_io_stack_location

我们需要关注的两个结构体是:

该结构体位于 IO_STACK_LOCATION结构中,标识驱动程序处理 I/O 请求的逻辑、虚拟或物理设备。

把上面的结构体组好到一起,就是DRIVER_OBJECT

每个驱动程序都包含主要功能代码(major function codes),这些代码告诉驱动程序应执行哪些操作来满足 I/O 请求。所有驱动程序必须至少支持:

下面将给一个实际的例子,直接上demo。

核心功能将被放置在vikingdrv2DeviceControl例程中,该例程有两个参数:

首先把IO_STACK_LOCATION 指针存储到栈上,该结构用来接受用户发来的信息:

大致结构如下:

然后我们定义名为 DriverEntry 的主函数。如前所述,此函数获取指向DRIVER_OBJECT结构的指针。为了知道在提供IRP_MJ代码时必须执行哪个函数,驱动程序必须定义调度例程(dispatch routine)。这里最重要的是使其能够处理IRP_MJ_DEVICE_CONTROL消息:让它指向 vikingdrv2DeviceControl函数。

这就是一个简单基础的驱动实例~,确实很基础,但是能用。

参考自https://leanpub.com/windowskernelprogramming,写一个简单的驱动程序,需要完成三个功能:

驱动程序客户端和驱动程序本身必须具有“通用”说话方式。DeviceIoControl 函数将控制代码直接发送到指定的设备驱动程序,使设备执行相应的操作。这个函数有三个重要的部分:

创建入口点:
DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)

设置调度例程来处理IRP_MJ_DEVICE_CONTROL/驱动程序对象:我们将函数命名为vikingdrv2DeviceControl
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = vikingdrv2DeviceControl;

提供device namesymlink name名称,然后创建设备对象,以便客户端可以访问驱动程序并打开文件系统句柄。

现在我们有一个指向设备对象的指针,通过提供符号链接使用户模式调用方可以访问它。

前面是准备处理请求部分,下面是如何处理它。

首先,我们必须找到我们的堆栈位置(从驱动程序的角度来看),并确认我们的客户端/用户给了我们一个我们能够处理的 IOCTL。

然后我们处理缓冲区以检索客户端准备的 ThreadData 结构
auto data = (ThreadData*)stack->Parameters.DeviceIoControl.Type3InputBuffer;

最终,我们会处理客户提供的数据。这里我们修改进程的线程优先级:

在内核部分:驱动程序正在等待请求。现在客户端代码呢?

首先,让我们创建一个处理用户提供的参数的 main 函数。

然后使用符号链接打开设备的句柄。

现在,调用 DeviceIoControl 并在之后关闭设备句柄。

编译此驱动程序会生成一个文件.sys该文件可以作为服务安装:
sc create viking_drv2 type= kernel binpath= C:\viking_driver2.sys

然后禁用签名验证,如果驱动程序已签名,则启用测试签名模式并禁用完整性检查。

重启并启动服务。

这个例子参考自Windows Kernel Programming。肯定会运行的,但是问题是目的是提权,而不是修改线程优先级。

寻找线程内存环境:

PsLookupProcessByProcessId API 结束时,名为 processsystem_processPEPROCESS 结构可用,并且包含获取有关请求的 PID(以及系统 pid 编号 4)的信息所需的所有内容。

获取进程 token:

上面所有操作完成之后,提权需要重新写一个客户端,先中止进程:
FindAndReplaceMember((PDWORD_PTR)process, (DWORD_PTR)targetToken, (DWORD_PTR)systemToken, MaxExpectedEprocessSize);

但是不用再启用vs,直接使用ps代替调用:

看看效果

 
typedef struct _IRP {
  CSHORT                    Type;
  USHORT                    Size;
  PMDL                      MdlAddress;
  ULONG                     Flags;
  union {
    struct _IRP     *MasterIrp;
    __volatile LONG IrpCount;
    PVOID           SystemBuffer;
  } AssociatedIrp;
  LIST_ENTRY                ThreadListEntry;
  IO_STATUS_BLOCK           IoStatus;
  KPROCESSOR_MODE           RequestorMode;
  BOOLEAN                   PendingReturned;
  CHAR                      StackCount;
  CHAR                      CurrentLocation;
  BOOLEAN                   Cancel;
  KIRQL                     CancelIrql;
  CCHAR                     ApcEnvironment;
  UCHAR                     AllocationFlags;
  union {
    PIO_STATUS_BLOCK UserIosb;
    PVOID            IoRingContext;
  };
  PKEVENT                   UserEvent;
  union {
    struct {
      union {
        PIO_APC_ROUTINE UserApcRoutine;
        PVOID           IssuingProcess;
      };
      union {
        PVOID                 UserApcContext;
#if ...
        _IORING_OBJECT        *IoRing;
#else
        struct _IORING_OBJECT *IoRing;
#endif
      };
    } AsynchronousParameters;
    LARGE_INTEGER AllocationSize;
  } Overlay;
  __volatile PDRIVER_CANCEL CancelRoutine;
  PVOID                     UserBuffer;
  union {
    struct {
      union {
        KDEVICE_QUEUE_ENTRY DeviceQueueEntry;
        struct {
          PVOID DriverContext[4];
        };
      };
      PETHREAD     Thread;
      PCHAR        AuxiliaryBuffer;
      struct {
        LIST_ENTRY ListEntry;
        union {
          struct _IO_STACK_LOCATION *CurrentStackLocation;
          ULONG                     PacketType;
        };
      };
      PFILE_OBJECT OriginalFileObject;
    } Overlay;
    KAPC  Apc;
    PVOID CompletionKey;
  } Tail;
} IRP;
typedef struct _IRP {
  CSHORT                    Type;
  USHORT                    Size;
  PMDL                      MdlAddress;
  ULONG                     Flags;
  union {
    struct _IRP     *MasterIrp;
    __volatile LONG IrpCount;
    PVOID           SystemBuffer;
  } AssociatedIrp;
  LIST_ENTRY                ThreadListEntry;
  IO_STATUS_BLOCK           IoStatus;
  KPROCESSOR_MODE           RequestorMode;
  BOOLEAN                   PendingReturned;
  CHAR                      StackCount;
  CHAR                      CurrentLocation;
  BOOLEAN                   Cancel;
  KIRQL                     CancelIrql;
  CCHAR                     ApcEnvironment;
  UCHAR                     AllocationFlags;
  union {
    PIO_STATUS_BLOCK UserIosb;
    PVOID            IoRingContext;
  };
  PKEVENT                   UserEvent;
  union {
    struct {
      union {
        PIO_APC_ROUTINE UserApcRoutine;
        PVOID           IssuingProcess;
      };
      union {
        PVOID                 UserApcContext;
#if ...
        _IORING_OBJECT        *IoRing;
#else
        struct _IORING_OBJECT *IoRing;
#endif
      };
    } AsynchronousParameters;
    LARGE_INTEGER AllocationSize;
  } Overlay;
  __volatile PDRIVER_CANCEL CancelRoutine;
  PVOID                     UserBuffer;
  union {
    struct {
      union {
        KDEVICE_QUEUE_ENTRY DeviceQueueEntry;
        struct {
          PVOID DriverContext[4];
        };
      };
      PETHREAD     Thread;
      PCHAR        AuxiliaryBuffer;
      struct {
        LIST_ENTRY ListEntry;
        union {
          struct _IO_STACK_LOCATION *CurrentStackLocation;
          ULONG                     PacketType;
        };
      };
      PFILE_OBJECT OriginalFileObject;
    } Overlay;
    KAPC  Apc;
    PVOID CompletionKey;
  } Tail;
} IRP;
 
typedef struct _DRIVER_OBJECT {
  CSHORT             Type;
  CSHORT             Size;
  PDEVICE_OBJECT     DeviceObject;
  ULONG              Flags;
  PVOID              DriverStart;
  ULONG              DriverSize;
  PVOID              DriverSection;
  PDRIVER_EXTENSION  DriverExtension;
  UNICODE_STRING     DriverName;
  PUNICODE_STRING    HardwareDatabase;
  PFAST_IO_DISPATCH  FastIoDispatch;
  PDRIVER_INITIALIZE DriverInit;
  PDRIVER_STARTIO    DriverStartIo;
  PDRIVER_UNLOAD     DriverUnload;
  PDRIVER_DISPATCH   MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1];
} DRIVER_OBJECT, *PDRIVER_OBJECT;
typedef struct _DRIVER_OBJECT {
  CSHORT             Type;
  CSHORT             Size;
  PDEVICE_OBJECT     DeviceObject;
  ULONG              Flags;
  PVOID              DriverStart;
  ULONG              DriverSize;
  PVOID              DriverSection;
  PDRIVER_EXTENSION  DriverExtension;
  UNICODE_STRING     DriverName;
  PUNICODE_STRING    HardwareDatabase;
  PFAST_IO_DISPATCH  FastIoDispatch;
  PDRIVER_INITIALIZE DriverInit;
  PDRIVER_STARTIO    DriverStartIo;
  PDRIVER_UNLOAD     DriverUnload;
  PDRIVER_DISPATCH   MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1];
} DRIVER_OBJECT, *PDRIVER_OBJECT;
 
NTSTATUS vikingdrv2DeviceControl(PDEVICE_OBJECT, PIRP Irp) {
        auto stack = IoGetCurrentIrpStackLocation(Irp);
        switch (stack->Parameters.DeviceIoControl.IoControlCode) {
            case IOCTL_number1: {
                auto data = (ThreadData*)stack->Parameters.DeviceIoControl.Type3InputBuffer;
            }
            ...
        }
    }
NTSTATUS vikingdrv2DeviceControl(PDEVICE_OBJECT, PIRP Irp) {
        auto stack = IoGetCurrentIrpStackLocation(Irp);
        switch (stack->Parameters.DeviceIoControl.IoControlCode) {
            case IOCTL_number1: {
                auto data = (ThreadData*)stack->Parameters.DeviceIoControl.Type3InputBuffer;
            }
            ...
        }
    }
NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath) {
        //调度例程 dispatch routine
        DriverObject->MajorFunction[IRP_MJ_CREATE] = vikingdrv2CreateClose;
        DriverObject->MajorFunction[IRP_MJ_CLOSE] = vikingdrv2CreateClose;
        DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = vikingdrv2DeviceControl; # 这
    }
NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath) {
        //调度例程 dispatch routine
        DriverObject->MajorFunction[IRP_MJ_CREATE] = vikingdrv2CreateClose;
        DriverObject->MajorFunction[IRP_MJ_CLOSE] = vikingdrv2CreateClose;
        DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = vikingdrv2DeviceControl; # 这
    }
#define IOCTL_PRIORITY_BOOSTER_SET_PRIORITY CTL_CODE(VIKINGDRV2_DEVICE, \
0x800, METHOD_NEITHER, FILE_ANY_ACCESS)
 
struct ThreadData {
    ULONG ThreadId;
    int Priority;
};
#define IOCTL_PRIORITY_BOOSTER_SET_PRIORITY CTL_CODE(VIKINGDRV2_DEVICE, \
0x800, METHOD_NEITHER, FILE_ANY_ACCESS)
 
struct ThreadData {
    ULONG ThreadId;
    int Priority;
};
 
 
UNICODE_STRING devName = RTL_CONSTANT_STRING(L"\\Device\\vikingdrv2"); // 驱动名
    UNICODE_STRING symLink = RTL_CONSTANT_STRING(L"\\??\\vikingdrv2"); // symlink
    PDEVICE_OBJECT DeviceObject;
    NTSTATUS status = IoCreateDevice(
        DriverObject,        // 自定义的驱动对象
        0,                   
        & devName,            //  device name,
        FILE_DEVICE_UNKNOWN,    // device type,
        0,                    // characteristics flags,
        FALSE,               
        & DeviceObject        // 输出指针位置
    );
    if (!NT_SUCCESS(status)) {
        KdPrint(("Failed to create device object (0x%08X)\n", status));
        return status;
    }
UNICODE_STRING devName = RTL_CONSTANT_STRING(L"\\Device\\vikingdrv2"); // 驱动名

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 7
支持
分享
最新回复 (1)
雪    币: 6307
活跃值: (3837)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
ObDereferenceObject这个都不用吗?还有我记得800是微软用的啊
2022-12-9 22:41
0
游客
登录 | 注册 方可回帖
返回
//