加载中!

我是流子吗?我不知道,或许是吧......或许又不是......我真的不知道.
<<  < 2008 - >  >>
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31

留言簿

公告

相关新闻

最新日志

最新评论

我的相册

搜索

登陆

友情连接

统计

2008-7-25 17:11:00
QQ与服务器通信的加密
 与Decode相对应,是一个加密函数Encode。    
  void   Encode(char   *src,int   srclen,char   *encodekey,char   *outbuffer,int   *  
  poutlen)    
  参数:    
  src:明文缓冲区。    
  Srclen:   明文缓冲区的长度。    
  Encodekey:固定16个字节的加密的密钥。    
  Outbuffer:输出加密缓冲区。    
  Poutlen:输出长度的保存地址。    
  说明:该函数入口地址:15f:456b62。将明文进行加密,密钥为encodekey。用d  
  ecode函数和同样的密钥可以进行解密。    
   
  l   登录服务器:    
  发送的数据包为    
  {BYTE   b1;固定为0x2    
  BYTE   b2;固定为0x3    
  BYTE   b3;固定为0XA    
  BYTE   b4;固定为0X0    
  BYTE   cmd;   登录服务器为0X15。    
  WORD   seq;   顺序号,从高到低存放    
  DWORD   oicq号;以从高到低顺利存放二进制的OICQ号。    
  BYTE   key[16]   ;随机产生的16个字节的密钥。    
  BYTE   buffer[64];64字节的加密内容。    
  BYTE   endchar   ;固定为0x3。    
   
  最核心的是buffer[64]的内容。用口令调用CalcPassword进行一次计算,然后作  
  为密钥对0长度的明文进行加密,得出16个字节的结果,再进行加密发送。例如口  
  令为'abc123',算法为    
  BYTE   passkey[16]    
  CalcPassword('abc123',6',passkey)    
   
  BYTE   keycode[16]    
  int   keycodelen=16;    
  Encode(0,0,passkey,keycode,&keycodelen)    
   
   
  BYTE   sndbuffer[51];    
  memset(sndbuffer,0,51)    
  memcpy(sndbuffer,keycode,16)    
  //sndbuffer其余的内容为当前机器的ip等信息,与检查口令无关    
   
  BYTE   result[64]    
  int   sresultlen=64    
  Encode(sndbuffer,51,随机产生16个字节的密钥,result,&resultlen)    
   
  最后把16个字节的随机密钥和64字节加密后的口令一同发给服务器验证。如果能  
  用sniffer侦听到别人与服务器的通信,就能进行口令破解。当然也可以通过服务  
  器进行在线的口令破解,只是速度很慢,没有实用价值。    
   
  l   如果登录成功,服务器返回16个字节的密钥--ServerKey。    
  l   UPD数据包的格式为    
  BYTE   b1;固定为2    
  BYTE   b2;固定为1    
  BYTE   b3;固定为0    
  BYTE   b4;固定为0    
  BYTE   cmd;登录为0X15    
  WORD   seq;从高到低顺序,与发送的seq一致。    
  BYTE   msg[56];    
  BYTE   endchar   ;固定0x3。    
  用口令经过一次CalcPassword计算,得出16个字节的密钥,对msg进行解密。从第  
  1个字节开始的16个字节即为与服务器通信的密钥暂称为ServerKey。该密钥经常  
  变化。    
  在本次登录中,以后所有跟服务器的通信都用这个ServerKey为密钥进行加密和解  
  密。    
    其它用户发来的加密消息的解密。    
  其它用户的发来的加密消息格式为:    
  BYTE   b1;固定为0x0    
  BYTE   b2;固定为0x3    
  BYTE   b3;固定为0xA或0X2    
  BYTE   salt;   OICQ号加密用    
  DWORD   EncodeOicqID;加密后的从高到低的oicq号。    
  DWORD   seq;序号    
  BYTE   msg[变长]    
   
  l   对方oicq号的解密。    
  将EncodeOicqID的4个字节分别与salt进行异或操作,然后取反。    
  如salt   =   0XA0,   EncodeOicqID   =   0X   5F5EBD1F。    
  //分别进行异或操作    
  0X   5F5EBD1F   XOR   0XA0A0A0A0   =   0X   FFFE1DBF    
  //再取反    
  NOT   0X   FFFE1DBF   =   0X1E240,转为10进制就是123456。因此对方的oicq号为123  
  456。    
  l   消息的解密。    
  先合成一个20字节的口令。前4个字节为从高到低的二进制对方的oicq号。后16个  
  字节为服务器发来的ServerKey。ServerKey的来源见第三节。    
  如对方的oicq号为123456,20字节的口令为    
  00   01   E2   40   +   16字节的ServerKey。    
  用口令算法对这20字节的口令进行计算,得16个字节的密钥,就可以解开对方发  
  来的消息。    
    发给其它用户消息的加密    
  在登录后,服务器会通知好友的IP地址和端口,以及一个16个字节的密钥。就是  
  当前的OICQ号加对方16个字节ServerKey通过CalcPass的计算结果。    
  向对方发送消息时,只要用这16个字节进行加密即可。  
posted @ 2008-7-25 17:11:00 流子 阅读全文 | 回复(0) | 引用通告 | 编辑
发表评论:
加载中!
Powered by Oblog.