吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 28827|回复: 148
收起左侧

[原创] 赛尔号通信数据的逆向分析与还原(思路篇)

    [复制链接]
seo52 发表于 2020-5-26 15:20

赛尔号通信数据的逆向分析与还原(思路篇)

0x01 前言

flash游戏即将淘汰,被称为最强的as加密方式Alchemy被应用于一些主流的页游,很多游戏都转战h5或者手游端。今天闲来没事,就上手一款童年游戏。"赛尔号",应该是全网首发吧

0x02 准备工具

FFDEC(强大的免费开源swf反编译工具) 、 Chrome浏览器 、 在线Hex编辑

0x03分析过程

使用 浏览器加载游戏并 通过 开发者工具抓取到数据包
可以发现一个dll.xml的配置文件
Dll信息
此游戏的习惯将核心数据存放于==TaomeeLibraryDLL.swf==文件当中。
此时直接将swf文件拖入FFDec会发现,读取失败。
读取失败
需要拖入Hex编辑器搞一下
CWS
==CWS== 是标识码 具体可以参考 Swf文件头信息,前面则是一些无关紧要的数据。
可以看到在Client.swf里对于swf文件的加载是这样处理的

private function onComplete(e:Event) : void
        {
            var info:DLLInfo = this._dllList[0];
            var byteArray:ByteArray = new ByteArray();
            if(this._isRelease)
            {
                this._stream.readBytes(new ByteArray(),0,7);//相当于设置了位置 前面可以看出到,标识码前面有7个字节是无用的数据 >>  this._stream.potion=7
            }
            this._stream.readBytes(byteArray);//
            if(this._isRelease)
            {
                byteArray.uncompress();//再进行Zlib解压处理
            }
            this._stream.close();//关闭字节流
            //然后就加载
            this._loader.loadBytes(byteArray,new LoaderContext(false,ApplicationDomain.currentDomain));
        }

思路清晰,可以干代码,这里使用了易语言
啦啦啦

导出文件
是

可以,再将其导入FFdec看看效果。
完美加载
解压后,开始找与通讯的类。一般搜索flash.net.Socke即可
==send(param1, param2) #4CAF50==发送数据包的函数

public function send(param1:uint, param2:Array) : uint
        {
            var loc3_:* = null;
            var loc4_:* = null;
            if(this.connected)
            {
                loc3_ = this.pack(this.userID,param1,param2);
                loc3_.position = 0;
                loc4_ = MessageEncrypt.encrypt(loc3_);//这里就开始加密了
                writeBytes(loc4_);//整个数据丢给
                flush();//这里就是发送数据出去了
                this.sendDataError(param1);
                DebugTrace.show(">>Socket[" + this.ip + ":" + this.port.toString() + "][cmdID:" + param1 + "]",getCmdLabel(param1),"[data length:" + this._sendBodyLen + "]");
                //这里可以清晰的看出 param1是数据包的命令码,param2为数据的整体
                return this._result;
            }
            return 0;
        }
    public function pack(param1:uint, param2:uint, param3:Array) : ByteArray
        {
            var loc4_:ByteArray = new ByteArray();
            this.serializeBinary(loc4_,param3);//这里是将数组序列化
            this._sendBodyLen = loc4_.length;
            var loc5_:ByteArray = this.packHead(param1,param2,loc4_);
            var loc6_:ByteArray = new ByteArray();
            loc6_.writeBytes(loc5_);
            loc6_.writeBytes(loc4_);
            return loc6_;
        }   
private function packHead(param1:uint, param2:uint, param3:ByteArray) : ByteArray
        {
            var loc6_:* = 0;
            var loc7_:int = 0;
            var loc4_:ByteArray = new ByteArray();
            var loc5_:uint = param3.length + HEAD_LENGTH;
            loc4_.writeUnsignedInt(loc5_);//写入数据包的长度
            loc4_.writeUTFBytes(VERSION);//写入通信的协议号
            loc4_.writeUnsignedInt(param2);//写入CmdId
            loc4_.writeUnsignedInt(param1);//写入UserID
            if(param2 > 1000)
            {
                loc7_ = 0;
                while(loc7_ < param3.length)
                {
                    loc6_ = uint(loc6_ ^ param3[loc7_] & 255);
                    loc7_++;
                }
                this._result = MSerial(this._result,param3.length + HEAD_LENGTH,loc6_,param2);//计算序列号
                loc4_.writeInt(this._result);//写入序列号
            }
            else
            {
                loc4_.writeInt(0);
            }
            return loc4_;
        }
  • 这里有1个知识点,记一下
    public class SocketEncryptImpl extends Socket 这个类是继承了 Socket,所以在发送数据包的时候writeBytes(loc4_);和flush(); 其实是省略了 Socket.writeBytes和Socket.flush()

    private static var NO_ENCRYPT_LEN:int = 4;
        public function MessageEncrypt()
        {
            super();
        }
    
        public static function encrypt(param1:ByteArray) : ByteArray
        {
            var loc2_:int = param1.readUnsignedInt() - NO_ENCRYPT_LEN;
            var loc3_:ByteArray = new ByteArray();
            loc3_.writeUnsignedInt(0);
            MEncrypt(param1,loc2_,loc3_);
            loc3_.position = 0;
            loc3_.writeUnsignedInt(loc3_.length);
            trace("outData.length:" + loc3_.length);
            loc3_.position = 0;
            return loc3_;
        }
    
        public static function decrypt(param1:ByteArray) : ByteArray
        {
            var loc2_:int = param1.readUnsignedInt() - NO_ENCRYPT_LEN;
            var loc3_:ByteArray = new ByteArray();
            loc3_.writeUnsignedInt(0);
            MDecrypt(param1,loc2_,loc3_);
            loc3_.position = 0;
            loc3_.writeUnsignedInt(loc3_.length);
            loc3_.position = 0;
            return loc3_;
        }

    根据分析可得,MEncrypt(param1,loc2,loc3);
    传入的参数是 原始数据param1 、加密的长度、加密后的数据loc3_
    继续找 MEncrypt函数内容

public function MEncrypt(_arg_1:ByteArray, _arg_2:int, _arg_3:ByteArray):void
    {
        var _local_16:*;
        var _local_15:int;
        var _local_7:int;
        var _local_10:int;
        var _local_11:int;
        var _local_13:int;
        var _local_14:int;
        var _local_6:int;
        var _local_9:int;
        var _local_4:int = ESP;
        _local_15 = _local_4;
        _local_4 = (_local_4 - 16);
        ESP = (_local_4 & 0xFFFFFFF0);
//获取尺寸,可忽略
var _local_5:int = getDefinitionByName("org.taomee.net.SocketEncryptImpl").size;

        if (_local_5 == 51706)
        {
            ESP = (_local_4 & 0xFFFFFFF0);
            _local_6 = _arg_2;
            _local_4 = (_local_4 - 16);
            si32(_local_6, _local_4);
            ESP = _local_4;
            F_malloc();
            _local_4 = (_local_4 + 16);
            _local_7 = eax;
            ESP = (_local_4 & 0xFFFFFFF0);
            CModule.writeBytes(_local_7, _local_6, _arg_1);
            _local_9 = 0;
            si32(_local_9, (_local_15 - 4));
            ESP = (_local_4 & 0xFFFFFFF0);
            ESP = (_local_4 & 0xFFFFFFF0);
            //_local_10此时是取解密的密钥Key
            _local_10 = CModule.mallocString(getDefinitionByName("com.robot.core.net.SocketConnection").key);
            _local_11 = (_local_10 & 0xFFFFFFFC);
            var _local_12:* = li32(_local_11);
            var _temp_1:* = (_local_12 + -16843009);
            _local_12 = (_local_12 & 0x80808080);
            _local_12 = (_local_12 ^ 0x80808080);
            _local_5 = (_local_12 & _temp_1);

            outer_block:
            {

                if (_local_5 != 0)
                {
                    _local_13 = (_local_11 + 4);
                    while ((_local_14 = (_local_10 + _local_9)) < _local_13)
                    {
                        _local_5 = li8(_local_14);
                        if (_local_5 == 0) break outer_block;
                        _local_9 = (_local_9 + 1);
                    };
                };
                _local_13 = (_local_11 + 4);
                do 
                {
                    _local_14 = li32(_local_13);
                    _local_5 = (_local_14 + -16843009);
                    _local_12 = (_local_14 & 0x80808080);
                    _local_12 = (_local_12 ^ 0x80808080);
                    _local_5 = (_local_12 & _local_5);
                    if (_local_5 != 0)
                    {
                        _local_5 = (_local_14 & 0xFF);
                        if (_local_5 == 0)
                        {
                            _local_9 = (_local_13 - _local_10);
                            break;
                        };
                        _local_5 = li8(_local_13 + 1);
                        if (_local_5 == 0)
                        {
                            _local_5 = (1 - _local_10);
                            _local_9 = (_local_5 + _local_13);
                            break;
                        };
                        _local_5 = li8(_local_13 + 2);
                        if (_local_5 == 0)
                        {
                            _local_5 = (2 - _local_10);
                            _local_9 = (_local_5 + _local_13);
                            break;
                        };
                        _local_5 = li8(_local_13 + 3);
                        if (_local_5 == 0)
                        {
                            _local_5 = (3 - _local_10);
                            _local_9 = (_local_5 + _local_13);
                            break;
                        };
                    };
                    _local_13 = (_local_13 + 4);
                } while (true);

            }//outer_block
            _local_4 = (_local_4 - 32);
            _local_5 = (_local_15 - 4);
            si32(_local_5, (_local_4 + 16));
            si32(_local_9, (_local_4 + 12));
            si32(_local_10, (_local_4 + 8));
            si32(_local_6, (_local_4 + 4));
            si32(_local_7, _local_4);
            ESP = _local_4;

            F__Z15MEncrypt_x86_32PKhiS0_iPi();
            _local_4 = (_local_4 + 32);
            _local_6 = eax;
            if (_local_7 != 0)
            {
                _local_4 = (_local_4 - 16);
                si32(_local_7, _local_4);
                ESP = _local_4;
                F_idalloc();
                _local_4 = (_local_4 + 16);
            };
            _local_5 = li32(_local_15 - 4);
            ESP = (_local_4 & 0xFFFFFFF0);
            CModule.readBytes(_local_6, _local_5, _arg_3);
            if (_local_6 != 0)
            {
                _local_4 = (_local_4 - 16);
                si32(_local_6, _local_4);
                ESP = _local_4;
                F_idalloc();
                _local_4 = (_local_4 + 16);
            };
            if (_local_10 != 0)
            {
                _local_4 = (_local_4 - 16);
                si32(_local_10, _local_4);
                ESP = _local_4;
                F_idalloc();
                _local_4 = (_local_4 + 16);
            };
        };
        _local_4 = _local_15;
        ESP = _local_4;
        return (_local_16);
    }

     public function F__Z15MEncrypt_x86_32PKhiS0_iPi():void
    {
        var _local_17:int;
        var _local_2:int;
        var _local_9:int;
        var _local_7:int;
        var _local_5:int;
        var _local_3:int;
        var _local_12:int;
        var _local_6:int;
        var _local_14:int;
        var _local_11:int;
        var _local_15:int;
        var _local_16:int;
        var _local_4:int;
        var _local_10:int;
        var _local_1:int = ESP;
        _local_17 = _local_1;
        _local_2 = li32(_local_17 + 4);
        _local_3 = (_local_2 + 1);
        _local_5 = li32(_local_17 + 16);
        si32(_local_3, _local_5);
        _local_1 = (_local_1 - 16);
        si32(_local_3, _local_1);
        ESP = _local_1;
        F_malloc();
        _local_7 = li32(_local_17 + 12);
        _local_9 = li32(_local_17 + 8);
        _local_11 = li32(_local_17);
        _local_1 = (_local_1 + 16);
        _local_12 = eax;
        _local_14 = _local_12;
        _local_15 = _local_2;
        _local_16 = 0;
        if (_local_2 >= 1)
        {
            do 
            {
                _local_6 = li8(_local_11);
                _local_4 = 0;
                _local_10 = _local_9;
                if (_local_16 != _local_7)
                {
                    _local_10 = (_local_9 + _local_16);
                    _local_4 = (_local_16 + 1);
                };
                var _local_8:* = li8(_local_10);
                _local_8 = (_local_8 ^ _local_6);
                si8(_local_8, _local_14);
                _local_14 = (_local_14 + 1);
                _local_11 = (_local_11 + 1);
                _local_15 = (_local_15 + -1);
                _local_16 = _local_4;
            } while (_local_15 != 0);
        };
        _local_14 = (_local_12 + _local_2);
        si8(0, _local_14);
        _local_8 = (_local_2 + -1);
        if (_local_8 >= 0)
        {
            _local_11 = (0 - _local_2);
            if (_local_11 <= -1)
            {
                _local_11 = -1;
            };
            _local_8 = (_local_2 + _local_11);
            _local_11 = (_local_8 + 1);
            do 
            {
                _local_8 = li8(_local_14);
                var _local_13:* = li8(_local_14 - 1);
                _local_13 = (_local_13 >>> 3);
                _local_8 = (_local_13 | _local_8);
                si8(_local_8, _local_14);
                _local_8 = li8(_local_14 - 1);
                _local_8 = (_local_8 << 5);
                si8(_local_8, (_local_14 - 1));
                _local_14 = (_local_14 + -1);
                _local_11 = (_local_11 + -1);
            } while (_local_11 != 0);
        };
        _local_8 = li8(_local_12);
        _local_8 = (_local_8 | 0x03);
        si8(_local_8, _local_12);
        _local_8 = (_local_2 % _local_7);
        _local_8 = (_local_9 + _local_8);
        _local_8 = li8(_local_8);
        _local_8 = (_local_8 * 13);
        _local_9 = (_local_8 % _local_3);
        if (_local_9 != 0)
        {
            _local_1 = (_local_1 - 16);
            si32(__ZZ15MEncrypt_x86_32PKhiS0_iPiE10temp_bytes, _local_1);
            _local_8 = (_local_12 + _local_9);
            si32(_local_8, (_local_1 + 4));
            _local_8 = (_local_3 - _local_9);
            si32(_local_8, (_local_1 + 8));
            ESP = _local_1;
            Fmemcpy();
            _local_1 = (_local_1 + 16);
            _local_1 = (_local_1 - 16);
            si32(_local_9, (_local_1 + 8));
            si32(_local_12, (_local_1 + 4));
            _local_8 = (__ZZ15MEncrypt_x86_32PKhiS0_iPiE10temp_bytes + _local_8);
            si32(_local_8, _local_1);
            ESP = _local_1;
            Fmemcpy();
            _local_1 = (_local_1 + 16);
            var _temp_1:* = li32(_local_5);
            _local_1 = (_local_1 - 16);
            si32(_temp_1, (_local_1 + 8));
            si32(__ZZ15MEncrypt_x86_32PKhiS0_iPiE10temp_bytes, (_local_1 + 4));
            si32(_local_12, _local_1);
            ESP = _local_1;
            Fmemcpy();
            _local_1 = (_local_1 + 16);
        };
        eax = _local_12;
        _local_1 = _local_17;
        ESP = _local_1;
    }

我们来看这个Key是如何获取的 ==com.robot.core.net.SocketConnectio==  找到此类
在 ==RobotCoreDLL.swf==此dll上面可以找出

public static function setEncryptKeyStringArr(param1:Array) : void
        {
            _encryptKeyStringArr = param1;
        }
public static function get key() : String
        {
            var loc2_:int = 0;
            var loc3_:* = null;
            var loc1_:String = "";
            if(_encryptKeyStringArr == null)
            {
                loc1_ = "!crAckmE4nOthIng:-)";
            }
            else
            {
                loc2_ = 0;
                while(loc2_ < _encryptKeyStringArr.length)
                {
                    loc3_ = StringUtil.replace(_encryptKeyStringArr[loc2_],"*","");
                    loc1_ = loc1_ + loc3_;
                    loc2_++;
                }
            }
            return loc1_;
        }

这位程序员也是挺可爱的,默认的密钥为 ==crack me Nothing :-)==
然后找出设置 ==setEncryptKeyStringArr== 的地方,一般设置密钥如果不是固定的,则可能是服务器返回的数据。如登录的时候,返回密钥。所以我们可以找登录的函数

private static function onLogin(param1:SocketEvent) : void
        {
            if(MainManager.isNewUser)
            {
                StatManager.sendStat2014("_newtrans_","fOnlineSucc","");
            }
            SocketConnection.removeCmdListener(CommandID.LOGIN_IN,onLogin);
            EventManager.addEventListener(RobotEvent.CREATED_ACTOR,onCreatedActor);
            MainManager.setup(param1.data);
            var loc2_:ByteArray = param1.data as ByteArray;
            var loc3_:int = loc2_.readUnsignedInt();
            initKey(loc3_);
            MapConfig.setup();
            MapSeatPointConfig.setup();
            sendSystemInfo();
            SocketConnection.send(1022,86066824);
        }

private static function initKey(param1:int) : void
        {
            var loc2_:String = "c&o&m.--rob-ot.c--o-r-e.&n-et.S-oc-ke-t&C-on-n-e-c-t-i-on";
            var loc3_:* = "s*e*tE&&&n*c";
            loc3_ = loc3_ + "r*yp*t&&&&Ke*yS*tr*i&n&&g*Arr";
            loc2_ = StringUtil.replace(loc2_,"-","");
            loc2_ = StringUtil.replace(loc2_,"&","");
            loc3_ = StringUtil.replace(loc3_,"*","");
            loc3_ = StringUtil.replace(loc3_,"&","");
            param1 = param1 ^ MainManager.actorInfo.userID;
            var loc4_:String = MD5.hash(param1 + "");
            var loc5_:* = MainManager.actorInfo.userID + "";
            var loc6_:* = [];
            var loc7_:int = 0;
            while(loc7_ < 10)
            {
                loc6_[loc7_] = "*" + loc4_.charAt(loc7_) + "*";
                loc7_++;
            }
            getDefinitionByName(loc2_)[loc3_](loc6_);
        }

在 ==RobotAppDLL.swf==此dll中,可以找到登陆包返回处理的函数。里面包含初始化密钥的处理方式,而且是只取前10位
当然直接搜索 ==setEncryptKeyStringArr== 是无效的,因为是==getDefinitionByName==
综合以上就基本上完成数据的解密工作了。

我使用的是易语言来进行操作
seer

MDe

Key

_De

Key获取
Key处理Key获取

效果图

0x04 写在最后

tm的加解密方式是通用的,只是密钥不同。
如赛尔号的是从返回包截取的
摩尔庄园 “^FStx,wl6NquAVRF@f%6”
赛尔号2  “taomee_seer2k~#”
小花仙 “v#93ta0mee+fl0WErd0t2eatMee&#$+@n0”

从09年到现在,tm的游戏从序列号自加1到封包的加密,也是历经了一段历史了吧,如今各种技术层出不穷。写这篇文章也纯属爱好和对技术的热爱。以前期盼着每周五的更新,到现在也是对过去的一种致敬吧。

免费评分

参与人数 81威望 +2 吾爱币 +176 热心值 +77 收起 理由
BUTU + 1 我很赞同!
Laign + 1 版主太强了
weianan + 1 + 1 我很赞同!
月球引力 + 1 + 1 用心讨论,共获提升!
Kristin_ + 1 + 1 用心讨论,共获提升!
hjy12305 + 1 + 1 谢谢@Thanks!
夷则玖矣 + 1 用心讨论,共获提升!
formyself520 + 1 + 1 用心讨论,共获提升!
九天临兵帝 + 1 + 1 谢谢@Thanks!
lookerJ + 1 + 1 谢谢@Thanks!
ruanzeyu + 1 我很赞同!
weilian丶yezi + 1 用心讨论,共获提升!
yuqiumin + 1 + 1 热心回复!非常好
cx87080165 + 1 + 1 用心讨论,共获提升!
guet123c + 1 + 1 谢谢@Thanks!
YouLii + 1 + 1 用心讨论,共获提升!
rehiber + 1 我很赞同!
九州xxx + 1 + 1 谢谢@Thanks!
回荡 + 1 + 1 我很赞同!
繁星夏若离 + 1 + 1 谢谢@Thanks!
Acosos + 1 + 1 我很赞同!
az730308539 + 1 + 1 谢谢@Thanks!
AboutLee57 + 1 + 1 谢谢@Thanks!
sxlcity + 1 + 1 谢谢分享,学习了!
lendone + 1 + 1 谢谢@Thanks!
BrainFlower + 1 + 1 热心回复!
乄落日乀 + 1 + 1 用心讨论,共获提升!
Psyber + 1 谢谢@Thanks!
萝卜哥哥 + 1 + 1 热心回复!
温柔的一哥 + 1 + 1 已经处理,感谢您对吾爱破解论坛的支持!
soyiC + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
既草日月又日天 + 1 + 1 热心回复!
Leoken + 1 + 1 用心讨论,共获提升!
camedeus + 1 + 1 学习
a767421378 + 1 + 1 用心讨论,共获提升!
lmjg520 + 1 + 1 谢谢@Thanks!
星海月明 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
zhoumeto + 1 + 1 用心讨论,共获提升!
花前月下醉红颜 + 1 + 1 我很赞同!
lzc-sky + 1 + 1 热心回复!
独行风云 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
lyslxx + 1 + 1 我很赞同!
a22999 + 1 + 1 用心讨论,共获提升!
yixi + 1 + 1 我很赞同!
gtp_ + 1 + 1 我很赞同!
冰课玏好喝 + 1 + 1 我很赞同!
unbeaten + 1 + 1 谢谢@Thanks!
handsome + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
yxdyxd163 + 1 热心回复!
zyh666 + 1 + 1 没个技术都不好意思说自己玩赛尔号的
Cheremace + 1 + 1 我很赞同!
keygen2525 + 1 + 1 用心讨论,共获提升!
失眠图书馆 + 1 + 1 我很赞同!
gutian + 2 + 1 用心讨论,共获提升!
490694561 + 2 + 1 用心讨论,共获提升!
游伊伊 + 1 + 1 我很赞同!
muyu1314520 + 1 热心回复!
q74330 + 1 + 1 我很赞同!
魅夜 + 1 + 1 我很赞同!
林亖 + 1 + 1 热心回复!
北辰東閣 + 1 + 1 谢谢@Thanks!
火林xyh + 1 + 1 我很赞同!
fisherman + 1 + 1 热心回复!
灵影 + 1 + 1 谢谢@Thanks!
love514415 + 1 + 1 谢谢@Thanks!
139752 + 1 + 1 热心回复!
喵藏、喵了个藏 + 1 我很赞同!
jnez112358 + 1 + 1 谢谢@Thanks!
a940284833 + 1 + 1 我很赞同!
丶峰宇 + 1 + 1 我很赞同!
Hmily + 2 + 100 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
风生·水起 + 2 + 1 用心讨论,共获提升!
JustHehe + 1 + 1 我很赞同!
清辞 + 1 + 1 谢谢@Thanks!
rootGo4it + 1 + 1 热心回复!
YetAnotherUser + 1 热心回复!
Myitmx + 1 + 1 我很赞同!
傲天越 + 1 + 1 我很赞同!
星月与你 + 1 + 1 我很赞同!
忆魂丶天雷 + 1 + 1 用心讨论,共获提升!
细水流长 + 2 + 1 热心回复!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| seo52 发表于 2020-5-27 11:21
源码已经贴出
赛尔号发包例子(易语言)
https://www.52pojie.cn/thread-1187731-1-1.html
(出处: 吾爱破解论坛)
小卜队长 发表于 2020-5-26 15:33
jonnn 发表于 2020-5-26 15:24
猪头。 发表于 2020-5-26 16:10
满满的都是回忆啊 想当年  啧啧啧
HA? 发表于 2020-5-26 17:06
现在还在玩
zyx1211 发表于 2020-5-26 17:54
当年也研究过 那时候看不懂AS代码 直接自己用js调用as代码哈哈 挺怀念那个时候的
傲天越 发表于 2020-5-26 19:15
支持大佬!!!
一枝傲寒 发表于 2020-5-26 19:56
回忆杀来一波~
wang2019 发表于 2020-5-26 22:00
回忆一波!~
吾爱破解2020 发表于 2020-5-26 22:08
支持大佬!!
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-3-29 09:26

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表