年世界杯彩票 世界杯足球竞猜app 2018世界杯彩票发售 足球竞猜 竞彩足球 俄罗斯vs沙特 足球世界杯赌球开庄 足球彩票投注app 足彩复式投注计算 体彩世界杯竞猜规则 世界杯赌球app哪个好 竞彩足球比分直播360彩票 世界杯 赌球模式 竞彩足球稳定盈利 世界杯赌球可靠吗 世界杯足彩娱乐 世界杯足彩 张路 竞彩足球比分360 足球竞猜4串4啥意思 股市抽资世界杯赌博 竞彩足球庄家如何盈利 世界杯2018哪里可以赌球 足球彩票网 足球计算器竞彩网 足球外围大小球 足球外围靠谱吗 2018年世界杯体育彩票 体彩世界杯足球竞猜 外围足球网址 外围足球网址 足球彩票哪里买靠谱 世界杯赌外围什么意思 俄罗斯世界杯彩票预测 世界杯皇冠线上赌球网址 足球外围投注app 世界杯买彩票软件 竞猜足球胜平负开奖结果 2018世界杯彩票往上在哪买 世界杯2018彩票网上怎么买 世界杯怎么买球 转载 解密QQ消息文件格式 - 数据库恢复技术交流专区 - 数据恢复,winhex视频,数据恢复培训,硬盘数据恢复,raid0,raid1,raid5数据恢复,雨荷数据 - Powered by Discuz!

扫一扫,访问微社区

新浪微博登陆

只需一步, 快速开始

登录 | 加入雨荷 | 找回密码

数据恢复,winhex视频,数据恢复培训,硬盘数据恢复,raid0,raid1,raid5数据恢复,雨荷数据

 找回密码
 加入雨荷

扫一扫,访问微社区

新浪微博登陆

只需一步, 快速开始

总共6066条微博

动态微博

查看: 5897|回复: 24

转载 解密QQ消息文件格式

  [复制链接]

该用户从未签到

新浪微博达人勋

发表于 2008-12-22 18:02:51 | 显示全部楼层 |阅读模式
QQ的消息实际上是存放在本地的,位于"QQ安装目录\QQ号码\MsgEx.db"内。关于QQ消息文件格式的文章,网上有不少,但是没有一篇是完整并且可重现。结合QQ聊天记录察看器 5.1,我做了一些研究,重现了读取并显示历史消息的完整过程。

一个很好的学习QQ相关算法的实例,是它的Linux版本LumaQQ

首先,MsgEx.db文件的大致结构可以参考QQ聊天记录查看器 5.3 华军版
IStorage的详细介绍可以在MSDN中查到,CHM就是使用了这个格式。为了方便的操作这个COM接口,我们可以直接使用Decompiling CHM (help) files with C#中提供的RelatedObjects.Storage.dll

消息的加密密码存放在Matrix.db中,提取出来之后就可以解密实际存放消息文本的Data.msj文件了
(值得注意的是,QQ使用的数据加密算法并不是上面帖子里提到的Blowfish,而是TEA算法,可以参考QQ的TEA填充算法C#实现

QQ分若干种消息类型,诸如双人消息、群消息和系统公告等,格式有一些差异。

具体的细节,看看代码就清楚了。一个简单的QQ消息类的实现如下:

namespace Van.Utility.QQMsg
{
    public enum QQMsgType
    {
        BIM, C2C, Group, Sys, Mobile, TempSession //Disc
    }

    class QQMsgMgr
    {
        private static readonly int s_MsgTypeNum = (int)QQMsgType.TempSession + 1;
        private static readonly string[] s_MsgName = new string[] {
            "BIMMsg", "C2CMsg", "GroupMsg", "SysMsg", "MobileMsg", "TempSessionMsg"
        };
        private IStorageWrapper m_Storage;
        private byte[] m_Password;

        private List<string>[] m_MsgList = new List<string>[s_MsgTypeNum];

        public void Open(string QQID)
        {
            Open(QQID, null);
        }
        public void Open(string QQID, string QQPath)
        {
            if (QQPath == null)
            {
                using (Microsoft.Win32.RegistryKey reg = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"Software\Tencent\QQ"))
                {
                    QQPath = reg.GetValue("Install") as string;
                }
                if (QQPath == null) return;
            }

            for (int i = 0; i < m_MsgList.Length; ++i)
            {
                m_MsgList = new List<string>();
            }
            m_Storage = null;
            m_Password = null;

            m_Storage = new IStorageWrapper(QQPath + QQID + @"\MsgEx.db");
            m_Password = QQMsgMgr.GetGlobalPass(m_Storage, QQID);

            if (m_Password == null) m_Storage = null;

            foreach (IBaseStorageWrapper.FileObjects.FileObject fileObject in m_Storage.foCollection)
            {
                if (fileObject.FileType == 1)
                {
                    for (int i = 0; i < m_MsgList.Length; ++i)
                    {
                        if (fileObject.FilePath == s_MsgName)
                        {
                            m_MsgList.Add(fileObject.FileName);
                        }
                    }
                }
            }
        }

        public void OutputMsg()
        {
            for (int i = 0; i < s_MsgTypeNum; ++i)
            {
                OutputMsg((QQMsgType)i);
            }
        }
        public void OutputMsg(QQMsgType type)
        {
            if (m_Storage == null) return;
            if (m_Password == null) return;

            int typeIndex = (int)type;
            if (typeIndex < 0 || typeIndex >= s_MsgTypeNum)
            {
                throw new ArgumentException("Invalid QQMsgType", "type");
            }

            string filePath = s_MsgName[typeIndex] + "\\";
            Directory.CreateDirectory(filePath);

            foreach (string QQID in m_MsgList[typeIndex])
            {
                string fileName = filePath + QQID + ".msj";
                OutputMsg(type, QQID, fileName);
            }
        }
        public void OutputMsg(QQMsgType type, string QQID)
        {
            if (m_Storage == null) return;
            if (m_Password == null) return;

            int typeIndex = (int)type;
            if (typeIndex < 0 || typeIndex >= s_MsgTypeNum)
            {
                throw new ArgumentException("Invalid QQMsgType", "type");
            }

            string filePath = s_MsgName[typeIndex] + "\\";
            Directory.CreateDirectory(filePath);

            string fileName = filePath + QQID + ".msj";
            OutputMsg(type, QQID, fileName);
        }

        private void OutputMsg(QQMsgType type, string QQID, string fileName)
        {
            string msgPath = s_MsgName[(int)type] + QQID;
            IList<byte[]> msgList = QQMsgMgr.DecryptMsg(m_Storage, msgPath, m_Password);
            Encoding encoding = Encoding.GetEncoding(936);

            using (FileStream fs = new FileStream(fileName, FileMode.Create))
            {
                using (StreamWriter sw = new StreamWriter(fs))
                {
                    for (int i = 0; i < msgList.Count; ++i)
                    {
                        using (MemoryStream ms = new MemoryStream(msgList))
                        {
                            using (BinaryReader br = new BinaryReader(ms, Encoding.GetEncoding(936)))
                            {
#if false
                                fs.Write(msgList, 0, msgList.Length);
#else
                                int ticks = br.ReadInt32();
                                DateTime time = new DateTime(1970, 1, 1) + new TimeSpan(0, 0, ticks);
                                switch (type)
                                {
                                    case QQMsgType.BIM:
                                    case QQMsgType.C2C:
                                    case QQMsgType.Mobile:
                                        ms.Seek(1, SeekOrigin.Current);
                                        break;
                                    case QQMsgType.Group:
                                        ms.Seek(8, SeekOrigin.Current);
                                        break;
                                    case QQMsgType.Sys:
                                        ms.Seek(4, SeekOrigin.Current);
                                        break;
                                    case QQMsgType.TempSession: //?
                                        ms.Seek(9, SeekOrigin.Current);
                                        break;
                                }
                                if (type == QQMsgType.TempSession)
                                {
                                    int gLen = br.ReadInt32();
                                    string groupName = encoding.GetString(br.ReadBytes(gLen));
                                    if (groupName.Length > 0) sw.WriteLine("{0}", groupName);
                                }
                                int nLen = br.ReadInt32();
                                string id = encoding.GetString(br.ReadBytes(nLen));
                                sw.WriteLine("{0}: {1}", id, time.ToString());
                                int cLen = br.ReadInt32();
                                string msg = encoding.GetString(br.ReadBytes(cLen));
                                msg.Replace("\n", Environment.NewLine);
                                sw.WriteLine(msg);
                                sw.WriteLine();
#endif
                            }
                        }
                    }
                }
            }
        }

        public void OutputFileList()
        {
            if (m_Storage == null) return;

            Dictionary<string, long> dic = new Dictionary<string, long>();
            foreach (IBaseStorageWrapper.FileObjects.FileObject fileObject in m_Storage.foCollection)
            {
                if (fileObject.FileType == 2 && fileObject.FileName == "Index.msj")
                {
                    dic[fileObject.FilePath] = fileObject.Length / 4;
                }
            }

            for (int i = 0; i < m_MsgList.Length; ++i)
            {
                Console.WriteLine("{0}", s_MsgName);
                foreach (string ID in m_MsgList)
                {
                    Console.WriteLine("\t{0}: {1}", ID, dic[s_MsgName + ID]);
                }
            }
        }

        private static IBaseStorageWrapper.FileObjects.FileObject GetStorageFileObject(IStorageWrapper iw, string path, string fileName)
        {
            foreach (IBaseStorageWrapper.FileObjects.FileObject fileObject in iw.foCollection)
            {
                if (fileObject.CanRead)
                {
                    if (fileObject.FilePath == path && fileObject.FileName == fileName) return fileObject;
                }
            }
            return null;
        }
        private static byte[] Decrypt(byte[] src, byte[] pass, long offset)
        {
            RedQ.QQCrypt decryptor = new RedQ.QQCrypt();
            return decryptor.QQ_Decrypt(src, pass, offset);
        }

        private static IList<byte[]> DecryptMsg(IStorageWrapper iw, string path, byte[] pass)
        {
            List<byte[]> msgList = new List<byte[]>();

            int num = 0;
            int[] pos = null;
            int[] len = null;
            using (IBaseStorageWrapper.FileObjects.FileObject fileObject = GetStorageFileObject(iw, path, "Index.msj"))
            {
                if (fileObject == null) return msgList;
                int fileLen = (int)fileObject.Length;
                num = fileLen / 4;
                pos = new int[num + 1];
                using (BinaryReader br = new BinaryReader(fileObject))
                {
                    for (int i = 0; i < num; ++i)
                    {
                        pos = br.ReadInt32();
                    }
                }
            }
            using (IBaseStorageWrapper.FileObjects.FileObject fileObject = GetStorageFileObject(iw, path, "Data.msj"))
            {
                if (fileObject != null)
                {
                    int fileLen = (int)fileObject.Length;
                    len = new int[num];
                    pos[num] = fileLen;
                    for (int i = 0; i < num; ++i)
                    {
                        len = pos[i + 1] - pos;
                    }
                    using (BinaryReader br = new BinaryReader(fileObject))
                    {
                        for (int i = 0; i < num; ++i)
                        {
                            fileObject.Seek(pos, SeekOrigin.Begin);
                            byte[] data = br.ReadBytes(len);
                            byte[] msg = Decrypt(data, pass, 0);
                            msgList.Add(msg);
                        }
                    }
                }
            }
            return msgList;
        }
        private static byte[] GetGlobalPass(IStorageWrapper iw,
string QQID)
        {
            System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create();
            byte[] dataID = new byte[QQID.Length];
            for (int i = 0; i < QQID.Length; ++i) dataID = (byte)(QQID);
            byte[] hashID = md5.ComputeHash(dataID);
            IBaseStorageWrapper.FileObjects.FileObject fileObject = GetStorageFileObject(iw, "Matrix", "Matrix.db");
            if (fileObject != null)
            {
                using (BinaryReader br = new BinaryReader(fileObject))
                {
                    byte[] data = br.ReadBytes((int)fileObject.Length);
                    long len = data.Length;
                    if (len < 6 || data[0] != 0x51 || data[1] != 0x44) return null;
                    if (len >= 32768) return null;

                    bool bl = false;
                    int i = 6;
                    while (i < len)
                    {
                        bl = false;
                        byte type = data[i++];
                        if (i + 2 > len) break;
                        int len1 = data + data[i + 1] * 256;
                        byte xor1 = (byte)(data ^ data[i + 1]);
                        i += 2;
                        if (i + len1 > len) break;
                        for (int j = 0; j < len1; ++j) data[i + j] = (byte)(~(data[i + j] ^ xor1));
                        if (len1 == 3 && data == 0x43 && data[i + 1] == 0x52 && data[i + 2] == 0x4B)
                        {
                            bl = true;
                        }
                        i += len1;

                        if (type > 7) break;
                        if (i + 4 > len) break;
                        int len2 = data + data[i + 1] * 256 + data[i + 2] * 256 * 256 + data[i + 3] * 256 * 256 * 256;
                        byte xor2 = (byte)(data ^ data[i + 1]);
                        i += 4;
                        if (i + len2 > len) break;
                        if (type == 6 || type == 7)
                        {
                            for (int j = 0; j < len2; ++j) data[i + j] = (byte)(~(data[i + j] ^ xor2));
                        }
                        if (bl && len2 == 0x20)
                        {
                            byte[] dataT = new byte[len2];
                            for (int j = 0; j < len2; ++j) dataT[j] = data[i + j];
                            return Decrypt(dataT, hashID, 0);
                        }
                        i += len2;
                    }
                    if (i != len) return null;
                }
            }
            return null;
        }
    }
}

利用这个类,你就可以方便的导出QQ中的历史消息了。

从上面的分析可以看到,查看本地的历史消息是不需要你的QQ密码的,加密密钥来源于你的QQ号码的MD5散列。所以为了保证安全,最好不要在公共电脑或者别人的电脑上使用QQ并记录历史消息。在个人电脑上,最好将历史消息加密。





最近花了几天时间跟踪了一下“QQ聊天记录查看器 5.3 华军版”,总算把聊天记录的存储方法弄清了。大家不要笑我,只是好奇而已,呵呵。

1.聊天记录存储方式

QQ聊天记录保存在MsgEx.db文件中。以前很早的版本是保存在Msg.db中,文件结构也与现在不同,我们就不分析了。

MsgEx.db采用Storage结构化存储。关于Storage复合文档的知识请查阅Microsoft相关文档,我们不做赘述。

大家可以用VC自带的DocFile View工具查看该文件的内容,可以看到文件结构大致如下:


|----MsgEx.db
|   |----C2CMsg
|     |----QQ号码
|         |----Data.msj
|         |----Index.msj
|   |----IMInfo
|     |----info.dat
|   |----Matrix
|     |----Matrix.db
|   |----SysMsg
|     |----10000
|         |----Data.msj
|         |----Index.msj
|   |----DiscMsg
|   |----GroupMsg
|   |----MobileMsg
|---------TempSessionMsg


消息内容都存储在每个号码下面的Data.msj中,通过Index.msj索引。消息内容是经过加密处理的,必须经过解密才能看到。

2.解密方法

消息内容采用BlowFish分组加密。每8个字节为一个分组。密钥Key通过QQ号码生成,具体算法稍后讨论。

解密方法:

a.取前8个字节,通过BlowFish解密, 得到decryptKey;

b.decryptKey与后面8个字节XOR,对结果再进行一次BlowFish解密;

c.将decryptKey与前8个字节XOR,得到第一组结果;

d.decryptKey与后面8个字节XOR,重复b,c两步;

e.最终全部数据解密完毕。

最后会剩下一组8字节无法解密,这个实际上是冗余数据,似乎是用来作为校验。

3.具体步骤

以上解密时,BlowFish的密钥是一个全局公用密钥Key。Key要通过QQ号码生成,具体步骤是:

a.将QQ号码进行MD5变换,得到Md5Key

b.取Matrix.db的数据,对其进行解码。简单说一下Matrix.db文件的结构:

Matrix.db采用分块存储,每个Record包含类型、名字长度、名字、内容长度、内容几个字段组成。用数据结构表示就是:


struct Record{
char rType;
short nLen;
char Name[nLen];
int rLen;
char Content[rLen];
};


初始内容也是通过加密存储的。解密方法很简单:将长度的低位字节和高位字节XOR,得到key;将内容逐个与key进行XOR,就得到结果。对名字和内容分别进行解密即可。解密后会看到STL, TIP, CRK, CPH, CAH等字段,不清楚具体的啥含义,感兴趣的同学可以自己去研究研究。我们要用到的是CRK字段,长度为32字节(如果本地聊天记录加密,可能会有变化,没试过)。将得到的CRK字段作为pData。

c.用Md5Key对pData进行BlowFish解密,得到全局密钥Key

4.结论

以上讨论的都是本地聊天记录没有加密的情况。如果选择了加密,没有密码是肯定解不出来滴,大伙就不用费心了

[ 本帖最后由 haobinnan 于 2008-12-22 18:04 编辑 ]
  • TA的每日心情
    开心
    2017-2-2 08:54
  • 签到天数: 64 天

    [LV.6]站长亲人

    新浪微博达人勋

    发表于 2008-12-22 22:36:44 | 显示全部楼层
    从哪里搞到的这么好的资料?:37|
  • TA的每日心情
    慵懒
    2013-10-17 22:20
  • 签到天数: 7 天

    [LV.3]偶尔蹭饭

    新浪微博达人勋

    发表于 2008-12-23 00:34:59 | 显示全部楼层

    该用户从未签到

    新浪微博达人勋

     楼主| 发表于 2008-12-23 07:23:35 | 显示全部楼层

    回复 2# rainhe 的帖子

    对大家有用就好  :165| :165| :165|

    该用户从未签到

    新浪微博达人勋

    发表于 2008-12-23 11:03:39 | 显示全部楼层
    这个得顶一下!即使是转的,也是好贴!
  • TA的每日心情
    开心
    2013-4-7 21:16
  • 签到天数: 14 天

    [LV.3]偶尔蹭饭

    新浪微博达人勋

    发表于 2009-1-23 00:28:38 | 显示全部楼层
    好资料:36| :36| :36| :36| :36|
  • TA的每日心情
    擦汗
    2015-4-1 22:53
  • 签到天数: 55 天

    [LV.5]站长亲戚

    新浪微博达人勋

    发表于 2009-2-23 20:46:55 | 显示全部楼层

    该用户从未签到

    新浪微博达人勋

    发表于 2009-5-11 14:20:32 | 显示全部楼层
    狂顶啊!!!  太好了

    该用户从未签到

    新浪微博达人勋

    发表于 2009-6-1 14:07:17 | 显示全部楼层
    一看到那满篇的代码就头晕了,没明白,不过下面的介绍还是蛮清楚的

    该用户从未签到

    新浪微博达人勋

    发表于 2009-8-19 11:31:41 | 显示全部楼层
  • TA的每日心情
    开心
    2015-9-29 13:35
  • 签到天数: 3 天

    [LV.2]偶尔串门

    新浪微博达人勋

    发表于 2009-10-31 05:04:15 | 显示全部楼层

    该用户从未签到

    新浪微博达人勋

    发表于 2009-11-9 12:32:40 | 显示全部楼层
    这个得顶一下!即使是转的,也是好贴!
  • TA的每日心情
    擦汗
    2012-10-25 16:12
  • 签到天数: 58 天

    [LV.5]站长亲戚

    新浪微博达人勋

    发表于 2010-2-22 23:43:43 | 显示全部楼层
    这个是老版本了,09。10版的就不是了

    该用户从未签到

    新浪微博达人勋

    发表于 2010-3-4 10:41:42 | 显示全部楼层

    该用户从未签到

    新浪微博达人勋

    发表于 2010-5-8 22:07:35 | 显示全部楼层
    发表回复
    您需要登录后才可以回帖 登录 | 加入雨荷 新浪微博登陆

    本版积分规则

    年世界杯彩票 世界杯足球竞猜app 2018世界杯彩票发售 足球竞猜 竞彩足球 俄罗斯vs沙特 足球世界杯赌球开庄 足球彩票投注app 足彩复式投注计算 体彩世界杯竞猜规则 世界杯赌球app哪个好 竞彩足球比分直播360彩票 世界杯 赌球模式 竞彩足球稳定盈利 世界杯赌球可靠吗 世界杯足彩娱乐 世界杯足彩 张路 竞彩足球比分360 足球竞猜4串4啥意思 股市抽资世界杯赌博 竞彩足球庄家如何盈利 世界杯2018哪里可以赌球 足球彩票网 足球计算器竞彩网 足球外围大小球 足球外围靠谱吗 2018年世界杯体育彩票 体彩世界杯足球竞猜 外围足球网址 外围足球网址 足球彩票哪里买靠谱 世界杯赌外围什么意思 俄罗斯世界杯彩票预测 世界杯皇冠线上赌球网址 足球外围投注app 世界杯买彩票软件 竞猜足球胜平负开奖结果 2018世界杯彩票往上在哪买 世界杯2018彩票网上怎么买 世界杯怎么买球
    猪哥风云劲爆A,独家正版福利传真(新料)
    独家梅花来料,特码传真梅花图(手写版)
    特码直通车,手写九龙内幕(电脑版)
    特码生肖对对拼,萧萧特码报,新急智金囊
    特码大先赢钱决,先锋特码玄机诗,马会输尽光
    特码令(新),六合简报(新图),手机短信(新图)
    易经救世报(正版),香港挂牌宝典(新图)
    牛派劫钟,牛派波色,牛派脸谱
    牛派如来,正版五点来料,正版综合资料
    港台神算-(合),马会财经-(合),白姐急旋风-(合)
    曾女士铁板神数-(合),老版曾女士(合)(妙算)
    新版九龙内幕,正版蜗牛报,香港彩霸王(正版)
    抓码王,另生肖特码王,2018综合资料
    六合财经王,六合赌神,六合横财
    六合圆你梦-B,九龙内幕
    另版吉数赌经-B,另版香港六合皇
    另潮汕赌经濠华版B,李 大 仙(另版)
    另梅花四合一B,另澳门三合图
    另大刀彩综合-(合),白小姐祺袍(小版)
    另中四柱,另东方心经,黄大仙救世
    曾道人.六合彩网站,六合彩图库,六合彩特码
    千金点特,白小姐特码信封
    内部透码(信封),幸运六合彩(信封)
    内幕透特,港京特码狂篇(新料)
    内幕消息,曾道人神算王,曾新玄机
    六彩阴阳(正版),特 新 报
    六合通缉令,金太阳(新图)
    老版梅花四合-B,老版香港彩霸王
    老版曾女士-B(妙算),香江堵经
    老版地藏王,老版金鬼将军
    老版刘伯温、老版六合兵法
    老弥陀佛,六合之都,天机泄码,天数特码
    老潮汕澳门三合,老潮汕台湾神算
    绝杀三肖及门数,无字天书,万花来料
    组码玄机,奇人论坛中特,六合先锋诗
    红姐心水论坛欢迎你,八卦王心水论坛
    红姐免费图库天线宝宝网,六合彩美女图
    红太阳心水论坛,十二生肖传奇
    小金猴第二网站,免费平码六码复式
    再现特码料,港奥联合欲钱料+禁一肖
    太子报、精忠报民、曾女士指码
    天赐神码,天下无敌,天尊铁板神算
    虎头蛇尾公司,百发百中三肖二尾一波
    天线宝宝,天线宝宝,另白小姐祺袍
    天下第一点肖单,发财诗/杀三肖一门
    曾女士救世明珠、香港预测老版
    无敌猪哥,无敌猪哥,死人码(新版)
    白小姐必赢特码皇,新濠江堵经,濠江精选
    护民图库,红姐图库,抓码王心水高手坛
    惠泽社群755755,无限惊喜心水论坛
    六和彩.六喝彩.六合菜.香港六合彩图库.6合彩
    六合禅机-(合),香港+台湾神算
    六合杀手正版综合资料-(合),另版彩霸王综合
    六合彩图库,香港惠泽社群官方网
    六合彩图香港报码聊天室 香港六合彩免费图库
    六合开奖号码查询,六合直播,香港六合网站
    六合天书,特码天书,老三怪
    六合内部玄机B(原小版),曾道人特码救世报
    六合公司,六合管家婆,六合白小姐
    香港九龙王六合彩专家论坛
    澳门数输精光,港澳联合欲钱料,无字天书
    六合资料大全,湖南综合资料,香港天线宝宝
    话里知特_中特玄机话(另),黄大仙梅花解码图
    港澳罗大仙正版点歌单,曾道人每期一玄机
    凤凰马经,香江特码救世,黄大仙送码
    香港陆合彩曾道人,官方陆合彩开奖直播
    陈教授平特一肖,东方之珠平特一肖
    话里知特_中特玄机话(另),黄大仙梅花解码图
    葡京赌侠会员正版,香港马会传真药诗玄机
    另香港神算,另澳门三合,另台湾神算
    牛派如来,正版五点来料,正版综合资料
    潮汕赌经濠华版,曾道人赌神
    港澳罗大仙正版点歌单,曾道人每期一玄机
    九龙玄机诗,配码玄机+组码玄机
    港台绝杀二肖及五行,正宗国望诗
    天下第一点肖单,发财诗/杀三肖一门
    绝杀三肖,一肖及一尾,欲钱玄机
    香港六马会开奖结果_香港马开装结果
    白小姐中特网_特马网站今晚开特马
    今期高清跑狗玄机图论坛
    白小姐必赢特码皇,白小姐特码消息
    白小姐四句诗,天下第一诗,曾道人吉尾
    福建草头诗,再现特码料玄机诗
    香港九龙六合彩图库,六合彩图
    铁树银花,香港马会特码四句诗,特码二肖精光诗
    澳门数输精光,港澳联合欲钱料
    老弥陀佛,六合之都,天机泄码,天数特码
    凤凰马经,黄大仙送码
    一肖一码期期准 ,一点红香港马会官方网
    赢钱及点特尾数,波色及波路,特码大包围
    香港曾道人免费资料,一波中特免费公开资料
    精准天机诗w版,香港马会特码四句诗
    无敌猪哥,死人码(新版),无限惊喜心水论坛
    旺角心水论坛,曾一个码,曾道人玉像-
    正宗国望诗,九龙玄机诗,配码玄机+组码玄机
    红姐心水论坛欢迎你,八卦王心水论坛
    霸王彩资料五点来料 综合资料及五点来料
    曾道人上下策,正版特码王
    最精准的六合彩白小姐特码
    无字天书-1,波色输光料
    曾夫人论坛,天线宝宝最快开奖现场
    新版内部玄机,新版东方心经
    大圣指路,台湾妈祖灵码
    平码三中二,复式二中二,平码3中3
    最专业的曾道人特码论坛
    另新濠江赌经,另白姐特码救世
    另曾玄机,另香港六合皇
    王中王铁算盘四肖中特
    大丰收心水高手资料
    白小姐一肖一码开
    惠泽了知/正版输尽光
    港京特码狂篇(新料),当期会员资料图(新料)
    2018白小姐正版先锋诗
    天线宝宝凤凰马经
    2018年全年波色生肖诗
    2018新版跑狗图解码图
    2018年香港马会资料大全东方心经
    2018年香港笨人鬼马诗
    2018年香港正版挂牌彩图之全篇
    2018年白小姐马会免费资料大全
    2018年白小姐一句玄机料
    2018年特马资料大全免费
    2018年正宗一句玄机料
    2018年歇后语1到153期
    2018年最准波色生肖诗
    2018年最准一句梅花诗
    2018年曾道人免费资料大全正版
    2018年四不像特肖图
    2018年另版输尽光资料
    2018年另版澳门葡京赌侠诗
    2018年刘伯温全年资料
    2018香港白小姐一肖中特马
    2018黄大仙玄机料001-153期
    675555香港开奖结果六合开奖结果手机查询
    东方心经2018马报资料

    友情链接1: 香港马会2018年开奖结果查询 黄大仙王牌九肖全年版 香港马会开奖结果 六合彩图库 王中王中特网免费资料大全 看图解特马横财图解 雷锋报彩图高级会员版 雷锋内幕报玄机图 2018年香港马会资料大全东方心经 2018年东方心经今期马报资料 2018年六给彩今晚开奖结果 香港100%最准一肖中特 2018白小姐一肖中特马 全年资料2018年正版开奖结果 2018全年另版输尽光 管家婆彩图四不像肖图 东方心经ad版仙人指路 白小姐精准一句特马诗 香港内部一肖一码一码 正版马会免费资料大全白小姐 新跑狗高清跑狗图彩图 广东赌王图库资料大全 2018另版葡京赌侠诗 管家婆彩图每期自动更新 东方心经今期彩图 2018年一句梅花诗 246天天开彩资料大全 2018年香港正版挂牌每期自动更新 一句梅花诗2018全年 一点红心水高手论坛 东方心经ab版仙人指路 刘伯温一句天机诗 大红鹰高手心水论运

    Copyright © 2001-2015 All Rights Reserved雨荷数据安全技术论坛 陕ICP备17009169号

    QQ|申请友链|小黑屋|手机版|Archiver|雨荷数据安全技术论坛 ( 陕ICP备17009169号

    白姐风采 正版管家婆一句话赢大钱 万众期待 心水玄机 香港666在线 今晚点我必中一肖图片 一句梅花诗2018全年,一句梅花诗2018 48111co横财富超级中特网 中央紫禁城总论坛 陆小姐传密B 当日玄机-A 刘伯温一句天机诗 龙仔四合一 世家心水论坛 全年平特肖公式 万人堂心水论坛 化冰人论坛] 六合奇计-A 352 六合奇计-B 青 苹 果 特肖秘籍 h4 港彩内幕报 港京出码表(新料) 4748.cc  七肖特码彩坛 375 六合小天才-A 神童高手心水论坛 中央紫禁城总论坛 特码霸王-2 牛派金身济世 平特一肖公式规律 大姐免费主论坛 现场报码 另新内幕-2 n259 潮州六合赌王-1 平特网心水主论坛 内部特码 天线宝宝刘合彩官方网 特码包中 权威消息-A 另老金光佛 六合兵法 102 六合明珠 六合168 白姐加大-A 现场报码现场报码 六合宝典心水论坛 特码诗880 陆合彩图库 陆合彩资料  九龙新报(新), 会员资料 六合彩皇-1 港澳大拼盘A 老版香港彩霸王-A
    快速回复 返回顶部 返回列表