首页
社区
课程
招聘
[求助]QQ2009的聊天记录文件Msg2.0文件格式?
发表于: 2008-12-13 16:51 41813

[求助]QQ2009的聊天记录文件Msg2.0文件格式?

2008-12-13 16:51
41813
QQ2009的聊天记录文件由08的MsgEx.db改为了Msg2.0.db,里面的块记录结构没变,但内容变了。另外不知道它怎么加密了,以前用的是QQ号码,不知道现在是否用了QQ密码加密,如果用了QQ密码,那可能就只有知道了密码的情况下才可以查看别人的聊天记录了。

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (25)
雪    币: 360
活跃值: (77)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
2
本帖没看懂lz啥意思
2008-12-13 18:29
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
我也想学习,密切关注楼主的帖子。。。。
2009-2-12 10:59
0
雪    币: 202
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
QQ的Msg保存是一COM Storage 方式,使用VC 工具读出分析,肯定是加过密的
2009-2-13 12:50
0
雪    币: 53
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
可以逆一下从MSG.10到MSG2.0的过程。。。
2009-2-27 16:41
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
支持~关注一下~腾讯又换格式真是麻烦啊~
2009-3-31 20:02
0
雪    币: 203
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
非常观注。。。。。
2009-4-30 19:25
0
雪    币: 191
活跃值: (19)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
你可以用7z解包...
2009-4-30 19:37
0
雪    币: 191
活跃值: (19)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
然后解密吧,不会了..
2009-4-30 19:38
0
雪    币: 203
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
7z解包?怎么解,改成什么扩展名?
2009-4-30 19:54
0
雪    币: 100
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
听说文件貌似是加密了.

具体怎么加密不太清楚.
2009-4-30 21:51
0
雪    币: 202
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
不会用密码加密的 一旦更换密码 那不是聊天记录就会丢失么 现在网上也有读2009聊天记录的软件
2009-4-30 23:01
0
雪    币: 66
活跃值: (25)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
13
改成EXE,用UNIEXTRACT抽文件,可以
2009-6-4 23:53
0
雪    币: 348
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
沒試過,等大牛來解吧
2009-6-5 00:07
0
雪    币: 211
活跃值: (40)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
15
是lz77 压缩?
2009-6-6 19:06
0
雪    币: 320
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
装好7z以后直接右键7z,解压到文件夹就可以解出来了,解出来是分开文件夹存放的。进一步如何读取请教高人了。另外解开以后大小都比原来小,不知是何原因
2009-6-14 18:15
0
雪    币: 230
活跃值: (17)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
tgs
17
7ZIP打开就能解出来
2009-6-20 01:25
0
雪    币: 203
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
是用QQ密码加密的,改了密码也能读
2009-7-9 08:54
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
msg2.0.db,这个东西真麻烦,不象之前的msgex那么容易破解。下面简短陈述。看的懂得拿走,看不懂的自己想。

如果你连msg2.0.db是什么都不知道,那就别往下看了。你肯定看不懂。更浪费时间。

1.需要:7-zip,DBcompresser或者Paradox (Paradox用起来麻烦需要library,推荐DBC)

2 用7—zip释放你需要破解得msg2.0.db。 得到buddy,discuss,group,mobile,system这5个文件夹。以及lastmsginfo.dat , Matrix.dat,seqbase.dat 这3个加密的dat文件。

3 需要你自己的msg2.0 并且释放。得到buddy,discuss,group,mobile,system这5个文件夹。以及lastmsginfo.dat , Matrix.dat,seqbase.dat 这3个加密的dat文件。注:buddy是重点,其余的文件夹缺失,没有关系。

4 打开需破解的buddy文件夹,里面就是很多qq号码组成的文件夹。再任意打开其中一个看到content.dat,index.dat,info.dat 三个dat文件。 将自己的info.dat 复制到需破解buddy文件夹下。根据号码复制自己需要的。当然,你也可以全部复制。

5 把7-zip 释放的3个你自己的dat文件,既lastmsginfo.dat , Matrix.dat,seqbase.dat 覆盖到需破解的msq2.0文件夹中。(却一不可)

6 用DBcompresse组合文件,重命名为msg2.0.db,默认储存路径为C:\gainover 。放入user\XXXX里面。(DOS可以直接combine,这个我没研究,看到有人研究过)

7 用复制合成的msg2.0 登陆自己的号码,就能直接看到其中记录。目标人一般在你的黑名单或已删除联系人中。

8 破解完毕。享受吧。该哭的哭,该笑的笑。

如果你懂java.可以直接破解dat,算法已有。还有,别以为这些buddy里面的dat很容易破解。Passware Kit 没有破出来,想破壳的人...绕道吧...

感谢朋友DiLi,提供 qq2009 msg2.0.db VB结构。

以下是msq2.0.db 分析图。如果需要查看内容的话,用IStorage::OpenStream函数就可以打开,这里不多说。

// ClassTest.cpp : Defines the entry point for the console application.

//

#include "stdafx.h"

#include "objidl.h"

#include "comdef.h"

void PrintDB(IEnumSTATSTG *pEnum,IStorage *pStore,int Depth)

{

    STATSTG statstg;

  

    while(NOERROR == pEnum->Next(1,&statstg,NULL))

    {

        for(int i=0;i<Depth;i++)printf("\t|");

        wprintf(_T("---%s\n"),statstg.pwcsName);

        if(statstg.type == STGTY_STORAGE)

        {

            IStorage *pStore1=NULL;

            HRESULT hr;

            hr=pStore->OpenStorage(statstg.pwcsName,NULL,

                STGM_READ|STGM_DIRECT|STGM_SHARE_EXCLUSIVE,

                NULL,

                0,&pStore1);

            if(hr != S_OK || pStore1==NULL)

            {

                wprintf(_T("open %s error\n"),statstg.pwcsName);

                continue;

            }

            IEnumSTATSTG *pEnum1=NULL;

            pStore1->EnumElements(0,NULL,0,&pEnum1);

            PrintDB(pEnum1,pStore1,Depth+1);

            pEnum1->Release();

            pStore1->Release();

        }

    }

}

int _tmain(int argc, _TCHAR* argv[])

{

    wchar_t szFileName[]=_T("E:\\下载保存\\XXXX\\msg2.0.db"//换成你的QQ);

    ::CoInitialize(NULL);

    IStorage *pStore=NULL;

    IStream *pStream=NULL;

    HRESULT hr=E_FAIL;

    hr=::StgOpenStorage(_bstr_t(szFileName),NULL,STGM_READ|STGM_DIRECT|STGM_SHARE_EXCLUSIVE,NULL,0,&pStore);

    if(hr != S_OK || pStore==NULL)

    {

        printf("open failed\n");

        return 0;

    }

    IEnumSTATSTG *pEnum=NULL;

    hr = pStore->EnumElements(0,NULL,0,&pEnum );

    if(hr != S_OK || pStore==NULL)

    {

        printf("enumerate failed\n");

        return 0;

    }

    PrintDB(pEnum,pStore,0);

    pEnum-> Release();

    pStore->Release();

    return 0;

}

输出结果

---buddy

    |---8362xx

    |    |---info.dat

    |    |---index.dat

    |    |---content.dat

    |---169329xx

    |    |---info.dat

    |    |---index.dat

    |    |---content.dat

---group

    |---2048838xx

    |    |---info.dat

    |    |---index.dat

    |    |---content.dat

    |---2049667xx

    |    |---info.dat

    |    |---index.dat

    |    |---content.dat

---mobile

---system

    |---1

    |    |---index.dat

    |    |---content.dat

    |---3

    |    |---index.dat

    |    |---content.dat

    |---4

    |    |---index.dat

    |    |---content.dat

---discuss

---Matrix.dat

---seqbase.dat

---lastmsginfo.dat

以下是JAVA。

package com;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

/**

* Decry LoginUinList.dat

* @author rmb

* 2008-08-07

*/

public class LoginUinListDecry {

FileOutputStream fw = null;

FileInputStream fr = null;

boolean isFileEnd = false;

int[] ascii = ;

/**

* init Decry,Encry file handle

* @return

*/

public int initFile(){

int result = -1;

try {

   fw = new FileOutputStream((new File("LoginUinList_Decry.txt")));

   fr = new FileInputStream((new File("LoginUinList.dat")));

   result = 1;

} catch (FileNotFoundException e) {

   result = -1;

   e.printStackTrace();

}

return result;

}

/**

* Judge file effectiveness

* @return

*/

public int isEffectHead(){

int result = -1;

try{

   if(fr!=null){

    byte[] byte_head = new byte[13];

    fr.read(byte_head);

    if(byte_head[0] == 0x51 && byte_head[1] == 0x41 ){ //&& byte_head[4] == 0x0E

     result = 1;

    }

    if(result>0){

     fr.read(new byte[6]);

    }

   }

}

catch(Exception e){

   result = -1;

   e.printStackTrace();

}

return result;

}

/**

* decry LoginUinList data

* @param key

* @param orig_Data

* @return

*/

public byte[] decryData(byte key,byte[] encry_Data){

/* mov     dl, byte ptr [ecx+esi]

   * not     dl

   * xor     dl, al

   * mov     byte ptr [ecx+esi], dl

   */

byte single_Data;

for(int i=0;i<encry_Data.length;i++){

   single_Data = encry_Data[i];

   single_Data = (byte)(~single_Data);

   single_Data = (byte)(single_Data^key);

   encry_Data[i] = single_Data;

}

return encry_Data;

}

public byte[] getEncryData(byte encryDataLength){

byte[] encryData = new byte[encryDataLength];

int read_num = 0;

try {

   read_num = fr.read(encryData);

   if(read_num!=encryData.length){

    isFileEnd = true;

   }

   return encryData;

} catch (IOException e) {

   e.printStackTrace();

}

return null;

}

public byte[] getKeyField(int length){

int read_num = 0;

if(fr!=null){

   byte[] keyField = new byte[length];

   try {

    read_num = fr.read(keyField);

    if(read_num!=keyField.length){

     isFileEnd = true;

    }

    return keyField;

   } catch (IOException e) {

    e.printStackTrace();

    return null;

   }

  

}

return null;

}

public byte getKey(byte[] KeyField){

byte key;

key = KeyField[1];

return key;

}

public byte getKeyDataValue(byte[] KeyField){

byte key;

key = KeyField[0];

return key;

}

public boolean isNeedDecry(byte key){

int int_key = (int)key;

if(int_key<5){

   return false;

}

return true;

}

public boolean isNeedJump(byte[] KeyField){

if(KeyField[0]==0x09){

   return true;

}

return false;

}

public byte[] trunAround(byte[] DateValue){

byte[] temp = new byte[DateValue.length];

for(int i=0;i<temp.length;i++){

   temp[i] = DateValue[DateValue.length-i-1];

}

return temp;

}

public int writeData(byte[] decryData){

try{

   fw.write(decryData);

   return 1;

}

catch(Exception e){

   e.printStackTrace();

}

return -1;

}

public int writeDataString(byte[] decryData){

try{

   int height = 0;

   int down = 0;

   for(int i=0;i<decryData.length;i++){

    height = ((decryData[i]&240)>>4);

    if(height<0){

     height = 0;

    }

    down = (decryData[i]&15);

    if(down<0){

     down = 0;

    }

    fw.write(ascii[height]);

    fw.write(ascii[down]);

   }

   return 1;

}

catch(Exception e){

   e.printStackTrace();

}

return -1;

}

public void fileFlush(){

try {

   fw.flush();

} catch (IOException e) {

   e.printStackTrace();

}

}

public void jump(){

try {

   fr.read(new byte[8]);

} catch (IOException e) {

   e.printStackTrace();

}

}

public int run(){

int result = -1;

byte[] keyField;

byte key;

byte[] decryData;

byte[] encryData;

if(initFile()>0){

   if(isEffectHead()>0){

    while(!isFileEnd){

     result=-1;

     keyField = getKeyField(3);

     if(keyField==null) break;

     if(isNeedJump(keyField)){

      jump();

      writeData(new byte[]);//block line

      continue;

     }

     key = getKey(keyField);

     encryData = getEncryData(key);

     if(encryData==null) break;

     decryData = decryData(key,encryData);

     writeData(decryData);

     writeData(new byte[]);//:

   

     keyField = getKeyField(4);

     if(keyField==null) break;

     key = getKeyDataValue(keyField);

     encryData = getEncryData(key);

     if(encryData==null) break;

     if(isNeedDecry(key)){

      decryData = decryData(key,encryData);

      decryData = trunAround(decryData);

     }

     else{

      decryData = trunAround(encryData);

     }

     writeDataString(decryData);

     writeData(new byte[]);//break line

     fileFlush();

     result=1;

    }

   }

   destroy();

}

return result;

}

/**

* destroy

* @return

*/

public int destroy(){

int result = -1;

try{

   if(fw!=null){

    fw.close();

   }

   if(fr!=null){

    fr.close();

   }

   result = 1;

}

catch(Exception e){

   result = -1;

   e.printStackTrace();

}

return result;

}

public static void main(String[] args) {

LoginUinListDecry ListDecry = new LoginUinListDecry();

if(ListDecry.run()>0){

   System.out.println("Decry LoginUinList.dat Success");

}

else{

   System.out.println("Decry LoginUinList.dat Fail");

}

}
2010-2-8 11:35
0
雪    币: 203
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
真的能破?
比较怀疑,我测试看看~~

测试结果,失败~~~~~
2010-2-21 15:10
0
雪    币: 1028
活跃值: (216)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
21
TC会用7Z不会吧。。。。
2010-2-21 16:10
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
19楼的方法俺没试成功.有成功的吗?
关注中......
2010-3-21 12:29
0
雪    币: 203
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
是7-zip解压,能看到里面的结构包括buddy,discuss,group,mobile,system这5个文件夹,以及lastmsginfo.dat ,Matrix.dat,seqbase.dat 这3个加密的dat文件,聊天记录存在buddy中,与2008相比每个QQ号码文件夹中多了info.dat文件,我想关键是这个文件了。
2010-3-22 14:51
0
雪    币: 203
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
19楼的帖子在网上有,这个不是用来破解的,功能只是打开了QQ的msg2.0的存储结构,并没有涉及到里面的解密,另外java方法也只是适用于LoginUinList(QQ2008)文件,对于msg2.0中的dat文件并没有用,因为QQ2009中的dat文件也加密了
2010-3-22 14:56
0
雪    币: 203
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
不知有没有试过,就算用DEC压缩后替换为自己的QQ号,在陌生人或黑名单中也找不到数据
2010-3-22 15:06
0
游客
登录 | 注册 方可回帖
返回
//