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中的纪录了