免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2638 | 回复: 1
打印 上一主题 下一主题

[C++] 求助!winpcap+libnet发送数据包,报缓冲区溢出错误。! [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2014-04-01 23:19 |只看该作者 |倒序浏览
RT,当客户机第一次上网的时候,要302到一个广告页面,用winpcap抓包,libnet拼装包并发送,但每次调用libnet_write发送拼装好的包的时候,pcap_loop会报缓冲区溢出的错误,搞不定了...向各位大神求助...代码如下...(代码是本机上做测试用的,重定向到百度...嗯..不要在意这些细节...)

#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+;
        libnet = libnet_init(LIBNET_RAW4,(dev_name+, 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 createHttp302(u_char* ipPackage, u_char* tcpPackage){
        createTcpHeader(tcpPackage,TH_ACK|TH_PUSH|TH_FIN,httpContent);
        size_t httpSize = httpContent!=NULL?strlen((const char*)httpContent):0;
        createIpHeader(ipPackage,httpSize);
}


void createACKTcpHeader(u_char* ipPackage, u_char* tcpPackage){
        createTcpHeader(tcpPackage,TH_ACK|TH_SYN,NULL);
        createIpHeader(ipPackage,0);
}

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();
                        createACKTcpHeader((u_char*)requestIp,( u_char*)requestTcp);
                        createEthernetHeader((u_char*)ethernetHeader);
                        sendPackage();

                }
                else if (requestTcp->th_flags == (TH_ACK|TH_SYN))
                {
                        openNetDevice();
                        createHttp302(( u_char*)requestIp,(u_char*)requestTcp);
                        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);
        /* 开始捕捉 */
       
        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
2 [报告]
发表于 2014-04-03 15:57 |只看该作者
自己搞定了...结贴...
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP