winpcap抓包,如何判断这个包是否是HTTP的包?

sugarforever 2006-09-03 10:56:34
如题.多谢大虾指导
...全文
1876 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
Arthur_ 2006-09-06
  • 打赏
  • 举报
回复
shi
sugarforever 2006-09-05
  • 打赏
  • 举报
回复
那我是从tcp数据的第一位开始字符串匹配HTTP, CONTENT等东西吗?
Arthur_ 2006-09-05
  • 打赏
  • 举报
回复
格式是固定的,查一下就可以了,一般包括 HTTP/1.0,返回码应该是200以上,content
sugarforever 2006-09-05
  • 打赏
  • 举报
回复
没有人能给予更多的知道吗?
比如我应该如何解出HTTP头呢?
sugarforever 2006-09-04
  • 打赏
  • 举报
回复
光用端口号应该不行吧。
比如我开个qq。默认登陆的时候,是连接的某个服务器的。
那么通过抓包可以发现,qq是会不断地在80端口上发包的。
如果我用IE连接新浪等,那它也是走的80端口。我这个时候这两种包都会抓到,我如何判断哪种是http包呢?
寡人对TCP/IP没有深入的理解。望大虾们指教。
OOPhaisky 2006-09-04
  • 打赏
  • 举报
回复
在应用层是利用端口号来进行“复用/解复用”的,而不是利用协议号,这个楼主应该知道吧
OOPhaisky 2006-09-04
  • 打赏
  • 举报
回复
你既然获得完整的包了,那么就可以利用端口号判断一下是什么应用程序啊......
sugarforever 2006-09-04
  • 打赏
  • 举报
回复
继续请教,我现在已经抓下。

#include "pcap.h"
#include <string>

/* 4 bytes IP address */
typedef struct ip_address
{
u_char byte1;
u_char byte2;
u_char byte3;
u_char byte4;
}ip_address;

/* IPv4 header */
typedef struct ip_header
{
u_char ver_ihl; // Version (4 bits) + Internet header length (4 bits)
u_char tos; // Type of service
u_short tlen; // Total length
u_short identification; // Identification
u_short flags_fo; // Flags (3 bits) + Fragment offset (13 bits)
u_char ttl; // Time to live
u_char proto; // Protocol
u_short crc; // Header checksum
ip_address saddr; // Source address
ip_address daddr; // Destination address
u_int op_pad; // Option + Padding
}ip_header;

/* TCP header*/
typedef struct tcp_header
{
u_short sport; // Source port
u_short dport; // Destination port
u_int seq_num; // sequence number
u_int ack_num; // acknowledgement number
u_short hdr_len_resv_code; // Datagram length
u_short window; // window
u_short crc; // Checksum
u_short urg_pointer; // urgent pointer
u_int opt_pad; // options and padding
}tcp_header;

/* prototype of the packet handler */
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data);

/* send packet */
void packet_sender(pcap_t* fp, u_char* packet, int len);

pcap_t* handler = NULL;

main()
{
pcap_if_t *alldevs;
pcap_if_t *d;
int inum;
int i=0;
pcap_t *adhandle;
char errbuf[PCAP_ERRBUF_SIZE];
u_int netmask;
char packet_filter[] = "ip and tcp";
struct bpf_program fcode;

/* Retrieve the device list */
if(pcap_findalldevs(&alldevs, errbuf) == -1)
{
fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
exit(1);
}

/* Print the list */
for(d=alldevs; d; d=d->next)
{
printf("%d. %s", ++i, d->name);
if (d->description)
printf(" (%s)\n", d->description);
else
printf(" (No description available)\n");
}

if(i==0)
{
printf("\nNo interfaces found! Make sure WinPcap is installed.\n");
return -1;
}

printf("Enter the interface number (1-%d):",i);
scanf("%d", &inum);

/* Check if the user specified a valid adapter */
if(inum < 1 || inum > i)
{
printf("\nAdapter number out of range.\n");

/* Free the device list */
pcap_freealldevs(alldevs);
return -1;
}

/* Jump to the selected adapter */
for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++);

/* Open the adapter */
if ((adhandle= pcap_open_live(d->name, // name of the device
65536, // portion of the packet to capture.
// 65536 grants that the whole packet will be captured on all the MACs.
1, // promiscuous mode (nonzero means promiscuous)
1000, // read timeout
errbuf // error buffer
)) == NULL)
{
fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n");
/* Free the device list */
pcap_freealldevs(alldevs);
return -1;
}
handler = adhandle;
/* Check the link layer. We support only Ethernet for simplicity. */
if(pcap_datalink(adhandle) != DLT_EN10MB)
{
fprintf(stderr,"\nThis program works only on Ethernet networks.\n");
/* Free the device list */
pcap_freealldevs(alldevs);
return -1;
}

if(d->addresses != NULL)
/* Retrieve the mask of the first address of the interface */
netmask=((struct sockaddr_in *)(d->addresses->netmask))->sin_addr.S_un.S_addr;
else
/* If the interface is without addresses we suppose to be in a C class network */
netmask=0xffffff;


//compile the filter
if (pcap_compile(adhandle, &fcode, packet_filter, 1, netmask) <0 )
{
fprintf(stderr,"\nUnable to compile the packet filter. Check the syntax.\n");
/* Free the device list */
pcap_freealldevs(alldevs);
return -1;
}

//set the filter
if (pcap_setfilter(adhandle, &fcode)<0)
{
fprintf(stderr,"\nError setting the filter.\n");
/* Free the device list */
pcap_freealldevs(alldevs);
return -1;
}

printf("\nlistening on %s...\n", d->description);

/* At this point, we don't need any more the device list. Free it */
pcap_freealldevs(alldevs);

/* start the capture */
pcap_loop(adhandle, 0, packet_handler, NULL);

return 0;
}

void packet_sender(pcap_t* fp, const u_char* packet, int len)
{
int ret = 0;
if(fp != NULL && packet != NULL)
ret = pcap_sendpacket(fp, packet, len);
if(ret != 0)
printf("\nError sending packet: %s\n", pcap_geterr(fp));
}

/* Callback function invoked by libpcap for every incoming packet */
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data)
{
struct tm *ltime;
char timestr[16];
ip_header *ih;
const char* http = "http";
std::string body;
tcp_header *th;
u_int ip_len;
u_int tcp_len;
u_short sport,dport;
u_int tcpbd_len;

/* retireve the position of the ip header */
ih = (ip_header *) (pkt_data +
14); //length of ethernet header

/* retireve the position of the udp header */
ip_len = (ih->ver_ihl & 0xf) * 4;
th = (tcp_header *) ((u_char*)ih + ip_len);
tcp_len = ((th->hdr_len_resv_code & 0xf000) >> 12) * 4;
tcpbd_len = ih->tlen - ip_len - tcp_len;

char* tmp = new char[tcpbd_len + 1];
memcpy(tmp, ((u_char*)th + tcp_len), tcpbd_len);
tmp[tcpbd_len] = '\0';

body = tmp;
delete[] tmp;
std::string::size_type pos = body.find(http);

if(pos != std::string::npos)
{
/* convert the timestamp to readable format */
ltime=localtime(&header->ts.tv_sec);
strftime( timestr, sizeof timestr, "%H:%M:%S", ltime);

/* print timestamp and length of the packet */
printf("%s.%.6d len:%d \n", timestr, header->ts.tv_usec, header->len);

/* convert from network byte order to host byte order */
sport = ntohs( th->sport );
dport = ntohs( th->dport );

/* print ip addresses and udp ports */
printf("%d.%d.%d.%d.%d -> %d.%d.%d.%d.%d\n",
ih->saddr.byte1,
ih->saddr.byte2,
ih->saddr.byte3,
ih->saddr.byte4,
sport,
ih->daddr.byte1,
ih->daddr.byte2,
ih->daddr.byte3,
ih->daddr.byte4,
dport);
//}

/* send packet again */
if(handler)
packet_sender(handler, pkt_data, header->len);
}

这是我的代码,我是先剥ethernet header,然后是ip header,然后是tcp header,然后取到tcp包的数据部分。那我如何读取body中的信息呢?我上面的find方法肯定是不行的吧.
sugarforever 2006-09-04
  • 打赏
  • 举报
回复
谢谢wanfustudio(雁南飞)的解答。
winpcap可以设置filter只抓tcp包。所以分析协议类型ip_hdr->ip_p(就这个意思)
如果是6: TCP协议 这一步可以省略了。所谓的分析端口是源端口吧?这样一定能唯一确定吗?还是有点觉得不实在。
飞哥 2006-09-04
  • 打赏
  • 举报
回复
去掉以太帧头 +14
就是IP包了
分析协议类型ip_hdr->ip_p(就这个意思)
如果是6: TCP协议
去掉IP头 + 20
就是TCP包
分析端口:80
就可以了
Duwchy 2006-09-03
  • 打赏
  • 举报
回复
查看一下抓的包的内容,HTTP包都包含HTTP头等html代码
打开链接下载源码: https://pan.quark.cn/s/847069bb2538 标题中所提及的“EPSON L1118 L1119 L3106 L3108 L3115 L3116废墨清零软件+带教程说明.rar”具体指代的是为爱普生(EPSON)品牌下特定系列打印机量身定制的废墨清零专用程序,该系列打印机型号涵盖了L1118、L1119、L3106、L3108、L3115以及L3116等。 废墨清零作为打印机维护过程中的关键步骤,其核心作用在于处理因打印头清洁周期内累积的废墨所引发的打印机故障报警或工作中断现象。 文件描述部分与标题信息保持一致,进一步明确了该压缩文件内含的是针对上述指定型号打印机的废墨计数器重置工具,并且同步提供了操作教程,旨在辅助用户顺利完成软件应用。 在所标注的标签信息中,诸如“L1118废墨清零”之类的关键词,清晰表明了该软件套件是专门为这些特定型号打印机研发的,其根本目的在于清除设备内部记录的废墨数据,从而恢复打印机的标准作业效能。 在压缩文件内部署的文件清单如下:1. DataServiceLapper.dll:此文件可能扮演着服务管理层的动态链接库角色,主要负责处理打印机的相关数据服务,其中可能集成有废墨计数器重置的核心功能。 2. apdadrv.dll:该文件或许属于打印机驱动程序的构成部分,主要功能在于实现软件与打印机硬件之间的交互通讯,用于下达清零指令。 3. StrGene.dll:此动态链接库可能涉及字符串操作或数据加密的相关功能,其用途可能在于验证软件的合法性或保障数据传输的安全性。 4. Adjprog.exe:此文件极有可能为主控程序,用户需通过执行该可执行文件来启动废墨清零流程。 5. 使用说明.txt:该文本文件提供了软...
内容概要:本文深入解析了pytest自动化测试实战项目在软件行业中的应用,涵盖其核心特性、关键技术与实际应用场景。通过构建一个用户管理微服务的API测试项目,详细展示了如何利用pytest的Fixture机制、参数化测试、插件体系和标记系统实现高效、可维护的自动化测试框架。文章强调模块化设计、数据驱动测试及与持续集成系统的无缝整合,并结合具体代码案例阐述最佳实践,最后展望了AI赋能、云原生适配等未来发展方向。; 适合人群:具备Python基础、从事测试或开发工作的工程师,尤其是希望提升自动化测试能力的测试开发人员、QA工程师及DevOps从业者;适合工作1-3年、有一定实践经验的技术人员。; 使用场景及目标:① 掌握pytest在API测试、UI自动化、微服务集成中的落地方法;② 学习如何通过fixture复用、参数化和分层设计提升测试效率与可维护性;③ 将pytest集成到CI/CD流水线中,实现快速反馈与高质量交付。; 阅读建议:此资源以真实项目为导向,建议读者结合代码结构动手实践,重点理解fixture作用域、数据驱动设计与异常断言策略,并尝试引入pytest-cov、pytest-xdist等插件优化测试流程,在实践中掌握从零搭建企业级测试框架的能力。
源码链接: https://pan.quark.cn/s/69b5c1f90e9a Redis作为一款具备出色性能的键值型数据库,在多种应用场景中,如数据缓存与消息队列处理,得到了广泛的应用。在实际环境中部署时,为了保障服务的持续稳定以及资源的高效利用,常常会选用在后台模式下执行Redis。这种后台执行模式能够确保Redis在不干扰终端操作的前提下运行,从而增强整个系统的适应性。文章标题“redis后台启动redis后台启动”明确指出本主题的核心内容是关于如何在后台环境下来启动Redis服务器。描述部分“redis后台启动命令加对应redis.vbe。修改路径然后直接点击”给出了初步的操作指引,但对于初次接触的用户来说,可能显得不够详尽。接下来将全面阐释Redis后台启动的详细流程,并进一步探讨相关的技术要点。1. Redis后台启动指令: Redis在后台模式下启动通常借助`redis-server`指令并配合`--daemonize yes`参数实现。在命令行输入以下指令: ``` redis-server --daemonize yes ``` 此指令将使Redis以守护进程(daemon)的形式执行,即在后台运行且不占用终端界面。2. 配置文件的调整: 通常情况下,Redis的配置文件命名为`redis.conf`。在文件中找到`daemonize`选项,将其参数值设置为`yes`,随后保存并退出。通过这种方式配置后,每次启动Redis时,都会默认采用后台运行模式。启动命令可以简化为: ``` redis-server ```3. 日志文件的配置: 当Redis以守护进程形式运行时,其日志信息会被重定向至`stdout`和`stderr`。为了便...

65,210

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧