原理如下:
将每一个http的请求报文的host、URL、和其对应的tcp的源端口读取,写入list容器,接收到一个http响应报文,读取目的端口,与list容器里的源端口对比,对比成功则新建一个结构体将其对应的HOST和URL赋值给这个结构体,并删除list容器里的对应元素,如果这个响应报文携带数据,即状态码在200那一段的,以host为名字建立文件夹,并将数据写入这个文件夹,以URL命名。
现在的情况是 能建两个文件夹,也有文件写入但是不是按照预期写入,且有corrupted double-linked list和aborted (core dumped)报错。
各位大哥看看是什么原因,找了两天也不知道该怎么改。谢谢了!!!!
前两个是请求报文和响应报文的数据写入,算测试。
红色框出来的是创建的文件夹
下面贴代码:
main.cpp
#include "pcap.h"
#include "method.hpp"
#include <iostream>
#include <memory.h>
#include <string>
#include <vector>
#include <list>
#include <cstdio>
#include <fstream>
#include <iomanip>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <stdio.h>
using namespace std;
int main(int argc, char *argv[]){
int a=1 ,b = 1,i=1;
pcap_header pcap_head_buf;
pkt_header pkt_head_buf;
ip_header ip_head_buf;
tcp_header tcp_head_buf;
u_int16 srcport_buf;
u_int16 dstport_buf;
FILE *fp = NULL;
if (fopen("/home/yiyada/http/http7.pcap", "rb") == NULL){
printf("Fail to open the file");
}else
fp = fopen("/home/yiyada/http/http7.pcap", "rb");
getPcapFileHead(fp, pcap_head_buf);
fseek(fp, 0, SEEK_END);//改变流指针位置,失败不改变
long fileSize = ftell(fp);
long fpOffset = sizeof(pcap_header);
fseek(fp, fpOffset, SEEK_SET);//回调指针
/*!!*/
list <HttpList1> httplist;
/*!!*/
while ((fseek(fp, fpOffset, SEEK_SET) == 0) && (fpOffset < fileSize)){//循环处理每一个Pkt_Header
getPktHead(fp, pkt_head_buf);
fpOffset += (sizeof(pkt_header)+pkt_head_buf.caplen);
//fpOffset 当前位置 +sizeof( pkt_header) +sizeof (pkt_data) ,得到下一网络帧的 offset
u_int16 framType = getFramType(fp, pcap_head_buf.linktype);
if (framType == 0xdd86){//IPV6链接 , 跳过该网络帧
continue;
}
else{
getIpHead(fp, ip_head_buf);
if (ip_head_buf.Protocol != 0x06){// Protocol != 0x06 表示非TCP链接 , 跳过该网络帧
continue;
}
else { //TCP 链接类型
getTcpHead(fp, tcp_head_buf);
fseek(fp, -20, SEEK_CUR);
fread(&srcport_buf, 2, 1, fp);
fread(&dstport_buf, 2, 1, fp);
fseek(fp, 16, SEEK_CUR);
long tcp_data_size = fpOffset - ftell(fp);
// 当前位置在一个 tcp_header 后 ,fpOffset - 当前位置 得到 tcp_data 的长度
if(tcp_data_size != 0)
{
u_int8 tempBuf[4];
u_int8 tempBuf2[12];
string methodBuf;//似乎没有用
string urlBuf;
string hostBuf;
string uaBuf;
fread(tempBuf, 4, 1, fp);
fseek(fp, -4, SEEK_CUR);
char tcp_data_buf[100000];//总的传输字节数应该小于100000
memset(tcp_data_buf, 0, sizeof(tcp_data_buf) / sizeof(char));//内存清空
if((tempBuf[0] == 0x50 && tempBuf[1] == 0x4f && tempBuf[2] == 0x53 && tempBuf[3] == 0x54) ||
(tempBuf[0] == 0x47 && tempBuf[1] == 0x45 && tempBuf[2] == 0x54)
)//两个条件分别表示"POST"和"GET",判断成功表明该网络帧包含了一个http,get或者post链接
{
fread(tcp_data_buf, tcp_data_size, 1, fp);
matchHttp(tcp_data_buf, methodBuf, urlBuf, hostBuf, uaBuf);
/*!!*/
HttpList1 node = { urlBuf,hostBuf,srcport_buf };
httplist.push_back(node);//将请求报文加入list
/*!!!!!!!!!!!*/
//写请求报文
ofstream f1("/home/yiyada/http/request_msg.txt", ios::app); //打开文件用于写,若文件不存在就创建它
if (!f1)return 0; //打开文件失败则结束运行
f1 << "No." << a << endl;
f1 << "URL:"<<hostBuf+urlBuf<< endl;
f1 << "user-agent:" << uaBuf << endl;
f1 << "===========+===========+===========+===========" << endl;
f1.close();
a++;
}
else//写响应报文
{
fread(tempBuf2, 12, 1, fp);
fseek(fp, -12, SEEK_CUR);
if (tempBuf2[0] == 0x48 && tempBuf2[1] == 0x54 && tempBuf2[2] == 0x54 && tempBuf2[3] == 0x50 && tempBuf2[4] == 0x2f && tempBuf2[5] == 0x31 && tempBuf2[6] == 0x2e && tempBuf2[7] == 0x31 && tempBuf2[8] == 0x20 && tempBuf2[9] == 0x32 && tempBuf2[10] == 0x30 && ( 0<= tempBuf2[11] <=9 )){//HTTP/1.1 202判断
fread(tcp_data_buf, tcp_data_size, 1, fp);
char *data;
if (strstr(tcp_data_buf, "\r\n\r\n") == NULL)
cout << "error" << endl;
else
{
data = strstr(tcp_data_buf, "\r\n\r\n");
}
HttpList2 index_http=analyse(httplist,srcport_buf);//找到对应响应报文并删除
if(opendir(index_http.host.c_str())==NULL){
mkdir(index_http.host.c_str(),S_IRWXU|S_IRWXG|S_IRWXO);
}
ofstream out("/home/yiyada/http/res_msg.txt", ios::app);//打开文件用于写,若文件不存在就创建它
if (!out)return 0; //打开文件失败则结束运行
out << (data+4) << endl;
out.close();
rename("/home/yiyada/http/res_msg",index_http.URL.c_str());
ofstream f1("/home/yiyada/http/response_msg.txt", ios::app);//打开文件用于写,若文件不存在就创建它
if (!f1)return 0; //打开文件失败则结束运行
f1 << "No." << b << endl;
f1 << (data+4) << endl;
f1 << "===========+===========+===========+===========" << endl;
f1.close();
b++;
}
}
}
}
}
}
return 0;
}
method.hpp
#ifndef METHOD_H
#define METHOD_H
#include "pcap.h"
#include <cstdio>
#include <iostream>
#include <vector>
#include <string>
#include <list>
using namespace std;
typedef struct HttpList1 {
string URL;
string host;
u_int16 port;
}HttpList1;
typedef struct HttpList2 {
string URL;
string host;
}HttpList2;
void getPcapFileHead(FILE *fp, pcap_header &pcap_head){
fread(&pcap_head, sizeof(pcap_header), 1, fp);//返回真实写入的项数
}
void getPktHead(FILE *fp, pkt_header &pkt_head){
fread(&pkt_head, sizeof(pkt_header), 1, fp);
}
u_int32 getFramType(FILE *fp, u_int32 linktype){
if (linktype == 0x71){
Linux_cooked_capture temp;
fread(&temp, sizeof(temp), 1, fp);
return temp.FrameType;
}
else if (linktype == 0x01){
Ethernet temp;
fread(&temp, sizeof(temp), 1, fp);
return temp.FrameType;
}
else
return linktype;
}
void getIpHead(FILE *fp, ip_header &ip_head_buf){
fread(&ip_head_buf, sizeof(ip_header), 1, fp);
}
void getTcpHead(FILE *fp, tcp_header &tcp_head_buf){
fread(&tcp_head_buf, sizeof(tcp_header), 1, fp);
}
//请求报文
void matchHttp(char tcp_data_buf[], string&methodBuf, string&urlBuf, string&hostBuf, string&uaBuf){
vector <string> tempStrVector;//声明容器
string tempSring(tcp_data_buf);
for (string::size_type beginPos = 0; beginPos != tempSring.size();){
string::size_type endPos = beginPos;
while (++endPos && endPos != tempSring.size()){
if (tempSring[endPos] == '\n'){
break;
}
}
tempStrVector.push_back(tempSring.substr(beginPos, endPos - beginPos));//一行一行的存入
if (endPos == tempSring.size()){
break;
}
beginPos = endPos;
}//把数据存入VECTOR
for (vector <string>::iterator posVector = tempStrVector.begin(); posVector != tempStrVector.end(); ++posVector){
if (string::size_type tempPos = (*posVector).find("GET") != (*posVector).npos){
methodBuf = "GET";
string::size_type endPos = (*posVector).find("HTTP/1.1");
urlBuf = (*posVector).substr(tempPos + sizeof("GET") - 1, endPos - tempPos - sizeof("GET"));
} // “ GET ” 和 “ HTTP/1.1” 之间字符串为 url
if (string::size_type tempPos = (*posVector).find("POST") != (*posVector).npos){
string::size_type endPos = (*posVector).find("HTTP/1.1");
methodBuf = "POST";
urlBuf = (*posVector).substr(tempPos + sizeof("POST") - 1, endPos - tempPos - sizeof("POST"));
} // “ POST ” 和 “ HTTP/1.1” 之间的字符串为 url
if (string::size_type tempPos = (*posVector).find("Host:") != (*posVector).npos){
hostBuf = (*posVector).substr(tempPos + sizeof("Host:"));
} //" Host:" 后的字符串为 host
if (string::size_type tempPos = (*posVector).find("User-Agent:") != (*posVector).npos){
uaBuf = (*posVector).substr(tempPos + sizeof("User-Agent:"));
} // " User-Agent:" 后的字符串为 ua
}
}
//响应报文
HttpList2 analyse(list<HttpList1>& httplist,u_int16 srcport_buf){
list < HttpList1 > ::iterator lis = httplist.begin();
for (lis = httplist.begin(); lis != httplist.end(); ++lis){
if ((*lis).port==srcport_buf) {
HttpList2 found_req = {(*lis).URL,(*lis).host};
lis = httplist.erase(lis);
return found_req;
}
}
}
#endif
pcap.h
#ifndef DEFINEPCAP_H
#define DEFINEPCAP_H
typedef unsigned int u_int32;
typedef unsigned short u_int16;
typedef unsigned char u_int8;
typedef int int32;
typedef struct pcap_header{
u_int32 magic;
u_int16 Ver_major;
u_int16 Ver_minor;
int32 thiszone;
u_int32 sigfigs;
u_int32 snaplen;
u_int32 linktype;
}pcap_header;//占24字节
typedef struct timestamp{
u_int32 timestamp_s;
u_int32 timestamp_ms;
}timestamp;//时间戳
typedef struct pkt_header{
timestamp ts;
u_int32 caplen;
u_int32 len;
}pkt_header;
typedef struct Ethernet{
u_int8 DstMAC[6];//目的MAC地址
u_int8 SrcMAC[6];//源MAC地址
u_int16 FrameType;//以太网帧类型
}Ethernet;//4字节
typedef struct Linux_cooked_capture{
u_int16 package_type;
u_int16 address_type;
u_int16 address_length;
u_int16 un_used[4];
u_int16 FrameType; //帧类型
}Linux_cooked_capture;//10字节
typedef struct ip_header{
u_int8 Ver_HLen;
u_int8 TOS;
u_int16 TotalLen;
u_int16 ID;
u_int16 Flag_Segment;
u_int8 TTL;
u_int8 Protocol;
u_int16 Checksum;
u_int32 SrcIP;
u_int32 DstIP;
}ip_header;//20字节
typedef struct tcp_header{
u_int16 SrcPort;
u_int16 DstPort;
u_int32 SeqNo;
u_int32 AckNo;
u_int8 HeaderLen;//数据报头的长度(4 bit) + 保留(4 bit)
u_int8 Flags;
u_int16 Window;//窗口大小
u_int16 Checksum;//校验和
u_int16 UrgentPointer;//紧急指针
}tcp_header;//20字节
#endif
10 个解决方案
#1
为什么木有回复
#2
真的没有大哥可以帮看看吗 TAT
#3
有没有大佬可以来看看啊
#4
你要写抓包工具吧,代码太长,你可以使用gdb调试coredump,看看是哪一行代码导致崩溃,查看对应的变量内存,就可以找到原因。
#5
好的 我先试试,谢谢!!!
#6
可是这上面 的函数除了最后一个都不是我写的,我第一次用这种办法看,也看不出个所以然,请教 一下。
#7
点击第8行,也就是main那一行,监视相应的变量,运行错误只能靠调试,查看堆栈提示的行数存在的几个变量
#8
24行这个是 析构函数的问题吗。。。第一次 这样调试过,我也 看不懂。。。请教一下该如何发现这个问题在哪里呢?
#9
我试了下,这个程序很多隐患,一有逻辑错误segmentation fault,生成core dump。
先打开系统生成core:
ulimit -c unlimited
带上-g参数
g++ main.cpp -g
崩溃会产生core文件,运行:
gdb a.out core
进入gdb,输入backtrace可以看到堆栈信息,基本上就是那一行出问题,肯定是空指针,去做响应的修改,一直修改直到程序正常。
若要看汇编,直接敲入 layout asm可以查看汇编。
初学者更应该学习调试技巧,不是一句不熟就可以掩盖过去,这都得靠自己。
先打开系统生成core:
ulimit -c unlimited
带上-g参数
g++ main.cpp -g
崩溃会产生core文件,运行:
gdb a.out core
进入gdb,输入backtrace可以看到堆栈信息,基本上就是那一行出问题,肯定是空指针,去做响应的修改,一直修改直到程序正常。
若要看汇编,直接敲入 layout asm可以查看汇编。
初学者更应该学习调试技巧,不是一句不熟就可以掩盖过去,这都得靠自己。
#10
问题已经解决,一个函数参数传入的逻辑问题和 另一个函数 写法不规范
谢谢!!
#1
为什么木有回复
#2
真的没有大哥可以帮看看吗 TAT
#3
有没有大佬可以来看看啊
#4
你要写抓包工具吧,代码太长,你可以使用gdb调试coredump,看看是哪一行代码导致崩溃,查看对应的变量内存,就可以找到原因。
#5
好的 我先试试,谢谢!!!
#6
可是这上面 的函数除了最后一个都不是我写的,我第一次用这种办法看,也看不出个所以然,请教 一下。
#7
点击第8行,也就是main那一行,监视相应的变量,运行错误只能靠调试,查看堆栈提示的行数存在的几个变量
#8
24行这个是 析构函数的问题吗。。。第一次 这样调试过,我也 看不懂。。。请教一下该如何发现这个问题在哪里呢?
#9
我试了下,这个程序很多隐患,一有逻辑错误segmentation fault,生成core dump。
先打开系统生成core:
ulimit -c unlimited
带上-g参数
g++ main.cpp -g
崩溃会产生core文件,运行:
gdb a.out core
进入gdb,输入backtrace可以看到堆栈信息,基本上就是那一行出问题,肯定是空指针,去做响应的修改,一直修改直到程序正常。
若要看汇编,直接敲入 layout asm可以查看汇编。
初学者更应该学习调试技巧,不是一句不熟就可以掩盖过去,这都得靠自己。
先打开系统生成core:
ulimit -c unlimited
带上-g参数
g++ main.cpp -g
崩溃会产生core文件,运行:
gdb a.out core
进入gdb,输入backtrace可以看到堆栈信息,基本上就是那一行出问题,肯定是空指针,去做响应的修改,一直修改直到程序正常。
若要看汇编,直接敲入 layout asm可以查看汇编。
初学者更应该学习调试技巧,不是一句不熟就可以掩盖过去,这都得靠自己。
#10
问题已经解决,一个函数参数传入的逻辑问题和 另一个函数 写法不规范
谢谢!!