基于Filter-Hook Driver(使用ipfirewall.h)的IP过滤驱动

 

  IP过滤驱动可以广泛的应用于网络安全产品的研发,NDIS和TDI的驱动资料很多,有比较成熟的代码可以参考,但是使用IPFIREWALL.h开发的IP过滤驱动的资料非常少,这次自己做一个软件的时候参考VCKBASE上的一篇文章《开发Windows 2000/XP下的防火墙》(作者:Jesús O)的基础上,写了一个驱动,代码都做了详细的注释了,只要稍微有点驱动设计基础的都可以看得懂,我把自己的特殊的回调函数去掉了,保留了基本的完整框架,牛人就不需要看了,初学者都可以在此基础上继续快速开发。
1 SmatrixIPDiv.cpp文件
2  protocol.h头文件
3  SmatrixIPDiv.h头文件


*  Copyright (c)  2007 ,安全矩阵(Security Matrix)
*  All rights reserved.
*  
*  文件名称:SmatrixIPDiv.cpp
*  文件标识:S
*  摘    要:IP过滤驱动,利用ipfirewall捕获包、分析包、过滤包
*  开始时间:2006年12月26日
*/
extern 
" C "
{
    #include 
<stdio.h>
    #include 
<string.h>
    #include 
<stdlib.h>
    #include 
<ntddk.h>
    #include 
<ntddndis.h>
    #include 
<pfhook.h>
    #include 
<ndis.h>
    #include 
<ipfirewall.h>

}


#include 
" SmatrixIPDiv.h "
#include 
" protocol.h "

/ 自定义函数的声明 // /
// 关闭打开驱动函数
NTSTATUS DispatchCreateClose(PDEVICE_OBJECT pDevObj, PIRP pIrp);

// 驱动卸载函数
void  DriverUnload(PDRIVER_OBJECT pDriverObj);

// IO控制派遣函数(内核消息处理)
NTSTATUS DispatchIoctl(PDEVICE_OBJECT pDevObj, PIRP pIrp);


//  向过滤列表中添加一个过滤规则
NTSTATUS AddFilterToList(CIPFilter *  pFilter);

// 清除过滤列表
void  ClearFilterList();

//  注册钩子回调函数
NTSTATUS SetFilterFunction(IPPacketFirewallPtr filterFunction, BOOLEAN load);

// 包过滤函数
FORWARD_ACTION FilterPacket(unsigned  char   * PacketHeader,
                  unsigned 
char   * Packet, 
                  unsigned 
int  PacketLength, 
                  DIRECTION_E direction, 
                  unsigned 
int  RecvInterfaceIndex, 
                  unsigned 
int  SendInterfaceIndex);

// IP过滤器函数
FORWARD_ACTION IPFilterFunction(VOID          ** pData,
                    UINT         RecvInterfaceIndex,
                    UINT         
* pSendInterfaceIndex,
                    UCHAR         
* pDestinationType,
                    VOID         
* pContext,
                    UINT         ContextLength,
                    struct IPRcvBuf 
** pRcvBuf);
//  过滤列表首地址
struct CFilterList *  g_pHeader  =  NULL;


//  驱动内部名称和符号连接名称
#define DEVICE_NAME L " /Device/DevSMFltIP "
#define LINK_NAME L
" /DosDevices/DrvSMFltIp "

// 驱动入口函数
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegistryString)
{
    NTSTATUS status 
= STATUS_SUCCESS;

    
// 初始化各个派遣例程
    pDriverObj->MajorFunction[IRP_MJ_CREATE] = DispatchCreateClose;
    pDriverObj
->MajorFunction[IRP_MJ_CLOSE] = DispatchCreateClose;
    pDriverObj
->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctl;
    pDriverObj
->DriverUnload = DriverUnload;

        
// 创建、初始化设备对象
    
// 设备名称
    UNICODE_STRING ustrDevName;
    RtlInitUnicodeString(
&ustrDevName, DEVICE_NAME);
    
// 创建设备对象
    PDEVICE_OBJECT pDevObj;
    status 
= IoCreateDevice(pDriverObj, 
                
0,
                
&ustrDevName, 
                FILE_DEVICE_DRVFLTIP,
                
0,
                FALSE,
                
&pDevObj);
    
if(!NT_SUCCESS(status))
    
{
        
return status;
    }


        
// 创建符号连接名称
    
// 符号连接名称
    UNICODE_STRING ustrLinkName;
    RtlInitUnicodeString(
&ustrLinkName, LINK_NAME);
    
// 创建关联
    status = IoCreateSymbolicLink(&ustrLinkName, &ustrDevName);
    
if(!NT_SUCCESS(status))
    
{
        IoDeleteDevice(pDevObj);
        
return status;
    }

    
    
return STATUS_SUCCESS;
}



void  DriverUnload(PDRIVER_OBJECT pDriverObj)
{    
    
// 卸载过滤函数
    SetFilterFunction(IPFilterFunction,FALSE);
    
// 释放所有资源
    ClearFilterList();

    
// 删除符号连接名称
    UNICODE_STRING strLink;
    RtlInitUnicodeString(
&strLink, LINK_NAME);
    IoDeleteSymbolicLink(
&strLink);

    
// 删除设备对象
    IoDeleteDevice(pDriverObj->DeviceObject);
}


//  处理IRP_MJ_CREATE、IRP_MJ_CLOSE功能代码
NTSTATUS DispatchCreateClose(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
    pIrp
->IoStatus.Status = STATUS_SUCCESS;
//    pIrp->IoStatus.Information = 0;
    
// 完成此请求
    IoCompleteRequest(pIrp, IO_NO_INCREMENT);

    
return STATUS_SUCCESS;
}



//  I/O控制派遣例程
NTSTATUS DispatchIoctl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
    NTSTATUS status 
= STATUS_SUCCESS;

    
// 取得此IRP(pIrp)的I/O堆栈指针
    PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp);

    
// 取得I/O控制代码
    ULONG uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
    
// 取得I/O缓冲区指针和它的长度
    PVOID pIoBuffer = pIrp->AssociatedIrp.SystemBuffer;
    ULONG uInSize 
= pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
    
    
// 响应用户的命令
    switch(uIoControlCode)
    
{
    
case START_IP_HOOK:    // 开始过滤
        status = SetFilterFunction(IPFilterFunction,TRUE);
        
break;

    
case STOP_IP_HOOK:    // 停止过滤
        status = SetFilterFunction(IPFilterFunction,FALSE);
        
break;

    
case ADD_FILTER:    // 添加一个过滤规则
        if(uInSize == sizeof(CIPFilter))
            status 
= AddFilterToList((CIPFilter*)pIoBuffer);
        
else 
            status 
= STATUS_INVALID_DEVICE_REQUEST;
        
break;

    
case CLEAR_FILTER:    // 释放过滤规则列表
        ClearFilterList();
        
break;

    
default:
        status 
= STATUS_INVALID_DEVICE_REQUEST;
        
break;
    }

    
    
// 完成请求
    pIrp->IoStatus.Status = status;
    pIrp
->IoStatus.Information = 0;
    IoCompleteRequest(pIrp, IO_NO_INCREMENT);

    
return status;
}




// /
// 过滤列表

//  向过滤列表中添加一个过滤规则
NTSTATUS AddFilterToList(CIPFilter *  pFilter)
{
    
// 为新的过滤规则申请内存空间
    CFilterList* pNew = (CFilterList*)ExAllocatePool(NonPagedPool, sizeof(CFilterList));
    
if(pNew == NULL)
        
return STATUS_INSUFFICIENT_RESOURCES;

    
// 填充这块内存
    RtlCopyMemory(&pNew->ipf, pFilter, sizeof(CIPFilter));
    
    
// 连接到过滤列表中
    pNew->pNext = g_pHeader;
    g_pHeader 
= pNew;

    
return STATUS_SUCCESS;
}


//  清除过滤列表
void  ClearFilterList()
{
    CFilterList
* pNext;
    
// 释放过滤列表占用的所有内存
    while(g_pHeader != NULL)
    
{
        pNext 
= g_pHeader->pNext;
        
// 释放内存
        ExFreePool(g_pHeader);
        g_pHeader 
= pNext;
    }

}




//  包过滤函数
FORWARD_ACTION FilterPacket(unsigned  char   * PacketHeader,
                  unsigned 
char   * Packet, 
                  unsigned 
int  PacketLength, 
                  DIRECTION_E direction, 
                  unsigned 
int  RecvInterfaceIndex, 
                  unsigned 
int  SendInterfaceIndex)
{

    
// 提取IP头
    IPHeader* pIPHdr = (IPHeader*)PacketHeader;
    TCPHeader 
*pTCPHdr = NULL;
    UDPHeader 
*pUDPHdr = NULL;

    
if(pIPHdr->ipProtocol == 6)  // 是TCP协议
    {
        
// 提取TCP头
         pTCPHdr = (TCPHeader*)Packet;
        
// 我们接受所有已经建立连接的TCP封包
        if(!(pTCPHdr->flags & 0x02))
        
{
            
return FORWARD;
        }

    }


    
// 与过滤规则相比较,决定采取的行动
    CFilterList* pList = g_pHeader;
    
while(pList != NULL)
    
{
        
// 比较协议
        if(pList->ipf.protocol == 0 || pList->ipf.protocol == pIPHdr->ipProtocol)
        
{
            
// 查看源IP地址
            if(pList->ipf.sourceIP != 0 && 
                (pList
->ipf.sourceIP & pList->ipf.sourceMask) != pIPHdr->ipSource)
            
{
                pList 
= pList->pNext;
                
continue;
            }


            
// 查看目标IP地址
            if(pList->ipf.destinationIP != 0 && 
                (pList
->ipf.destinationIP & pList->ipf.destinationMask) != pIPHdr->ipDestination)
            
{
                pList 
= pList->pNext;
                
continue;
            }


            
// 如果是TCP封包,查看端口号
            if(pIPHdr->ipProtocol == 6)
            
{
                pTCPHdr 
= (TCPHeader*)Packet;
                
if(pList->ipf.sourcePort == 0 || pList->ipf.sourcePort == pTCPHdr->sourcePort)
                
{
                    
if(pList->ipf.destinationPort == 0 
                        
|| pList->ipf.destinationPort == pTCPHdr->destinationPort)
                    
{
                        
// 现在决定如何处理这个封包
                        if(pList->ipf.bDrop)
                            
return DROP;
                        
else
                            
return FORWARD;
                    }

                }

            }


            
// 如果是UDP封包,查看端口号
            else if(pIPHdr->ipProtocol == 17)
            
{
                pUDPHdr 
= (UDPHeader*)Packet;
                
if(pList->ipf.sourcePort == 0 || pList->ipf.sourcePort == pUDPHdr->sourcePort)
                
{
                    
if(pList->ipf.destinationPort == 0 
                        
|| pList->ipf.destinationPort == pUDPHdr->destinationPort)
                    
{
                        
// 现在决定如何处理这个封包
                        if(pList->ipf.bDrop)
                            
return DROP;
                        
else
                            
return FORWARD;
                    }

                }

            }

            
else 
            
{
                
// 对于其它封包,我们直接处理
                if(pList->ipf.bDrop)
                        
return DROP;
                    
else
                        
return FORWARD;
            }

        }


        
// 比较下一个规则
        pList = pList->pNext;
    }


    
// 我们接受所有没有注册的封包
    return FORWARD;
}


//  注册钩子回调函数
NTSTATUS SetFilterFunction(IPPacketFirewallPtr filterFunction, BOOLEAN load)
{
    
//{变量定义BEGIN}
    NTSTATUS status = STATUS_SUCCESS;           //内核状态
   
    NTSTATUS waitStatus 
= STATUS_SUCCESS;       //受信状态

    PDEVICE_OBJECT pDeviceObj 
= NULL;           //pDeviceObj变量将指向IP过滤驱动设备对象
    
    PFILE_OBJECT pFileObj 
= NULL;               //内核过滤器设备

    IP_SET_FIREWALL_HOOK_INFO filterData;        
//IP_SET_FIREWALL_HOOK_INFO结构
    
    UNICODE_STRING ustrFilterDriver;             
// IP过滤驱动的名称

    KEVENT event;                                
//
    
    IO_STATUS_BLOCK ioStatus;                    
//
   
    PIRP pIrp;                                   
//

    
//{变量定义END}

    
// 初始化IP过滤驱动的名称
    RtlInitUnicodeString(&ustrFilterDriver, DD_IP_DEVICE_NAME);
   
    
// 取得设备对象指针    
    status = IoGetDeviceObjectPointer(&ustrFilterDriver, STANDARD_RIGHTS_ALL, &pFileObj, &pDeviceObj);
    

    
if(!NT_SUCCESS(status))
    
{
        
return status;
    }


    
/// 使用到IP过滤驱动中设备对象的指针创建一个IRP///    
    
// 填充IP_SET_FIREWALL_HOOK_INFO结构

    filterData.FirewallPtr 
= filterFunction;
    filterData.Priority 
= 1;
    filterData.Add 
= load;

    
// 我们需要初始化一个事件对象。
    
// 构建IRP时需要使用这个事件内核对象,当IP过滤取得接受到此IRP,完成工作以后会将它置位

    KeInitializeEvent(
&event, NotificationEvent, FALSE);

    
// 为设备控制请求申请和构建一个IRP
    
    pIrp 
= IoBuildDeviceIoControlRequest(IOCTL_IP_SET_FIREWALL_HOOK,  // io control code
        pDeviceObj, 
        (PVOID) 
&filterData,
        sizeof(IP_SET_FIREWALL_HOOK_INFO),
        NULL,
        
0,
        FALSE,
        
&event,
        
&ioStatus);

    
if(NULL==pIrp)
    
{
        
// 如果不能申请空间得到pIrp,返回对应的错误代码
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    

    
    
/// 请求安装钩子回调函数/

    
// 发送此IRP到IP过滤驱动
    status = IoCallDriver(pDeviceObj, pIrp);

    
// 等待IP过滤驱动的通知
    if(status == STATUS_PENDING) 
    
{
        waitStatus
=KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
        
        
if (!NT_SUCCESS(waitStatus)) //受信状态不成功,返回
        {
            
return waitStatus;
        }


    }


    status 
= ioStatus.Status;


    
if(!NT_SUCCESS(status))//状态不成功,返回
    {
        
return status;
    }

   
/
    
    
// 清除内核资源/
    if(pFileObj != NULL)
        ObDereferenceObject(pFileObj);
    pDeviceObj 
= NULL;         //避免产生野指针
    pFileObj = NULL;            //避免产生野指针

    
return status;

}


// IP过滤器函数
FORWARD_ACTION IPFilterFunction(VOID          ** pData,
                    UINT         RecvInterfaceIndex,
                    UINT         
* pSendInterfaceIndex,
                    UCHAR         
* pDestinationType,
                    VOID         
* pContext,
                    UINT         ContextLength,
                    struct IPRcvBuf 
** pRcvBuf)
{
    FORWARD_ACTION result 
= FORWARD;

    unsigned 
char *packet = NULL;

    
int bufferSize = 0;

    struct IPRcvBuf 
*buffer =(struct IPRcvBuf **pData;
    
    PFIREWALL_CONTEXT_T fwContext 
= (PFIREWALL_CONTEXT_T)pContext;

    DIRECTION_E direction
=IP_RECEIVE;
    
    
//如果包指针不为空,IPRcvBuf中存在数据
    if(buffer != NULL)
    
{
        bufferSize 
= buffer->ipr_size;
        
        
while(buffer->ipr_next != NULL) //得到整个IPRcvBuf缓冲链中数据总长度
        {
            buffer 
= buffer->ipr_next;
            
            bufferSize 
+= buffer->ipr_size;
        }

        
        
//分配一个不分页的内存,将整个IPRcvBuf缓冲链放入其中
        packet = (unsigned char *) ExAllocatePool(NonPagedPool, bufferSize);
        
if(packet != NULL)
        
{
            IPHeader 
*ipp = (IPHeader *)packet;
            unsigned 
int offset = 0;
            
            buffer 
= (struct IPRcvBuf **pData;
            
            memcpy(packet, buffer
->ipr_buffer, buffer->ipr_size);   
            
            
while(buffer->ipr_next != NULL)
            
{     
                offset 
+= buffer->ipr_size;
                buffer 
= buffer->ipr_next;
                
                memcpy(packet 
+ offset, buffer->ipr_buffer, buffer->ipr_size);
            }

            
if (NULL != fwContext) 
            
{
                direction
=fwContext->Direction;
            }

            
else
            
{
                direction
=(DIRECTION_E)0;
            }


            
//调用包检测函数,通过返回FORWARD,否则返回DROP
            result = FilterPacket(packet,
                packet 
+ (ipp->ipHeaderLength * 4), 
                bufferSize 
- (ipp->ipHeaderLength * 4), 
                direction, 
                RecvInterfaceIndex, 
                (pSendInterfaceIndex 
!= NULL) ? *pSendInterfaceIndex : 0);
            
            
        }

        
        
    }

    
    
//释放分配的临时包缓存
    if(NULL != packet) ExFreePool(packet);
    
    
return result;
}


2  定义常见的封包结构信息
// 文件名称:protocol.h

typedef struct IPHeader 
{    UCHAR      ipHeaderLength:4;      // 头长度 
    UCHAR      ipVersion:4;          // 版本号 
    UCHAR     ipTOS;          // 服务类型 
    USHORT    ipLength;       // 封包总长度,即整个IP报的长度
    USHORT    ipID;          // 封包标识,惟一标识发送的每一个数据报
    USHORT    ipFlags;          // 标志
    UCHAR     ipTTL;          // 生存时间,就是TTL
    UCHAR     ipProtocol;     // 协议,可能是TCP、UDP、ICMP等
    USHORT    ipChecksum;     // 校验和
    ULONG     ipSource;       // 源IP地址
    ULONG     ipDestination;  // 目标IP地址
}
 IPPacket; 


typedef struct _TCPHeader
{
    USHORT            sourcePort;        
// 源端口号
    USHORT            destinationPort;    // 目的端口号
    ULONG            sequenceNumber;        // 序号
    ULONG            acknowledgeNumber;    // 确认序号
    UCHAR            dataoffset;        // 数据指针
    UCHAR            flags;            // 标志
    USHORT            windows;        // 窗口大小
    USHORT            checksum;        // 校验和
    USHORT            urgentPointer;        // 紧急指针
}
 TCPHeader;

typedef struct _UDPHeader
{
    USHORT            sourcePort;        
// 源端口号        
    USHORT            destinationPort;    // 目的端口号        
    USHORT            len;            // 封包长度
    USHORT            checksum;        // 校验和
}
 UDPHeader;
enum
  
{
    IPPROTO_IP                    
= 0,        // Dummy protocol for TCP.
    IPPROTO_HOPOPTS                = 0,        // IPv6 Hop-by-Hop options.  */
    IPPROTO_ICMP                = 1,        // Internet Control Message Protocol.  */
    IPPROTO_IGMP                = 2,        // Internet Group Management Protocol. */
    IPPROTO_IPIP                = 4,        // IPIP tunnels (older KA9Q tunnels use 94).  */
    IPPROTO_TCP                    = 6,        // Transmission Control Protocol.  */
    IPPROTO_EGP                    = 8,        // Exterior Gateway Protocol.  */
    IPPROTO_PUP                    = 12,        //    PUP protocol.  */
    IPPROTO_UDP                    = 17,        //    User Datagram Protocol.  */
    IPPROTO_IDP                    = 22,        //  XNS IDP protocol.  */
    IPPROTO_TP                    = 29,        //  SO Transport Protocol Class 4.  */
    IPPROTO_IPV6                = 41,        //    IPv6 header.  */
    IPPROTO_ROUTING                = 43,        //    IPv6 routing header.  */
    IPPROTO_FRAGMENT            = 44,        //    IPv6 fragmentation header.  */
    IPPROTO_RSVP                = 46,        //  Reservation Protocol.  */
    IPPROTO_GRE                    = 47,        //  General Routing Encapsulation.  */
    IPPROTO_ESP                    = 50,        // encapsulating security payload.  */
    IPPROTO_AH                    = 51,        // authentication header.  */
    IPPROTO_ICMPV6                = 58,        // ICMPv6.  */
    IPPROTO_NONE                = 59,        /* IPv6 no next header.  */
    IPPROTO_DSTOPTS                
= 60,        /* IPv6 destination options.  */
    IPPROTO_MTP                    
= 92,        /* Multicast Transport Protocol.  */
    IPPROTO_ENCAP                
= 98,        /* Encapsulation Header.  */
    IPPROTO_PIM                    
= 103,        /* Protocol Independent Multicast.  */
    IPPROTO_COMP                
= 108,        /* Compression Header Protocol.  */
    IPPROTO_RAW                    
= 255,        /* Raw IP packets.  */
    IPPROTO_MAX
  }
;
3   IP过滤驱动相关结构和宏定义
//  文件名称:SmatrixIPDiv.h
#ifndef __SMATRIXIPDIV_H__
#define __SMATRIXIPDIV_H__

//  自定义设备类型,在创建设备对象时使用
//  注意,自定义值的范围是32768-65535
#define FILE_DEVICE_DRVFLTIP   0x00654322

//  自定义的IO控制代码,用于区分不同的设备控制请求
//  注意,自定义值的范围是2048-4095
#define DRVFLTIP_IOCTL_INDEX   0x830

//
//  定义各种设备控制代码。分别是开始过滤、停止过滤、添加过滤规则、清除过滤规则
//  
#define START_IP_HOOK    CTL_CODE(FILE_DEVICE_DRVFLTIP, 
                DRVFLTIP_IOCTL_INDEX, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define STOP_IP_HOOK    CTL_CODE(FILE_DEVICE_DRVFLTIP, 
                DRVFLTIP_IOCTL_INDEX
+ 1 , METHOD_BUFFERED, FILE_ANY_ACCESS)
#define ADD_FILTER    CTL_CODE(FILE_DEVICE_DRVFLTIP, 
                DRVFLTIP_IOCTL_INDEX
+ 2 , METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define CLEAR_FILTER    CTL_CODE(FILE_DEVICE_DRVFLTIP, 
                DRVFLTIP_IOCTL_INDEX
+ 3 , METHOD_BUFFERED, FILE_ANY_ACCESS)

//  定义过滤规则的结构
struct CIPFilter
{
    USHORT protocol;        
// 使用的协议

    ULONG sourceIP;            
// 源IP地址
    ULONG destinationIP;        // 目标IP地址

    ULONG sourceMask;        
// 源地址屏蔽码
    ULONG destinationMask;        // 目的地址屏蔽码

    USHORT sourcePort;        
// 源端口号
    USHORT destinationPort;        // 目的端口号
    
    BOOLEAN bDrop;            
// 是否丢弃此封包
}
;

//  过滤列表
struct CFilterList
{
    CIPFilter ipf;        
// 过滤规则
    CFilterList* pNext;    // 指向下一个CFilterList结构
}
;

#endif 
//  __SMATRIXIPDIV_H__

          HHOOK g_hHook;
          HINSTANCE g_hinstDll;
          FARPROC pfMessageBoxA;
          
int  WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText,LPCTSTR lpCaption,UINT uType);
          BYTE OldMessageBoxACode[
5 ],NewMessageBoxACode[ 5 ];
          HMODULE hModule ;
          DWORD dwIdOld,dwIdNew;
          BOOL bHook
= false ;
          
void  HookOn();
          
void  HookOff();
          BOOL init();
LRESULT WINAPI MousHook(
int  nCode,WPARAM wParam,LPARAM lParam);
BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
                     )
{
    
switch (ul_reason_for_call)
    
{
        
case DLL_PROCESS_ATTACH:
            
if(!init())
            
{
                          MessageBoxA(NULL,
"Init","ERROR",MB_OK);
                          
return(false);
            }

        
case DLL_THREAD_ATTACH:
        
case DLL_THREAD_DETACH:
        
case DLL_PROCESS_DETACH:
                      
if(bHook) UnintallHook();  
                    
break;
    }

    
return TRUE;
}

LRESULT WINAPI Hook(
int  nCode,WPARAM wParam,LPARAM lParam) // 空的钩子函数
{
    
    
return(CallNextHookEx(g_hHook,nCode,wParam,lParam));
}

HOOKAPI2_API BOOL InstallHook()
// 输出安装空的钩子函数
{  
   g_hinstDll
=LoadLibrary("HookApi2.dll");
   g_hHook
=SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)Hook,g_hinstDll,0);
  
if (!g_hHook)
  
{
        MessageBoxA(NULL,
"SET ERROR","ERROR",MB_OK);
        
return(false);
   }

  
          
   
return(true);
}

HOOKAPI2_API BOOL UninstallHook()
// 输出御在钩子函数
{
  
    
return(UnhookWindowsHookEx(g_hHook));
}


BOOL init()
// 初始化得到MessageBoxA的地址,并生成Jmp XXX(MyMessageBoxA)的跳转指令
{
    hModule
=LoadLibrary("user32.dll");
    pfMessageBoxA
=GetProcAddress(hModule,"MessageBoxA");
    
if(pfMessageBoxA==NULL)
      
return false;
    _asm
    
{
        lea edi,OldMessageBoxACode
        mov esi,pfMessageBoxA
        cld
        movsd
        movsb
    }

    NewMessageBoxACode[
0]=0xe9;//jmp MyMessageBoxA的相对地址的指令
    _asm
    
{
        lea eax,MyMessageBoxA
        mov ebx,pfMessageBoxA
        sub eax,ebx
        sub eax,
5
        mov dword ptr [NewMessageBoxACode
+1],eax
    }

    dwIdNew
=GetCurrentProcessId(); //得到所属进程的ID
    dwIdOld=dwIdNew;
    HookOn();
//开始拦截
    return(true);
}


int  WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText,LPCTSTR lpCaption, UINT uType ) // 首先关闭拦截,然后才能调用被拦截的Api 函数
{   
    
int nReturn=0;
    HookOff();
    nReturn
=MessageBoxA(hWnd,"Hook",lpCaption,uType);
    HookOn();
    
return(nReturn);
}

void  HookOn()
{
    HANDLE hProc;
    dwIdOld
=dwIdNew;
    hProc
=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld);//得到所属进程的句柄
    VirtualProtectEx(hProc,pfMessageBoxA,5,PAGE_READWRITE,&dwIdOld);//修改所属进程中MessageBoxA的前5个字节的属性为可写
    WriteProcessMemory(hProc,pfMessageBoxA,NewMessageBoxACode,5,0);//将所属进程中MessageBoxA的前5个字节改为JMP 到MyMessageBoxA
    VirtualProtectEx(hProc,pfMessageBoxA,5,dwIdOld,&dwIdOld);//修改所属进程中MessageBoxA的前5个字节的属性为原来的属性
    bHook=true;
}

void  HookOff() // 将所属进程中JMP MyMessageBoxA的代码改为Jmp MessageBoxA
{
    HANDLE hProc;
    dwIdOld
=dwIdNew;
    hProc
=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld);
    VirtualProtectEx(hProc,pfMessageBoxA,
5,PAGE_READWRITE,&dwIdOld);
    WriteProcessMemory(hProc,pfMessageBoxA,OldMessageBoxACode,
5,0);
    VirtualProtectEx(hProc,pfMessageBoxA,
5,dwIdOld,&dwIdOld);
    bHook
=false;
}

// 测试文件:
int  APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     
int        nCmdShow)
{
    
    
if(!InstallHook()) 
    
{
        MessageBoxA(NULL,
"Hook Error!","Hook",MB_OK);
        
return 1;
    }

     MessageBoxA(NULL,
"TEST","TEST",MB_OK);//可以看见Test变成了Hook,也可以在其他进程中看见
    if(!UninstallHook()) 
    
{
        MessageBoxA(NULL,
"Uninstall Error!","Hook",MB_OK);
        
return 1;
    }

    
return 0;
}
 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值