Chinaunix

标题: netfilter内核修改点东西,可以出钱,有能力的希望可以帮助下我 [打印本页]

作者: yywx1314    时间: 2016-05-04 19:53
标题: netfilter内核修改点东西,可以出钱,有能力的希望可以帮助下我
netfilter下要获取http请求的相关参数,从SKB里获取http的请求相关内容,不需要写什么勾子什么的,只要告诉我怎么从skb里获取到http的内容就行了,可以出钱请人帮写代码,有能力的希望留下联系方式,谢谢了。
作者: Godbach    时间: 2016-05-04 22:08
回复 1# yywx1314

LZ 觉得难点在于什么。skb 都可以拿到,那就按照 skb->data 然后自己一点一点取数据就行了。

看一下置顶精华帖中构造 skb 的帖子,无非就是取出 iphdr,然后再取出 tcphdr,然后再解析出 tcp payload。然后解析出payload 中最开始的 GET /XXX 的数据就 OK 了。


   
作者: yywx1314    时间: 2016-05-04 22:33
解析出 tcp payload这里是难点,我怎么都解析不出这里
作者: yywx1314    时间: 2016-05-04 22:33
我是centos7,内核是3.10.0
作者: yywx1314    时间: 2016-05-04 22:34
Godbach 发表于 2016-05-04 22:08
回复 1# yywx1314

LZ 觉得难点在于什么。skb 都可以拿到,那就按照 skb->data 然后自己一点一点取数据就 ...


前辈可以给个具体的实现代码吗?
作者: Godbach    时间: 2016-05-04 22:46
回复 5# yywx1314

解析 iphdr 你知道怎么获取吗?


   
作者: yywx1314    时间: 2016-05-04 23:12
Godbach 发表于 2016-05-04 22:46
回复 5# yywx1314

解析 iphdr 你知道怎么获取吗?

struct sk_buff *sk = NULL;
sk = skb_copy(skb, GFP_ATOMIC);
struct iphdr *iph = ip_hdr(sk);
struct tcphdr *tcph;
char * payload = NULL;
tcph = (void*)iph + iph->ihl * 4;
if (iph->protocol == IPPROTO_TCP)
        {

        int daddr = iph->daddr;
        int dport = tcph->dest;
        int port = ntohs(dport);
        if (likely(port == 80)) {
                if (0 != skb_linearize(skb)) {
                                return NF_ACCEPT;
                }

                payload = skb->data + 40
                pr_warn("plyload数据 %s\n", payload);//我这里输出的好像不对,是乱码,而且每次刷新都不一样

        }
}


我是这样的,你看对吗?
作者: yywx1314    时间: 2016-05-04 23:13
Godbach 发表于 2016-05-04 22:46
回复 5# yywx1314

解析 iphdr 你知道怎么获取吗?


前辈,加个Q吧,我的QQ:五八74九7
作者: Godbach    时间: 2016-05-04 23:37
回复 7# yywx1314

                payload = skb->data + 40
                pr_warn("plyload数据 %s\n", payload);//我这里输出的好像不对,是乱码,而且每次刷新都不一样


通过 tcph 取出 payload,不要用 skb->data + 40。你怎么保证一定是 40 bytes 之后就是 payload 呢。

送你一行代码试试
  1. unsigned char *tcp_appdata = (unsigned char *) tcph + (tcph->doff << 2);
复制代码

作者: Godbach    时间: 2016-05-04 23:38
回复 8# yywx1314

六位 qq 号,很流弊的样子。


   
作者: yywx1314    时间: 2016-05-05 00:42
Godbach 发表于 2016-05-04 23:38
回复 8# yywx1314

六位 qq 号,很流弊的样子。

加我一下吧大哥,有问题我好问你
作者: yywx1314    时间: 2016-05-05 01:12
pr_warn("tcp_appdata数据 %s\n", tcp_appdata);这样输出的是乱码,而且只有一点点,感觉也不是
pr_warn("tcp_appdata数据 %s\n", &tcp_appdata);这样输出的也是一点点乱码
pr_warn("tcp_appdata数据 %s\n", *tcp_appdata);这样直接机子启动不了,哪出问题了?
到底要怎么访问得到这个变量呢?
作者: yywx1314    时间: 2016-05-05 01:12
Godbach 发表于 2016-05-04 23:38
回复 8# yywx1314

六位 qq 号,很流弊的样子。

你PM下我你的联系方式吧,我加你行不?
作者: Godbach    时间: 2016-05-05 01:38
回复 11# yywx1314

你的 qq 号不对啊。


   
作者: Godbach    时间: 2016-05-05 01:42
回复 7# yywx1314

用下面的方式取 iph, tcph 和 payload:
  1. struct iphdr *iph = ip_hdr(skb);
  2. tcph = (struct tcphdr *)((u_int32_t *)iph + iph->ihl);
  3. unsigned char *tcp_appdata = (unsigned char *) tcph + (tcph->doff << 2);
复制代码

作者: Godbach    时间: 2016-05-05 01:44
回复 12# yywx1314


pr_warn("tcp_appdata数据 %s\n", tcp_appdata);这样输出的是乱码,而且只有一点点,感觉也不是
pr_warn("tcp_appdata数据 %s\n", &tcp_appdata);这样输出的也是一点点乱码
pr_warn("tcp_appdata数据 %s\n", *tcp_appdata);这样直接机子启动不了,哪出问题了?


你得知道 tcp_appdata 是什么类型的数据,然后选择正确的打印方式。tcp_appdata 从通常意义上来讲,不要直接理解为 string。一个 byte 一个 byte 的打印出来(可以打印一段长度的),不要想当然的当成 string。
   
作者: yywx1314    时间: 2016-05-05 01:55
我的QQ对的,五八7四九7
作者: yywx1314    时间: 2016-05-05 01:58
Godbach 发表于 2016-05-05 01:44
回复 12# yywx1314

我知道了,我的QQ搞了主显帐号,现在可以加了,你加一下
作者: yywx1314    时间: 2016-05-05 02:22
还是没有搞定,不知道问题出在哪
作者: philarlala    时间: 2016-05-05 10:34
打印16进制的,可以跟抓包的16进制对比一下,如果正确的话,再把16进制转换成字符串就好了
作者: philarlala    时间: 2016-05-05 10:43
有一些是不可见字符的,16进制能对上就是行了,是要提取http 头部的内容吗?可以根据关键字以及http头部格式的特点进行截取,
作者: philarlala    时间: 2016-05-05 10:44
好像http头部的字段都是\r\n来隔开的吧,16进制就是0d 0a了,你自己抓包看看特点就好截取了
作者: Godbach    时间: 2016-05-05 11:11
本帖最后由 Godbach 于 2016-05-05 11:11 编辑

回复 20# philarlala

嗯,对的。最开始最好打印 16 进制,或者按照 char %c 打印。

   
作者: Godbach    时间: 2016-05-05 11:12
回复 18# yywx1314

把你的完整代码贴出来吧。QQ 讨论没有论坛参与的人多。


   
作者: yywx1314    时间: 2016-05-05 11:47
全部代码如下
        int i;
        struct sk_buff *sk = NULL;
        sk = skb_copy(skb, GFP_ATOMIC);
        struct iphdr *iph = ip_hdr(sk);//获取ip头指针
        struct tcphdr *tcph;//tcp头指针
        char * payload = NULL;
        tcph = (struct tcphdr *)((u_int32_t *)iph + iph->ihl);;//获取tcp开始位置
        if (iph->protocol == IPPROTO_TCP)//截获的是TCP类型的包
        {

                int daddr = iph->daddr;
                int dport = tcph->dest;
                int port = ntohs(dport);
                if (likely(port != 80)) {
                        //return NF_ACCEPT; //忽略不是远程 80 端口的包
                        pr_warn("非80端口%d\n", port);
                }else {
                        pr_warn("我是80端口 %d\n", port);
                        if (0 != skb_linearize(skb)) {
                                return NF_ACCEPT;
                        }
                        unsigned char *tcp_appdata = (unsigned char *) tcph + (tcph->doff << 2);
                        for(i=0;i<sizeof(tcp_appdata);i++){
                                pr_warn("%02x", *(tcp_appdata + i));//这里打印出来的全是00,也不知道问题出在哪
                        }
               
                        if(0 == strncmp(tcp_appdata, "GET", 3)) {
                                pr_warn("tcp_appdata数据 %s\n", "GET浏览");

                        }
                }

        }
作者: yywx1314    时间: 2016-05-05 11:49
philarlala 发表于 2016-05-05 10:43
有一些是不可见字符的,16进制能对上就是行了,是要提取http 头部的内容吗?可以根据关键字以及http头部格式 ...


是的,我需要提取http 头部的内容
作者: Godbach    时间: 2016-05-05 12:48
回复 25# yywx1314


                        pr_warn("我是80端口 %d\n", port);
                        if (0 != skb_linearize(skb)) {
                                return NF_ACCEPT;
                        }

红色的代码先去掉吧。

                        unsigned char *tcp_appdata = (unsigned char *) tcph + (tcph->doff << 2);
                        for(i=0;i<sizeof(tcp_appdata);i++){
                                pr_warn("%02x", *(tcp_appdata + i));//这里打印出来的全是00,也不知道问题出在哪
                        }   


这个地方不能用 sizeof 的。要计算一下 tcp payload 的长度。

话说你对 ip 和 tcp header 中一些关于长度的字段了解吗。还有 skb 的结构,你了解多少。
作者: philarlala    时间: 2016-05-05 12:58
sizeof(tcp_appdata)获取到的是指针的长度,不是指针指向的字符串的长度,一般用strlen 回复 25# yywx1314


   
作者: Godbach    时间: 2016-05-05 13:03
回复 28# philarlala

更合适的做法是,ip_total_len - ip_hdr_len - tcp_hdr_len 来计算 payload。不要假设 payload 一定是 string。


   
作者: philarlala    时间: 2016-05-05 13:41
嗯嗯,有可能payload 中有\0,strlen获取就不完整了回复 29# Godbach


   
作者: yywx1314    时间: 2016-05-05 13:45
真的太感谢楼上二次,我是第一次接触这个,实在是不好意思了




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2