Qt 抓包 检测第三方应用登录(只检测本地网卡 排除虚拟网卡 和无线网卡)

场景:客户端收到指令,启动第三方应用,但是第三方应用的登录状态未知,而客户端需要根据这个状态来进行下一步操作

方案:利用winPcap 抓包,根据抓到的数据来判断第三方应用的登录状态

1,winpCap 配置 

winpcap在VS2012 Qt5 X64下的配置_Persisterfan的博客-CSDN博客

2,写一个类 用来检测

#ifndef SYSTEMAPI_H
#define SYSTEMAPI_H

#include <QObject>

#include <stdio.h>
#include <stdlib.h>
#define HAVE_REMOTE
#include <pcap.h>
#include "pheader.h"


using namespace std;

class SystemAPi : public QObject
{
    Q_OBJECT
public:
    explicit SystemAPi(QObject *parent = nullptr);
    ~SystemAPi();

    void startVidyo();

signals:
    void vidyoLoinSuccess();

public slots:

private:
    int detectVidyoLogin();//检测vidyo启动


    bool m_vidyoDetectRun;
};

#endif // SYSTEMAPI_H

#include "systemapi.h"
#include <QtConcurrent>
#include <QDebug>
#include "../../third_party/easyloggingpp/src/easylogging++.h"
SystemAPi::SystemAPi(QObject *parent) : QObject(parent)
  ,m_vidyoDetectRun(false)
{

}

SystemAPi::~SystemAPi()
{
    m_vidyoDetectRun=false;
}

void SystemAPi::startVidyo()
{
   QtConcurrent::run(this,&SystemAPi::detectVidyoLogin); //多线程运行
}

int SystemAPi::detectVidyoLogin()
{   
    QString curNetName;

    PIP_ADAPTER_INFO pAdapterInfo=NULL;
    PIP_ADAPTER_INFO pAdapter=NULL;
    DWORD dwRetVal=0;
    pAdapterInfo=(IP_ADAPTER_INFO*)malloc(sizeof(IP_ADAPTER_INFO));
    ULONG ulOutBufLen=sizeof(IP_ADAPTER_INFO);
    if(GetAdaptersInfo(pAdapterInfo,&ulOutBufLen)!=ERROR_SUCCESS)
    {
        GlobalFree(pAdapterInfo);
        pAdapterInfo=(IP_ADAPTER_INFO*)malloc(ulOutBufLen);
    }
    if((dwRetVal=GetAdaptersInfo(pAdapterInfo,&ulOutBufLen))==NO_ERROR)
    {
        pAdapter=pAdapterInfo;
        while(pAdapter)
        {
            if(strstr(pAdapter->Description,"PCI")>0 && pAdapter->Type==MIB_IF_TYPE_ETHERNET)
            {
                printf("______________________________________\n");
                printf("Name:%s\n",pAdapter->AdapterName);
                printf("Desc:%s\n",pAdapter->Description);

                curNetName = QString::fromStdString(pAdapter->AdapterName);
                for(UINT i=0;i<pAdapter->AddressLength;i++)
                {
                    printf("%02X%c",pAdapter->Address[i],i==pAdapter->AddressLength-1?'\n':'-');
                }
                printf("Type:%d\n",pAdapter->Type);
                printf("Address:%s\n",pAdapter->IpAddressList.IpAddress.String);
                printf("Mask:%s\n",pAdapter->IpAddressList.IpMask.String);
                printf("Gateway:%s\n",pAdapter->GatewayList.IpAddress.String);
            }
            pAdapter=pAdapter->Next;
        }
    }
    else
        printf("Call to GetAdaptersInfo failed!\n");
    
m_vidyoDetectRun=true;
    pcap_if_t* alldevs; // list of all devices
    pcap_if_t* d; // device you chose

    pcap_t* adhandle;

    char errbuf[PCAP_ERRBUF_SIZE]; //error buffer
    int i=0;
    int inum;

    struct pcap_pkthdr *pheader; /* packet header */
    const u_char * pkt_data; /* packet data */
    int res;

    /* pcap_findalldevs_ex got something wrong */
    if (pcap_findalldevs_ex(const_cast<char*>(PCAP_SRC_IF_STRING), NULL /* auth is not needed*/, &alldevs, errbuf) == -1)
    {
        fprintf(stderr, "Error in pcap_findalldevs_ex: %s\n", errbuf);
        exit(1);
    }

    /* print the list of all devices */
    for(d = alldevs; d != NULL; d = d->next)
    {
        printf("%d. %s", ++i, d->name); // print device name , which starts with "rpcap://"
        if(d->description){
            printf(" (%s)\n", d->description); // print device description

             LOG(INFO)<<"new device name"<<d->name<<"    "<<curNetName.toStdString();
            if(!QString(d->name).contains(curNetName,Qt::CaseInsensitive))//在a中查找b,如果不存在,
                printf("................not found\n");
            else{//否则存在。
                inum=i;
                printf("................found\n");

            }
        }
        else
            printf(" (No description available)\n");
    }

    /* no interface found */
    if (i == 0)
    {
        printf("\nNo interface 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++); /* jump to the selected interface */

    /* open the selected interface*/
    if((adhandle = pcap_open(d->name, /* the interface name */
                             65536, /* length of packet that has to be retained */
                             PCAP_OPENFLAG_PROMISCUOUS, /* promiscuous mode */
                             1000, /* read time out */
                             NULL, /* auth */
                             errbuf /* error buffer */
                             )) == NULL)
    {
        fprintf(stderr, "\nUnable to open the adapter. %s is not supported by Winpcap\n",
                d->description);
        return -1;
    }

    printf("\nListening on %s...\n", d->description);

    pcap_freealldevs(alldevs); // release device list

    /* capture packet */
    while((res = pcap_next_ex(adhandle, &pheader, &pkt_data)) >= 0) {

        if(!m_vidyoDetectRun)
            return -1;
        if(res == 0)
            continue; /* read time out*/

        ether_header * eheader = (ether_header*)pkt_data; /* transform packet data to ethernet header */
        if(eheader->ether_type == htons(ETHERTYPE_IP)) { /* ip packet only */
            ip_header * ih = (ip_header*)(pkt_data+14); /* get ip header */

            if(ih->proto == htons(TCP_PROTOCAL)) { /* tcp packet only */
                int ip_len = ntohs(ih->tlen); /* get ip length, it contains header and body */

                int find_http = false;
                char* ip_pkt_data = (char*)ih;
                int n = 0;
                char buffer[BUFFER_MAX_LENGTH];
                int bufsize = 0;

                for(; n<ip_len; n++)
                {
                    /* http get or post request */
                    if(!find_http && ((n+3<ip_len && strncmp(ip_pkt_data+n,"GET",strlen("GET")) ==0 )
                                      || (n+4<ip_len && strncmp(ip_pkt_data+n,"POST",strlen("POST")) == 0)) )
                        find_http = true;

                    /* http response */
                    if(!find_http && n+8<ip_len && strncmp(ip_pkt_data+n,"HTTP/1.1",strlen("HTTP/1.1"))==0)
                        find_http = true;

                    /* if http is found */
                    if(find_http)
                    {
                        buffer[bufsize] = ip_pkt_data[n]; /* copy http data to buffer */
                        bufsize ++;
                    }
                }
                /* print http content */
                if(find_http) {
                    buffer[bufsize] = '\0';
                    //printf("%s\n", buffer);
                    qDebug()<<"http content"<<QString(buffer);
                    if(strstr(buffer,"SearchMyContactsResponse")!=NULL&&strstr(buffer,"faultcode")==NULL){
                        qDebug()<<"vidyo login success................."<<QString(buffer);
                        printf("%s\n", buffer);
                        emit vidyoLoinSuccess();
                        m_vidyoDetectRun=false;
                    }else{

                    }
                }
            }
        }
    }
    return 0;
}

#ifndef PHEADER_H_INCLUDED
#define PHEADER_H_INCLUDED
/*
*
*/

#define ETHER_ADDR_LEN 6 /* ethernet address */
#define ETHERTYPE_IP 0x0800 /* ip protocol */
#define TCP_PROTOCAL 0x0600 /* tcp protocol */
#define BUFFER_MAX_LENGTH 65536 /* buffer max length */
#define true 1  /* define true */
#define false 0 /* define false */

/*
* define struct of ethernet header , ip address , ip header and tcp header
*/
/* ethernet header */
typedef struct ether_header {
    u_char ether_shost[ETHER_ADDR_LEN]; /* source ethernet address, 8 bytes */
    u_char ether_dhost[ETHER_ADDR_LEN]; /* destination ethernet addresss, 8 bytes */
    u_short ether_type;                 /* ethernet type, 16 bytes */
}ether_header;

/* four bytes ip address */
typedef struct ip_address {
    u_char byte1;
    u_char byte2;
    u_char byte3;
    u_char byte4;
}ip_address;

/* ipv4 header */
typedef struct ip_header {
    u_char ver_ihl;         /* version and ip header length */
    u_char tos;             /* type of service */
    u_short tlen;           /* total length */
    u_short identification; /* identification */
    u_short flags_fo;       // flags and fragment offset
    u_char ttl;             /* time to live */
    u_char proto;           /* protocol */
    u_short crc;            /* header checksum */
    ip_address saddr;       /* source address */
    ip_address daddr;       /* destination address */
    u_int op_pad;           /* option and padding */
}ip_header;

/* tcp header */
typedef struct tcp_header {
    u_short th_sport;         /* source port */
    u_short th_dport;         /* destination port */
    u_int th_seq;             /* sequence number */
    u_int th_ack;             /* acknowledgement number */
    u_short th_len_resv_code; /* datagram length and reserved code */
    u_short th_window;        /* window */
    u_short th_sum;           /* checksum */
    u_short th_urp;           /* urgent pointer */
}tcp_header;

#endif // PHEADER_H_INCLUDED

3,效果

参考:https://www.cnblogs.com/blacksword/archive/2012/03/22/2411624.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 要将自定义的软键盘与第三方应用结合起来,您需要实现一个 Input Method(输入法)模块,并在系统中注册。以下是一些一般性的步骤: 1. 实现 Input Method 模块:您需要编写一个 Qt 插件,实现 QInputMethod 接口,并在其中实现自定义键盘的逻辑。 2. 注册 Input Method 模块:将编写的 Input Method 模块注册到系统中。对于 Windows 平台,您可以使用注册表进行注册;对于 Linux 平台,您需要在 /usr/share/ibus/component/ 或 /usr/lib/x86_64-linux-gnu/qt5/plugins/platforminputcontexts/ 中创建相应的文件。 3. 测试 Input Method 模块:在第三方应用程序中测试输入法是否能够正常工作。您可以使用 Qt 提供的输入法测试工具,在命令行中输入 `qinputmethodtest` 启动,然后选择测试应用程序,并测试您的自定义软键盘是否正常工作。 4. 集成 Input Method 模块:在第三方应用程序中启用您的输入法。您可以在应用程序中使用 Qt 提供的输入法接口来管理输入法,例如 `QInputMethod::setEnabled(true)` 来启用输入法,或 `QInputMethod::queryFocusObject()` 来获取当前输入焦点所在的对象。 请注意,对于某些特定的第三方应用程序,您可能需要进行额外的定制化工作,以使您的输入法与其更好地集成。 ### 回答2: QT是一个跨平台的应用程序开发框架,提供了丰富的组件和工具来创建用户界面。在QT中,可以通过自定义软键盘来增强用户输入体验,并且可以与第三方应用结合。 首先,我们可以在QT中创建一个自定义软键盘的窗口,使用QT提供的按钮组件和布局管理器等组件来构建软键盘的界面。可以根据需要自定义按钮的样式和功能,例如数字、字母、符号等。 其次,在第三方应用中,我们可以通过QT提供的槽和信号机制来实现与自定义软键盘的交互。可以在第三方应用的输入框中绑定一个槽函数,用于接收软键盘按钮的点击事件。 然后,在自定义软键盘中,可以通过发送信号的方式将被点击的按钮信息发送到第三方应用中。可以使用QT提供的信号和槽机制,将软键盘按钮的点击事件连接到第三方应用中的槽函数,从而实现第三方应用的交互。 最后,可以在第三方应用中的槽函数中获取到软键盘按钮的信息,并根据需求将其插入到当前焦点位置的输入框中,从而实现与自定义软键盘的结合。 总之,通过在QT中创建自定义软键盘的界面,并利用QT的信号和槽机制与第三方应用进行交互,可以实现自定义软键盘和第三方应用的结合。这样,用户可以在第三方应用中使用自定义软键盘,提高输入体验和便捷性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

土拨鼠不是老鼠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值