unit decrypt;
interface
uses
Windows,winsock,SysUtils,unitmyvar;
Function QQ_Decrypt(instr:string;instrlen:integer;key:TMyDword;var Outstr:string;var Outstrlen_ptr:integer):boolean ;
implementation
var
Decrypted:array[1..8] of char;
Crypt_Buff:string;
crypt_buff_ft8:string;
Pos_in_byte,Context_start:integer;
SessionKey:TMyDword;
procedure QQ_Decipher(V:TmyWORD;k:TmyDword;var w:TmyWORD);
var
y,Z,a,b,c,d:Longword;
n:Longword;
sum:Longword;
delta:Longword;
begin
y:=V[0];
z:=V[1];
a:=k[0];
b:=k[1];
c:=k[2];
d:=k[3];
n:=$10;
sum:=$E3779B90;
delta:=$9E3779B9;
while not (n = 0) do
begin
z:=z-(((y shl 4) + c) xor (y + sum )xor ((y shr 5) + d));
y:=y-(((z shl 4) + a) xor (z + sum) xor ((z shr 5) + b));
//dec(z,(((y shl 4) + c) xor (y + sum )xor ((y shr 5) + d)));
//dec(y,(((z shl 4) + a) xor (z + sum) xor ((z shr 5) + b)));
sum:=sum - delta;
n:=n-1;
end;
W[0]:=y;
W[1]:=z;
end;
Function Decrypt_every_8_byte(instrlenm:integer):Boolean;
var
i:integer;
a:byte;
b:byte;
outstrtemp:array[1..8] of char;
inmyword:Tmyword;
outmyword:Tmyword;
begin
result:=False;
for i:=1 to 8 do
begin
if ((context_start+i-1)>= instrlenm ) then exit;
a:= byte(decrypted);
b:= byte(crypt_buff);
decrypted:=char(a xor b);
end;
for i:=1 to 8 do
outstrtemp:=decrypted;
inmyword:= Tmyword(outstrtemp);
inmyword[0]:=ntohl(inmyword[0]);
inmyword[1]:=ntohl(inmyword[1]);
QQ_Decipher(inmyword,SessionKey,outmyword);
outstrtemp[1]:=Char((outmyword[0] and $FF000000) div $1000000);
outstrtemp[2]:=Char((outmyword[0] and $00FF0000) div $10000);
outstrtemp[3]:=Char((outmyword[0] and $0000FF00) div $100);
outstrtemp[4]:=Char(outmyword[0] and $000000FF);
outstrtemp[5]:=Char((outmyword[1] and $FF000000) div $1000000);
outstrtemp[6]:=Char((outmyword[1] and $00FF0000) div $10000);
outstrtemp[7]:=Char((outmyword[1] and $0000FF00) div $100);
outstrtemp[8]:=Char(outmyword[1] and $000000FF);
for i:=1 to 8 do
decrypted:= outstrtemp;
context_start:= context_start+8;
//inc(crypt_buff,8);
crypt_buff_ft8:=crypt_buff;
delete(crypt_buff,1,8);
pos_in_byte:=1;
result:=True;
end;
Function QQ_Decrypt(instr:string;instrlen:integer;key:TMyDword;var Outstr:string;var Outstrlen_ptr:integer):boolean ;
var
m:string[8];
Crypt_Buff_Pre_8:string[8];
OutP:string;
Counts,Padding:integer;
strword:string[8] ;
strchartemp:array[1..8] of char;
i:integer;
inmyword:Tmyword;
outmyword:Tmyword;
begin
result:=False;
Sessionkey:=key; //初始化 SESSIONKEY 值
for i:=1 to 8 do
Decrypted:=#0;
Crypt_Buff:='';
crypt_buff_ft8:='';
Pos_in_byte:=1;
Context_start:=1;
if (instrlen <16) or ((instrlen mod 8)<>0) then exit;//如果长度小于16或者不为8的整数倍跳出
strword:=instr; //传入头8个BYTE
for i:=1 to 8 do
strchartemp:=strword;
inmyword:= Tmyword(strchartemp);
inmyword[0]:=ntohl(inmyword[0]);
inmyword[1]:=ntohl(inmyword[1]);
qq_decipher(inmyword,Sessionkey,outmyword); //解密头8个BYTE
decrypted[1]:=Char((outmyword[0] and $FF000000) div $1000000);
decrypted[2]:=Char((outmyword[0] and $00FF0000) div $10000);
decrypted[3]:=Char((outmyword[0] and $0000FF00) div $100);
decrypted[4]:=Char(outmyword[0] and $000000FF);
decrypted[5]:=Char((outmyword[1] and $FF000000) div $1000000);
decrypted[6]:=Char((outmyword[1] and $00FF0000) div $10000);
decrypted[7]:=Char((outmyword[1] and $0000FF00) div $100);
decrypted[8]:=Char(outmyword[1] and $000000FF);
pos_in_byte:= (integer(decrypted[1]) and $7); //得到填充的长度
counts:=instrlen-pos_in_byte-10; //得到实际有效内容的长度
if counts<0 then exit; //如果实际有效内容的长度小于0跳出
FillMemory(@m,8,0); //用0x00 填充M 8个BYTE
FillMemory(@crypt_buff_pre_8,8,0);
//crypt_buff_pre_8:=m; //传给CRYPT_BUFF_PRE_8作为异或参数
outstrlen_ptr:=counts; //实际文字的长度
crypt_buff:=instr; //这儿出错了
CRYPT_BUFF_FT8:=INSTR;
Delete(crypt_buff,1,8); //向下移8位
context_start:=8;
pos_in_byte:=pos_in_byte+2; //这里要+2 因为下界为1 + POS_IN_BYTE
padding:=1;
while (padding<=2) do
begin
if (pos_in_byte <9) then
begin
pos_in_byte:= pos_in_byte+1;
padding:=padding+1;
end;
if (pos_in_byte=9) then
begin
crypt_buff_pre_8:=instr;
if not decrypt_every_8_byte(instrlen) then exit;
end;
end;
outp:='';
while(counts <> 0) do
begin
if(pos_in_byte <9) then
begin
outp:=outp+char(byte(crypt_buff_pre_8[pos_in_byte]) xor byte(decrypted[pos_in_byte]));
counts:=counts-1;
pos_in_byte:=pos_in_byte+1;
end;
if (pos_in_byte=9) then
begin
crypt_buff_pre_8:=crypt_buff_ft8;
if not decrypt_every_8_byte(instrlen) then exit;
end;
end;
for padding:=1 to 7 do
begin
if pos_in_byte <9 then
begin
if integer(byte(Crypt_Buff_Pre_8[pos_in_byte]) xor byte(decrypted[pos_in_byte]))<>0 then break;
pos_in_byte:=pos_in_byte+1;
end;
if pos_in_byte=9 then
begin
crypt_buff_pre_8:=crypt_buff;
if not decrypt_every_8_byte(instrlen) then break;
end;
end;
outstr:=outp;
result:=True;
end;
end.