急!贴出程序,关于corrupted double-linked list错误和aborted (core d

C++语言 码拜 8年前 (2017-05-08) 5652次浏览
C++新手,刚从学校出来实习,公司要求做一个分析pcap文件的小程序。
原理如下:
将每一个http的请求报文的host、URL、和其对应的tcp的源端口读取,写入list容器,接收到一个http响应报文,读取目的端口,与list容器里的源端口对比,对比成功则新建一个结构体将其对应的HOST和URL赋值给这个结构体,并删除list容器里的对应元素,假如这个响应报文携带数据,即状态码在200那一段的,以host为名字建立文件夹,并将数据写入这个文件夹,以URL命名。
现在的情况是 能建两个文件夹,也有文件写入但是不是按照预期写入,且有corrupted double-linked list和aborted (core dumped)报错。
各位大哥看看是什么原因,找了两天也不知道该怎么改。谢谢了!
前两个是请求报文和响应报文的数据写入,算测试。
急!贴出程序,关于corrupted double-linked list错误和aborted (core d
急!贴出程序,关于corrupted double-linked list错误和aborted (core d
急!贴出程序,关于corrupted double-linked list错误和aborted (core d
急!贴出程序,关于corrupted double-linked list错误和aborted (core d
红色框出来的是创建的文件夹
急!贴出程序,关于corrupted double-linked list错误和aborted (core d
下面贴代码:
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
解决方案

100

本人试了下,这个程序很多隐患,一有逻辑错误segmentation fault,生成core dump。
先打开系统生成core:
ulimit -c unlimited
带上-g参数
g++ main.cpp -g
崩溃会产生core文件,运行:
gdb a.out core
进入gdb,输入backtrace可以看到堆栈信息,基本上就是那一行出问题,肯定是空指针,去做响应的修改,一直修改直到程序正常。
若要看汇编,直接敲入 layout asm可以查看汇编。
刚开始学者更应该学习调试技巧,不是一句不熟就可以掩盖过去,这都得靠本人。

CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明急!贴出程序,关于corrupted double-linked list错误和aborted (core d
喜欢 (1)
[1034331897@qq.com]
分享 (0)