pcap_loop调用pcap_read_linux_mmap_v3循环捕获数据,此时程序已经进入正常嗅探过程,而我们应该重点关注的点应该是在这之前的启动过程。
整体了解之后发现一切都是围绕着socket展开,这个socket和以往纯应用层tcp/udp的socket不一样,它将Ethernet、ip、tcp层的数据都暴露出来,被称作原始套接字。
libpcap/tcpdump就是用原始套接字来捕获网卡数据,围绕着原始套接字又做了丰富的功能。本文抛开libpcap/tcpdump,用原始套接字实现了一个收和一个发。
#include
#include
#include
#include
#include
#include
#include
#include
#include
void printf_hex(char *data, int len, int count);
int main(int argc,char *argv[]) {
int sock_raw_fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if(sock_raw_fd < 0){
perror("socket");
return -1;
}
unsigned char buf[1024] = {0};
int len = recvfrom(sock_raw_fd, buf, sizeof(buf), 0, NULL, NULL);
printf_hex(buf,len,16);
return 0;
}
void printf_hex(char *data, int len, int count)
{
printf("start data=%p _pDataLen=%d", data,len);
int i = 0;
printf("\n");
for(i = 0; i < len; i++)
{
if(data[i] < 0x10) {
printf("0x0%x, ", data[i]);
} else {
printf("0x%x, ", data[i]);
}
if((!((i + 1) %count)) && (i > 0))
{
printf("\n");
}
}
printf("\n");
printf("\n");
printf("end _pData\n");
return;
}
上面的代码编译执行后会抓一个数据包并打印出来,同时用wireshark进行抓包,可以在抓包中发现打印的数据,并且是从链路层开始打印的。如果想获取ip,端口和网卡等信息,直接读数据即可,很多系统调用可能也是利用原始socket开发。
#include
#include
#include
#include
#include
#include
#include
#include
#include
void printf_hex(char *data, int len, int count);
int main(int argc,char *argv[]) {
int sock_raw_fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if(sock_raw_fd < 0){
perror("socket");
return -1;
}
unsigned char buf[14] = {0};//6+6+2
// int len = recvfrom(sock_raw_fd, buf, sizeof(buf), 0, NULL, NULL);
// printf_hex(buf,len,16);
struct sockaddr_ll sll;
struct ifreq req;
strncpy(req.ifr_name, "ens33", IFNAMSIZ);
if(ioctl(sock_raw_fd, SIOCGIFINDEX, &req) == -1){
perror("ioctl");
close(sock_raw_fd);
return -1;
}
bzero(&sll,sizeof(sll));
sll.sll_ifindex = req.ifr_ifindex;
buf[0]=0x00;
buf[1]=0x0c;
buf[2]=0x29;
buf[3]=0xbf;
buf[4]=0xfc;
buf[5]=0xef;
int len = sendto(sock_raw_fd, buf, sizeof(buf), 0, (struct sockaddr *)&sll, sizeof(sll));
if(len == -1){
perror("sendto");
return -1;
}
return 0;
}
void printf_hex(char *data, int len, int count)
{
printf("start data=%p _pDataLen=%d", data,len);
int i = 0;
printf("\n");
for(i = 0; i < len; i++)
{
if(data[i] < 0x10) {
printf("0x0%x, ", data[i]);
} else {
printf("0x%x, ", data[i]);
}
if((!((i + 1) %count)) && (i > 0))
{
printf("\n");
}
}
printf("\n");
printf("\n");
printf("end _pData\n");
return;
}
用tcpdump抓包会找到此包,如下图所示。
原始socket可以做很多事情,网上有篇文章讲如何用原始socket窃取ftp明文的用户名密码用ping命令发回。我想到的最有意思的也就是去做各种侦听伪造。哈哈哈。就像有一篇文章写的这个是骇客初级知识。tcpdump的最基本原理其实已经懂了,后面其实想把重心放在ffmpeg上,但也真心不希望这个是libpcap/tcpdump的最后一篇文章。