您的位置:首页 > 理论基础 > 计算机网络

Linux网络数据捕获之原始套接字

2012-08-11 16:39 363 查看
处于一些目的,有时需要对到达网口的所有网络数据进行捕获,系统也提供了这样的接口,稍微懂网络编程的都知道SOCK_DGRAM、SOCK_STREAM,差不多就UDP、TCP之类的吧。但是还有一个很少用的叫SOCK_RAW,原始套接字,使用它你可以捕获网卡上的所有网络数据,当然这需要超级用户权限。贴个列子吧,网上摘的,具体出处忘了

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <linux/if_ether.h>
#include <linux/in.h>
#include <linux/if.h>
#include <linux/sockios.h>
#include <sys/socket.h>
#include <netpacket/packet.h>
#include <net/ethernet.h>        /* the L2 protocols */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#define BUFFER_MAX 2048

int main(int argc, char *argv[])
{

int sock, n_read;
char buffer[BUFFER_MAX];

struct sockaddr_ll sll;
struct ifreq ifstruct;

if((sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0)
{
perror( "create socket error");
return -1;
}

memset(&sll, 0, sizeof(sll));
sll.sll_family = PF_PACKET;
sll.sll_protocol = htons(ETH_P_ALL);

//get net card index ethx->index
strcpy(ifstruct.ifr_name, "eth0");
ioctl(sock, SIOCGIFINDEX, &ifstruct);
sll.sll_ifindex = ifstruct.ifr_ifindex;

//bind net card
if (bind(sock, (struct sockaddr *)&sll, sizeof(sll)) == -1)
{
perror("bind error:\n");
return -1;
}

while(1)
{
n_read = recvfrom(sock, buffer, 2048, 0, NULL, NULL);
if(n_read <= 0)
{
perror("recvfrom\n");
return -1;
}
//process packet
}
return 0;
}


其实原始套接字不仅可以捕获数据,也可以发送数据,而且是任意格式的数据,从MAC头到IP头之类的数据段都在自己的控制范围之内,什么ARP攻击、DDoS攻击之类的都离不开原始套接字吧,不过这些封包是重点,这里篇幅有限不涉及封包了吧,只介绍如何将数据发出去
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <linux/if_ether.h>
#include <linux/in.h>
#include <linux/if.h>
#include <linux/sockios.h>
#include <sys/socket.h>
#include <netpacket/packet.h>
#include <net/ethernet.h>        /* the L2 protocols */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#define BUFFER_MAX 2048

int main(int argc, char *argv[])
{
int sockfd;
int n_write;
int n_res;

struct sockaddr_ll sll;
struct ifreq ifstruct;

char buffer[BUFFER_MAX];
char MAC_BUFFER[ETH_ALEN]= {0x00,0x18,0x82,0xab,0xd2,0xf9};
char TYPE_BUFFER[2] = {0x88,0x66};

if((sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0)
{
perror("create socket error:");
return -1;
}
n_res = 0;
n_write = 0;

memset(&sll, 0, sizeof(sll));
sll.sll_family = PF_PACKET;
sll.sll_protocol = htons(ETH_P_ALL);

//get netcard interface index ethx->ifindex
strcpy(ifstruct.ifr_name, "eth0");
ioctl(sockfd, SIOCGIFINDEX, &ifstruct);
sll.sll_ifindex = ifstruct.ifr_ifindex;

//get the local netcard mac
strcpy(ifstruct.ifr_name, "eth0");
ioctl(sockfd, SIOCGIFHWADDR, &ifstruct);
memcpy(sll.sll_addr, ifstruct.ifr_ifru.ifru_hwaddr.sa_data, ETH_ALEN);
sll.sll_halen = ETH_ALEN;

//bind the netcard
if(bind(sockfd, (struct sockaddr *)&sll, sizeof(sll)) == -1)
{
perror("bind error:");
return -1;
}

//get the netcard work mode
memset(&ifstruct, 0, sizeof(ifstruct));
strcpy(ifstruct.ifr_name, "eth0");
if(ioctl(sockfd, SIOCGIFFLAGS, &ifstruct) == -1)
{
perror("iotcl error:");
return -1;
}

//set the netcard work mode
ifstruct.ifr_flags |= IFF_PROMISC;

if(ioctl(sockfd, SIOCSIFFLAGS, &ifstruct) == -1)
{
perror("iotcl()\n");
printf("Fun:%s Line:%d\n", __func__, __LINE__);
return -1;
}

memcpy(buffer,MAC_BUFFER,ETH_ALEN);
memcpy(buffer+6,sll.sll_addr,ETH_ALEN);
memcpy(buffer+12,TYPE_BUFFER,2);

while(1)
{
n_res = sendto(sockfd, buffer, 1024,
0, (struct sockaddr *)&sll, sizeof(sll));

if(n_res < 0)
{
perror("sendto error:");
return -1;
}

n_write += n_res;

if(n_write >= 2048 * 2560)
{
break;
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: