免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123下一页
最近访问板块 发新帖
查看: 12427 | 回复: 25

linux下在应用层如何修改数据包 [复制链接]

论坛徽章:
1
CU十二周年纪念徽章
日期:2013-10-24 15:41:34
发表于 2008-07-08 09:49 |显示全部楼层
10可用积分
小妹我这段时间正在研究如何修改数据包,有说用netfilter,还有说用netfilter_queue什么的,更有的说是用libcap,libnet,又有说说是用netfilter中的mangle,真不知道到底是什么???
我现在用libpcap抓到了一些IP包和ARP包,那怎么修改里面的东西呢??,谢谢了!!

最佳答案

查看完整内容

来自CU,回馈CU.最原始的办法:以下代码截取数据链路层的所有包,也就是任何包来了你网卡都收的到,然后把数据存放再buffer里,你可以任意修改buffer(如果修改,你必须考虑到校验和之类,否则发不出去,但是你要是想修改ip头,物理地址等?嘿嘿,那就随便了),修改之后再通过sendto函数发出去,不重复发送,如果包来自自己网卡,会答应won't send me again。未使用任何复杂的工具软件,比如iptables,netlib等,他们也是靠这个写出 ...

论坛徽章:
0
发表于 2008-07-08 09:49 |显示全部楼层

贴代码

来自CU,回馈CU.
最原始的办法:以下代码截取数据链路层的所有包,也就是任何包来了你网卡都收的到,然后把数据存放再buffer里,你可以任意修改buffer(如果修改,你必须考虑到校验和之类,否则发不出去,但是你要是想修改ip头,物理地址等?嘿嘿,那就随便了),修改之后再通过sendto函数发出去,不重复发送,如果包来自自己网卡,会答应won't send me again。
未使用任何复杂的工具软件,比如iptables,netlib等,他们也是靠这个写出来的。程序截取自自己的主程序,所以可能比较累赘
以下代码直接复制到文件helpo.c,编译方式:gcc -o helpo helpo.c,运行方式./helpo all

#include    <sys/socket.h>
#include    <sys/ioctl.h>
#include    <fcntl.h>
#include    <unistd.h>
#include    <netinet/if_ether.h>
#include    <netinet/ip.h>
#include    <netinet/udp.h>
#include    <netinet/tcp.h>
#include    <net/if.h>
#include    <netdb.h>
#include    <stdio.h>
#include    <stdlib.h>
#include    <string.h>
#include    <linux/if_packet.h>
#include    <linux/errno.h>

int socket_init(void);
int showpacket(unsigned char* buffer);
int sendfd,sock;
struct sockaddr_ll in_addr;
struct sockaddr_ll dest;
struct ifreq ifr;


int main(argc,argv)
&nbsp;&nbsp;&nbsp;int    argc;
&nbsp;&nbsp;&nbsp;char   *argv[];
{
&nbsp;&nbsp;&nbsp;socklen_t destlen;
&nbsp;&nbsp;&nbsp;struct ethhdr      *eth_hdr;
&nbsp;&nbsp;&nbsp;int    recv_len, socklen,flag = 0,on=1,n=0;
&nbsp;&nbsp;&nbsp;unsigned char   buffer[65536];
&nbsp;&nbsp;&nbsp;int myflag=0;
&nbsp;&nbsp;&nbsp;struct packet_mreq mr;
&nbsp;&nbsp;&nbsp;int state=0;
&nbsp;&nbsp;&nbsp;int recv_buf_len,buflen;
&nbsp;&nbsp;&nbsp;int i=0;
&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;memset(&mr,0,sizeof(mr));
&nbsp;&nbsp;&nbsp;socklen=sizeof(struct sockaddr_ll);
&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;if(argc < 2)
&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("\n invalid argument!! \n");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(0);
&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;sock = socket_init();
&nbsp;&nbsp;sendfd=socket(PF_PACKET,SOCK_RAW,htons(ETH_P_ALL));
&nbsp;&nbsp;
&nbsp;&nbsp;strcpy(ifr.ifr_name,"eth0");
&nbsp;&nbsp;ioctl(sendfd,SIOCGIFINDEX,&ifr);
&nbsp;&nbsp;mr.mr_ifindex=ifr.ifr_ifindex;
&nbsp;&nbsp;mr.mr_type=PACKET_MR_PROMISC;
&nbsp;&nbsp;if(setsockopt(sendfd,SOL_PACKET,PACKET_ADD_MEMBERSHIP,&mr,sizeof(mr))==-1)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror(" can not set to promisc");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(0);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;if(strcmp(argv[1], "all") == 0)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;flag = 0;
&nbsp;&nbsp;&nbsp;else if(strcmp(argv[1], "debug") == 0)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;flag = 1;
&nbsp;&nbsp;&nbsp;else {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("\n wrong argument!!\n");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(0);
&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;while(1)
&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;memset(&dest, 0x0, socklen);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;memset(&in_addr, 0x0, socklen);   
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;recv_len = recvfrom(sock, buffer, sizeof(buffer), 0,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(struct sockaddr *)&in_addr, &socklen);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;showpacket(buffer);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(in_addr.sll_pkttype==PACKET_OUTGOING){printf("won't send me again;\n");continue;}&nbsp;&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;&nbsp;&nbsp;  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dest.sll_family=AF_PACKET;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dest.sll_ifindex =ifr.ifr_ifindex;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dest.sll_halen=htons(ETH_HLEN);     
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;memmove(&dest.sll_addr,buffer,sizeof(buffer[0])*8);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;n=sendto(sendfd,buffer,recv_len,0,(struct sockaddr*)&dest,sizeof(dest));
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(" send n=%d\n",n);

&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;return 0;
}

int socket_init()
{
&nbsp;&nbsp;&nbsp;struct    ifreq    ifr;
&nbsp;&nbsp;&nbsp;int   sock;
&nbsp;&nbsp;&nbsp;memset(&ifr, 0x0, sizeof(struct ifreq));
&nbsp;
&nbsp;&nbsp;&nbsp;if((sock = socket(PF_PACKET, SOCK_RAW, htons(0x0003))) < 0)
&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror(" socket ");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(0);
&nbsp;&nbsp;&nbsp;}
&nbsp;
&nbsp;&nbsp;&nbsp;strcpy(ifr.ifr_name, "eth0");
&nbsp;&nbsp;&nbsp;if(ioctl(sock, SIOCGIFFLAGS, &ifr) == -1)
&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror("siocgifflags");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(0);
&nbsp;&nbsp;&nbsp;}
&nbsp;
&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;ifr.ifr_flags |= IFF_PROMISC;
&nbsp;&nbsp;&nbsp;if(ioctl(sock, SIOCSIFFLAGS, &ifr) == -1)
&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror("fejwaio?");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(0);
&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;return sock;
}

int showpacket(unsigned char* buffer)
{
&nbsp;&nbsp;&nbsp;int i=0;
&nbsp;&nbsp;&nbsp;unsigned char buff[50];
&nbsp;&nbsp;&nbsp;memmove(buff,buffer,50);  
&nbsp;&nbsp;&nbsp;for(i=0;i<50;i++)
&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;if(i==25)printf("\n");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("%2x ",buff[i]);
&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;printf("\n");
}





[ 本帖最后由 hijohnny 于 2008-7-15 22:53 编辑 ]

论坛徽章:
0
发表于 2008-07-08 10:00 |显示全部楼层
netfilter是哪一层的?

论坛徽章:
0
发表于 2008-07-08 10:14 |显示全部楼层
修改数据包,最好使用netfilter,netfilter是linux内核协议栈的一部分,可以在包在协议栈的传递过程中
加上hook,控制包的走向

论坛徽章:
0
发表于 2008-07-08 10:17 |显示全部楼层
netfilter是网络层,我认为IP和ARP包本身很难修改,因为内核采用tcp/ip协议是kernel控制的。
通过linux里面的kernel parameter,也就是说/etc/sysctl.conf里可能能够修改里面一些有限的东西。比如说队列、MTU等,但是这应该不算修改包本身,只是修改发包和通讯的一些方式而已。

论坛徽章:
1
CU十二周年纪念徽章
日期:2013-10-24 15:41:34
发表于 2008-07-08 12:58 |显示全部楼层
我在网上搜时有人说用libpcap和libnet,不知道可不可以修改

论坛徽章:
0
发表于 2008-07-08 14:53 |显示全部楼层
可以使用libpcap来捕捉,然后通知内核丢弃被捕捉的包,然后把修改以后的包用libnet再发出去。我试过,可以用的。如果不要求性能的话这种方法就够了,可以使用python来进行快速开发。如果需要保证性能,那就最好用netfilter,或者是iptables mangle也行。

论坛徽章:
0
发表于 2008-07-08 14:56 |显示全部楼层
小MM又做坏事!
做坏事最好用netfilter

论坛徽章:
1
CU十二周年纪念徽章
日期:2013-10-24 15:41:34
发表于 2008-07-08 15:20 |显示全部楼层
6楼的哥哥能否说得详细点呢,怎么通知内核呢,怎么修改呢,哥哥能贴一下代码吗?谢谢了!!!

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
发表于 2008-07-08 16:46 |显示全部楼层
应用层修改的话好像可以用setsockopt
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

SACC2021中国系统架构师大会

【数字转型 架构重塑】2021年5月20日-22日第十三届中国系统架构师大会将在云端进行网络直播。

大会为期3天的议程,涉及20+专场,近120个主题,完整迁移到线上进行网络直播对会议组织来说绝非易事;但考虑到云端会议的直播形式可以实现全国各地技术爱好者的参与,也使ITPUB作为技术共享交流平台得到更好的普及,我们决定迎难而上。
http://sacc.it168.com/


大会官网>>
  

北京盛拓优讯信息技术有限公司. 版权所有 16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP