实现一个简单的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( ...
随机推荐
- MenuDrawer的使用
---恢复内容开始--- MenuDrawer框架是一个可以实现上下左右滑动的框架,在使用中可以在xml文件中配置也可以在java代码中实现效果的配置 可以以jar的形式或依赖的形式存在 用 ...
- PDO 提供了三种不同的错误处理模式
PDO::ERRMODE_SILENT 此为默认模式. PDO 将只简单地设置错误码,可使用 PDO::errorCode() 和 PDO::errorInfo() 方法来检查语句和数据库对象.如果错 ...
- git 分支策略
转 http://www.ruanyifeng.com/blog/2012/07/git.html 作者: 阮一峰 如果你严肃对待编程,就必定会使用"版本管理系统"(Versio ...
- 【设计模式 - 2】之单例模式(Singleton)
1 模式简介 单例模式在代码中是非常常用的,如线程池.数据库连接.注册表.共享资源.一些非常消耗资源的组件,等等. 单例模式主要解决如下问题: 确保一个特殊类的实例是独一无二的: 确保这个类 ...
- MySQL字符串函数
字符串大写和小写转换 MySQL 字符串大写和小写转化函数有两对: lower(), uppper() 和 lcase(), ucase() mysql> select lower('DDD') ...
- BZOJ 1806 IOI2007 Miners 矿工配餐 动态规划
题目大意:将一个123序列拆分为两个子序列.定义每一个数的贡献值为以这个数结尾的长度最大为3的子串中不同数的数量,求贡献值和的最大值 令f[i][a1][a2][b1][b2]为前i个数分成两组,第一 ...
- android 54 播放音视频
mainActivity: package com.sxt.day07_09; import java.util.ArrayList; import java.util.HashMap; import ...
- Android(java)学习笔记201:网络图片浏览器的实现(ANR)
1.我们在Android下,实现使用http协议进行网络通信,请求网络数据.这里是获取网络上的图片信息,让它可以显示在手机上: 但是我们这个手机连接网络是很费时间,如果我们在主线程(UI线程)中写这个 ...
- (转载)记录函数 getStyle() 获取元素 CSS 样式
设置元素(element)的css属性值可以用element的style属性,例如要将element的背景色设置为黑色,可以这么做: element.style.backgroundColor = ' ...
- 第二天——hibernate讲完了
hibernate 逐步优化 第一步 只按照步骤来提取的 jre包导入错误 第二步 继续封装,把增删改查提取出来,同时进行代码的封装 HQL语句 be stranger in the code .be ...