Linux抓包程序
来源:互联网
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/ip.h>
#include <string.h>
#include <netdb.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/if_ether.h>
#include <net/ethernet.h>
void die(char *why, int n)
{
perror(why);
exit(n);
}
int do_promisc(char *nif, int sock )
{
struct ifreq ifr;
strncpy(ifr.ifr_name, nif,strlen(nif)+1);
if((ioctl(sock, SIOCGIFFLAGS, &ifr) == -1)) //获得flag
{
die("ioctl", 2);
}
ifr.ifr_flags |= IFF_PROMISC; //重置flag标志
if(ioctl(sock, SIOCSIFFLAGS, &ifr) == -1 ) //改变模式
{
die("ioctl", 3);
}
return 0;
}
//修改网卡成PROMISC(混杂)模式
/* =============================================================================================================下面是实现捕获和分析UDP协议数据包的函数定义
=============================================================================================================*/
void udp_protocol_packet_callback( u_char *packet_content)
{
struct udphdr *udp_protocol;
// UDP协议数据变量
u_short source_port;
// 源端口号
u_short destination_port;
// 目的端口号
udp_protocol = (struct udphdr*)(packet_content + 14+20);
// 获得UDP协议数据内容
source_port = ntohs(udp_protocol->source);
// 获得源端口号
destination_port = ntohs(udp_protocol->dest);
// 获得目的端口号
printf("---------- UDP Protocol (Transport Layer) ----------\n");
printf("Source port:%d\n", source_port);
printf("Destination port:%d\n", destination_port);
switch (destination_port)
//根据端口号判断应用层协议类型
{
case 138:
printf("NETBIOS Datagram Service\n");
break;
// 端口号为138,表示上层协议为NETBIOS 数据报服务
case 137:
printf("NETBIOS Name Service\n");
break;
// 端口号为137,表示上层协议为NETBIOS 名字服务
case 139:
printf("NETBIOS session service\n");
break;
// 端口号为139,表示上层协议为NETBIOS 会话服务
case 53:
printf("name-domain server \n");
break;
// 端口号为53,表示上层协议为域名服务
case 4000:
printf("QQ server \n");
break;
case 1863:
printf("MSN server \n");
break;
case 9001:
printf("OTHERS \n");
break;
default:
printf("NOT WELL-KNOWN PROTOCOL.\n");
break; //其他没有分析
}
} /* =============================================================================================================下面是实现捕获和分析TCP协议数据包的函数定义
=============================================================================================================
*/
void tcp_protocol_packet_callback( u_char *packet_content)
{
struct tcphdr *tcp_protocol;
// TCP协议数据变量
u_short source_port;
// 源端口号
u_short destination_port;
// 目的端口号
tcp_protocol = (struct tcphdr*)(packet_content + 14+20);
// 获得UDP协议数据内容
source_port = ntohs(tcp_protocol->source);
// 获得源端口号
destination_port = ntohs(tcp_protocol->dest);
// 获得目的端口号
printf("---------- TCP Protocol (Transport Layer) ----------\n");
printf("Source port:%d\n", source_port);
printf("Destination port:%d\n", destination_port);
switch (destination_port)
//根据端口号判断应用层协议类型
{
case 7:
printf("ECHO server \n");
break;
case 21:
printf("FTP server \n");
break;
case 23:
printf("TELNET server \n");
break;
case 25:
printf("SMTP server \n");
break;
case 53:
printf("DNS server \n");
break;
case 80:
printf("HTTP server \n");
break;
case 2049:
printf("NFS server \n");
break;
case 6667:
printf("IRCD server \n");
break;
default:
printf("NOT WELL-KNOWN PROTOCOL.\n");
break; //其他没有分析
}
}
/*
=============================================================================================================
下面是分析IP协议的函数的定义
=============================================================================================================
*/
void ip_protocol_packet_callback( u_char *packet_content)
{
struct iphdr *ip_protocol; // IP协议变量
printf("---------- IP Protocol (Network Layer) ----------\n");
ip_protocol = (struct iphdr*)(packet_content + 14); //获得IP协议数据内容
printf("Protocol:%d\n", ip_protocol->protocol); //获得协议类型
switch (ip_protocol->protocol) // 根据协议类型判断
{
case IPPROTO_TCP:
printf("The Transport Layer Protocol is TCP\n");
break;
/* 上层协议为TCP协议 */
case IPPROTO_UDP:
printf("The Transport Layer Protocol is UDP\n");
break;
/* 上层协议为UDP协议 */
case IPPROTO_ICMP:
printf("The Transport Layer Protocol is ICMP\n");
break;
/* 上层协议为ICMP协议 */
case IPPROTO_IGMP:
printf("The Transport Layer Protocol is IGMP\n");
break;
default:
break;
}
printf("TCP pkt :FORM:[%s]\n",inet_ntoa(*(struct in_addr*)&(ip_protocol->saddr)));
printf("TCP pkt :TO: [%s]\n",inet_ntoa(*(struct in_addr*)&(ip_protocol->daddr)));
switch (ip_protocol->protocol)
{
case IPPROTO_TCP:
tcp_protocol_packet_callback(packet_content);
break;
case IPPROTO_UDP:
udp_protocol_packet_callback(packet_content);
break;
default:
break;
}
}
/*
=============================================================================================================
下面是分析以太网协议的回调函数的定义
=============================================================================================================
*/
void ethernet_protocol_packet_callback( u_char *packet_content)
{
u_short ethernet_type; /* 以太网类型 */
struct ether_header *ethernet_protocol; /* 以太网协议变量 */
u_char *mac_string; /* 以太网地址 */
static int packet_number = 1;
printf("**************************************************\n");
printf("The %d packet is captured.\n", packet_number);
printf("-------- Ehternet Protocol (Link Layer) --------\n");
ethernet_protocol = (struct ether_header*)packet_content;
/* 获得以太网协议数据内容 */
printf("Ethernet type is :\n");
ethernet_type = ntohs(ethernet_protocol->ether_type);
/* 获得以太网类型 */
printf("%04x\n", ethernet_type);
switch (ethernet_type)
{
case 0x0800:
printf("The network layer is IP protocol\n");
break;
/* 上层协议为IP协议 */
case 0x0806:
printf("The network layer is ARP protocol\n");
printf("---------- ARP Protocol (Network Layer) ----------\n");
break;
/* 上层协议为ARP协议 */
case 0x8035:
printf("The network layer is RARP protocol\n");
printf("---------- RARP Protocol (Network Layer) ----------\n");
break;
/* 上层协议为RARP协议 */
default:
break;
}
switch (ethernet_type)
{
case 0x0800:
ip_protocol_packet_callback( packet_content);
break;
// 上层协议为IP协议,就调用分析IP 协议的函数,注意参数的传递
default:
printf("Mac Source Address is : \n");
mac_string = ethernet_protocol->ether_shost;
printf("%02x:%02x:%02x:%02x:%02x:%02x\n", *mac_string, *(mac_string + 1), *(mac_string + 2), *(mac_string + 3), *(mac_string + 4), *(mac_string + 5));
//获得源以太网地址
printf("Mac Destination Address is : \n");
mac_string = ethernet_protocol->ether_dhost;
printf("%02x:%02x:%02x:%02x:%02x:%02x\n", *mac_string, *(mac_string + 1), *(mac_string + 2), *(mac_string + 3), *(mac_string + 4), *(mac_string + 5));
// 获得目的以太网地址
break;
}
printf("**************************************************\n");
packet_number++;
}
char buf[40960];
int main()
{
struct sockaddr_in addr;
int sock;
int r = 0;
socklen_t len = 0;
u_char *ptemp;
if((sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) == -1) //建立socket ,man socket可以看到上面几个宏的意思
{
die("socket", 1);
}
do_promisc("eth0", sock); //eth0为网卡名称
system("ifconfig");
for(;;)
{
len = sizeof(addr);
if(recvfrom(sock,(char *)buf,sizeof(buf), 0, (struct sockaddr *)&addr,&len) > 0){
}
else{
continue;
}
//成功则返回接收到的字符数,失败返回-1,调试的时候可以增加一个输出r的语句判断是否抓到包
buf[r] = 0;
ptemp = buf;
ethernet_protocol_packet_callback(ptemp);//调用以太网协议的回调函数
usleep(1000);
// perror("dump");
}
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <