您的位置:首页 > 编程语言 > Delphi

QQ 聊天记录解密类 DELPHI版

2008-10-14 18:39 295 查看
以前写的一个QQ聊天记录解密时写的,加密解密就是麻烦

如需要QQTEA单元,参见上一篇文章

{

/----------------------------------------------|

| QQ消息解密类 |

| Writeted By RYYD |

| Mail:ryyd@163.com |

----------------------------------------------/

}

unit QQMSG;

interface

uses ActiveX,Classes,Sysutils,QQTEA,Windows,StdCtrls,comobj,Axctrls,MD5,Dialogs;

type

IntType=array of Integer;

PerMSG=record

Content:string;

Time:TDateTime;

Name:string;

Group:string;

end;

MSGType=(C2CMsg,SysMsg,DiscMsg,GroupMsg,TempSessionMsg,MobileMsg);

TQQMSG=class

private

QQ:string;//用来存储QQ号

FileName:string;//用来存储消息文件名

RootStorage:IStorage; //用来储存结构化文件的根文件

Key:ByteType;//全局解密KEY

QQHash:ByteType; //存储QQ号的Hash Byte数组

MatrixData:ByteType;//存储Matrix.db的内容

C2CMsgList:TStrings;//好友列表

SysMsgList:TStrings;//系统信息列表

DiscMsgList:TStrings;//组列表

GroupMsgList:TStrings;//群列表

TempSessionMsgList:TStrings;//临时消息列表

MobileMsgList:TStrings;//移动消息列表

procedure GetMatrixData;//得到MatrixData数据

function GetRealByte(Des:ByteType):ByteType; //得到一个Byte数组去除了0后的真实数组

procedure GetKey;//得到全局解密KEY

procedure GetQQHash;//得到QQ号的Hash Byte数组;

function GetByteString(InByte:ByteType):string;overload;//得到二进制BYTE数组的字符串形式

function GetByteString(InByte:ByteType;InBegin:Integer;InLen:Integer):string;overload;//得到二进制BYTE数组的字符串形式

procedure GetRootStorage;//得到根文件

procedure GetList;//得到所有的列表

function GetBS(InByte:ByteType):string;

function GetIntegerFromFourByte(a1:Byte;a2:Byte;a3:Byte;a4:Byte):Integer;

function GetRealMessage(InByte:ByteType;InMSGType:MSGType):PerMSG;//从解密后的某条Byte里获取完整的消息

public

function GetMSG(InMSGType:MSGtype;Number:string):string;//得到全部的消息;

procedure Print;

constructor Create(InFileName:string;InQQ:string); //构造函数,传入参数为结构化文件的文件名以及QQ号码

end;

implementation

uses MainUnit;

function TQQMSG.GetRealMessage(InByte: ByteType;InMSGType: MSGType):PerMSG;

var

DateTime:TDateTime;

Position:Integer;

NameLength:Integer;

Name:string;

MSGLength:Integer;

MSG:string;

GroupLength:Integer;

Group:string;

TempByteData:ByteType;

begin

Position:=4;

DateTime:=EncodeDate(1970,1,1)+EncodeTime(0,0,0,0);

DateTime:=DateTime+GetIntegerFromFourByte(InByte[0],InByte[1],InByte[2],InByte[3])/24/3600;

case InMSGType of

C2CMsg:Position:=Position+1;

SysMsg:Position:=Position+4;

DiscMsg:Position:=Position+1;

GroupMsg:Position:=Position+8;

TempSessionMsg:Position:=Position+9;

MobileMsg:Position:=Position+1;

end;

if InMSGType=TempSessionMsg then

begin

GroupLength:=GetIntegerFromFourByte(InByte[Position],InByte[Position+1],InByte[Position+2],InByte[Position+3]);

Position:=Position+4;

//Group:=GetByteString(InByte,Position,GroupLength);

SetLength(TempByteData,GroupLength);

CopyMemory(@TempByteData[0],@InByte[Position],GroupLength);

Group:=GetBS(TempByteData);

Position:=Position+GroupLength;

end;

NameLength:=GetIntegerFromFourByte(InByte[Position],InByte[Position+1],InByte[Position+2],InByte[Position+3]);

Position:=Position+4;

//Name:=GetByteString(InByte,Position,NameLength);

SetLength(TempByteData,NameLength);

CopyMemory(@TempByteData[0],@InByte[Position],NameLength);

Name:=GetBS(TempByteData);

Position:=Position+NameLength;

MSGLength:=GetIntegerFromFourByte(InByte[Position],InByte[Position+1],InByte[Position+2],InByte[Position+3]);

Position:=Position+4;

//MSG:=GetByteString(InByte,Position,MSGLength);

SetLength(TempByteData,MSGLength);

CopyMemory(@TempByteData[0],@InByte[Position],MSGLength);

MSG:=GetBS(TempByteData);

Result.Content:=MSG;

Result.Time:=DateTime;

Result.Name:=Name;

Result.Group:=Group;

end;

function TQQMSG.GetIntegerFromFourByte(a1: Byte; a2: Byte; a3: Byte; a4: Byte):Integer;

var

TempByte:array[1..4] of Byte;

begin

TempByte[1]:=a1;

TempByte[2]:=a2;

TempByte[3]:=a3;

TempByte[4]:=a4;

CopyMemory(@Result,@TempByte[1],4);

end;

function TQQMSG.GetBS(InByte: ByteType):string;

var

i: Integer;

begin

for i := 0 to Length(InByte) - 1 do Result:=Result+' '+IntToStr(InByte[i]);

end;

function TQQMSG.GetMSG(InMSGType: MSGType; Number: string):string;

var

OpenString:string;

TempStorage:IStorage;

MSGStorage:IStorage;

TempStream:IStream;

TempOutOleStream:TOlestream;

TempOutStream:TMemoryStream;

Index,Data:ByteType;

FileLen,Num:Integer;

Pos,Len:array of Integer;

i,t:Integer;

TempOutString:string;

TempData,TempMSG:ByteType;

TempDecrypter:TQQTEA;

Position,EndPosition:Integer;

j: Integer;

TempDateTime:TDateTime;

PerM:PerMSG;

TempStringList:TStrings;

TempString:string;

begin

TempOutString:='';

TempDecrypter:=TQQTEA.Create;

case InMSGType of

C2CMsg:OpenString:='C2CMsg';

SysMsg:OpenString:='SysMsg';

DiscMsg:OpenString:='DiscMsg';

GroupMsg:OpenString:='GroupMsg';

TempSessionMsg:OpenString:='TempSessionMsg';

MobileMsg:OpenString:='MobileMsg';

end;

OleCheck(RootStorage.OpenStorage(StringToOleStr(OpenString),nil,STGM_READWRITE or STGM_SHARE_EXCLUSIVE,nil,0,TempStorage));

OleCheck(TempStorage.OpenStorage(StringToOleStr(Number),nil,STGM_READWRITE or STGM_SHARE_EXCLUSIVE,nil,0,MSGStorage));

OleCheck(MSGStorage.OpenStream(StringToOleStr('Index.msj'),nil,STGM_READWRITE or STGM_SHARE_EXCLUSIVE,0,TempStream));

TempOutOleStream:=TOleStream.Create(TempStream);

TempOutStream:=TMemoryStream.Create;

TempOutStream.Size:=0;

TempOutStream.CopyFrom(TempOutOleStream,TempOutOleStream.Size);

TempOutOleStream.Free;

TempOutStream.Position:=0;

SetLength(Index,TempOutStream.Size);

for i:=0 to length(Index)-1 do Index[i]:=0;

TempOutStream.ReadBuffer(Index[0],TempOutStream.size);

TempOutStream.Free;

OleCheck(MSGStorage.OpenStream(StringToOleStr('Data.msj'),nil,STGM_READWRITE or STGM_SHARE_EXCLUSIVE,0,TempStream));

TempOutOleStream:=TOleStream.Create(TempStream);

TempOutStream:=TMemoryStream.Create;

TempOutStream.Size:=0;

TempOutStream.CopyFrom(TempOutOleStream,TempOutOleStream.Size);

TempOutOleStream.Free;

TempOutStream.Position:=0;

SetLength(Data,TempOutStream.Size);

for i:=0 to length(Data)-1 do Data[i]:=0;

TempOutStream.ReadBuffer(Data[0],TempOutStream.size);

TempOutStream.Free;

FileLen:=Length(Index);

Num:=Trunc(FileLen/4);

SetLength(Pos,Num+1);

t:=0;i:=0;

while i<Length(Index) do

begin

CopyMemory(@pos[t],@Index[i],4);

i:=i+4;

t:=t+1;

end;

FileLen:=Length(Data);

SetLength(Len,Num);

pos[Num]:=fileLen;

for i:=0 to Num-1 do

begin

len[i]:= pos[i+1]-pos[i];

end;

TempStringList:=TStringList.Create;

for i :=0 to Num - 1 do

begin

TempString:='';

Position:=Pos[i];

SetLength(TempData,Len[i]);

CopyMemory(@TempData[0],@Data[Position],Len[i]);

TempMSG:=TempDecrypter.DeCrypt(TempData,Key);

PerM:=GetRealMessage(TempMSG,InMSGType);

TempString:=TempString+DateTimeToStr(PerM.Time);

TempString:=TempString+#13+#10;

TempString:=TempString+PerM.Name+': '+PerM.Content;

TempStringList.Add(TempString);

TempStringList.Add('');

end;

Result:=TempStringList.Text;

TempDecrypter.Destroy;

end;

procedure TQQMSG.GetList;

var

EnumStatStg:IEnumStatStg;

StatStg:TStatStg;

TempStorage:IStorage;

begin

OleCheck(RootStorage.OpenStorage(StringToOleStr('C2CMsg'),nil,STGM_READWRITE or STGM_SHARE_EXCLUSIVE,nil,0,TempStorage));

OleCheck(TempStorage.EnumElements(0,nil,0,EnumStatStg));

while EnumStatStg.Next(1,StatStg,nil)=S_Ok do

begin

C2CMsgList.Add(StatStg.pwcsName);

end;

OleCheck(RootStorage.OpenStorage(StringToOleStr('SysMsg'),nil,STGM_READWRITE or STGM_SHARE_EXCLUSIVE,nil,0,TempStorage));

OleCheck(TempStorage.EnumElements(0,nil,0,EnumStatStg));

while EnumStatStg.Next(1,StatStg,nil)=S_Ok do

begin

SysMsgList.Add(StatStg.pwcsName);

end;

{OleCheck(RootStorage.OpenStorage(StringToOleStr('DiscMsg'),nil,STGM_READWRITE or STGM_SHARE_EXCLUSIVE,nil,0,TempStorage));

OleCheck(TempStorage.EnumElements(0,nil,0,EnumStatStg));

while EnumStatStg.Next(1,StatStg,nil)=S_Ok do

begin

DiscMsgList.Add(StatStg.pwcsName);

end; }

OleCheck(RootStorage.OpenStorage(StringToOleStr('GroupMsg'),nil,STGM_READWRITE or STGM_SHARE_EXCLUSIVE,nil,0,TempStorage));

OleCheck(TempStorage.EnumElements(0,nil,0,EnumStatStg));

while EnumStatStg.Next(1,StatStg,nil)=S_Ok do

begin

GroupMsgList.Add(StatStg.pwcsName);

end;

OleCheck(RootStorage.OpenStorage(StringToOleStr('TempSessionMsg'),nil,STGM_READWRITE or STGM_SHARE_EXCLUSIVE,nil,0,TempStorage));

OleCheck(TempStorage.EnumElements(0,nil,0,EnumStatStg));

while EnumStatStg.Next(1,StatStg,nil)=S_Ok do

begin

TempSessionMsgList.Add(StatStg.pwcsName);

end;

end;

procedure TQQMSG.GetRootStorage;

begin

if FileExists(FileName) then

begin

OleCheck(StgOpenStorage(StringToOleStr(FileName),nil,STGM_READWRITE or STGM_SHARE_EXCLUSIVE,nil,0,RootStorage));

end;

end;

function TQQMSG.GetByteString(InByte: ByteType):string;

var

TempStringStream:TStringStream;

begin

TempStringStream:=TStringStream.Create('');

TempStringStream.WriteBuffer(InByte[0],Length(InByte));

Result:=TempStringStream.DataString;

TempStringStream.Free;

end;

function TQQMSG.GetByteString(InByte: ByteType; InBegin: Integer; InLen: Integer):string;

var

TempStringStream:TStringStream;

begin

TempStringStream:=TStringStream.Create('');

TempStringStream.WriteBuffer(InByte[InBegin],InLen);

Result:=TempStringStream.DataString;

TempStringStream.Free;

end;

procedure TQQMSG.Print;

var

i:Integer;

TempString:string;

begin

for i := 0 to Length(Key) - 1 do

begin

TempString:=TempString+inttostr(Key[i])+' ';

end;

MainUnit.MainForm.Caption:=TempString;

end;

constructor TQQMSG.Create(InFileName: string; InQQ: string);

begin

C2CMsgList:=TStringList.Create;

SysMsgList:=TStringList.Create;

DiscMsgList:=TStringList.Create;

GroupMsgList:=TStringList.Create;

TempSessionMsgList:=TStringList.Create;

MobileMsgList:=TStringList.Create;

QQ:=InQQ;

FileName:=InFileName;

GetRootStorage;

GetList;

GetKey;

end;

function TQQMSG.GetRealByte(Des:ByteType):ByteType;

var

l:Integer;

begin

for l := 0 to Length(Des) - 1 do

begin

if Des[l]=0 then Break;

end;

SetLength(Des,l);

SetLength(Result,length(Des));

CopyMemory(@Result[0],@Des[0],Length(Des));

end;

procedure TQQMSG.GetQQHash;

var

TempMD5:MD5Digest;

begin

TempMD5:=MD5String(QQ);

SetLength(QQHash,Length(TempMD5));

CopyMemory(@QQHash[0],@TempMD5[0],Length(TempMD5));

end;

procedure TQQMSG.GetKey;

var

Len,Len1,Len2:Integer;

bl:Boolean;

i,j:Integer;

typeB,xor1,xor2:Byte;

dataT,TempByte:ByteType;

TempDecrypter:TQQTEA;

begin

GetQQHash;

GetMatrixData;

TempDecrypter:=TQQTEA.Create;

Len:=Length(MatrixData);

if ((Len<6) or (MatrixData[0] <> $51) or (MatrixData[1] <> $44)) then

begin

Key:=nil;

Exit;

end;

if Len >= 32768 then

begin

Key:=nil;

Exit;

end;

bl:=false;

i:=6;

while i<Len do

begin

bl:=False;

typeb:=MatrixData[i];

i:=i+1;

if (i + 2) > len then Break;

Len1:=MatrixData[i]+MatrixData[i+1]*256;

xor1:=Byte(MatrixData[i] xor MatrixData[i+1]);

i:=i+2;

if (i+len1)>Len then Break;

for j := 0 to Len1-1do

begin

MatrixData[i+j]:=Byte(not(MatrixData[i+j] xor xor1));

end;

if (Len1=3) and (MatrixData[i]=$43) and (MatrixData[i+1]=$52) and (MatrixData[i+2]=$4B) then

begin

bl:=true;

end;

i:=i+len1;

if typeB > 7 then break;

if (i + 4)> len then break;

len2:= MatrixData[i] + MatrixData[i + 1] * 256 + MatrixData[i + 2] * 256 * 256 + MatrixData[i + 3] * 256 * 256 * 256;

xor2:=byte(MatrixData[i] xor MatrixData[i + 1]);

i:=i+4;

if (i + len2) > len then break;

if ((typeB=6) or (typeB=7)) then

begin

for j := 0 to len2-1 do

begin

MatrixData[i+j]:=Byte(not(MatrixData[i+j] xor xor2));

end;

end;

if (bl and (len2=$20)) then

begin

SetLength(dataT,len2);

for j := 0 to Len2-1 do dataT[j]:=MatrixData[i+j];

TempByte:=TempDecrypter.Decrypt(dataT,QQHash);

SetLength(Key,Length(TempByte));

CopyMemory(@Key[0],@TempByte[0],Length(TempByte));

Exit;

end;

i:=i+len2;

end;

if (i<>len) then

begin

Key:=nil;

exit;

end;

end;

procedure TQQMSG.GetMatrixData;

var

i:Integer;

MatrixStroage:IStorage;

MatrixDBFileStream:IStream;

TempOutOleStream:TOlestream;

TempOutStream:TMemoryStream;

begin

OleCheck(RootStorage.OpenStorage(StringToOleStr('Matrix'),nil,STGM_READWRITE or STGM_SHARE_EXCLUSIVE,nil,0,MatrixStroage));

OleCheck(MatrixStroage.OpenStream(StringToOleStr('Matrix.db'),nil,STGM_READWRITE or STGM_SHARE_EXCLUSIVE,0,MatrixDBFileStream));

TempOutOleStream:=TOleStream.Create(MatrixDBFileStream);

TempOutStream:=TMemoryStream.Create;

TempOutStream.Size:=0;

TempOutStream.CopyFrom(TempOutOleStream,TempOutOleStream.Size);

TempOutOleStream.Free;

TempOutStream.Position:=0;

SetLength(MatrixData,TempOutStream.Size);

for i:=0 to length(MatrixData)-1 do MatrixData[i]:=0;

TempOutStream.ReadBuffer(MatrixData[0],TempOutStream.size);

TempOutStream.Free;

end;

end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: