求助!c++在win7下使用winpcap+libnet发送数据包,报缓冲区溢出错误。!

保护单身狗协会理事长_退休 发布于 2014/04/02 09:34
阅读 1K+
收藏 0

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 Found\n"
"Location: %s\n"
"Connection:close\n\n"
"<html>\n\t<head>\n\t\t<meta http-equiv=\"Refresh\"content=\"0 ; "
"url=www.baidu.com\">\n\t</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: %s\n", 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 WinPcap\n");
/* 释放设备列表 */
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);
}



加载中
0
calvary
calvary

 人才啊。。

保护单身狗协会理事长_退休
保护单身狗协会理事长_退休
赚车钱…没办法…
0
zengraoli
zengraoli

最终怎么处理的?用到了你的代码,不过也没解决问题

0
zengraoli
zengraoli

引用来自“zengraoli”的评论

最终怎么处理的?用到了你的代码,不过也没解决问题

=====================================================

我自己并不是太了解,打算今晚开始弄,初步判断你这边是windows的环境问题;

windows对LIBNET_RAW4支持不好,换成LINK的试试,或者直接在linux用LIBNET_RAW4;

晚上我去测一下,如果弄好,我把代码发出来,多谢你给的部分代码,很有用,省了不少时间!

返回顶部
顶部