Socket_Kernel_Module 04

本文介绍如何在Linux内核中统计特定IP间交换的TCP SYN数据包数量,通过修改内核代码并添加Hook函数实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2.3 统计SYN包数

修改IPHeader是发送方的修改,这里讲修改接收方。

由Kernel_TCPIP知道,内核的入口函数为netif_rx(), IP层入口函数为ip_rcv(), tcp层入口函数为tcp_v4_rcv(), 因此统计TCP的SYN包数,就在net/ipv4/tcp_ipv4.c中的tcp_v4_rcv()添加Hook函数即可

2.3.1修改tcp_v4_rcv

int (*myHook_TCPSYN)(struct sk_buff*) == 0;

int tcp_v4_rcv(struct sk_buff* skb)

{

     //....

     if( !tcp_prequeue(sk, skb))

     {

         if(myHook_TCPSYN)

         {    

             myHook_TCPSYN(skb);

         }

     }

 

}

//结尾添加

EXPORT_SYMBOL(myHook_TCPSYN);

int myHook_TCPSYN_count = 0;

EXPORT_SYMBOL(myHook_TCPSYN_count); //内核共享数据

然后要重新编译内核

 

2.3.2 myHook_TCPSYN.c

#define __KERNEL__

#define MODULE

#include <linux/module.h>

#include <linux/skbuff.h>

#include <linux/tcp.h>

#include <linux/ip.h>

#include <linux/proc_fs.h>

#include <net/ip.h>

//big-endian和little-endian转换,big用在网络中,而linux中是little

#define u32toValue(x) ((__u32)( /

                                  (((__u32)(x) & (__u32)0x000000ffUL) << 24) | /

                                  (((__u32)(x) & (__u32)0x0000ff00UL) <<   8) | /

                                  (((__u32)(x) & (__u32)0x00ff0000UL) >>   8) | /

                                  (((__u32)(x) & (__u32)0xff000000UL) >> 24) ))

extern int myHook_TCPSYN_count;

extern int (*myHook_TCPSYN)(struct sk_buff*);

 

//转为可打印地址

static void IpAddressToString(unsigned long i, char* s)

{

     unsinged long j1, j2,j3,j4;

     j1 = (i & 0x000000FF);

     j2 = (i & 0x0000FF00)>>8;

     j3 = (i & 0x00FF0000)>>16;

     j4 = (i & 0xFF000000)>>24;

     sprintf(s, "%u.%u.%u.%u", j4,j3,j2,j1); //注意顺序

}

 

//hook函数的实现

int myHook_TCPSYN_impl(struct sk_buff* skb)

{

    strcut iphdr* iph;

    strcut tcphdr* th;

    char szSourceIP[50], szTargetIP[50];

 

    iph = skb->nh.iph;

    if( iph->protocol == IPPROTO_TCP)  //判断是否是TCP

    {

         th = skb->h.th;

         if( th->syn)            //判断是否是SYN包

         {

             IpAddressToString(u32toValue(skb->nh.iph->saddr), szSourceIP);

             IpAddressToString(u32toValue(skb->nh.iph->daddr), szTargetIP);

             if( strcmp(szSourceIP, "192.168.0.1") == 0 && //判断源地址是否是自己, 根据实践地址修改

                 strcmp(szTargetIP, "192.168.0.2") == 0) //判断目的地址, 根据实践地址修改

             {

                 myHook_TCPSYN_count++;

                 if( myHook_TCPSYN_count > 0x0fffff) myHook_TCPSYN_count = 0;

                 printk(%s --> %s ===> SYNcount=%d/n", szSourceIP, szTargetIP, myHook_TCPSYN_count);

             }

         }

    }     

    return 0;

}

 

static int init_hook( void )
{
    myHook_TCPSYN = myHook_TCPSYN_impl;  //后门函数指向了真正的实现函数

    printk("myHook_TCPSYN installed");        //表示加载成功
    return 0;
}

 

static int exit_hook(void)

{

    myHook_TCPSYN= 0;                    //后门函数清0
    printk("myHook_TCPSYN removed/n"); //表示卸载成功

    return 0;
}

 

MODULE_LICENSE("GPL"); //表示采用的开放协议

module_init(init_hook);     //为当加载Module时,自动调用init_hook
module_exit(exit_hook);   //当卸载Module时,自动调用exit_hook;

 

2.3.3 Makefile和加载卸载

如上个例子,此处省略,

加载运行后,就看到/var/log/message中的纪录了

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值