|
/*发送这13个字节的报文到QQ服务器*/ len = write(qc->server,buff_tx,13);
/*我们采用了非阻塞的套节字, 所以么设置超时, 并检查socket 事件!*/ bzero(&timeout,sizeof(timeout)); /*超时一秒*/ timeout.tv_sec = 1; timeout.tv_usec = 0; /*设置需要监视的socket*/ FD_ZERO(&fds); FD_SET(qc->server, &fds); /*检查socket 事件*/ e = select(qc->server+1,&fds,NULL,NULL,&timeout);
if(e==-1e==0){ /*超时了… */ fprintf(stderr,"request login token timeout.\n"); return -EFAULT;
}
/*好了!服务器回应数据出现了把接收数据放入buff_rx */ len = read(qc->server,buff_rx,sizeof(buff_rx));
if(len<=0){ /*读入数据失败*/ fprintf(stderr,"request login token error.\n"); return -EFAULT;
}
if(buff_rx[0] != 0x02 ){ /*不是QQ报文*/ fprintf(stderr,”not qq data .\n”); return –EFAULT;
}
#if 0 tmp16 = *((uint16_t*)&buff_rx[1]); printf("respond source tag x\n",ntohs(tmp16));
#endif
tmp16 = *((uint16_t*)&buff_rx[3]);
if(htons(tmp16) != 0x0062 ){ /*不是登录令牌回应*/ fprintf(stderr,”not login token data.\n”); return –EFAULT;
}
if(ntohs(*((uint16_t*)&buff_rx[5])) != seq){ /*不是我们发出的数据,因为序号不对,起码是传输出错了*/ fprintf(stderr,"request login token sequence incorrect.\n"); return -EFAULT;
}
/*检查是否含有令牌数据*/
if(buff_rx[7] != 0x00){ fprintf(stderr,"failed to request login token.\n"); return -EINVAL;
}
/*令牌的长度*/ len = buff_rx[8];
printf("login token length is %d bytes\n",len);
/*复制令牌到我们的缓存*/ bcopy(&buff_rx[9],token,len);
printf("login token :"); HEX_PRINT(&buff_rx[9],len); return len;
}
登录
当我们获取登录令牌成功后,我们就可以开始我们的登录了过程了。
我捕获的数据长度(抛去协议数据)是460 字节
捕获的数据如下:
0x02, 协议开始
0x0d, 0x51, 版本 QQ2005beta2
0x00, 0x22, 登录请求
0x1a, 0x15, 报文序号
0x14, 0xc5, 0xaa, 0xea, QQ 号码我的号码348498666 = 0xeaaac514
0xd4,0xf3, 0x20, 0x2b, 0xc8, 0x65, 0x24, 0x55,
0xea, 0x61, 0x4a, 0xd5, 0xd3,0xae, 0x8e, 0xc8,登录数据数据密钥 16字节
…… 加密过的数据
0x03
我们除去报头的7 个字节,密钥16 字节,4 字节的号码, 还有0x03 这一个字节, 所以加密过的数据是460 -7 -16 -1 -4 = 432
其实我们在填充数据的时候,16 字节的初始密钥我们可以采用随即生成。这样安全性也许会更好。
我在自己写了个程序,采用密钥0xd4,0xf3, 0x20, 0x2b, 0xc8, 0x65, 0x24, 0x55,0xea, 0x61, 0x4a, 0xd5, 0xd3,0xae, 0x8e, 0xc8 对加密的432 字节数据解密后,还原出416 字节的登录数据,表明,那16 字节确实是初始的加密密钥。
下面说明这些数据的意义:
0 ― 15 共16 字节
0x28 ,0xb0 ,0x5f ,0xec ,0x84 ,0x96 ,0x7a ,0xea ,
0x4d ,0xab ,0x72 ,0xc8 ,0xed ,0xdd ,0x14 ,0x92 ,
这16字节是先把密码作两次MD5-16 运算得到一个HASH, 然后把这个结果作为密钥用TEA 加密一个任意的字串,可以是空!得到这16字节,服务器其实只是看看能不能在服务器端解密, 并不关心解密后的内容!
16 -51 共36字节
0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , 0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , 0x00 ,0x00 ,0x00 ,0x23 ,0xa2 ,0x10 ,0x55 ,0x97 , 0x52 ,0xd8 ,0x1e ,0xb4 ,0xd7 ,0x87 ,0x89 ,0x4a , 0x12 ,0x7d ,0xd1 ,0x01
看起来是固定的内容
上一篇:命令行下可以解读TCP数据报内容的Sniffer
下一篇:QQ协议分析之TCPF包结构
|