예제 #1
0
        public static int Walk(int x, int y)
        {
            /* 行走到大约位于中心的位置:
             * 00 00 00 3F 31 00 00 08 35 29 75 C9 B0 00 00 03 2E 00 00 00 00 00 00 01 DD 00 00 01 62 00 00 00 1E 09 05 01 0A 23 01 03 78 03 79 05 40 7A E3 33 33 33 33 33 04 82 4A 0A 01 04 83 56 04 82 5E
             * x坐标是0x1DD, y坐标是0x162.
             * 不同的坐标,封包的长度居然不一样。
             * 不过意外发现只需要修改x, y坐标即可实现行走到相应的位置。
             * 其余的数据的含义无需分析出来,哪怕长度并不同,也能正常用。
             * 包体的第二个int是x坐标,范围大约是0~0x3c0;
             * 包体的第三个int是y坐标,范围大约是0~0x280.
             * 坐标可以超出上限,但是会消失在屏幕范围内。
             * 再点一次屏幕,人就回来了。
             */

            _PacketData PacketData = new _PacketData();
            string      example    = "00 00 00 3F 31 00 00 08 35 29 75 C9 B0 00 00 03 2E 00 00 00 00 00 00 01 DD 00 00 01 62 00 00 00 1E 09 05 01 0A 23 01 03 78 03 79 05 40 7A E3 33 33 33 33 33 04 82 4A 0A 01 04 83 56 04 82 5E ";

            byte[] plain = Misc.HexString2ByteArray(example);
            Packet.ParsePacket(plain, ref PacketData);

            byte[] x_b = Misc.Int2ByteArray(x);
            byte[] y_b = Misc.Int2ByteArray(y);
            x_b.CopyTo(PacketData.body, 4);
            y_b.CopyTo(PacketData.body, 8);

            plain = Packet.GroupPacket(ref PacketData);
            string PlainStr = Misc.ByteArray2HexString(plain);

            return(SendPacketManually(PlainStr));
        }
예제 #2
0
        public static void Login(ref _PacketData RecvPacketData)
        {
            byte[] b = Misc.ArraySlice(RecvPacketData.body, RecvPacketData.body.Length - 4, RecvPacketData.body.Length);        //取LOGIN_IN接收封包的后4个字节
            int    d = Misc.GetIntParam(b, 0);
            string s = (d ^ RecvPacketData.userId).ToString();

            b = System.Text.Encoding.UTF8.GetBytes(s);
            s = Misc.GetMD5(b);
            s = s.Substring(0, 10);         //取md5后的前10个字节作为密钥
            Algorithm.InitKey(s);
        }
예제 #3
0
        public static int SendPacketNum = 0;                    //发送封包序号
        #endregion


        #region 解析一条完整的封包,各项数据放入一个结构体中
        public static void ParsePacket(byte[] packet, ref _PacketData PacketData)
        {
            if (packet.Length >= 17)
            {
                PacketData.length  = Misc.GetIntParam(packet, 0);
                PacketData.version = packet[4];
                PacketData.cmdId   = Misc.GetIntParam(packet, 5);
                PacketData.userId  = Misc.GetIntParam(packet, 9);
                PacketData.result  = Misc.GetIntParam(packet, 13);
                PacketData.body    = Misc.ArraySlice(packet, 17, PacketData.length);
            }
        }
예제 #4
0
        public static byte[] GroupPacket(ref _PacketData PacketData)
        {
            byte[] length = Misc.Int2ByteArray(PacketData.length);
            byte[] cmdId  = Misc.Int2ByteArray(PacketData.cmdId);
            byte[] userId = Misc.Int2ByteArray(PacketData.userId);
            byte[] result = Misc.Int2ByteArray(PacketData.result);

            byte[] packet = new byte[PacketData.length];
            length.CopyTo(packet, 0);
            packet[4] = PacketData.version;
            cmdId.CopyTo(packet, 5);
            userId.CopyTo(packet, 9);
            result.CopyTo(packet, 13);
            PacketData.body.CopyTo(packet, 17);

            return(packet);
        }
예제 #5
0
        public static int Chat(string content)
        {
            /* 喊话“A”
             * 00 00 00 1B 31 00 00 08 36 29 75 C9 B0 00 00 02 78 00 00 00 00 00 00 00 02 41 30
             * 喊话“aaa”
             * 00 00 00 1D 31 00 00 08 36 29 75 C9 B0 00 00 02 88 00 00 00 00 00 00 00 04 61 61 61 30
             * 喊话“暑期福利放送”
             * 00 00 00 2C 31 00 00 08 36 29 75 C9 B0 00 00 01 D4 00 00 00 00 00 00 00 13 E6 9A 91 E6 9C 9F E7 A6 8F E5 88 A9 E6 94 BE E9 80 81 30
             * 喊话“我*30”,喊话字数上限为30(30个汉字,30个英语字母,等等)
             * 00 00 00 74 31 00 00 08 36 29 75 C9 B0 00 00 02 A5 00 00 00 00 00 00 00 5B E6 88 91 E6 88 91 E6 88 91 E6 88 91 E6 88 91 E6 88 91 E6 88 91 E6 88 91 E6 88 91 E6 88 91 E6 88 91 E6 88 91 E6 88 91 E6 88 91 E6 88 91 E6 88 91 E6 88 91 E6 88 91 E6 88 91 E6 88 91 E6 88 91 E6 88 91 E6 88 91 E6 88 91 E6 88 91 E6 88 91 E6 88 91 E6 88 91 E6 88 91 E6 88 91 30
             * */

            _PacketData PacketData = new _PacketData();
            string      example    = "00 00 00 1B 31 00 00 08 36 29 75 C9 B0 00 00 02 78 00 00 00 00 00 00 00 02 41 30 ";

            byte[] plain = Misc.HexString2ByteArray(example);
            Packet.ParsePacket(plain, ref PacketData);     //版本号和命令号准备就绪

            byte[] a = new byte[7] {
                0, 0, 0, 0, 0, 0, 0
            };
            byte[] c = System.Text.Encoding.UTF8.GetBytes(content);
            byte[] b = new byte[1] {
                (byte)(c.Length + 1)
            };
            byte[] d = new byte[1] {
                30
            };
            byte[] body = new byte[9 + c.Length];
            a.CopyTo(body, 0);
            b.CopyTo(body, 7);
            c.CopyTo(body, 8);
            d.CopyTo(body, 8 + c.Length);
            PacketData.body = body;                          //包体

            PacketData.length = 17 + PacketData.body.Length; //长度

            //序列号和米米号在调用SendPacketManually()的时候会自动修复

            plain = Packet.GroupPacket(ref PacketData);
            string PlainStr = Misc.ByteArray2HexString(plain);

            return(SendPacketManually(PlainStr));
        }
예제 #6
0
파일: Form1.cs 프로젝트: iyzyi/SeerPacket
        public void AddList(string type, int num, ref _PacketData PacketData, byte[] plain, byte[] cipher)
        {
            ListViewItem li = new ListViewItem(type);

            li.SubItems.Add(num.ToString());
            li.SubItems.Add(PacketData.length.ToString());
            li.SubItems.Add(PacketData.version.ToString());
            li.SubItems.Add(PacketData.userId.ToString());
            li.SubItems.Add(PacketData.cmdId.ToString());
            li.SubItems.Add(Command.GetCommandName(PacketData.cmdId));
            li.SubItems.Add(PacketData.result.ToString());
            li.SubItems.Add(Misc.ByteArray2HexString(PacketData.body));
            li.SubItems.Add(Misc.ByteArray2HexString(plain));
            li.SubItems.Add(Misc.ByteArray2HexString(cipher));

            // 添加到封包log列表中
            PacketLogList.Add(li);
            //Console.WriteLine(PacketLogList.Count);

            // 这段由PacketFilter内部实现
            // 若关键字过滤的文本框中没有字符,则将该条封包log添加到UI的listview框中
            //if (String.IsNullOrEmpty(textBox5.Text))
            //{
            //    this.listView1.Items.Add(li);
            //}

            PacketFilter(li);

            if (type == "send")
            {
                iSendPacketNum++;
            }
            if (type == "recv")
            {
                iRecvPacketNum++;
            }
            label4.Text = String.Format("本次连接中,发送封包{0}条,接收封包{1}条", iSendPacketNum, iRecvPacketNum);


            //this.listView1.Items[this.listView1.Items.Count - 1].EnsureVisible();
            //列表刷新时自动拉到最后
        }
예제 #7
0
        public static void CalculateResult(ref _PacketData PacketData)
        {
            int result = 0;

            if (PacketData.cmdId > 1000)
            {
                int v6 = 0, v7 = 0;
                while (v7 < PacketData.body.Length)
                {
                    v6 = (v6 ^ PacketData.body[v7]) & 255;
                    v7++;
                }
                result = Algorithm.MSerial(Result, PacketData.body.Length, v6, PacketData.cmdId);
            }
            else
            {
                result = 0;
            }
            PacketData.result = result;
        }
예제 #8
0
        //private static async void RecvLeaveMapPacket(int MapId)
        private static void RecvLeaveMapPacket(int MapId)
        {
            //await Task.Run(() => {
            //    while (!Listen.bLeaveMap)
            //    {
            //        ;
            //    }
            //});

            //MessageBox.Show("ENTER MAP ing");
            Thread.Sleep(100);


            _PacketData PacketData = new _PacketData();
            string      EntryMap   = "00 00 00 21 31 00 00 07 D1 09 C0 B6 F7 00 00 02 55 00 00 00 00 00 00 00 0A 00 00 02 D5 00 00 00 AC ";

            // 包体是4个int,第一个是0,第二个是地图号,第三第四个分别是x,y坐标
            byte[] plain = Misc.HexString2ByteArray(EntryMap);
            Packet.ParsePacket(plain, ref PacketData);

            byte[] temp  = Misc.Int2ByteArray(0);
            byte[] mapid = Misc.Int2ByteArray(MapId);
            //byte[] x = Misc.Int2ByteArray(490);
            //byte[] y = Misc.Int2ByteArray(280);         // 默认传送坐标为(490,280)
            byte[] x    = Misc.Int2ByteArray(0x2d5);
            byte[] y    = Misc.Int2ByteArray(0xac);
            byte[] body = new byte[16];
            temp.CopyTo(body, 0);
            mapid.CopyTo(body, 4);
            x.CopyTo(body, 8);
            y.CopyTo(body, 12);
            PacketData.body = body;

            plain = Packet.GroupPacket(ref PacketData);
            string PlainStr = Misc.ByteArray2HexString(plain);

            SendPacketManually(PlainStr);
        }
예제 #9
0
        public static int SendPacketManually(string PlainStr)
        {
            if (!Misc.CheckHexString(PlainStr))
            {
                MessageBox.Show("封包数据格式错误,请检查十六进制字符串的格式是否正确");
                return(0);
            }
            byte[]      plain          = Misc.HexString2ByteArray(PlainStr);
            _PacketData SendPacketData = new _PacketData();

            Packet.ParsePacket(plain, ref SendPacketData);
            Packet.CalculateResult(ref SendPacketData);                         //更新序列号
            SendPacketData.userId = Packet.UserId;                              //修改为当前登录的米米号
            plain = Packet.GroupPacket(ref SendPacketData);
            byte[] cipher = Packet.encrypt(plain);

            int res = SendPacket.Send(Packet.Socket, cipher);

            Packet.Result = SendPacketData.result;
            Packet.SendPacketNum++;
            Program.UI.AddList("send", Packet.SendPacketNum, ref SendPacketData, plain, cipher);

            return(res);
        }
예제 #10
0
        public static void ProcessingRecvPacket(int socket, byte[] buffer, int length)
        {
            _PacketData RecvPacketData = new _PacketData();

            Array.Copy(buffer, 0, RecvBuf, RecvBufLen, length);                     //接收封包的数据追加到接收封包缓冲区的尾部,以解决断包的问题
            RecvBufLen += length;                                                   //更新接收封包缓冲区的长度

            if (Socket != socket)
            {
                #region 直接过滤的接收封包

                if (length > 20)
                {
                    Console.WriteLine("接收封包-解析过滤 : [ {0}...... ]\n", Misc.ByteArray2HexString(RecvBuf, 20));
                }
                else
                {
                    Console.WriteLine("接收封包-解析过滤 : [ {0}]\n", Misc.ByteArray2HexString(RecvBuf, length));
                }

                RecvBufIndex += length;                                             //更新接收封包缓冲区的索引

                if (RecvBufIndex == RecvBufLen)
                {
                    //如果接收封包缓冲区索引等于接收封包缓冲区长度
                    //说明刚好取完所有的包,不存在断包的情况,所以此时将二者的值都设为0
                    RecvBufLen   = 0;
                    RecvBufIndex = 0;
                }

                #endregion
            }
            else
            {
                while (true)                                                        //从接收封包缓冲区中不停地取出一条条接收封包,直到取完或遇到断包
                {
                    if (RecvBufLen >= 4)
                    {
                        int PacketLen = Misc.GetIntParam(RecvBuf, RecvBufIndex);
                        if (RecvBufIndex + PacketLen <= RecvBufLen)                 //不是断包
                        {
                            #region 从缓冲区中取出一条接收封包,解析并发送(同时会监测cmdId为1001和105的封包)

                            byte[] cipher = Misc.ArraySlice(RecvBuf, RecvBufIndex, RecvBufIndex + PacketLen);   //取出一条接收封包

                            byte[] plain;
                            if (NeedDecrypt(cipher))                                        //解密或者不解密封包
                            {
                                plain = decrypt(cipher);
                            }
                            else
                            {
                                plain = cipher;
                            }

                            ParsePacket(plain, ref RecvPacketData);                                       //解析封包
                            RecvPacketNum++;
                            Program.UI.AddList("recv", RecvPacketNum, ref RecvPacketData, plain, cipher); //更新UI界面的列表


                            #region 登录包(cmdId == 1001)
                            if (RecvPacketData.cmdId == 1001)                       //登陆LOGIN_IN包
                            {
                                Login(ref RecvPacketData);                          //处理登录数据,拿到密钥
                                Socket    = socket;                                 //设置全局socket通信号
                                Result    = RecvPacketData.result;                  //LOGIN_IN的recv包是含有序列号的
                                UserId    = RecvPacketData.userId;                  //米米号
                                HaveLogin = true;                                   //是否登录
                            }
                            #endregion

                            //Listen.listen(ref RecvPacketData);

                            RecvBufIndex += PacketLen;                              //更新接收封包缓冲区的索引

                            #endregion
                        }
                        else                                                        //断包,等待下一次接收封包的到来
                        {
                            break;
                        }
                    }
                    else                                                            //断包,等待下一次接收封包的到来
                    {
                        break;
                    }

                    #region 取完缓冲区内所有的包后重置RecvBufLen和RecvBufIndex
                    if (RecvBufIndex == RecvBufLen)
                    {
                        //如果接收封包缓冲区索引等于接收封包缓冲区长度
                        //说明刚好取完所有的包,不存在断包的情况,所以此时将二者的值都设为0
                        RecvBufLen   = 0;
                        RecvBufIndex = 0;
                    }
                    #endregion
                }
            }
        }
예제 #11
0
        public static int ProcessingSendPacket(int socket, byte[] cipher, int length)
        {
            _PacketData SendPacketData = new _PacketData();
            int         res            = 0;

            if (cipher.Length < 17 || Misc.ByteArray2HexString(cipher, 2) != "00 00 ")
            {
                #region 直接过滤的发送封包(这个包也得发送出去,但是我们的封包解析程序不会解析这一条封包)

                res = SendPacket.Send(socket, cipher);          //直接发送封包

                if (cipher.Length > 20)
                {
                    Console.WriteLine("发送封包-解析过滤 : [ {0}...... ]\n", Misc.ByteArray2HexString(cipher, 20));
                }
                else
                {
                    Console.WriteLine("发送封包-解析过滤 : [ {0}]\n", Misc.ByteArray2HexString(cipher));
                }

                #endregion
            }
            else
            {
                #region 需要解析的发送封包

                if (!HaveLogin)
                {
                    Socket = socket;                                //通信号
                }

                byte[] plain;
                if (NeedDecrypt(cipher))
                {
                    plain = decrypt(cipher);                        //解密封包
                    ParsePacket(plain, ref SendPacketData);         //解析封包
                    CalculateResult(ref SendPacketData);            //修改序列号
                    plain  = GroupPacket(ref SendPacketData);       //组合封包
                    cipher = encrypt(plain);                        //加密封包
                }
                else                                                //无需加密只有一种情况,即处于登录界面
                {                                                   //这种情况下并不需要修改序列号,只解析封包即可
                    plain = cipher;
                    ParsePacket(plain, ref SendPacketData);         //解析封包

                    #region 登陆前 伪造米米号
                    // 如果 "伪造米米号" 对应的文本框不为空,
                    // 则登录前的封包,米米号修改为该文本框中的米米号。
                    // 这个是用于测试赛尔号的伪造登录。正常游戏则置空即可。
                    if (!HaveLogin && !String.IsNullOrEmpty(Program.UI.textBox11.Text) &&
                        !String.IsNullOrEmpty(Program.UI.textBox12.Text) &&
                        Program.UI.textBox12.Text.Length == 32 && SendPacketData.cmdId == 103)
                    {
                        int    iSubUserId = Int32.Parse(Program.UI.textBox11.Text);
                        byte[] subUserId  = Misc.Int2ByteArray(iSubUserId);
                        subUserId.CopyTo(cipher, 9);
                        subUserId.CopyTo(plain, 9);

                        byte[] doubleMD5Pwd;
                        doubleMD5Pwd = System.Text.Encoding.UTF8.GetBytes(Program.UI.textBox12.Text);
                        doubleMD5Pwd.CopyTo(cipher, 17);
                        doubleMD5Pwd.CopyTo(plain, 17);

                        ParsePacket(plain, ref SendPacketData);
                    }
                    #endregion
                }

                res = SendPacket.Send(socket, cipher);              //发送封包
                if (HaveLogin)
                {
                    Result = SendPacketData.result;                                           //更新全局序列号(登录前的不用更新,也不能更新)
                }
                SendPacketNum++;                                                              //发送封包的总序号
                Program.UI.AddList("send", SendPacketNum, ref SendPacketData, plain, cipher); //UI界面的列表增加这条发送记录

                #endregion
            }
            return(res);
        }