首页 > 其他分享 >逆向 | 驱动IRP通信模板

逆向 | 驱动IRP通信模板

时间:2024-05-16 19:42:19浏览次数:18  
标签:逆向 DbgPrintEx LEVEL IRP ERROR DPFLTR ID 模板 pIrp

逆向 | 驱动IRP通信模板

踩了很多坑,比如说IoCreateDevice以后要删除,符号链接也要在卸载的时候删除啥的。
反正存个模板在这儿下次就能套了:

#include <ntddk.h>
#include <stdio.h>
#include <stdlib.h>

// 0-2047是保留的,可以用2048-4095
#define OPER1 CTL_CODE(FILE_DEVICE_UNKNOWN, 3001, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define OPER2 CTL_CODE(FILE_DEVICE_UNKNOWN, 3002, METHOD_BUFFERED, FILE_ANY_ACCESS)

PDEVICE_OBJECT g_pDeviceObj = NULL;
VOID DriverUnload(PDRIVER_OBJECT DriverObject) {
    (DriverObject);
    
    // 删除符号链接
    UNICODE_STRING SymbolicLinkName;
    RtlInitUnicodeString(&SymbolicLinkName, L"\\??\\MyTestDriver");
    IoDeleteSymbolicLink(&SymbolicLinkName);
    // 删除设备
    IoDeleteDevice(g_pDeviceObj);
    DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "DriverUnload~\r\n");
    
}

NTSTATUS IrpCreateProc(PDEVICE_OBJECT pDevice, PIRP pIrp) {
    (pDevice);
    // 处理自己的业务
    DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[info] IrpCreateProc~\r\n");
    // 设置返回状态
    pIrp->IoStatus.Status = STATUS_SUCCESS;   // getlasterror()
    pIrp->IoStatus.Information = 0;            // 返回给r3多少数据
    IoCompleteRequest(pIrp, IO_NO_INCREMENT);
    return STATUS_SUCCESS;
}

NTSTATUS IrpCloseProc(PDEVICE_OBJECT pDevice, PIRP pIrp) {
    (pDevice);
    // 处理自己的业务
    DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[info] IrpCloseProc~\r\n");
    // 设置返回状态
    pIrp->IoStatus.Status = STATUS_SUCCESS;   // getlasterror()
    pIrp->IoStatus.Information = 0;            // 返回给r3多少数据
    IoCompleteRequest(pIrp, IO_NO_INCREMENT);
    return STATUS_SUCCESS;
}

NTSTATUS IrpDeviceProc(PDEVICE_OBJECT pDevice, PIRP pIrp) {
    (pDevice);
    // 处理自己的业务
    DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[info] IrpDeviceProc~\r\n");
    NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
    PIO_STACK_LOCATION pIrpStack;
    ULONG uIoControlCode;
    PVOID pIoBuffer;
    ULONG uInLength;
    ULONG uOutLength;
    
    // 初始化输入输出缓冲区
    UCHAR ReadBuf[1024] = { 0 };
    UCHAR WriteBuf[] = "hello Mz1! ";

    // 获取IRP数据
    pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
    // 获取控制码
    uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
    // 获取缓冲区地址(输入和输出缓冲区都是一个)
    pIoBuffer = pIrp->AssociatedIrp.SystemBuffer;
    // r3 发送数据的长度
    uInLength = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
    // r0 发送数据的长度
    uOutLength = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;

    // 根据操作码决定操作
    switch (uIoControlCode) {
    case OPER1:
        DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[info] OPER1\r\n");
        // 接收&输出数据
        DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "       接收字节数: %d \r\n", uInLength);
        DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "       输出字节数: %d \r\n", uOutLength);
        // read
        memcpy(ReadBuf, pIoBuffer, uInLength);
        DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "       recv: %s \r\n", ReadBuf);
        // write
        memcpy(pIoBuffer, WriteBuf, sizeof(WriteBuf));
        // set status
        pIrp->IoStatus.Information = sizeof(WriteBuf);
        status = STATUS_SUCCESS;
        break;
    case OPER2:
        DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[info] OPER2\r\n");
        pIrp->IoStatus.Information = 0;
        status = STATUS_SUCCESS;
        break;
    }




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

NTSTATUS DriverEntry(
    _In_ PDRIVER_OBJECT     DriverObject,
    _In_ PUNICODE_STRING    RegistryPath
){
    (RegistryPath);
    DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "DriverEntry~\r\n");
    DriverObject->DriverUnload = DriverUnload;

    PDEVICE_OBJECT pDeviceObj = NULL;
    // 创建设备对象名称,这个名字是给r0看的,要挂到树上
    UNICODE_STRING Devicename;
    RtlInitUnicodeString(&Devicename, L"\\Device\\MyDevice");

    // 创建设备
    NTSTATUS status = IoCreateDevice(
        DriverObject,    // 当前设备属于哪个驱动对象
        0,
        &Devicename,    // 设备对象的名称
        FILE_DEVICE_UNKNOWN,
        FILE_DEVICE_SECURE_OPEN,
        FALSE,
        &pDeviceObj         // [out]设备对象指针
    );
    if (status != STATUS_SUCCESS) {
        DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[err] IoCreateDevice~\r\n");
        return status;
    }
    g_pDeviceObj = pDeviceObj;    // 复制一份全局对象
    // 设置交互数据方式
    pDeviceObj->Flags |= DO_BUFFERED_IO;
    // 创建符号链接名称
    UNICODE_STRING SymbolicLinkName;
    // r3: CreateFile "\\\\.\\MyTestDriver"
    RtlInitUnicodeString(&SymbolicLinkName, L"\\??\\MyTestDriver");
    // 创建符号链接
    status = IoCreateSymbolicLink(&SymbolicLinkName, &Devicename);
    if (status != STATUS_SUCCESS) {
        DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[err] IoCreateSymbolicLink~\r\n");
        return status;
    }
    // 设置派遣函数
    DriverObject->MajorFunction[IRP_MJ_CREATE] = IrpCreateProc;
    DriverObject->MajorFunction[IRP_MJ_CLOSE] = IrpCloseProc;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IrpDeviceProc;
    
    return STATUS_SUCCESS;
}

r3部分:

// r3proj.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <Windows.h>
#include <winioctl.h>

// 0-2047是保留的,可以用2048-4095
#define OPER1 CTL_CODE(FILE_DEVICE_UNKNOWN, 3001, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define OPER2 CTL_CODE(FILE_DEVICE_UNKNOWN, 3002, METHOD_BUFFERED, FILE_ANY_ACCESS)

HANDLE g_hDevice;

DWORD IoControl(DWORD dwIoCode, PVOID InBuff, DWORD InBuffLen, PVOID OutBuff, DWORD OutBuffLen) {
    DWORD dw = 0;
    // 设备句柄/操作码/输入缓冲区地址/长度/输出缓冲区地址/输出缓冲区长度/返回长度/指向OVERLAPPED此处为NULL
    DeviceIoControl(g_hDevice, dwIoCode, InBuff, InBuffLen, OutBuff, OutBuffLen, &dw, NULL);
    return dw;
}



int main()
{
    // 打开Device
    // \\\\.\\MyTestDriver
    g_hDevice = CreateFile(L"\\\\.\\MyTestDriver", GENERIC_READ|GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
    DWORD err = GetLastError();
    printf("err: %d \n", err);
    if (g_hDevice != INVALID_HANDLE_VALUE) {
        printf("CreateFile ok \n");
    }
    else {
        printf("error \n");
        return -1;
    }
    // 测试通信
    UCHAR InBuffer[1024] = "hihihihihihihihihihihihiashdasda";
    UCHAR OutBuffer[1024] = { 0 };
    DWORD ret = IoControl(OPER1, InBuffer,  sizeof(InBuffer), OutBuffer, sizeof(OutBuffer));
    
    
    printf("r3 recv[%d]: `%s` \n", ret, OutBuffer);
    CloseHandle(g_hDevice);

    printf("Over ok \n");
    return 0;
}


标签:逆向,DbgPrintEx,LEVEL,IRP,ERROR,DPFLTR,ID,模板,pIrp
From: https://www.cnblogs.com/Mz1-rc/p/18196603

相关文章

  • 微信开发-主动推送模板消息给特定用户
    其实也比较简单,设置模板后推送即可,具体官方说明文档如下:接口调用请求说明http请求方式:POSThttps://api.weixin.qq.com/cgi-bin/template/del_private_template?access_token=ACCESS_TOKENPOST数据说明如下:{"template_id":"Dyvp3-Ff0cnail_CDSzk1fIc6-9lOkxsQE7ex......
  • C++模板编程-enable_if
    std::enable_if的使用对于重载的函数或者函数模板的选择上,编译器内部有一个自己的规则,并不是简单粗暴的对函数就优先选择,对函数模板就靠后选择替换失败并不是一个错误(SFINAE):SubstitutionFailureIsNotAnError,SFINAE看成是C++语言的一种特性或者说一种模板设计中要遵循的......
  • 【iOS逆向与安全】iOS远程大师:通过H5后台远程查看和协助iPhone设备
    前言在移动设备测试和远程协助的过程中,能够远程查看和协助iPhone设备是一项非常实用的功能。为了解决这一需求,我开发了一款名为iOS远程大师的产品,允许用户通过H5后台界面查看和协助越狱或非越狱的iPhone设备。本文将详细介绍iOS远程大师的开发过程和技术实现。一、技术实现整......
  • ansible自定义模板部署apache服务
    使用Ansible来部署Apache服务是一个很好的选择,因为它可以自动化部署过程,确保所有的服务器上都有相同的配置。以下是一个简单的步骤指南,展示如何使用Ansible来部署Apache服务:1创建角色目录首先,在/etc/ansible/roles下创建apache目录:mkdir-p/etc/ansible/roles/apache2......
  • Ubuntu 24.04 LTS x86_64 OVF (sysin) - VMware 虚拟机模板
    Ubuntu24.04LTSx86_64OVF(sysin)-VMware虚拟机模板Ubuntu24.04LTS(GNU/Linux6.8.0-31-genericx86_64)请访问原文链接:Ubuntu24.04LTSx86_64OVF(sysin)-VMware虚拟机模板,查看最新版。原创作品,转载请保留出处。作者主页:sysin.orgUbuntu24.04LTS(GNU/Li......
  • Rocky Linux 9.3 x86_64 OVF (sysin) - VMware 虚拟机模板
    RockyLinux9.3x86_64OVF(sysin)-VMware虚拟机模板以社区方式驱动的企业Linux,RHEL100%1:1兼容免费发行版请访问原文链接:RockyLinux9x86_64OVF(sysin)-VMware虚拟机模板,查看最新版。原创作品,转载请保留出处。作者主页:sysin.orgRockyLinux9.3(5.14.0-36......
  • NSSCTF round#22逆向
    NSSCTFround#22逆向1.wp要及时写不然忘光光2.赛题分文件夹放ezcrypt下载下来是python打包的exe,解包出pyc用pycdc反编译看一下嗯不认识BEFORE_WITH命令。丢到gpt4o里看看还蛮准确的,和作者提供的源码一样。不过对填充的处理不对,原程序是填充'\x00'。不过比自己硬看好太多......
  • P3366 【模板】最小生成树
    链接:https://www.luogu.com.cn/problem/P3366模板题:kruskal代码:核心是对边的排序,遍历,选择。#include<iostream>#include<vector>#include<algorithm>#include<math.h>#include<sstream>#include<string>#include<string.h>#include<......
  • 【django学习-28】列表界面模板下载与上传文件
    前言,我们在实际项目开发过程中,经常有列表界面,有上传功能,并且支持先下载模板,后上传1.实现效果与前端展示<formmethod="post"enctype="multipart/form-data"action="/depart/multi/">{%csrf_token%}<divclass="form-group"><inputtyp......
  • NPOI读取模板文件生成Excel
    前不久实现了用NPOI组件替代Microsoft.Office.Interop.Excel原生组件实现导出数据到Excel的需求,其中踩了几个坑,这里记录一下。不能使用wps创建模板文件不能使用一个文件流,对已存在Excel文件进行修改NPOI中sheet、row、cell都是以0作为起始序号,Office原生组件是以1作为起始序......