首页
社区
课程
招聘
[旧帖] [求助]"QQ聊天记录文件存储方式解密"中的源码转delphi问题 0.00雪花
发表于: 2008-2-12 21:35 7514

[旧帖] [求助]"QQ聊天记录文件存储方式解密"中的源码转delphi问题 0.00雪花

2008-2-12 21:35
7514
原帖地址:http://bbs.pediy.com/showthread.php?t=37109
VC源码Part1
#include "winsock2.h"
#pragma comment(lib, "ws2_32.lib")

extern unsigned int Key4;
extern unsigned int Key3;
extern unsigned int Key2;
extern unsigned int Key1;

extern void Decrypt(unsigned int *ebx, unsigned int *edi);

/* input: 8 bytes long */
int blowfish_decrypt(char *pIn, char *key, char *pOut)
{
    unsigned int ebx, edi;

    Key4 = *(int *)key;
    Key3 = *(int *)(key+4);
    Key2 = *(int *)(key+8);
    Key1 = *(int *)(key+12);
    
    Key1 = ntohl(Key1);
    Key2 = ntohl(Key2);
    Key3 = ntohl(Key3);
    Key4 = ntohl(Key4);

    ebx = *(unsigned int *)(pIn+0);
    edi = *(unsigned int *)(pIn+4);
    
    ebx = ntohl(ebx);
    edi = ntohl(edi);

    Decrypt(&ebx, &edi);

    ebx = ntohl(ebx);
    edi = ntohl(edi);

    memcpy(pOut, &ebx, 4);
    memcpy(pOut+4, &edi, 4);
    //MsgEx_DumpHex(pOut, 8);

    return 0;
}


/* total_len: len of pOut, should be given at calling */
int QQMSG_decode(char *pIn, int len, char *key, char *pOut, int *total_len)
{
    int n;
    char *pEdi;    //原始指针,指向前8个字节
    char *pLocal;    //前驱指针,指向后8个字节
    int BLOCK_LEN=8;
    int count=0;
    int offset = 0;
    char *pbuffer;
    char buffer[8];
    char ebx_edi[8];
    char cl=0;
    int i=0;
    int retLen;
    
    if((len % 8) != 0)
        return -1;
    
    if(len < 0x10)
        return -1;
    
    n = len;
    pLocal = pIn;
    blowfish_decrypt(pIn, key, ebx_edi);
    cl = *ebx_edi;
    cl &= 0x7;
    n -= cl;
    n -= 0xa;
    if(*total_len < n)
        return -1;
    
    if(n == 0)
        return -1;

    *total_len = n;
    retLen = n;

    n=0;
    offset = BLOCK_LEN;
    
    memset(buffer, 0, 8);
    pEdi = pIn;
    pLocal += BLOCK_LEN;
    pbuffer = buffer;
    n = cl+1;
    count = 1;

    while(count <= 2)
    {
        if(n < BLOCK_LEN)
        {
            n++;
            count++;
            continue;
        }
        if(n != BLOCK_LEN)
            continue;
        
        pbuffer = pEdi;    //pIn
        pIn = pLocal;
        
        /* xor ebx_edi with bytes afterward */
        for(i=0; i < BLOCK_LEN; i++)
        {
            char *p;
            if((offset+i) >= len)
                return -1;
            p = pLocal+i;
            cl = *p;
            p = ebx_edi+i;
            (*p) ^= cl;
        }
        
        /* compute new ebx_edi */
        blowfish_decrypt(ebx_edi, key, ebx_edi);
        offset += BLOCK_LEN;
        pEdi = pLocal;
        pLocal += BLOCK_LEN;
        n = 0;
    };
    
    //end of while

    if(*total_len == 0)
        goto final_process;

    while(*total_len != 0)
    {
        char *p;
        if(n < BLOCK_LEN){
            p = pOut;
            cl = *(char*)(pbuffer+n);
            cl ^= *(char*)(ebx_edi+n);
            pOut++;
            n++;
            (*total_len)--;
            *p = cl;
            continue;
        }
        if(n != BLOCK_LEN)
            continue;
        pbuffer = pEdi;
        pIn = pLocal;
        
        i = 0;
        /* xor ebx_edi with bytes afterward */
        do{
            if((offset+i) >= len)
                return -1;
            cl = *(pLocal+i);
            *(ebx_edi+i) ^= cl;
            i++;
        }while(i<BLOCK_LEN);
        
        /* compute new ebx_edi */
        blowfish_decrypt(ebx_edi, key, ebx_edi);
        offset += BLOCK_LEN;
        pEdi = pLocal;
        pLocal += BLOCK_LEN;
        n = 0;
    }//end of while
    
final_process:
    count = 1;
    do{
        if(n < BLOCK_LEN){
            char *p;
            p = pOut;
            cl = *(char*)(pbuffer+n);
            cl ^= *(char*)(ebx_edi+n);
            if(cl != 0)
                return -1;
            n++;
            count++;
            continue;
        }

        if(n != BLOCK_LEN)
            continue;
        
        pbuffer = pEdi;
        pIn = pLocal;
        i = 0;
        do{
            if((offset+i) >= len)
                return -1;
            cl = *(pLocal+i);
            *(ebx_edi+i) ^= cl;
            i++;
            
        }while(i<BLOCK_LEN);

        /* compute new ebx_edi */
        blowfish_decrypt(ebx_edi, key, ebx_edi);
        offset += BLOCK_LEN;
        pEdi = pLocal;
        pLocal += BLOCK_LEN;
        n = 0;        
    }while(count < 7);
    
    *total_len = retLen;
    return 0;
    
}


Part2
#define F_FUNCTION(x, k1, k2, c)  ((((x) >> 5) + (k1)) ^ (((x) << 4) + (k2)) ^ ((c) +(x)))
#define C_BLOWFISH    16

unsigned int Key4 = 0;
unsigned int Key3 = 0;
unsigned int Key2 = 0;
unsigned int Key1 = 0;


//软件里面的解密运算过程
//注意:编译器会将有符号数的右移翻译成SAR指令,而我们需要的是SHR指令,所以必须定义成无符号数
void Decrypt(unsigned int *ebx, unsigned int *edi)
{

    int C1 = 0xE3779B90;
    int k = 0;

    for(k = 0 ; k < C_BLOWFISH; k++)
    {
        *edi -= F_FUNCTION((*ebx), Key1, Key2, C1);
        *ebx -= F_FUNCTION((*edi), Key3, Key4, C1);
        C1  += 0x61C88647;
    }
}

//上面的函数的逆
void Encrypt(unsigned int *edx, unsigned int *ebx)
{
    int C1 = 0x00000000;
    int k=0;
    for(k = 0 ; k < C_BLOWFISH; k++)
    {
        C1  -= 0x61C88647;
        (*edx) += F_FUNCTION((*ebx), Key3, Key4, C1);
        *ebx += F_FUNCTION((*edx), Key1, Key2, C1);    
    }
}


我转的Delphi代码:
unit QQmsg_Decode;

interface
uses
  winsock,windows;
function  blowfish_decrypt(pIn:pChar; key:pChar;pOut:pChar):integer;
function QQMSGdecode(pIn:pchar;len:integer;key:pchar; pOut:pchar;total_len:pInteger):integer;
procedure Decrypt(ebx,edi:pCardinal);
procedure Encrypt(edx,ebx:pCardinal);
implementation
var
  Key1,Key2,Key3,Key4:Cardinal;
const
  C_BLOWFISH=16;

function F_FUNCTION(x, k1, k2, c:Cardinal):Cardinal;
begin
  result:=((((x) shr 5) + (k1)) xor (((x) shl 4) + (k2)) xor ((c) +(x)))
end;

function  blowfish_decrypt(pIn:pChar; key:pChar;pOut:pChar):integer;
var
   ebx:Cardinal;
   edi:Cardinal;
   temp_p:pChar;
begin

    Key4 := pinteger(key)^;
  temp_p:=key+4;
    Key3 := pinteger(temp_p)^;
  temp_p:=key+8;
    Key2 := pinteger(temp_p)^;
  temp_p:=key+12;
    Key1 := pinteger(temp_p)^;
    
    Key1 := ntohl(Key1);
    Key2 := ntohl(Key2);
    Key3 := ntohl(Key3);
    Key4 := ntohl(Key4);

    ebx := PCardinal(pIn)^;
  temp_p:=pIn+4;
    edi := pCardinal(temp_p)^;
    
    ebx := ntohl(ebx);
    edi := ntohl(edi);

    Decrypt(@ebx, @edi);

    ebx := ntohl(ebx);
    edi := ntohl(edi);

     CopyMemory(pOut, @ebx, 4);
   temp_p:= pOut+4;
     CopyMemory(temp_p, @edi, 4);
   result:= 0;
end;

function QQMSGdecode(pIn:pchar;len:integer;key:pchar; pOut:pchar;total_len:pInteger):integer;
var
    n,BLOCK_LEN,i,retLen,offset,count:integer;
    pEdi,pLocal,pbuffer,p,temp_p:pChar;
    buffer,ebx_edi:array[0..7] of char;
    cl:char;

begin
  BLOCK_LEN:=8;
  i:=0;
  offset:=0;
  count:=0;
  cl:=chr(0);
    if((len mod 8) <> 0) then
  begin
        result:= -1;
    exit;
  end;
    
    if(len < $10)  then
  begin
        result:= -1;
    exit;
  end;
    
    n := len;
    pLocal := pIn;
    blowfish_decrypt(pIn, key, @ebx_edi);
    cl := ebx_edi[0];
    cl :=Chr(ord(cl) and $7);
    n :=n - ord(cl);
    n :=n - $a;
    if(total_len^ < n)then
  begin
        result:= -1;
    exit;
  end;

    if(n = 0)then
  begin
        result:= -1;
    exit;
  end;

    total_len^ := n;
    retLen := n;

    n:=0;
    offset := BLOCK_LEN;
    
    zeromemory(@buffer,8);
    pEdi := pIn;
    pLocal :=pLocal+ BLOCK_LEN;
    pbuffer := buffer;
    n := ord(cl)+1;
    count := 1;

    while(count <= 2) do
    begin
        if(n < BLOCK_LEN) then
        begin
            inc(n);
            inc(count);
            continue;
        end;
        if(n <> BLOCK_LEN)  then
            continue;
        
        pbuffer := pEdi;    //pIn
        pIn := pLocal;


        for i:=0 to BLOCK_LEN -1 do
        begin
            if((offset+i) >= len)then
        begin
          result:= -1;
          exit;
        end;
            p := pLocal+i;
            cl := p^;
            p := ebx_edi+i;
            p^ :=Chr(ord(p^) xor ord(cl));
        end;

        blowfish_decrypt(ebx_edi, key, ebx_edi);
        offset :=offset+ BLOCK_LEN;
        pEdi := pLocal;
        pLocal :=pLocal+ BLOCK_LEN;
        n := 0;
    end;
    
    //end of while

    if(total_len^ <> 0) then

    while(total_len^ <> 0)do
    begin
        if(n < BLOCK_LEN)then
     begin
            p := pOut;
      temp_p:=pbuffer+n;
            cl := pchar(temp_p)^;
      temp_p:=pbuffer+n;
            cl :=chr(ord(cl) xor ord(pchar(temp_p)^));
            inc(pOut);
            inc(n);
            dec(total_len^);
            p^ := cl;
            continue;
        end;
        if(n <> BLOCK_LEN) then
            continue;
        pbuffer := pEdi;
        pIn := pLocal;
        
        i := 0;
        repeat
            if((offset+i) >= len)then
        begin
          result:= -1;
          exit;
        end;
            p := pLocal+i;
            cl := p^;
      p := ebx_edi+i;
            p^ :=Chr(ord(p^) xor ord(cl));
            inc(i);
        until (i>=BLOCK_LEN);


        blowfish_decrypt(ebx_edi, key, ebx_edi);
        offset :=offset+ BLOCK_LEN;
        pEdi := pLocal;
        pLocal :=pLocal+ BLOCK_LEN;
        n := 0;
    end;//end of while

    count := 1;
    repeat
        if(n < BLOCK_LEN)then
    begin
            p := pOut;
      temp_p:=pbuffer+n;
            cl := pchar(temp_p)^;
      temp_p:=pbuffer+n;
            cl :=chr(ord(cl) xor ord(pchar(temp_p)^));
            if(ord(cl) <> 0)then
        begin
          result:= -1;
          exit;
        end;
            inc(n);
            inc(count);
            continue;
        end;

        if(n <> BLOCK_LEN) then
            continue;
        
        pbuffer := pEdi;
        pIn := pLocal;
        i := 0;
        repeat
            if((offset+i) >= len) then
        begin
          result:= -1;
          exit;
        end;
            p := pLocal+i;
            cl := p^;
      p := ebx_edi+i;
            p^ :=Chr(ord(p^) xor ord(cl));
            inc(i);
            
        until(i>=BLOCK_LEN);

        blowfish_decrypt(ebx_edi, key, ebx_edi);
        offset := offset+BLOCK_LEN;
        pEdi := pLocal;
        pLocal :=pLocal+ BLOCK_LEN;
        n := 0;
    until(count >= 7);
    
    total_len^ := retLen;
    result:= 0;
    
end;

procedure Decrypt(ebx,edi:pCardinal);
var
  C1: Cardinal;
    k :integer;
begin


  C1 := $E3779B90;
    for k:= 0 to  C_BLOWFISH -1 do
    begin
        edi^ := edi^ - F_FUNCTION((ebx^), Key1, Key2, C1);
        ebx^ := ebx^ - F_FUNCTION((edi^), Key3, Key4, C1);
        C1   := C1 + $61C88647;
    end;
end;

//上面的函数的逆
procedure Encrypt(edx,ebx:pCardinal);
var
  C1: integer;
    k :integer;
begin
  C1 := $0;
    for k:= 0 to  C_BLOWFISH -1 do
  begin
        C1   := C1 - $61C88647;
    edx^ := edx^ + F_FUNCTION((ebx^), Key3, Key4, C1);
        ebx^ := ebx^ + F_FUNCTION((edx^), Key1, Key2, C1);
    end;
end;

end.


问题如下:转了编译后delphi程序可正常执行,但是调用QQMSGdecode返回的结果不对!是不是哪里错了,哪位大侠帮小弟看看呵..

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (6)
雪    币: 134
活跃值: (84)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
2

unsigned int Key4 = 0;
unsigned int Key3 = 0;
unsigned int Key2 = 0;
unsigned int Key1 = 0;
只是猜
2008-2-12 21:58
0
雪    币: 269
活跃值: (38)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
可是这几个变量在调用的时候都要重新赋值的啊....
感觉没冠希啊..
2008-2-13 20:31
0
雪    币: 269
活跃值: (38)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
检查出来了~原来是我输入的参数错了~~~~
2008-2-14 23:07
0
雪    币: 498
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
编译后是不是可以直接读取聊天记录文件 不用安装QQ就可以用吧?
2008-2-15 11:36
0
雪    币: 203
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
magicwolf
能提供完整程序吗
2008-7-4 14:33
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
呵呵,能共享下代码吗?
2008-7-10 13:23
0
游客
登录 | 注册 方可回帖
返回
//