所属类别:技术博客
文章作者:Red_angelX
特别推荐:免费发布信息 承包关键词~~抢爆了!HOT!
注:本人只是从LUMA QQ的 Source Code里面把相应Java语言翻译成C#,纯技术研究,并没有对TC产品做任何逆向分析,不承担任何法律责任!转载请保持本文完整性网上有c/c++,vb,delphi,java,perl各种版本的tea填充算法,唯独没有C#的,这让我这种狂热喜爱C#的人如何承受,于是,花3天时间看了各种代码经历无数失败的挫折终于用C#完成了该填充算法,废话不多说,直接给代码/*********************************************************FILE : QQCrypt.cs9.22更正:一处笔误造成解密失败的BUG 优化部分代码**********************************************************/usingSystem;namespaceRedQ...{/**///////QQMsgEn/DeCryptClass///WritenByRed_angelXOn2006.9.13///publicclassQQCrypt...{//QQTEA-16Encrypt/DecryptClass//////AndalsoLumaQQ//ssourcecode//CopyRight:NoCopyRight^_^//Author:Red_angelX//NetWorkisFree,Tencentis****!////ClassBegin//AD:FindJob!!,IfyouWantGivemeaJob,ContentMe!!//Copied&translatedfromLumaQQ//ssourcecode`FromLumaQQ///ssourcecode:privatebyte[]Plain;//指向当前的明文块privatebyte[]prePlain;//指向前面一个明文块privatebyte[]Out;//输出的密文或者明文privatelongCrypt,preCrypt;//当前加密的密文位置和上一次加密的密文块位置,他们相差8privatelongPos;//当前处理的加密解密块的位置privatelongpadding;//填充数privatebyte[]Key=newbyte[16];//密钥privateboolHeader;//用于加密时,表示当前是否是第一个8字节块,因为加密算法//是反馈的,但是最开始的8个字节没有反馈可用,所有需要标//明这种情况privatelongcontextStart;//这个表示当前解密开始的位置,之所以要这么一个变量是为了//避免当解密到最后时后面已经没有数据,这时候就会出错,这//个变量就是用来判断这种情况免得出错publicQQCrypt()...{////TODO:在此处添加构造函数逻辑//}//Push数据byte[]CopyMemory(byte[]arr,intarr_index,longinput)//lenth=4...{if(arr_index+4>arr.Length)...{//不能执行returnarr;}arr[arr_index+3]=(byte)((input&0xff000000)>>24);arr[arr_index+2]=(byte)((input&0x00ff0000)>>16);arr[arr_index+1]=(byte)((input&0x0000ff00)>>8);arr[arr_index]=(byte)(input&0x000000ff);arr[arr_index]&=0xff;arr[arr_index+1]&=0xff;arr[arr_index+2]&=0xff;arr[arr_index+3]&=0xff;returnarr;}longCopyMemory(longOut,byte[]arr,intarr_index)...{if(arr_index+4>arr.Length)...{returnOut;//不能执行}longx1=arr[arr_index+3]<<24;longx2=arr[arr_index+2]<<16;longx3=arr[arr_index+1]<<8;longx4=arr[arr_index];longo=x1x2x3x4;o&=0xffffffff;returno;}longgetUnsignedInt(byte[]arrayIn,intoffset,intlen/**//*Defaultis4*/)...{longret=0;intend=0;if(len>8)end=offset+8;elseend=offset+len;for(inti=offset;i<end;i++)...{ret<<=8;ret=arrayIn[i]&0xff;}return(ret&0xffffffff)(ret>>32);}longRand()...{Randomrd=newRandom();longret;ret=rd.Next()+(rd.Next()%1024);returnret;}privatebyte[]Decipher(byte[]arrayIn,byte[]arrayKey,longoffset)...{//longY,z,a,b,c,d;longsum,delta;//Y=z=a=b=c=d=0;byte[]tmpArray=newbyte[24];byte[]tmpOut=newbyte[8];if(arrayIn.Length<8)...{//Error:returnreturntmpOut;}if(arrayKey.Length<16)...{//Error:returnreturntmpOut;}sum=0xE3779B90;sum=sum&0xFFFFFFFF;delta=0x9E3779B9;delta=delta&0xFFFFFFFF;/**//*tmpArray[3]=arrayIn[offset];tmpArray[2]=arrayIn[offset+1];tmpArray[1]=arrayIn[offset+2];tmpArray[0]=arrayIn[offset+3];tmpArray[7]=arrayIn[offset+4];tmpArray[6]=arrayIn[offset+5];tmpArray[5]=arrayIn[offset+6];tmpArray[4]=arrayIn[offset+7];tmpArray[11]=arrayKey[0];tmpArray[10]=arrayKey[1];tmpArray[9]=arrayKey[2];tmpArray[8]=arrayKey[3];tmpArray[15]=arrayKey[4];tmpArray[14]=arrayKey[5];tmpArray[13]=arrayKey[6];tmpArray[12]=arrayKey[7];tmpArray[19]=arrayKey[8];tmpArray[18]=arrayKey[9];tmpArray[17]=arrayKey[10];tmpArray[16]=arrayKey[11];tmpArray[23]=arrayKey[12];tmpArray[22]=arrayKey[13];tmpArray[21]=arrayKey[14];tmpArray[20]=arrayKey[15];Y=CopyMemory(Y,tmpArray,0);z=CopyMemory(z,tmpArray,4);a=CopyMemory(a,tmpArray,8);b=CopyMemory(b,tmpArray,12);c=CopyMemory(c,tmpArray,16);d=CopyMemory(d,tmpArray,20);*/longY=getUnsignedInt(arrayIn,(int)offset,4);longz=getUnsignedInt(arrayIn,(int)offset+4,4);longa=getUnsignedInt(arrayKey,0,4);longb=getUnsignedInt(arrayKey,4,4);longc=getUnsignedInt(arrayKey,8,4);longd=getUnsignedInt(arrayKey,12,4);for(inti=1;i<=16;i++)...{z-=((Y<<4)+c)^(Y+sum)^((Y>>5)+d);z&=0xFFFFFFFF;Y-=((z<<4)+a)^(z+sum)^((z>>5)+b);Y&=0xFFFFFFFF;sum-=delta;sum&=0xFFFFFFFF;}tmpArray=CopyMemory(tmpArray,0,Y);tmpArray=CopyMemory(tmpArray,4,z);tmpOut[0]=tmpArray[3];tmpOut[1]=tmpArray[2];tmpOut[2]=tmpArray[1];tmpOut[3]=tmpArray[0];tmpOut[4]=tmpArray[7];tmpOut[5]=tmpArray[6];tmpOut[6]=tmpArray[5];tmpOut[7]=tmpArray[4];returntmpOut;}privatebyte[]Decipher(byte[]arrayIn,byte[]arrayKey)...{returnDecipher(arrayIn,arrayKey,0);}privatebyte[]Encipher(byte[]arrayIn,byte[]arrayKey,longoffset)...{byte[]tmpOut=newbyte[8];byte[]tmpArray=newbyte[24];//longY,z,a,b,c,d;//Y=z=a=b=c=d=0;longsum,delta;if(arrayIn.Length<8)...{//Error:returntmpOut;}if(arrayKey.Length<16)...{//Error:returntmpOut;}sum=0;delta=0x9E3779B9;delta&=0xFFFFFFFF;/**//*tmpArray[3]=arrayIn[offset];tmpArray[2]=arrayIn[offset+1];tmpArray[1]=arrayIn[offset+2];tmpArray[0]=arrayIn[offset+3];tmpArray[7]=arrayIn[offset+4];tmpArray[6]=arrayIn[offset+5];tmpArray[5]=arrayIn[offset+6];tmpArray[4]=arrayIn[offset+7];tmpArray[11]=arrayKey[0];tmpArray[10]=arrayKey[1];tmpArray[9]=arrayKey[2];tmpArray[8]=arrayKey[3];tmpArray[15]=arrayKey[4];tmpArray[14]=arrayKey[5];tmpArray[13]=arrayKey[6];tmpArray[12]=arrayKey[7];tmpArray[19]=arrayKey[8];tmpArray[18]=arrayKey[9];tmpArray[17]=arrayKey[10];tmpArray[16]=arrayKey[11];tmpArray[23]=arrayKey[12];tmpArray[22]=arrayKey[13];tmpArray[21]=arrayKey[14];tmpArray[20]=arrayKey[15];Y=CopyMemory(Y,tmpArray,0);z=CopyMemory(z,tmpArray,4);a=CopyMemory(a,tmpArray,8);b=CopyMemory(b,tmpArray,12);c=CopyMemory(c,tmpArray,16);d=CopyMemory(d,tmpArray,20);*/longY=getUnsignedInt(arrayIn,(int)offset,4);longz=getUnsignedInt(arrayIn,(int)offset+4,4);longa=getUnsignedInt(arrayKey,0,4);longb=getUnsignedInt(arrayKey,4,4);longc=getUnsignedInt(arrayKey,8,4);longd=getUnsignedInt(arrayKey,12,4);for(inti=1;i<=16;i++)...{sum+=delta;sum&=0xFFFFFFFF;Y+=((z<<4)+a)^(z+sum)^((z>>5)+b);Y&=0xFFFFFFFF;z+=((Y<<4)+c)^(Y+sum)^((Y>>5)+d);z&=0xFFFFFFFF;}tmpArray=CopyMemory(tmpArray,0,Y);tmpArray=CopyMemory(tmpArray,4,z);tmpOut[0]=tmpArray[3];tmpOut[1]=tmpArray[2];tmpOut[2]=tmpArray[1];tmpOut[3]=tmpArray[0];tmpOut[4]=tmpArray[7];tmpOut[5]=tmpArray[6];tmpOut[6]=tmpArray[5];tmpOut[7]=tmpArray[4];returntmpOut;}privatebyte[]Encipher(byte[]arrayIn,byte[]arrayKey)...{returnEncipher(arrayIn,arrayKey,0);}privatevoidEncrypt8Bytes()...{byte[]Crypted;for(Pos=0;Pos<=7;Pos++)...{if(this.Header==true)...{Plain[Pos]=(byte)(Plain[Pos]^prePlain[Pos]);}else...{Plain[Pos]=(byte)(Plain[Pos]^Out[preCrypt+Pos]);}}Crypted=Encipher(Plain,Key);for(inti=0;i<=7;i++)...{Out[Crypt+i]=(byte)Crypted[i];}for(Pos=0;Pos<=7;Pos++)...{Out[Crypt+Pos]=(byte)(Out[Crypt+Pos]^prePlain[Pos]);}Plain.CopyTo(prePlain,0);preCrypt=Crypt;Crypt=Crypt+8;Pos=0;Header=false;}privateboolDecrypt8Bytes(byte[]arrayIn,longoffset)...{longlngTemp;for(Pos=0;Pos<=7;Pos++)...{if(this.contextStart+Pos>arrayIn.Length-1)...{returntrue;}prePlain[Pos]=(byte)(prePlain[Pos]^arrayIn[offset+Crypt+Pos]);}try...{prePlain=this.Decipher(prePlain,Key);}catch...{returnfalse;}lngTemp=prePlain.Length-1;contextStart+=8;Crypt+=8;Pos=0;returntrue;}privateboolDecrypt8Bytes(byte[]arrayIn)...{returnDecrypt8Bytes(arrayIn,0);}PublicMethods!#regionPublicMethods!/**///////QQTEA加密函数//////要加密的字串///密钥///偏移///publicbyte[]QQ_Encrypt(byte[]arrayIn,byte[]arrayKey,longoffset)...{Plain=newbyte[8];prePlain=newbyte[8];longl;Pos=1;padding=0;Crypt=preCrypt=0;arrayKey.CopyTo(Key,0);//KeyMustBe16Length!Header=true;Pos=2;//计算头部填充字节数Pos=(arrayIn.Length+10)%8;if(Pos!=0)Pos=8-Pos;//输出长度Out=newbyte[arrayIn.Length+Pos+10];//把POS存到PLAIN的第一个字节//0xf8后面3位是空的,正好给PosPlain[0]=(byte)((Rand()&0xf8)Pos);//用随机数填充1到Pos的内容for(inti=1;i<=Pos;i++)...{Plain[i]=(byte)(Rand()&0xff);}Pos++;padding=1;//继续填充两个字节随机数,满8字节就加密while(padding<3)...{if(Pos<8)...{Plain[Pos]=(byte)(Rand()&0xff);padding++;Pos++;}elseif(Pos==8)...{this.Encrypt8Bytes();}}intI=(int)offset;l=0;//明文内容,满8字节加密到读完l=arrayIn.Length;while(l>0)...{if(Pos<8)...{Plain[Pos]=arrayIn[I];I++;Pos++;l--;}elseif(Pos==8)...{this.Encrypt8Bytes();}}//末尾填充0,保证是8的倍数padding=1;while(padding<9)...{if(Pos<8)...{Plain[Pos]=0;Pos++;padding++;}elseif(Pos==8)...{this.Encrypt8Bytes();}}returnOut;}publicbyte[]QQ_Encrypt(byte[]arrayIn,byte[]arrayKey)...{returnQQ_Encrypt(arrayIn,arrayKey,0);}/**///////QQTEA解密函数//////要解密字串///密钥///偏移///publicbyte[]QQ_Decrypt(byte[]arrayIn,byte[]arrayKey,longoffset)...{byte[]error=newbyte[0];//检查是否是8的倍数至少16字节if(arrayIn.Length<16(arrayIn.Length%8!=0))...{//ReturnWhat?returnerror;}if(arrayKey.Length!=16)...{//ReturnWhat?returnerror;}byte[]m;longI,Count;m=newbyte[offset+8];arrayKey.CopyTo(Key,0);Crypt=preCrypt=0;//计算消息头部,明文开始的偏移,解密第一字节和7相与得到prePlain=this.Decipher(arrayIn,arrayKey,offset);Pos=prePlain[0]&7;//计算明文长度Count=arrayIn.Length-Pos-10;if(Count<=0)...{//ReturnWhat?returnerror;}Out=newbyte[Count];preCrypt=0;Crypt=8;this.contextStart=8;Pos++;padding=1;//跳过头部while(padding<3)...{if(Pos<8)...{Pos++;padding++;}elseif(Pos==8)...{for(inti=0;i<m.Length;i++)m[i]=arrayIn[i];if(this.Decrypt8Bytes(arrayIn,offset)==false)...{//ReturnWhat?returnerror;}}}//解密明文I=0;while(Count!=0)...{if(Pos<8)...{Out[I]=(byte)(m[offset+preCrypt+Pos]^prePlain[Pos]);I++;Count--;Pos++;}elseif(Pos==8)...{m=arrayIn;preCrypt=Crypt-8;if(this.Decrypt8Bytes(arrayIn,offset)==false)...{//ReturnWhat?returnerror;}}}//最后的解密部分,检查尾部是不是0for(padding=1;padding<=7;padding++)...{if(Pos<8)...{if((m[offset+preCrypt+Pos]^prePlain[Pos])!=0)...{//ReturnWhat?returnerror;}Pos++;}elseif(Pos==8)...{for(inti=0;i<m.Length;i++)m[i]=arrayIn[i];preCrypt=Crypt;if(this.Decrypt8Bytes(arrayIn,offset)==false)...{//ReturnWhat?returnerror;}}}returnOut;}publicbyte[]QQ_Decrypt(byte[]arrayIn,byte[]arrayKey)...{returnQQ_Decrypt(arrayIn,arrayKey,0);}#endregion}}有了这个,加上一些现成的协议分析,你就可以做自己的QQ客户端了。发表于 @ 2006年09月19日 16:59:00评论(loading...AddFeedbackCountStack("1246701"))编辑新一篇:C#编写贪吃蛇游戏 RedSnake旧一篇:SafeDel 文件安全删除器alpha
相关信息· 网页中关闭IE的图像工具栏和XP主题
· redhat linux 9下ms06_040漏洞溢出测试笔记
· 保护SQL服务器的安全-安全安装
· SAMBA最简单的配置方法
68244
39803
