Linux系统有线网络抓包程序
来源:互联网 发布:无线网络破解软件 编辑:程序博客网 时间:2024/04/28 07:47
今天心血来潮,玩一玩linux抓包。思路如下:
1、使用raw socket接收网络数据;
2、先解析以太帧头,得到是IP还是ARP包;
3、再解析IP头,知道是UDP还是TCP;
4、再解析UDP、TCP,得到IP地址、端口号等信息。
注意事项:
1、网络传输使用大端字节序,对于如端口号、数据长度等字段,要使用ntohs做转换,否则结果不正确。
2、对于创建raw socket,不同参数得到的数据包不同,如传递ETH_P_IP则不会接收ARP、RARP包。
完整代码:
#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <stdarg.h>#include <netdb.h>#include <sys/ioctl.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/ip.h>#include <netinet/tcp.h>#include <netinet/udp.h>#include <netinet/in.h>#include <netpacket/packet.h>#include <net/if.h>#include <arpa/inet.h>#include <net/ethernet.h>#define BUFFER_SIZE 2048int debug_level = 0;#define _AUTHOR "Late Lee"#define _VERSION_STR "1.0"#define _DATE ""// 默认打印error等级enum{ MSG_ERROR = 0, MSG_WARNING, MSG_INFO, MSG_DEBUG, MSG_MSGDUMP, MSG_EXCESSIVE, };void ll_printf(int level, const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));void ll_printf(int level, const char *fmt, ...){ va_list ap; va_start(ap, fmt); if (debug_level >= level) {#ifdef CONFIG_DEBUG_SYSLOG if (wpa_debug_syslog) { vsyslog(syslog_priority(level), fmt, ap); } else {#endif /* CONFIG_DEBUG_SYSLOG */ //debug_print_timestamp();#ifdef CONFIG_DEBUG_FILE if (out_file) { vfprintf(out_file, fmt, ap); fprintf(out_file, "\n"); } else {#endif /* CONFIG_DEBUG_FILE */ vprintf(fmt, ap); printf("\n");#ifdef CONFIG_DEBUG_FILE }#endif /* CONFIG_DEBUG_FILE */#ifdef CONFIG_DEBUG_SYSLOG }#endif /* CONFIG_DEBUG_SYSLOG */ } va_end(ap);}void show_version(char* name){ printf("%s by %s, version: %s\n", name, _AUTHOR, _VERSION_STR);}const char* my_opt = "hvd:i:";void usage(char* name){ show_version(name); printf(" -h, short help\n"); printf(" -v, show version\n"); printf(" -d, debug level\n"); printf(" -i, ethernet device\n"); exit(0);}void dump(const char *buffer, int len){ int i, j, n; int line = 16; char c; unsigned char* buf = (unsigned char *)buffer; // 必须是unsigned char类型 n = len / line; if (len % line) n++; for (i=0; i<n; i++) { //printf("0x%08x: ", (unsigned int)(buf+i*line)); // linux ok printf("0x%8p: ", buf+i*line); // windows ok for (j=0; j<line; j++) { if ((i*line+j) < len) printf("%02x ", buf[i*line+j]); else printf(" "); } printf(" "); for (j=0; j<line && (i*line+j)<len; j++) { if ((i*line+j) < len) { c = buf[i*line+j]; printf("%c", c >= ' ' && c < '~' ? c : '.'); } else printf(" "); } printf("\n"); }}int setPromiscMode(int socket, const char* eth, bool enable){ // 混杂模式 struct ifreq req; strcpy(req.ifr_name, eth); ioctl(socket, SIOCGIFFLAGS, &req); if (enable) { req.ifr_flags |= IFF_PROMISC; } else { req.ifr_flags &= ~IFF_PROMISC; } int ret = ioctl(socket, SIOCSIFFLAGS, &req); if (ret < 0) { perror("Set promisc mode failed:"); return -1; } return 0;}int initSocket(const char* eth){ int ret = 0; int fd = -1; if (eth == NULL) { return -1; } // 注意与下面绑定时协议一致 fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP)); // tocheck ETH_P_IP | if (fd < 0) { perror("init socket failed:"); return -1; } // 接收buffer大小 int size = BUFFER_SIZE; ret = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(int)); if (ret < 0) { goto end; } // 绑定网卡 struct ifreq req; strcpy(req.ifr_name, eth); ioctl(fd, SIOCGIFINDEX, &req); struct sockaddr_ll addr; addr.sll_family = PF_PACKET; addr.sll_ifindex = req.ifr_ifindex; addr.sll_protocol = htons(ETH_P_IP); // 取决于此处协议 ETH_P_ALL ETH_P_IP |ETH_P_ARP ret = bind(fd, (struct sockaddr *)&addr, sizeof(sockaddr_ll)); if (ret < 0) { goto end; } // 混杂模式 //setPromiscMode(fd, eth, true);end: if (ret < 0) { close(fd); return ret; } else { return fd; }}int deintSocket(int socket){ close(socket); return 0;}int showMacAddr(const struct ether_header *ethhead){ printf("mac: [%02x:%02x:%02x:%02x:%02x:%02x] --> ", ethhead->ether_shost[0], ethhead->ether_shost[1], ethhead->ether_shost[2], ethhead->ether_shost[3], ethhead->ether_shost[4], ethhead->ether_shost[5]); printf("mac: [%02x:%02x:%02x:%02x:%02x:%02x]\n", ethhead->ether_dhost[0], ethhead->ether_dhost[1], ethhead->ether_dhost[2], ethhead->ether_dhost[3], ethhead->ether_dhost[4], ethhead->ether_dhost[5]); return 0;}int parseTcpHeader(const char* buffer){ struct tcphdr* hdr = (struct tcphdr*)buffer; printf("port: [%d] --> [%d]\n", ntohs(hdr->th_sport), ntohs(hdr->th_dport)); return 0;}int parseUdpHeader(const char* buffer){ const struct udphdr* hdr = reinterpret_cast<const struct udphdr *>(buffer); // (struct udphdr*)buffer; // 长度字段与实际接收数据不符合,不知原因为何 printf("port: [%d] --> [%d] [%d bytes]\n", ntohs(hdr->uh_sport), ntohs(hdr->uh_dport), ntohs(hdr->uh_ulen)); return 0;}int parseIpHeader(const char* buffer){ if (NULL == buffer) { return -1; } #if 0 const struct ip* pstIP = reinterpret_cast<const struct ip *>(buffer); //(struct ip *)buffer; /* 协议类型、源IP地址、目的IP地址 */ struct protoent* pstIpProto = getprotobynumber(pstIP->ip_p); if(NULL != pstIpProto) { printf("%s(%d) ", pstIpProto->p_name, pstIP->ip_p); } else { printf("%s(%d) ", "None", pstIP->ip_p); } printf("ip: [%s] --> ", inet_ntoa(pstIP->ip_src)); printf("[%s]\n", inet_ntoa(pstIP->ip_dst)); struct protoent* pstIpProto = getprotobynumber(hdr->protocol); if(NULL != pstIpProto) { printf("%s(%d) ", pstIpProto->p_name, hdr->protocol); } else { printf("%s(%d) ", "None", hdr->protocol); } #endif const struct iphdr* hdr = (struct iphdr *)buffer; struct in_addr saddr; saddr.s_addr = hdr->saddr; printf("ip: [%s] --> ", inet_ntoa(saddr)); saddr.s_addr = hdr->daddr; printf("[%s] [%d bytes] ", inet_ntoa(saddr), ntohs(hdr->tot_len)); switch (hdr->protocol) { case IPPROTO_TCP: printf("TCP\n"); parseTcpHeader(buffer+sizeof(iphdr)); break; case IPPROTO_UDP: printf("UDP\n"); parseUdpHeader(buffer+sizeof(iphdr)); break; case IPPROTO_ICMP: printf("ICMP\n"); break; case IPPROTO_IGMP: printf("IGMP\n"); break; default: break; } #if 0 if ( == IPPROTO_TCP) { printf("TCP\n"); parseTcpHeader(buffer+sizeof(iphdr)); } if (hdr->protocol == IPPROTO_UDP) { printf("UDP\n"); parseUdpHeader(buffer+sizeof(iphdr)); } if (hdr->protocol == IPPROTO_ICMP) { printf("ICMP\n"); } if (hdr->protocol == IPPROTO_IGMP) { printf("IGMP\n"); } #endif return 0;}int parsePakcet(const char* buffer){ if (buffer == NULL) { return -1; } const struct ether_header *ethhead = reinterpret_cast<const struct ether_header *>(buffer); //(struct ether_header*)buffer; /////////////////// int type = ntohs(ethhead->ether_type); if (type == ETHERTYPE_ARP) { printf("ethnet type: ARP\n"); showMacAddr(ethhead); } if (type == ETHERTYPE_IP) { //printf("ethnet type: IP\n"); showMacAddr(ethhead); parseIpHeader(buffer+sizeof(struct ether_header)); } //printf("-------------------------------------------\n"); return 0;}int startCapture(int socket){ int ret = 0; socklen_t len = sizeof(struct sockaddr); char buffer[BUFFER_SIZE] = {0}; while (1) { memset(buffer, '\0', BUFFER_SIZE); ret = recvfrom(socket, buffer, BUFFER_SIZE, 0, NULL, &len); if (ret < 0) { continue; } //printf("--recv len: %d\n", ret); if (debug_level) dump(buffer, ret); parsePakcet(buffer); usleep(10*1000); } return 0;}int main(int argc, char* argv[]){ char eth[8] = "eth0"; while(1) { int c = getopt(argc, argv, my_opt); ll_printf(8, "option char: %x %c\n", c, c); if (c < 0) { break; } switch(c) { case 'd': debug_level = atoi(optarg); //printf("debug level: %d\n", debug_level); break; case 'i': strncpy(eth, optarg, 8); break; case '?': case 'h': default: usage(argv[0]); break; } } printf("Start capture on %s\n", eth); int socket = initSocket(eth); if (socket < 0) { printf("Init socket failed.\n"); return -1; } startCapture(socket); return 0;}
注:为什么要表明“有线网络”?因为还要做无线网络抓包。
李迟 2016.9.6 周二 夜
0 0
- Linux系统有线网络抓包程序
- Linux下编写网络抓包程序
- Linux下编写网络抓包程序
- Linux下编写网络抓包程序
- Linux下编写网络抓包程序
- Linux 网络抓包
- Linux 网络抓包
- iOS 系统网络抓包
- Linux网络管理之网络抓包
- 一个简单的网络抓包程序
- iOS系统网络抓包方法
- iOS系统网络抓包方法
- iOS系统网络抓包方法
- tcpdump_iOS系统网络抓包方法
- iOS系统网络抓包方法
- iOS系统网络抓包方法
- iOS系统网络抓包方法
- iOS系统网络抓包方法
- 插入排序 递归算法
- 线程池技术
- MySql函数大全
- Unity 2D 终结手册 (3) - 精灵编辑_Unity3d 开发技术
- Search for a Range 区间搜索
- Linux系统有线网络抓包程序
- Coursera机器学习 week5 神经网络的学习 assignment
- std::map的使用
- 剑指Offer:字符流中第一个不重复的字符
- 10、Foundation框架
- 为什么Android程序中的Looper.loop()不会造成ANR异常
- BZOJ4320 ShangHai2006 Homework
- [美剧赏析] 权力的游戏<Game of Thrones>完全赏析 (5-6)
- Unity3d导出安卓项目错误