实现一个简单的sniffer
#include<stdio.h>
#include<pcap.h>
#include<unistd.h>
#include<stdlib.h>
//#include<pcap/bpf.h>
#include<netinet/ip.h>
#include<netinet/ip_icmp.h>
#include<netinet/tcp.h>
#include<netinet/udp.h>
#include<netinet/ether.h>
#include<arpa/inet.h>
#define ETHER_SIZE 14 ///get_packet()回调函数
///header:收到的数据包的pcap_pkthdr类型的指针
///packet:收到的数据包数据
void get_packet(u_char*args, const struct pcap_pkthdr *header,const u_char *packet){ static int count = 1;
const char * payload;
printf("==================================packet number: %d=============================\n",count++); ///ETHER_SIZE:以太帧首部长度14个字节
///IP包头(tcp包头(数据))
///IP包头(udp包头(数据))
///IP包头(icmp包头(数据))
struct ip * ip = (struct ip *)(packet + ETHER_SIZE);
printf("IP header length: %d\n",ip->ip_hl<<2);
printf("From %s\n",inet_ntoa(ip->ip_src));
printf("To %s\n",inet_ntoa(ip->ip_dst));
int ip_hl = ip->ip_hl<<2; ///对报文类型进行了扩展
///可以分析IP包、ICMP包、TCP包、UDP包
switch(ip->ip_p){ case IPPROTO_TCP:
{
printf("----Protocol TCP----\n");
struct tcphdr *tcp = (struct tcphdr *)(packet + 14 + ip_hl);
printf("tcp -> source:%d\n",ntohs(tcp -> source));
printf("tcp -> dest:%d\n",ntohs(tcp -> dest));
printf("tcp -> seq:%d\n",ntohs(tcp -> seq));
printf("tcp -> ack_seq:%d\n",ntohs(tcp -> ack_seq));
printf("tcp -> headerLenth:%d\n",tcp -> doff << 2);
printf("tcp -> fin:%d\n",tcp -> fin);
printf("tcp -> syn:%d\n",tcp -> syn);
printf("tcp -> rst:%d\n",tcp -> rst);
printf("tcp -> psh:%d\n",tcp -> psh);
printf("tcp -> ack:%d\n",tcp -> ack);
printf("tcp -> urg:%d\n",tcp -> urg);
printf("tcp -> window:%d\n",ntohs(tcp -> window));
printf("tcp -> check:%d\n",ntohs(tcp -> check));
//printf("tcp -> urg_ptr:%d\n",tcp -> urg_ptr); int h_size = tcp->doff<< 2;
int payload_size = ntohs(ip->ip_len) - ip_hl - h_size; int i = payload_size;
printf("payload is:%d\n",i); while(i > 0)
{
printf("%02x ", packet[i]);
if( i % 16 == 0 )
printf("\n");
i--;
}
printf("\n");
break;
}
case IPPROTO_UDP:
{
printf("----Protocol UDP----\n");
struct udphdr *udp = (struct udphdr *)(packet + 14 + ip_hl);
printf("udp -> source:%d\n",ntohs(udp -> source));
printf("udp -> dest:%d\n",ntohs(udp -> dest));
printf("udp -> length:%d\n",ntohs(udp -> len));
printf("udp -> check:%d\n",ntohs(udp -> check));
int payload_size = ntohs(ip->ip_len) - ip_hl - 8;
int i = payload_size;
printf("payload is:%d\n",i); while(i > 0)
{
printf("%02x ", packet[i]);
if( i % 16 == 0 )
printf("\n");
i--;
}
printf("\n");
break;
}
case IPPROTO_ICMP:
{
printf("----Protocol ICMP----\n");
struct icmphdr *icmp = (struct icmphdr *)(packet + 14 + ip_hl); if(icmp -> type == 8)
{
printf("--icmp_echo request--\n");
printf("icmp -> type:%d\n",icmp -> type);
printf("icmp -> code:%d\n",icmp -> code);
printf("icmp -> checksum:%d\n",icmp -> checksum); printf("icmp -> id:%d\n",icmp -> un.echo.id);
printf("icmp -> sequence:%d\n",icmp -> un.echo.sequence);
int payload_size = ntohs(ip->ip_len) - ip_hl - 8;
int i = payload_size;
printf("payload is:%d\n",i); while(i > 0)
{
printf("%02x ", packet[i]);
if( i % 16 == 0 )
printf("\n");
i--;
}
printf("\n");
}
else if(icmp -> type == 0)
{
printf("--icmp_echo reply--\n");
printf("icmp -> type:%d\n",icmp -> type);
printf("icmp -> code:%d\n",icmp -> code);
printf("icmp -> checksum:%d\n",icmp -> checksum); printf("icmp -> id:%d\n",icmp -> un.echo.id);
printf("icmp -> sequence:%d\n",icmp -> un.echo.sequence);
int payload_size = ntohs(ip->ip_len) - ip_hl - 8;
int i = payload_size;
printf("payload is:%d\n",i); while(i > 0)
{
printf("%02x ", packet[i]);
if( i % 16 == 0 )
printf("\n");
i--;
}
printf("\n");
}
else
{
printf("icmp -> type:%d\n",icmp -> type);
printf("icmp -> code:%d\n",icmp -> code);
printf("icmp -> checksum:%d\n",icmp -> checksum);
int payload_size = ntohs(ip->ip_len) - ip_hl - 8;
int i = payload_size;
printf("payload is:%d\n",i); while(i > 0)
{
printf("%02x ", packet[i]);
if( i % 16 == 0 )
printf("\n");
i--;
}
printf("\n");
}
break;
}
case IPPROTO_IP:
{
printf("----Protocol IP----\n");
//printf("IP header length: %d\n",ip -> ip_hl<<2);
printf("IP version: %d\n",ip -> ip_v);
printf("IP type of service: %d\n",ip -> ip_tos);
printf("IP total length: %d\n",ip -> ip_len);
printf("IP identification: %d\n",ip -> ip_id);
printf("IP fragment offset field: %d\n",ip -> ip_off);
printf("IP time to live: %d\n",ip -> ip_ttl);
printf("IP protocol: %d\n",ip -> ip_p);
printf("IP checksum: %d\n",ip -> ip_sum);
int payload_size = ntohs(ip->ip_len) - ip_hl;
int i = payload_size;
printf("payload is:%d\n",i);
while(i > 0)
{
printf("%02x ", packet[i]);
if( i % 16 == 0 )
printf("\n");
i--;
}
printf("\n");
break;
}
default:printf("Protocol unknown\n");
return; }
} int main(int argc,char*argv[]){ char *dev, errbuf[PCAP_ERRBUF_SIZE];
struct bpf_program fp;
char filter_exp[] = "port 23";
bpf_u_int32 mask;
bpf_u_int32 net;
struct pcap_pkthdr header;
const u_char *packet;
int num_packets = 10; ///pcap_lookupdev()自动获取网络接口,返回一个网络接口的字符串指针
///如果出错,errbuf存放出错信息
///若想手动指定,则跳过此步,将要监听的网络字符串硬编码到pcap_open_live中
dev = pcap_lookupdev(errbuf);
if(dev==NULL){
printf("ERROR:%s\n",errbuf);
exit(2);
}
printf("The sniff interface is:%s\n",dev); ///pcap_lookupnet()获得设备的IP地址,子网掩码等信息
///net:网络接口的IP地址
///mask:网络接口的子网掩码
if(pcap_lookupnet(dev,&net,&mask,errbuf)==-1){
printf("ERROR:%s\n",errbuf);
net = 0;
mask = 0;
} ///pcap_open_live()打开网络接口
///BUFSIZ:抓包长度
///第三个参数:0代表非混杂模式,1代表混杂模式
///第四个参数:等待的毫秒数,超过这个值,获取数据包的函数会立即返回,0表示一直等待直到有数据包到来
pcap_t * handle = pcap_open_live(dev,BUFSIZ,1,0,errbuf);
if(handle == NULL){
printf("ERROR:%s\n",errbuf);
exit(2);
}
/*这里我们测试发现不能过滤,注释掉这部分代码,程序可以正常运行了。
///pcap_compile()编译过滤表达式
///fp指向编译后的filter_exp
///filter_exp过滤表达式
///参数四:是否需要优化过滤表达式
if(pcap_compile(handle,&fp,filter_exp,0,net)==-1){
printf("Can't parse filter %s:%s\n",filter_exp,pcap_geterr(handle));
return(2);
} ///pcap_setfilter()应用这个过滤表达式
///完成过滤表达式后,我们可以使用pcap_loop()或pcap_next()登抓包函数抓包了
if(pcap_setfilter(handle,&fp)==-1){
printf("cant' install filter %s:%s\n",filter_exp,pcap_geterr(handle));
return(2);
}
*/
printf("Hello\n"); // packet = pcap_next(handle,&header);
// printf("Get a packet with length %d.\n",header.len); ///
///num_packets:需要抓的数据包的个数,一旦抓到了num_packets个数据包,pcap_loop立即返回。负数表示永远循环抓包,直到出错
///get_packet:回调函数指针
//pcap_loop(handle,num_packets,get_packet,NULL);
pcap_loop(handle,-1,get_packet,NULL); pcap_freecode(&fp); ///pcap_close()释放网络接口
///关闭pcap_open_live()获取的pcap_t的网络接口对象并释放相关资源
pcap_close(handle);
return(0);
}
实现一个简单的sniffer的更多相关文章
- 哪种缓存效果高?开源一个简单的缓存组件j2cache
背景 现在的web系统已经越来越多的应用缓存技术,而且缓存技术确实是能实足的增强系统性能的.我在项目中也开始接触一些缓存的需求. 开始简单的就用jvm(java托管内存)来做缓存,这样对于单个应用服务 ...
- 在Openfire上弄一个简单的推送系统
推送系统 说是推送系统有点大,其实就是一个消息广播功能吧.作用其实也就是由服务端接收到消息然后推送到订阅的客户端. 思路 对于推送最关键的是服务端向客户端发送数据,客户端向服务端订阅自己想要的消息.这 ...
- ASP.NET Aries 入门开发教程2:配置出一个简单的列表页面
前言: 朋友们都期待我稳定地工作,但创业公司若要躺下,也非意念可控. 若人生注定了风雨飘摇,那就雨中前行了. 最机开始看聊新的工作机会,欢迎推荐,创业公司也可! 同时,趁着自由时间,抓紧把这系列教程给 ...
- 计算机程序的思维逻辑 (60) - 随机读写文件及其应用 - 实现一个简单的KV数据库
57节介绍了字节流, 58节介绍了字符流,它们都是以流的方式读写文件,流的方式有几个限制: 要么读,要么写,不能同时读和写 不能随机读写,只能从头读到尾,且不能重复读,虽然通过缓冲可以实现部分重读,但 ...
- 如何开发一个简单的HTML5 Canvas 小游戏
原文:How to make a simple HTML5 Canvas game 想要快速上手HTML5 Canvas小游戏开发?下面通过一个例子来进行手把手教学.(如果你怀疑我的资历, A Wiz ...
- CSharpGL(24)用ComputeShader实现一个简单的图像边缘检测功能
CSharpGL(24)用ComputeShader实现一个简单的图像边缘检测功能 效果图 这是红宝书里的例子,在这个例子中,下述功能全部登场,因此这个例子可作为使用Compute Shader的典型 ...
- CSharpGL(23)用ComputeShader实现一个简单的ParticleSimulator
CSharpGL(23)用ComputeShader实现一个简单的ParticleSimulator 我还没有用过Compute Shader,所以现在把红宝书里的例子拿来了,加入CSharpGL中. ...
- 应用OpenMP的一个简单的设计模式
小喵的唠叨话:最近很久没写博客了,一是因为之前写的LSoftmax后馈一直没有成功,所以在等作者的源码.二是最近没什么想写的东西.前两天,在预处理图片的时候,发现处理200w张图片,跑了一晚上也才处理 ...
- 用php实现一个简单的链式操作
最近在读<php核心技术与最佳实践>这本书,书中第一章提到用__call()方法可以实现一个简单的字符串链式操作,比如,下面这个过滤字符串然后再求长度的操作,一般要这么写: strlen( ...
随机推荐
- ExtJs 4: How To Add Grid Cell Tooltip
最近忙一个项目的时候需要实现鼠标移到grid的某一行上提示消息.花了半天时间才解决.在网上找很久终于有找到一个有用的.我的版本是extjs4. 效果如图 Ext.onReady(function () ...
- 多次读取请求request里数据
如果请求是GET方法,可以直接通过getParameter(String param)方法读取指定参数,可读取多次: 而POST方法的参数是存储在输入流中,只能读一次,不能多次读取. 有时需要在fil ...
- Project Server 2013两个权限模型介绍
Project Server 2013中无法使用“新建用户”功能? 当我们的Project Server 2013刚刚安装好时,在PWA的服务器设置中找不到新建用户的选项,是什么原因造成的呢? 原来是 ...
- 在C#中使用InputBox
以前用VB编程常用InputBox,现在学了C#,竟然找不到它了--后来到网上查到了,现在贡献给大家:1.首先要添加引用Microsoft.VisualBasic2.命名空间 Using Micros ...
- iOS-UICollectionView自定义布局
UICollectionView自定义布局 转载: http://answerhuang.duapp.com/index.php/2013/11/20/custom_collection_view_l ...
- short a = 128, byte b = (byte)a 强制类型转换
package 笔试; public class ShortToByte { /** * @param args */ public static void main(String[] args) { ...
- FaceBook要在视频领域打败YouTube?
据<纽约时报>报道,FaceBook正在探索一项新的策略来直接把音乐视频嵌入到用户的News Feeds中.目前,具有代表性的视频网站有YouTube和Vimeo,它们可以在社交网络上分享 ...
- iOS 数据持久化(1):属性列表与对象归档
@import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css); @import url(/ ...
- Linux软件安装,RPM与YUM
为了防止无良网站的爬虫抓取文章,特此标识,转载请注明文章出处.LaplaceDemon/SJQ. http://www.cnblogs.com/shijiaqi1066/p/3843955.html ...
- easyui 常用代码
最近在公司制作内部使用数据管理网页,用到了easyui,使用过程中发现与jquery的写法有比较多不一样的地方,趁现在有空,先做个笔记. (这里主要说明的是combobox的用法,其他的像textbo ...