RT,当客户机第一次上网的时候,要302到一个广告页面,用winpcap抓包,libnet拼装包并发送,但每次调用libnet_write发送拼装好的包的时候,pcap_loop会报缓冲区溢出的错误,搞不定了...向各位大神求助...代码如下...(代码是本机上做测试用的,重定向到百度...嗯..不要在意这些细节...) 代码如下: // Test.cpp : 定义控制台应用程序的入口点。 //
#include "stdafx.h" #include "Test.h" #include "libnet/libnet-headers.h" #include "libnet/libnet-functions.h"
#ifdef _DEBUG #define new DEBUG_NEW #endif
#define HTTP_PORT 0x5000 #define TCP_WID_SIZE 4096
typedef struct libnet_ipv4_hdr IPHeader; typedef struct libnet_tcp_hdr TCPHeader; typedef struct libnet_ethernet_hdr EthernetHeader;
typedef uint32_t u_int32_t; typedef uint16_t u_int16_t; typedef uint8_t u_int8_t;
void analyzePackage(const u_char* packageData); // 唯一的应用程序对象
CWinApp theApp;
static pcap_t *adhandle; int listener(); void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data);
using namespace std;
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { int nRetCode = 0;
HMODULE hModule = ::GetModuleHandle(NULL);
if (hModule != NULL) { // 初始化 MFC 并在失败时显示错误 if (!AfxWinInit(hModule, NULL, ::GetCommandLine(), 0)) { // TODO: 更改错误代码以符合您的需要 _tprintf(_T("错误: MFC 初始化失败n")); nRetCode = 1; } else { // TODO: 在此处为应用程序的行为编写代码。 listener(); //openNetDevice(); } } else { // TODO: 更改错误代码以符合您的需要 _tprintf(_T("错误: GetModuleHandle 失败n")); nRetCode = 1; }
return nRetCode; }
static char* dev_name=NULL;
u_int8_t httpContent[] = "HTTP/1.0 302 Foundn" "Location: %sn" "Connection:closenn" "<html>nt<head>ntt<meta http-equiv="Refresh"content="0 ; " "url=www.baidu.com">nt</head>n</html>n";
static int fl = 0; static libnet_t* libnet = NULL; void openNetDevice() { static char buf[LIBNET_ERRBUF_SIZE];
printf("%s",dev_name+8); libnet = libnet_init(LIBNET_RAW4,(dev_name+8), buf);
if(NULL==libnet){ printf(buf); } }
void createTcpHeader(u_char* tcpPackage,u_int8_t flag,u_int8_t* httpContent){ TCPHeader *tcp = (TCPHeader*)tcpPackage; u_int32_t seq = libnet_get_prand(LIBNET_PRu32); u_int32_t ack = tcp->th_seq; ack++; size_t httpSize = httpContent!=NULL?strlen((const char*)httpContent):0; int fla= libnet_build_tcp(ntohs(tcp->th_dport),ntohs(tcp->th_sport),ntohl(seq),ntohl(ack),flag,TCP_WID_SIZE,0,0,20+httpSize, httpContent!=NULL?httpContent:NULL,httpSize,libnet,0); }
void createIpHeader(u_char* ipPackage,u_int16_t httpContentSize){ IPHeader *ip = (IPHeader*)ipPackage; u_int16_t ipLength = 40; u_int8_t typeOfService = 0; u_int8_t identification = 0; u_int16_t frag = 0x4000; u_int8_t timeToLive = 63; u_int8_t protocol =IPPROTO_TCP; u_int16_t checkSum = 0;//设置为0,libnet会自动计算校验和 u_int32_t sourceIpAddr =ip->ip_dst.S_un.S_addr; u_int32_t destinationIpAddr = ip->ip_src.S_un.S_addr; int re = libnet_build_ipv4(ipLength ,typeOfService, identification,frag, timeToLive, IPPROTO_TCP,checkSum, sourceIpAddr,destinationIpAddr,NULL,0, libnet, 0); }
void createEthernetHeader(u_char* ethernetHeaderData){ EthernetHeader *ethernetHeader = (EthernetHeader*)ethernetHeaderData; libnet_ptag_t ethernet_protocol_tag = 0; libnet_build_ethernet(ethernetHeader->ether_shost,ethernetHeader->ether_dhost, ETHERTYPE_IP,0,NULL,libnet,ethernet_protocol_tag);
}
void sendPackage(){ pcap_breakloop(adhandle); if(libnet==NULL){printf("libnet context is NULL");return;} fl = libnet_write(libnet); //if(fla==0)return; libnet_clear_packet(libnet); libnet_close_raw4(libnet); libnet_destroy(libnet); }
void analyzePackage(const u_char* packageData){ EthernetHeader *ethernetHeader = (EthernetHeader*)packageData; IPHeader *requestIp = (IPHeader*)(packageData+14); TCPHeader *requestTcp = (TCPHeader*)((u_char*)requestIp+(requestIp->ip_hl&0xf)*4);//包数据数组偏移ip头长度 if(requestIp->ip_p==IPPROTO_TCP/*&&requestTcp->th_dport==HTTP_PORT*/){ libnet_t* libnet = NULL; if(requestTcp->th_flags == TH_SYN){ pcap_breakloop(adhandle); /******************************** * 对于这样的一个握手数据包 * 我们应该要建立连接了 * 回复一个syn ack 就是了 *********************************/ openNetDevice(); createTcpHeader((u_char*)requestTcp,TH_ACK|TH_SYN,NULL); createIpHeader((u_char*)requestIp,0); createEthernetHeader((u_char*)ethernetHeader); sendPackage();
} else if (requestTcp->th_flags == (TH_ACK|TH_SYN)) { openNetDevice(); createTcpHeader((u_char*)requestTcp,TH_ACK|TH_PUSH|TH_FIN,httpContent); size_t httpSize = httpContent!=NULL?strlen((const char*)httpContent):0; createIpHeader((u_char*)requestIp,httpSize); createEthernetHeader((u_char*)ethernetHeader); sendPackage();
} } }
int listener(){ pcap_if_t *alldevs; pcap_if_t *d; int inum; int i=0; char errbuf[PCAP_ERRBUF_SIZE]; u_int netmask; char packet_filter[] = "ip and tcp"; struct bpf_program fcode;
/* 获得设备列表 */ if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1) { fprintf(stderr,"Error in pcap_findalldevs: %sn", errbuf); exit(1); }
/* 打印列表 */ for(d=alldevs; d; d=d->next) { printf("%d. %s", ++i, d->name); if (d->description) printf(" (%s)n(%s)n",d->name, 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);
if(inum < 1 || inum > i) { printf("nInterface number out of range.n"); /* 释放设备列表 */ pcap_freealldevs(alldevs); return -1; }
/* 跳转到已选设备 */ for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++); dev_name = new char[strlen(d->name)]; strcpy(dev_name , d->name); /* 打开适配器 */ if ( (adhandle= pcap_open(d->name, // 设备名 65536, // 要捕捉的数据包的部分 // 65535保证能捕获到不同数据链路层上的每个数据包的全部内容 PCAP_OPENFLAG_PROMISCUOUS, // 混杂模式 1000, // 读取超时时间 NULL, // 远程机器验证 errbuf // 错误缓冲池 ) ) == NULL) { fprintf(stderr,"nUnable to open the adapter. %s is not supported by WinPcapn"); /* 释放设备列表 */ pcap_freealldevs(alldevs); return -1; }
/* 检查数据链路层,为了简单,我们只考虑以太网 */ if(pcap_datalink(adhandle) != DLT_EN10MB) { fprintf(stderr,"nThis program works only on Ethernet networks.n"); /* 释放设备列表 */ pcap_freealldevs(alldevs); return -1; }
if(d->addresses != NULL) /* 获得接口第一个地址的掩码 */ netmask=((struct sockaddr_in *)(d->addresses->netmask))->sin_addr.S_un.S_addr; else /* 如果接口没有地址,那么我们假设一个C类的掩码 */ netmask=0xffffff;
//编译过滤器 if (pcap_compile(adhandle, &fcode, packet_filter, 1, netmask) <0 ) { fprintf(stderr,"nUnable to compile the packet filter. Check the syntax.n"); /* 释放设备列表 */ pcap_freealldevs(alldevs); return -1; }
//设置过滤器 if (pcap_setfilter(adhandle, &fcode)<0) { fprintf(stderr,"nError setting the filter.n"); /* 释放设备列表 */ pcap_freealldevs(alldevs); return -1; }
printf("nlistening on %s...n", d->description);
/* 释放设备列表 */ pcap_freealldevs(alldevs); /* 开始捕捉 */ printf(errbuf); pcap_loop(adhandle,0, packet_handler, NULL);
return 0; }
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data) { analyzePackage(pkt_data); }
|
引用来自“zengraoli”的评论
最终怎么处理的?用到了你的代码,不过也没解决问题
=====================================================
我自己并不是太了解,打算今晚开始弄,初步判断你这边是windows的环境问题;
windows对LIBNET_RAW4支持不好,换成LINK的试试,或者直接在linux用LIBNET_RAW4;
晚上我去测一下,如果弄好,我把代码发出来,多谢你给的部分代码,很有用,省了不少时间!