实现一个简单的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( ...
随机推荐
- 一些技术blog和安全blog
1.安全blog: http://zenxds.com/blog/ http://navisec.it/ http://huaidan.org/ http://leapar.lofter.com/ h ...
- c#基础语言编程-按值类型和引用类型传递参数
引言 在介绍传递参数介绍前,请明白参数类型和传递方式是不同的.传递方式分为按值类型和引用类型传递参数.参数类型有值类型和引用类型,这个和C++是不同的.这里的传递方式对应c++中的深复制和浅复制. 两 ...
- [Windows] Adobe Photoshop CC 2015官方原版下载 附破解补丁&破解教程
Photoshop自CS6以后改为CC,目前Photoshop CC 2015是最新版,发布日期为2015年6月. <ignore_js_op> 下载安装主程序: 主程序及补丁下载地址 ...
- richTextBox1 转到行号
private void button2_Click(object sender, EventArgs e) { Win32CommonDialog.frm_GOTO frm = new ...
- Qt 学习之路:Canvas
在 QML 刚刚被引入到 Qt 4 的那段时间,人们往往在讨论 Qt Quick 是不是需要一个椭圆组件.由此,人们又联想到,是不是还需要其它的形状?这种没玩没了的联想导致了一个最直接的结果:除了圆角 ...
- java获取当前方法
1.获取当前方法堆栈,我们一般用 StackTraceElement[] stes = Thread.currentThread().getStackTrace(); 想要获取当前方法,切记不够灵活, ...
- ES6的let命令实现猜想
今天看了看阮一峰的<ECMAScript 6入门>的let和const命令,看完let之后自己测试了一把,仿佛处在云里雾里之中.代码如下: "use strict"; ...
- Android Studio创建工程时一直卡在下载Gradle
一直提示这个进度条,查了不少资料,有的说FQ,有的说下载gradle后运行下bin里面的批处理,再在环境变量里Path中加入路径,我都试了,都不和... 按理说FQ了可以下载了吧,但是半天没下载完,一 ...
- 手势交互之GestureDetector
GsetureDetector 一.交互过程 触屏的一刹那,触发MotionEvent事件 被OnTouchListener监听,在onTouch()中获得MotionEvent对象 GestureD ...
- Spring通过SchedulerFactoryBean实现调度任务的配置
http://blog.csdn.net/hu_shengyang/article/details/19815201(里面是配置) 介绍SchedulerFactoryBean http://blog ...