使用libpcab抓包&处理包
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <string.h>
#include <pcap.h>
#include <ctype.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h> /* 默认捕获长度 (每个包捕获的最大长度) */
#define SNAP_LEN 1518 /* 以太网头部14个字节 */
#define SIZE_ETHERNET 14 /* 以太网地址6个字节 */
#define ETHER_ADDR_LEN 6 #define NUM_PACKET 5
#define PACKETS_NUM 2000
#define TCP_FLAG 0
#define UDP_FLAG 1
#define MYIP "192.168.1.106"
/* UDP header */
struct sniff_udp {
uint16_t sport; /* source port */
uint16_t dport; /* destination port */
uint16_t udp_length;
uint16_t udp_sum; /* checksum 检验和 */
}; /* Ethernet header */
struct sniff_ethernet {
u_char ether_dhost[ETHER_ADDR_LEN]; /* destination host address */
u_char ether_shost[ETHER_ADDR_LEN]; /* source host address */
u_short ether_type; /* IP? ARP? RARP? etc */
}; /* IP header */
struct sniff_ip {
u_char ip_vhl; /* version << 4 | header length >> 2 */
u_char ip_tos; /* type of service */
u_short ip_len; /* total length */
u_short ip_id; /* identification */
u_short ip_off; /* fragment offset field */
#define IP_RF 0x8000 /* reserved fragment flag */
#define IP_DF 0x4000 /* dont fragment flag */
#define IP_MF 0x2000 /* more fragments flag */
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
u_char ip_ttl; /* time to live */
u_char ip_p; /* protocol */
u_short ip_sum; /* checksum */
struct in_addr ip_src,ip_dst; /* source and dest address */
};
#define IP_HL(ip) (((ip)->ip_vhl) & 0x0f)
#define IP_V(ip) (((ip)->ip_vhl) >> 4) /* TCP header */
typedef unsigned long tcp_seq;
struct sniff_tcp {
u_short th_sport; /* source port */
u_short th_dport; /* destination port */
tcp_seq th_seq; /* sequence number */
tcp_seq th_ack; /* acknowledgement number */
u_char th_offx2; /* data offset, rsvd */
#define TH_OFF(th) (((th)->th_offx2 & 0xf0) >> 4)
u_char th_flags;
#define TH_FIN 0x01
#define TH_SYN 0x02
#define TH_RST 0x04
#define TH_PUSH 0x08
#define TH_ACK 0x10
#define TH_URG 0x20
#define TH_ECE 0x40
#define TH_CWR 0x80
#define TH_FLAGS (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR)
u_short th_win; /* window */
u_short th_sum; /* checksum */
u_short th_urp; /* urgent pointer */
}; int tcp_num_count;
int udp_num_count;
int fin, syn, rst, push, ack, urg, ece, cwr; void callback(unsigned char*, const struct pcap_pkthdr*, const unsigned char*); int main()
{
char errBuf[PCAP_ERRBUF_SIZE];
char *dev = NULL; // dev应设置为网卡
/* 获取网络设备接口,即网络设备名 */
dev = pcap_lookupdev(errBuf); // dev应设置为网卡
/* 显示捕获设备信息
* printf("Device: %s\n", dev);
*/
if (dev == NULL) {
printf("%s\n", errBuf);
exit(1);
}
// netp为ip地址, bpf_u_int32为32位无符号整型
bpf_u_int32 netp = 0, maskp = 0;
int ret = 0;
/* 获取网络号和掩码,成功返回0 */
ret = pcap_lookupnet(dev, &netp, &maskp, errBuf);
if (ret == -1) {
printf("%s\n", errBuf);
exit(1);
}
// printf("ip = %d\n", netp); 应转化为点二进制形式 // 打开网络接口
// 参数分别为接口名, 捕获数据包的长度不能超过65535字节
// 混杂模式, 等待的ms数(超过该时间函数立即返回,0表示一直等待)
pcap_t* pcap_handle = pcap_open_live(dev, SNAP_LEN, 1, 0, errBuf);
//实例 pcap_t *pcap_handle = pcap_open_live("eth0", 1024, 1, 0, errBuf);
if (pcap_handle == NULL) {
printf("%s\n", errBuf);
exit(1);
} /* pcap_datalink();
* 返回数据链路层类型,例如DLT_EN10MB;
* 确保我们对以太网设备捕获
*/
if (pcap_datalink(pcap_handle) != DLT_EN10MB) {
fprintf(stderr, "%s is not an Ethernet\n", dev);
exit(EXIT_FAILURE);
} // 捕获单个数据包 const u_char *pcap_next(pcap_t *p,struct pcap_pkthdr *h);
// 参数分别为:打开网络接口返回的指针 捕获的数据包头
/*
const unsigned char *packet_addr = NULL; // 捕获的包的地址
struct pcap_pkthdr packet_header; // 抓到的时间 实际长度 原来长度
packet_addr = pcap_next(pcap_handle, &packet_header);
printf("Packet's length is:%d\n", packet_header.len); // 原来长度
printf("Packet's true length is:%d\n", packet_header.caplen);
*/ // 捕获多个数据包 int pcap_loop(pcap_t *p,int cnt,pcap_handler callback,u_char *user);
// 每捕获一个就调用callback指定的回调函数,可在回调函数中处理数据包
// 参数分别为:同pcap_next 指定捕获数据包的个数(设为-1将一直捕获)
// 参数分别为:回调函数(名字自取) 向回调函数中传递的参数 // 回调函数说明 void callback(u_char *userarg,const struct pcap_pkthdr *pkthdr,const u_char *packet)
// 参数:pcap_loop的最后一个参数 捕获的数据包的头(同pcap_next第二个参数)
// 参数:捕获的的数据包数据 /* 设置回掉函数并开始捕获包 */
if (pcap_loop(pcap_handle, NUM_PACKET, callback, NULL) < 0) {
perror("pcap_loop finish!\n");
} // 捕获多个数据包 int pcap_dispatch(pcap_t *p,int cnt,pcap_handler callback,u_char *user);
// 说明:和pcap_loop类似,只是超过x毫秒后返回(x是pcap_open_live的第四个参数) // 关闭网络接口
pcap_close(pcap_handle);
} //void func(unsigned char *argument, const struct pcap_pkthdr *packet_header, const unsigned char *packet_data)
//{
// printf("使用pcap_loop的回调函数,该包长度为%d\n", packet_header->len);
//} void callback(unsigned char *args, const struct pcap_pkthdr *header, const unsigned char *packet) {
static int count = 1; /* 包计数器,记录捕获多少包 */
/* 显示包总数
* printf("\nPacket number %d:\n", count);
* count++;
*/
/* declare pointers to packet headers */
struct sniff_ethernet *ethernet; /* 以太网头部 */
struct sniff_ip *ip; /* IP 头部 */
struct sniff_tcp *tcp; /* TCP 头部 */
struct sniff_udp *udp; /* UDP 头部 */
unsigned char *payload; /* Packet payload */
int size_ip;
int size_tcp;
int size_udp;
int size_payload; int proto_flag = 2; // 0=TCP_FLAG; 1=UDP_FLAG
//==== /* 定义以太网头部 */
ethernet = (struct sniff_ethernet*)(packet);
/* 定义/计算 IP 头部偏移 */
ip = (struct sniff_ip*)(packet + SIZE_ETHERNET);
size_ip = IP_HL(ip)*4; // ip头部长度
if (size_ip < 20) {
printf(" * Invalid IP header length: %u bytes\n", size_ip);
return;
}
/* 显示源IP和目的IP print source and destination IP addresses */
// only print internet->me information
if(strcmp(inet_ntoa(ip->ip_src), MYIP) == 0)
return;
/* 确定协议 determine protocol */
switch(ip->ip_p) {
case IPPROTO_TCP: //useful
// printf(" Protocol: TCP\n");
proto_flag=0;
break;
case IPPROTO_UDP: //useful
// printf(" Protocol: UDP\n");
proto_flag=1;
break;
case IPPROTO_ICMP: //useless
// printf(" Protocol: ICMP\n");
return;
case IPPROTO_IP: //useless
// printf(" Protocol: IP\n");
return;
default:
// printf(" Protocol: unknown\n");
return;
}
/*
* This packet is TCP.
*/
if (proto_flag == 0) {
/* 定义/计算 TCP 头部偏移 */
tcp = (struct sniff_tcp *) (packet + SIZE_ETHERNET + size_ip);
/* 计算TCP头部长度 */
size_tcp = TH_OFF(tcp) * 4;
if (size_tcp < 20) {
printf (" * Invalid TCP header length: %u bytes\n", size_tcp);
return;
}
// printf(" From: %s\n", inet_ntoa(ip->ip_src));
// printf(" To: %s\n", inet_ntoa(ip->ip_dst));
printf (" Src port : %d\n", ntohs (tcp->th_sport));
printf (" Dst port : %d\n", ntohs (tcp->th_dport));
printf (" Seq number: %d\n", ntohl (tcp->th_seq));
int fin=0;
if(tcp->th_flags & TH_FIN)
fin=1;
printf (" FIN : %d\n", fin); /* define/compute tcp payload (segment) offset */
payload = (unsigned char *) (packet + SIZE_ETHERNET + size_ip + size_tcp); /* compute tcp payload (segment) size , 即TCP报文数据部分字节数 */
size_payload = ntohs (ip->ip_len) - (size_ip + size_tcp);
printf (" TCP size_payload: %d\n", size_payload);
printf (" Payload (%d bytes):\n", size_payload);
/*
if (size_payload > 0) {
//printf (" Payload (%d bytes):\n", size_payload);
// insert_tcp_hex_mysql(0, inet_ntoa(ip->ip_src), inet_ntoa(ip->ip_dst), ntohs (tcp->th_sport), ntohs (tcp->th_dport), payload, ntohl (tcp->th_seq), size_payload,fin );
}
*/
} //end tcp
//=====================================================================================
/*
* This packet is UDP.
*/
else if (proto_flag == 1) {
/* define/compute udp header offset */
udp = (struct sniff_udp *) (packet + SIZE_ETHERNET + size_ip);
// printf(" From: %s\n", inet_ntoa(ip->ip_src));
// printf(" To: %s\n", inet_ntoa(ip->ip_dst));
printf (" Src port: %d\n", ntohs (udp->sport));
printf (" Dst port: %d\n", ntohs (udp->dport));
printf ("udp length:%d\n", ntohs (udp->udp_length));
// printf ("udp sum:%d\n", ntohs (udp->udp_sum)); /* define/compute udp payload (segment) offset */
payload = (unsigned char *) (packet + SIZE_ETHERNET + size_ip + 8);
size_payload = ntohs (ip->ip_len) - (size_ip + 8);
printf (" UDP size_payload: %d\n", size_payload);
}//end udp
return;
}
使用libpcab抓包&处理包的更多相关文章
- tcpdump抓取HTTP包
tcpdump抓取HTTP包 tcpdump -XvvennSs 0 -i eth0 tcp[20:2]=0x4745 or tcp[20:2]=0x4854 0x4745为"GET&quo ...
- 使用Chrome或Fiddler抓取WebSocket包
首先,HTTP是建立在TCP协议基础上的,而WebSocket通常也是建立在TCP上,所以说为什么有些网页游戏抓不到包而有些又可以,这仅是因为你使用的抓包工具是针对了HTTP的通信协议. 我先从抽象的 ...
- wireshark设置抓服务器的包
wireshark设置抓服务器的包:
- 利用Fiddler抓取websocket包
一.利用fiddler抓取websockt包 打开Fiddler,点开菜单栏的Rules,选择Customize Rules... 这时会打开CustomRules.js文件,在class Handl ...
- 使用wireshark抓取TCP包分析1
使用wireshark抓取TCP包分析1 前言 介绍 目的 准备工作 传输 创建连接 握手 生成密钥 发送数据 断开连接 结论 前言 介绍 本篇文章是使用wireshrak对某个https请求的tcp ...
- libnids关于计算校验和引起的抓不到包的现象的解决方法
libnids关于计算校验和引起的抓不到包的现象的解决方法: nids.h中有这么一段: struct nids_chksum_ctl { u_int netaddr; u_int mask; u_i ...
- 用wiershark抓dns数据包
wireshark是非常好的抓包工具,捕获工具也很强大.比如说我只要抓dns数据包,其他数据包全部丢弃. 步骤如下: 选择菜单->捕获-捕获接口-输入-所选择接口的捕获过滤器:port 53 1 ...
- 手机通过Charles抓取https包
因为fiddler不能在mac上使用,而Charles是跨平台的,可以在mac上使用,所以需要了解一下Charles的使用 安装破解版Charles 下载破解版包,先启动一次未破解版的Ch ...
- Android移动网络如何抓取数据包
1)下载tcpdump工具 tcpdump(dump the traffic on a network)是Linux中强大的网络数据采集分析工具之一,可以将网络中传送的数据包头完全截获下来提供分析.它 ...
随机推荐
- Linux——查看
查看当前系统版本: lsb_release -a #没有装:yum install lsb 查看当前运行端口: netstat -atunlp #没有装:yum install net-tools - ...
- ACM 2003~2005
ACM 2003 求实数的绝对值 import java.util.Scanner; public class Lengxc { public static void main(String[] ar ...
- ASP.NET MVC4.0 后台获取不大前台传来的file
<td>选择图片</td> <td> <input type="file" id="uploadImg" name=& ...
- 纯js轮播图练习-1
偶尔练习,看视频自己学着做个简单的纯JS轮播. 简单的纯js轮播图练习-1. 样子就是上面图片那样,先不管好不好看,主要是学会运用和理解轮播的原理 掌握核心的理论知识和技术的操作,其他的都可以在这个基 ...
- sea.js模块化工具
sea.js 一. sea.js向全局中引入了两个变量seajs.define: 1.seajs用加载文件 seajs.use(deps,callback)异步引入入口模块 路径要以sea.js文件所 ...
- 内网环境下为Elasticsearch 5.0.2 添加head服务
背景: 本项目的服务器是内网环境,没有网络,因此需要在离线的环境中,安装head服务. 需要用到的安装包有: node的安装包 elasticsearch的head插件源码 说明:此次只讲述为elas ...
- 应用性能管理(APM, Application Performance Management)
当下成熟的互联网公司都建立有从基础设施到应用程序的全方位监控系统,力求及时发现故障进行处理并为优化程序提供性能数据支持,降低整体运维成本.国内外商业的APM有Compuware.iMaster.博睿B ...
- 分治与递归-找k个临近中位数的数
问题描述:给定由n个互不相同的数组成的集合S以及正整数k≤n,试设计一个O(n)时间算法找出S中最接近S的中位数的k个数. 算法描述: 用线性时间选择实现的算法找到中位数 S’=除去中位数外的S S& ...
- 转载:C语言指针使用的注意事项
相信大家对指针的用法已经很熟了,这里也不多说些定义性的东西了,只说一下指针使用中的注意事项吧. 一.在定义指针的时候注意连续声明多个指针时容易犯的错误,例如int * a,b;这种声明是声明了一个指向 ...
- 武汉ber优步司机奖励政策(1月4日~1月10日)
滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...