一个简单的sniffer抓包程序
来源:互联网 发布:用友软件破解版 编辑:程序博客网 时间:2024/05/01 19:31
#include "unp.h"#include <linux/if_ether.h>/* Ethernet header are are always exactly 14 bytes */#define SIZE_ETHERNET14/* Ethernet address are 6 bytes */#define ETHER_ADDR_LEN6#define LINE_WIDTH16/*+---------+---------+---------------------------------------------------+| Version | Header | Type of Service | Total Length || | Length | | || (4bit) | (4bit) | (8bit) | (16bit) |+---------+---------+-----------------+--------+------------------------+| Identification | Flag | Fragment Offset || | | || (16bit) | (3bit) | (13bit) |+-------------------+-----------------+--------+------------------------+| Time to Live | Protocol | Header Checksum || | | || (8bit) | (8bit) | (16bit) |+-------------------+-----------------+---------------------------------+| Source IP Address || || (32bit) |------------------------------------------------------------------------+| Destination IP Address || || (32bit) |+-----------------------------------------------------------------------+| Options || || (32bit) |+-----------------------------------------------------------------------+| Data || || ... |+-----------------------------------------------------------------------+*/struct sniff_ip {u_charip_vhl;/* version &0xf0 >> 4 | header len &0x0f*/ unsigned char ip_tos;/* type of service*/ unsigned short ip_len;/* total length */ unsigned short ip_id;/* Identification */ unsigned short ip_off;/* flag offset field */#define IP_REF0x800/* reserved flagment flag */#define IP_DF0x400/* dont fragment flag */#define IP_MF0x200/* more fragment flag */#define IP_OFFMASK0x1fff/* mask for fragment bits */ unsigned char ip_ttl;/* time to live */ unsigned char ip_protocol;/* protocol */ unsigned short ip_cksum;/* checksum */ struct in_addr ip_src;/* source address */ struct in_addrip_dst;/* destination address */};#define IP_HL(ip)((ip->ip_vhl) & 0x0f)#define IP_V(ip)(((ip->ip_vhl) & 0xf0) >> 4)/*Ehernet II帧结构:帧头:6个字节的目的MAC地址和6字节的源MAC地址。2字节的类型字段,表示封装在数据中的数据类型。数据:46-1500字节的数据字段。帧尾 :4字节的帧效验序列。+-------+--------------+----------------------------------------+------+| D-MAC | S-MAC | TYPE | DATA | CRC || 6B | 6B | 2B | | 4B |+-------+--------------+----------------------------------------+------+ */struct sniff_ethernet {u_charether_dhost[ETHER_ADDR_LEN];/* destination host address */u_charether_shost[ETHER_ADDR_LEN];/* source host address */u_short ether_type;/* IP? ARP? RARP? etc */};/* TCP 格式 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| | || Source Port | Destination Port || | |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| || Sequence Number || |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| || Acknowledgment NUmber || |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Data | |U|A|P|R|S|F| ||offset| Reserved |R|C|S|S|Y|I| Window || | |G|K|H|T|N|N| |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| | || Checksum | Urgent Pointer || | |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| | || Options | Padding || | |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| || Data || |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+*/typedef u_int tcp_seq;struct sniff_tcp {u_shortth_sport;/* source port */u_short th_dport;/* destination port */tcp_seqth_seq;/* sequence number */tcp_seq th_ack;/* acknowledgment number */u_char th_offx2;/* data offset, reserved , 因为保留位全为0,被拆成两部分*/#define TH_OFF(th) (((th->th_offx2) & 0xf0) >> 4) u_charth_flags;/* flags */#define TH_FIN0x01 #define TH_SYN0x02 #define TH_RST0x04 #define TH_PUSH0x08 #define TH_ACK0x10 #define TH_URG 0x20#define TH_ECE0x40#define TH_CWR0x80#define TH_FLAGS(TH_FIN | TH_SYN | TH_RST | TH_ACK | TH_URG | TH_ECE | TH_CWR) u_shortth_win;/* window */u_short th_sum;/* checksum */u_short th_urp;/* urgent pointer */};/* * 打印一行(16个字节): offset hex ascii * * 00000 47 45 54 20 2f 20 48 54 54 50 2f 31 2e 31 0d 0a GET / HTTP/1.1.. */voidprint_hex_ascii_line(const u_char *payload, ssize_t len, ssize_t offset) {ssize_ti;intgap;const u_char*ch;/* offset */printf("%05d\t", offset);/* hex */ch = payload;for (i = 0; i < len; ++i) {printf("%02x ", *ch++);if (i == LINE_WIDTH / 2 - 1) printf("%2c ", ' ');}if (len < LINE_WIDTH / 2) printf("%2x ", ' ');/* 不够8个字节时打印空格 */if (len < LINE_WIDTH) {gap = LINE_WIDTH - len;while(gap-- > 0) printf("%2c ", ' ');}printf("\t");/* ascii */ch = payload;for (i = 0; i < len; ++i) {if (isprint(*ch))printf("%c", *ch);elseprintf("%c", '.');++ch;}printf("\n");}/* * 打印有效载荷(避免打印二进制) */voidprint_payload(const u_char *payload, ssize_t len) {ssize_tlen_rem = len;ssize_tline_len;ssize_toffset= 0;const u_char*ptr = payload;if (len_rem == 0) {return;}/* 只有一行 */if (len <= LINE_WIDTH) {print_hex_ascii_line(ptr, len, offset);return;}/* data跨越多行 */for ( ; ; ) {printf("len_rem: %d offset : %d\n", len_rem, offset);if (len_rem <= LINE_WIDTH) {print_hex_ascii_line(ptr, len_rem, offset);break;}print_hex_ascii_line(ptr, LINE_WIDTH, offset);len_rem -= LINE_WIDTH;ptr += LINE_WIDTH;offset += LINE_WIDTH;}}voidgot_packet(const u_char *packet) {static int count= 1;/* packet counter *//* 声明指向分组的指针 */struct sniff_ethernet*ethernet;struct sniff_tcp*tcp;struct sniff_ip*ip;const u_char*p, *payload;ssize_t size_ip;ssize_t size_tcp;ssize_t size_payload;/* 有效载荷 */printf("\nPacket number %d:\n", count++);printf("\t源主机\t\t\t目标主机\n");ethernet = (struct sniff_ethernet *)packet;p = ethernet->ether_shost;printf("\t%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",p[6] & 0xff, p[7] & 0xff,p[8] & 0xff, p[9] & 0xff,p[10] & 0xff, p[11] & 0xff);p = ethernet->ether_dhost;printf("\t%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",p[0] & 0xff, p[1] & 0xff,p[2] & 0xff, p[3] & 0xff, p[4] & 0xff, p[5] & 0xff);ip = (struct sniff_ip *)(packet + SIZE_ETHERNET);size_ip = IP_HL(ip) * 4;if (size_ip < 20) {printf(" Invalid IP header length: %zu\n", size_ip);return;}printf("\tFrom:%s", inet_ntoa(ip->ip_src));printf("\tTo:%s\n", inet_ntoa(ip->ip_dst));switch(ip->ip_protocol) {case IPPROTO_TCP:printf("\tProtocl: TCP\n");break;case IPPROTO_UDP:printf("\tProtocl: UDP\n");return;case IPPROTO_ICMP:printf("\tProtocl: ICMP\n");return;case IPPROTO_IP:printf("\tProtocl: IP\n");return;case IPPROTO_RAW:printf("\tProtocl: RAW\n");return;default:printf("\tProtocl: Unknown\n");return;}/* * 只处理tcp *//* 定义和计算tcp head偏移 */tcp = (struct sniff_tcp *)(packet + SIZE_ETHERNET + size_ip);size_tcp = TH_OFF(tcp) * 4;if (size_tcp < 20) {printf("\tInvalid TCP header length:%zu bytes\n", size_tcp);return;}printf("\t源端口: %d\t\t目标端口:%d\n", tcp->th_sport, tcp->th_dport);/* 定义/计算有效载荷段偏移 */payload = (u_char *)(packet + SIZE_ETHERNET + size_ip + size_tcp); /* 计算tcp 载荷大小 */size_payload = ntohs(ip->ip_len) - (size_ip + size_tcp);/* * 打印有效载荷的长度 */if (size_payload > 0) {printf("\tPayload (%zu bytes): \n", size_payload);print_payload(payload, size_payload);}}/** PF_PACKET协议簇可以让一个应用程序把数据包变成似乎从网络层接收的样子* 但是没有办法抓到那些不是发向自己主机的包。* 正如我们前面看到的,网卡丢弃所有不含有主机MAC地址的数据包* 这是因为网卡处于非混杂模式,即每个网卡只处理源地址是它自己的帧!* 只有三个例外:* 如果一个帧的目的MAC地址是一个受限的广播地址(255.255.255.255)那么它将被所有的网卡接收:* 如果一个帧的目的地址是组播地址,那么它将被那些打开组播接收功能的网卡所接收;* 网卡如被设置成混杂模式,那么它将接收所有流经它的数据包*/intmain() { int sockfd; ssize_t n; u_char buf[MAXLINE]; if ((sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_IP))) < 0) { perror("create sockt"); exit(EXIT_FAILURE); }//抓包for ( ; ; ) {n = recvfrom(sockfd, buf, MAXLINE, 0, 0, 0);/******************************************* ** 14 6(dest)+6(source)+2(type or length) ** + ** 20 ip header ** + ** 8 icmp,tcp or udp header ** = 42 *********************************************/if (n < 42) {fprintf(stdout, "Incomplete header, packet corrupt.\n"); continue;}got_packet(buf);}return 0;}
说明: 此程序中的unp.h 是参考UNP这本书,但是只是简单的包含了socket必须的头文件以及几个出错打印函数。
参考: Unix Network Programming -v3
http://blog.csdn.net/linux_embedded/article/details/8836847
- 一个简单的sniffer抓包程序
- 一个简单的网络抓包程序
- Linux下sniffer抓包程序程序的实现
- 一个简单的抓ARP包程序分析
- Sniffer抓包教程
- 简单的抓包演示程序
- 最简单的抓包程序
- 一个简单的抓包代码
- Sniffer抓包软件学习
- Sniffer抓包中文教程
- Sniffer的完整代码,基于winpcap抓包统计吞吐量
- winpcap的一个小的抓包测试程序
- 使用winPcap(libpcap)实现的简单抓包程序
- 一个适用于windows和linux的抓包程序
- 一个适用于windows和linux的抓包程序
- 用sniffer抓icmp包来分析
- (图文)Sniffer抓包软件学习
- packet sniffer抓包软件使用体验
- fedora10安装libpcap
- 安装gcc 4.8以支持C++ 0x11
- 【OpenCV】访问图像中每个像素的值
- linux内核学习 进程表示
- ----------------------------------------------------------------------------------------------------
- 一个简单的sniffer抓包程序
- 中 lpk.dll 毒了 -_-
- C#开机自动启动软件
- 每天一指令
- 连连看算法(判断两个图是否可消除)
- LPCTSTR 类型
- 找源码的常用网站
- JAVA Swing.JTable.DefaultTableModel
- uva 10285 记忆化搜索