内核态提取URL

1461阅读 0评论2009-12-18 ubuntuer
分类:LINUX

昨天在和dreamice大哥聊应用层防火墙的时候,问了些比较白痴的问题....比如内核态获取URL...呵呵 今天实现了下发现也不是很难...参考了ipp2p那么多协议的分析...好了不废话了....
http.c

CODE:
#include
#include
#include

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

MODULE_LICENSE("GPL");
MODULE_AUTHOR("kenthy@163.com");

static struct nf_hook_ops os_attack_ops;

void check_http(const unsigned char* haystack, unsigned int len)
{
   char  url[100];
   char* host_tmp;
   char* url_tmp = url;

   if(len>3)
    {
    #if 0
     printk("len is %d\n", len);
     printk("%s\n", haystack);
    #endif

     if(memcmp(haystack, "GET", 3)==0)   
       {
         host_tmp = strstr(haystack,"Host:");
         while(*host_tmp!='\r')
             *url_tmp++ = *host_tmp++;

         *url_tmp='\0';  
         printk("http connect----%s\n",url);
       }
   }
}

unsigned int
os_attack_detect(unsigned int hooknum,
                 struct sk_buff** skb,
                 const struct net_device *in,
                 const struct net_device *out,
                 int (*okfn)(struct sk_buff*))
{
    struct iphdr *iph = NULL;
    struct tcphdr *tcph = NULL;
    struct tcphdr _otcph;
    unsigned char* haystack;
    int hlen;


    iph = ip_hdr(*skb);
    haystack =(char*)iph+(iph->ihl*4);
    hlen = ntohs(iph->tot_len)-(iph->ihl*4);

    if (iph->protocol == IPPROTO_TCP) {
        tcph = skb_header_pointer(*skb, ip_hdrlen(*skb), sizeof(_otcph), &_otcph);
      
        haystack += tcph->doff*4;
        hlen -= tcph->doff*4;
     
        check_http(haystack, hlen);
    }

    return NF_ACCEPT;
}

static int __init init(void)
{
    int ret;
    os_attack_ops.hook = os_attack_detect;
    os_attack_ops.hooknum = NF_IP_LOCAL_OUT;
    os_attack_ops.pf = PF_INET;
    os_attack_ops.priority = NF_IP_PRI_FIRST;

    ret = nf_register_hook(&os_attack_ops);
    if (ret < 0) {
        printk("http detect:can't register http detect hook!\n");
        return ret;
    }
    printk("insmod http detect module\n");
    return 0;
}

static void __exit fini(void)
{
    nf_unregister_hook(&os_attack_ops);
    printk("remove http detect module.\n");
}

module_init(init);
module_exit(fini);

Makefile

CODE:
obj-m := http.o

KDIR := /lib/modules/$(shell uname -r)/build/
PWD := $(shell pwd)

all:module

module:
        $(MAKE) -C $(KDIR) M=$(PWD) modules

clean:
        rm -rf *.ko *.mod.c *.o Module.* modules.* .*.cmd .tmp_versions

脱掉外套ip头,在脱掉内衣tcp头,ok现在就是好色的你想要的了...也就是haystack了

CODE:
  haystack += tcph->doff*4;
  hlen -= tcph->doff*4;
  check_http(haystack, hlen);

这里的haystack就是上层的一些数据...

用wireshark抓包看到http请求如下:

CODE:
"GET /u2/76292/ HTTP/1.1\r\n"
     "Accept: */*\r\n"
     "Accept-Language: zh-cn\r\n"
     "Accept-Encoding: gzip, deflate\r\n"
     "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; CIBA; TheWorld)\r\n"
     "Host:blog.chinaunix.net\r\n"
     "Connection: Keep-Alive\r\n\r\n";

我这里只是提取了Host你可以根据自己需要提取别的...

if(memcmp(haystack, "GET", 3)==0) //这里并没有使用端口判断...直接看头三个char是不是GET,这里也可以||memcmp(haystack, "POST", 4)   
       {
/*就是找到Host,所以Accept  Accept-Language Host的顺序不是固定的,所以别根据第几行,也就是多少个'\n'来找
   至于strstr函数这个不是这里考虑的,我也没看strstr的源码,你们自己也可以写kmp来找到Host*/
     host_tmp = strstr(haystack,"Host:");

       /*这里就是将Host:blog.chinaunix.net赋给url_tmp了*/
         while(*host_tmp!='\r')
             *url_tmp++ = *host_tmp++;

         *url_tmp='\0';  
         printk("http connect----%s\n",url);
       }



ok其实也蛮简单的,弄清楚了的话...   有个帖子是url过滤的..   今天先休息下,明天基于这个url提取再做个URL过滤的....
代码在CentOS5.3 2.6.18上测试通过了

图片是测试结果

[ 本帖最后由 ubuntuer 于 2009-12-17 16:19 编辑 ]




(136.86 KB) 2009-12-17 16:17
 
点击在新窗口查看全图
CTRL+鼠标滚轮放大或缩小
 
可以看看我的cu的帖子
 
上一篇:c语言抓取网页数据
下一篇:netlink+netfilter+BloomFilter内核态过滤URL