summaryrefslogtreecommitdiff
path: root/model/packetpredict.py
blob: 5661fc453552ddb350a5a3fbdf2446783e6f7d26 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
import joblib
from pandas.core.frame import DataFrame
import os
import re
import numpy as np


class PacketData(object):
    """
    预测类:
    构造函数1:传入msg和msg处理后的data部分pkt,模型所在的pkl位置
    构造函数2:传入一个csv文件,用不到,也没测试过
    传msg和pkt进去的时候,最好用try,格式不对会报错

    主要方法:
    predict:直接预测,返回结果
    predict_npy:从默认npy文件处读取一个dict,dict的key是一个tuple,里面是ip对,判断当前包是否载dict里,更新dict的内容并预测
                如果dict[ipSet]中结果已经是0(0表示恶意,1表示良性),或者已经判断了20个包,则不更新,直接返回之前的结果
    update_helper:帮助更新的方法,不直接调用
    """
    def __init__(self, msg, pkt, modelpath='model/lgbm_packetin_model.pkl', feature_dic={}):
        if feature_dic == {}:
            self.flow_list = [
                int(re.search(r'dst_port=\d{1,5}', pkt).group().split('=')[1]),  # 目的端口
                int(re.search(r'src_port=\d{1,5}', pkt).group().split('=')[1]),  # 源端口
                int(re.search(r'flags=\d{1,3}', pkt).group().split('=')[1]),  # flags
                int(re.search(r'window_size=\d{1,10}', pkt).group().split('=')[1]) if 'tcp' in pkt else 0,  # win_size
                float(re.search(r'reason=\d{1,10}', msg).group().split('=')[1]),  # reason
                int(re.search(r'\'in_port\': \d{1,5}', msg).group().split(': ')[1]),  # in_port
                float(re.search(r'total_len=\d{1,5}', msg).group().split('=')[1]),  # min_len
                float(re.search(r'total_len=\d{1,5}', msg).group().split('=')[1]),  # max_len
                float(re.search(r'total_len=\d{1,5}', msg).group().split('=')[1]),  # means_len
                1,  # 包数目
                1  # 标签,默认是1
            ]
        else: self.flow_list = feature_dic
        self.model = joblib.load(modelpath)
        self.ipSet = tuple(re.findall(r"\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b", pkt))
        self.line1 = msg
        self.line2 = pkt

    # 用不到的,从csv读取数据
    @classmethod
    def from_csv(cls, csv_path, modelpath='model/lgbm_packetin_model.pkl'):
        feature_dic = {}
        with open(csv_path, 'r') as f:
            pcapNum = 0
            while True:
                pcapNum += 1
                line1 = f.readline().strip()
                line2 = f.readline().strip()
                if not line2 or not line1: break
                if pcapNum >= 20: break
                ipSet = tuple(re.findall(r"\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b", line2))
                try:
                    if 'tcp' in line2:
                        window_size = re.search(r'window_size=\d{1,10}', line2).group().split('=')[1]
                    else:
                        window_size = 0

                    if ipSet not in feature_dic:
                        flow_list = [
                            re.search(r'dst_port=\d{1,5}', line2).group().split('=')[1],  # 目的端口
                            re.search(r'src_port=\d{1,5}', line2).group().split('=')[1],  # 源端口
                            re.search(r'flags=\d{1,3}', line2).group().split('=')[1],  # flags
                            window_size,
                            re.search(r'reason=\d{1,10}', line1).group().split('=')[1],  # reason
                            re.search(r'\'in_port\': \d{1,5}', line1).group().split(': ')[1],  # in_port
                            float(re.search(r'total_len=\d{1,5}', line1).group().split('=')[1]),  # min_len
                            float(re.search(r'total_len=\d{1,5}', line1).group().split('=')[1]),  # max_len
                            float(re.search(r'total_len=\d{1,5}', line1).group().split('=')[1]),  # means_len
                            pcapNum,  # 包数目
                        ]
                        feature_dic[ipSet] = flow_list
                    else:
                        this_length = float(re.search(r'total_len=\d{1,5}', line1).group().split('=')[1])
                        feature_dic[ipSet][-2] += 1
                        feature_dic[ipSet][-3] = (feature_dic[ipSet][-3] * (feature_dic[ipSet][-2] - 1) + this_length) \
                                                 / feature_dic[ipSet][-2]
                        if this_length > feature_dic[ipSet][-4]:
                            feature_dic[ipSet][-4] = this_length
                        else:
                            feature_dic[ipSet][-5] = this_length
                except Exception as e:
                    pass
        return cls('1', '2', feature_dic=feature_dic)

    def predict(self):
        previous_out = self.flow_list.pop(-1)
        pre_out = self.model.predict(DataFrame(self.flow_list).T)
        pre_out = pre_out.tolist()[0]           # ndarray转int
        self.flow_list.append(pre_out)
        return pre_out

    # 保存到一个dict,和update一样的
    def predict_save(self, feature_hash):
        return self.update_helper(feature_hash)

    # 保存到npy文件
    def predict_npy(self, npypath='model/feature_dict.npy', feature_hash=None):
        if os.path.exists(npypath):
            dict_load = np.load(npypath, allow_pickle=True)

            feature_hash = dict_load.item()
            pre_out, feature_dict = self.update_helper(feature_hash)
            if pre_out == -1:                           # -1表示不需要写回保存的文件
                return feature_dict[self.ipSet][-1]+2
            else:
                np.save(npypath, feature_dict)
                return pre_out
        else:
            feature_hash = {self.ipSet: self.flow_list}
            np.save('model/feature_dict.npy', feature_hash)
            return self.predict()

    def update_helper(self, feature_hash):
        ipSet = self.ipSet
        if self.ipSet in feature_hash:
            # 如果存在且已至为0,或者num>=20则直接返回
            if feature_hash[ipSet][-1] == 0 or feature_hash[ipSet][-2] >=20:
                return -1, feature_hash

            this_length = float(re.search(r'total_len=\d{1,5}', self.line1).group().split('=')[1])
            feature_hash[ipSet][-2] += 1
            feature_hash[ipSet][-3] = (feature_hash[ipSet][-3] * (feature_hash[ipSet][-2] - 1) + this_length) \
                                      / feature_hash[ipSet][-2]
            if this_length > feature_hash[ipSet][-4]:
                feature_hash[ipSet][-4] = this_length
            else:
                feature_hash[ipSet][-5] = this_length
            feature_hash[ipSet].pop(-1)
            pre_out = self.model.predict(DataFrame(feature_hash[ipSet]).T)
            pre_out = pre_out.tolist()[0]
            feature_hash[ipSet].append(pre_out)
        else:
            # 如果不存在
            self.flow_list.pop(-1)      # 先删了默认的tag
            pre_out = self.model.predict(DataFrame(self.flow_list).T)
            pre_out = pre_out.tolist()[0]
            self.flow_list.append(pre_out)      # 再加回去
            feature_hash[ipSet] = self.flow_list
        return pre_out, feature_hash

    def predict_mysql(self):
        pass


if __name__ == '__main__':
    # 来自恶意样本Shifu
    line1 = "version=0x4,msg_type=0xa,msg_len=0x6c,xid=0x0,OFPPacketIn(buffer_id=343,cookie=0,data=""RT\x00\x125\x02\x08\x00'\xc1v\xc3\x08\x00E\x00\x004\x002@\x00\x80\x063\xbb\n\x00\x02k\xbc*\xfeA\xc0\x0e\x01\xbb\xf1\x1e=2\x00\x00\x00\x00\x80\x02 \x00\x98$\x00\x00\x02\x04\x05\xb4\x01\x03\x03\x02\x01\x01\x04\x02"",match=OFPMatch(oxm_fields={'in_port': 1}),reason=0,table_id=0,total_len=66)"
    line2 = "ethernet(dst='52:54:00:12:35:02',ethertype=2048,src='08:00:27:c1:76:c3'), ipv4(csum=13243,dst='188.42.254.65',flags=2,header_length=5,identification=50,offset=0,option=None,proto=6,src='10.0.2.107',tos=0,total_length=52,ttl=128,version=4), tcp(ack=0,bits=2,csum=38948,dst_port=443,offset=8,option=[TCPOptionMaximumSegmentSize(kind=2,length=4,max_seg_size=1460), TCPOptionNoOperation(kind=1,length=1), TCPOptionWindowScale(kind=3,length=3,shift_cnt=2), TCPOptionNoOperation(kind=1,length=1), TCPOptionNoOperation(kind=1,length=1), TCPOptionSACKPermitted(kind=4,length=2)],seq=4045290802,src_port=49166,urgent=0,window_size=8192)"
    thispacket = PacketData(line1, line2)
    print('测试1:', thispacket.predict())
    print(thispacket.predict_npy())

    # 来自良性样本weibo
    line1 = "version=0x4,msg_type=0xa,msg_len=0x618,xid=0x0,OFPPacketIn(buffer_id=4294967295,cookie=0,data='\x02\x1a\xc5\x01\x00\x00\x02\x1a\xc5\x02\x00\x00\x08\x00E\x00\x05\xdc\x7f\xf3@\x00 \x06\xcdH\x01\x02\xf3i\x01\x01\x12t\x00PL$\xee\xe1\xd1\x1d\x86\xf8\xc8\xe8\x80\x10!\xf0\x9f\x19\x00\x00\x01\x01\x08\n\x1d\x16\xdc\xd9\n\xf7\xf8\xd7ke\xda\x92^\xcag\x94\x8fB\xed\x92}\xbd)8>\x83[\xdd\x9f""|A\xd6/|O\xe3\xfb\xad#M_\x1e\xc0n\xef\xe0\xd3e\xba\xb0E\x86\xce\xc0DD\x8d2\x16\xea\xaf\x9c1\xef\x83^\xaf\xe2D\xb5\xbb\xb1\x92\xca\xf1V\xee\xdeX\xcc2$\x83p\x90\x11\x83\x9f\xad{\xac\x9f\x08-%\x18:\x95\xc0\xfa*\xd6e\xcf\xc0M>\xe5\xf7\x9dR\xe5\x089\x1f""\xd62\xa7.\x88\xd1K\xb9\xf1\x87\xc3M\x1b\xfe\x10\xebI\xb4%\x99\xa7\xb4\xd3\xaee\xb7\xb6\'\x92\xb0\x86\xca.{\xed\x07\x1f\x85z\xbe\x96\xdb\x9e28\x07\x91^\x8b\xa4~\xc8\x9av\x99\xbc\xc9\xe2mB\xe6i$y^G\x89\x06K\x12k\xa8\xb3\xfd\x9d\xb4\xeb0\xbbu\x8b\xa6#\xa6Qk\xcbx:\xb2\x9b\x95\x8feb\xe9F\x11\x8a{\x1c>\x9cCF=\xaa\xcb\r\xc4\xf3\xc5zD?\x06\xac\xe2\x00\rJ\xe0\xff\x00\xc0\x16\xa5\x1f\x08\xac\xc0#\xfbBs\xf5QW\x1c-U\xd0\xceX\xaaL\xf2\xc5\xf9%\xc7\x1fZ\xb0b\xde\xb9\x07\x18\xafF\x1f\x06\xed\x03n\xfe\xd1\x9c\xe7\xb1E\xa9G\xc2K@1\xf6\xf9\xbf\xef\x85\xae\x8faW\xb1\x9a\xc4Au<\xde y\xe7""\xa5M\xea\x8c\xc4c\x8a\xf4t\xf8Sh\x83\x1fo\x9c\xff\x00\xc0EK\xff\x00\n\xc2\xd4\xa9_\xb6\xcd\xcf\xfb""\xab\xd8N\xfb\x12\xf1\x14\xdfS\xc7\xe7\xba\x0cOPEb\xdc\xcc\x1eL\xee?\x8d{|\x9f\x07\xacd\x07\x17\xf3\x8c\xff\x00\xb0\xb5JO\x81\x9a|\x9c\xb6\xa3?\xfd\xf0\xb4K\r6\xcd#\x8b\xa6\x91\xe2s<B""N\x07\xbda\xdd\xce-\xe2wS\x9c\x8cs\xde\xbe\x80\x9f\xf6}\xd3\xa6\x18:\xad\xd6=\x91j\x8d\xd7\xec\xd3\xa6\xdc\xc7\xb0\xebW\x8a=\xa3Z!BQz\x98\xd4\xc4)\xad\x0f\x97t}3\xe1\xef\xc2\x1d/T\xf1\x06\xa7mo\xa7\xc0\xf3\xfd\xb1\xdd\xfeg\x92\xe0\xe0|\x80\xe4\x96\xf4\x02\xad\xcf\xe1\xddg\xe3-\xee\x9b\xe2;\x9d[\xfe\x10m\x1e\x02\xed\xa7Evs6\x0eG\xda\n\x12\x06\xe0\xb8#<\x8a\xf5\xa6\xfd\x84t\x1dO\xc7\xd6\xfe%\xd7\xbcQ\xa9\xeb\xd1\xd9\x90\xd6:]\xcc1\x8b[f\x07!\x82\x81\xf37\xb9\xae\xef\xc7\x1f\xb2\xd7\x85\xbe""Ae\x0e\xb9\xba\xf6+M\xe65\x95\x01\x03p\xc1\xe8Ez\x91\xd1jyrM\xecxM\x87\xec\x9f\xa2\xcc\xad}s\xac\xaf\x8ed\x9dL\xa5\xfcD^Uf\xc0\xc6\xd6F\xc0\x04\xf3\xc0\xef]\x17\x84~\x1fx^\xdbQ\xfb&\x9be?\x81|Ue\x1b\xb7\x91\xa7\xce\xc6\x19\x14\xa8\x01\xc2\x9f\x96T\xcfb85\xf4\x0f\x86>\x12\xe9\x9e\x13\xd0\xac\xb4\x9d:W\x86\xc6\xd2%\x86(\xd5F\x02\x8e\x94\xcd_\xe1>\x9f\xab\xdc\xd9\xdd}\xaeX.\xed$\xf3""\x9e5]\xc0te>\xa0\x8e\rn\xa6\xb61T\xda>i\xf8\x8bc\xaax\xb2\xfa\xebG\xd4c\xb7Y\xad\xe2Kx\xa5\x132-\xe3\x1f\x98\xb9P>PWw\x198 \xd7\xa3\xf8gD\xb0\xd0\xfc;kk\x13\xed\x10\xa0DfbO\x07\x1f\x96+\xac\xb8\xfd\x9e\xad.\xbcYw\xae\\k\xb7\xb3K3\x83\x1c\x0c\x8b\xb2\x15\x08\x17j\xfe\xa7\xf15v\xe7\xe0\x7f\x9byk,\x1e \xbb\xb5\x86\x16\xdd$)\n\x11(\xf4$\xf2?\n\x1c\xd3\xd8\xc7\xd9J\xe7\x95|Q\x97AO\x08\xca\xba\xca\xc1>\x92\xe0\xa5\xcaO\xbb\r\xc7\x00\xe0\x1c\x0e\xbc\xd7\x8a^i\x7f\x03\xbe\x1cxwG\xd2\xc5\xc0\xd2$\xd5e\xfbm\x8c\xe1\xc9*\xfb\xc6>n\xc3\x04\xd7\xdaR|\x1e\xb0\x9a\x06\x8ak\xb9&\x8d\x86\nI\x1a\x90\x7f\n\xe2|]\xfb\x1b|=\xf1\xd5\xc5\x9c\xfa\xce\x9a\x97r\xd9\x8cBLJ\x02\x0c\xe7\x00\x0e\xde\xd4)E\x15\xec\xe4|\xf5\xf03\xc3gQ\xf8\x8f\xe2\x7f\x16]\xea\xeb}{\xbc\xd9\x08\xa29O(\x1f\xdd\xb8\xf7+\x8a\xfa\x1f\xe0\xfe\xbe\xda\x97\xc5\x9dsOG\x06\x0b\x1d60\xc3\xfd\xb6\x93?\xca\xafx\x7f\xf6c\xf0\xff\x00\x855\xeb\x9dKJ\xbb\x9a\xc5nc\x11\xcbm\x12(C\x8e\x87\xd8\xe2\xbao\x00\xfc!\xb2\xf0\x17\x8a5\xcdn\x0b\xd9\xae\xeeu]\xa1\xd6U\x00F\x14\x0c\x01\x8f\xa5\x13\x94^\xc2\xa7NQ\x95\xd9\xe8\x94QEdw\x88zW\x19\xf1""k\x8b=\x1e\x1b\xbf\xf8I\x13\xc2\xfa]\xbc\xdef\xa1{\xb1ZV\x8bi\xda\x91\x96\x04\x02\\\xafbH\xc8\x1c\x9a\xec\xcfJ\xe4\xbco\xf0\xfe\xc3\xc7?\xd9f\xf6\xea\xf6\xd8\xe9\xd7B\xf2\x0f\xb3H\xa0y\xa0\x10\xac\xca\xca\xca\xd8\xc9##\x83\xcfZ\x00\xf2/\r\xf8\x8b\xc7\x9e*\xb6\x96\xca\xe7\xc4\x17Z,\xb6\x1aU\xc6\xa5\x14\xf2ZD\x97\x17h\xd7\x12\xad\xab\xcc\x85p\xbf\xba\x8dK(\x00\xe5\xb9\xc1\xe2\xb6\xed<u\xe3\x1dS\xc4\x1f\r\xee\x9ak+-\x0fZ\x81\x85\xc41\xa1ig\x9b\xec\xcc\xe4\xe4\xfd\xc4V\x1c\x01\xc9\xcdu\xda\xc7\xc2m;[x\xa6\xbb\xd6usz {Io#\xb8H\xe5\xb9\xb7v\xcbC!T\x00\xaes\x82\x00a\xce\rm\\\xf8+C\xb8:\x101*G\xa3n\xfb\x1cH\xf8U\x063\x19\x04w\x1bN(\x15\xcf\x1e\xd4<e\xe3o\x07\xf8\x95\xb4\xd3\xac\x1dF\xf2]""\xf2\xe4\xbe\xb5n\xb6\xb6\x12\xdd!C\x1f\xd9]W%UY\xb7)<\x80\xbd\xc95\xc4|?\xf8\x89\xe3;\xfdkE\xd2\xed\xfcY\xab\xddiw\x1a\x14z\xb2\xcfu\xfd\x99\xe7\xb9yG\xdef\x1c.\x1b\xee\x9f\x98~\x15\xee\xb6?\x05\xbc3mql\xd7s\xdekV\xf6q<\x166Z\xac\xe2x,\xd1\xf1\xb8""\xe0\x13\x9c\x01\x97,@\x18\x04TK\xf0\'\xc1+\xe3\x16\xd7\x86\x91\xa7\x05\xfe\xcf\xfb\x07\xd8>\xcd\x1f\x93\x8f0?\x99\xd3;\xb8\xc7\xd2\x81\x9c\x15\xcf\xc4\x14\x08I\xe2',match=OFPMatch(oxm_fields={'in_port': 1}),reason=0,table_id=0,total_len=1518)"
    line2 = "ethernet(dst='02:1a:c5:01:00:00',ethertype=2048,src='02:1a:c5:02:00:00'), ipv4(csum=52552,dst='1.1.18.116',flags=2,header_length=5,identification=32755,offset=0,option=None,proto=6,src='1.2.243.105',tos=0,total_length=1500,ttl=32,version=4), tcp(ack=2264451304,bits=16,csum=40729,dst_port=19492,offset=8,option=[TCPOptionNoOperation(kind=1,length=1), TCPOptionNoOperation(kind=1,length=1), TCPOptionTimestamps(kind=8,length=10,ts_ecr=184023255,ts_val=488037593)],seq=4007776541,src_port=80,urgent=0,window_size=8688), 'ke\xda\x92^\xcag\x94\x8fB\xed\x92}\xbd)8>\x83[\xdd\x9f""|A\xd6/|O\xe3\xfb\xad#M_\x1e\xc0n\xef\xe0\xd3e\xba\xb0E\x86\xce\xc0DD\x8d2\x16\xea\xaf\x9c1\xef\x83^\xaf\xe2D\xb5\xbb\xb1\x92\xca\xf1V\xee\xdeX\xcc2$\x83p\x90\x11\x83\x9f\xad{\xac\x9f\x08-%\x18:\x95\xc0\xfa*\xd6e\xcf\xc0M>\xe5\xf7\x9dR\xe5\x089\x1f""\xd62\xa7.\x88\xd1K\xb9\xf1\x87\xc3M\x1b\xfe\x10\xebI\xb4%\x99\xa7\xb4\xd3\xaee\xb7\xb6\'\x92\xb0\x86\xca.{\xed\x07\x1f\x85z\xbe\x96\xdb\x9e28\x07\x91^\x8b\xa4~\xc8\x9av\x99\xbc\xc9\xe2mB\xe6i$y^G\x89\x06K\x12k\xa8\xb3\xfd\x9d\xb4\xeb0\xbbu\x8b\xa6#\xa6Qk\xcbx:\xb2\x9b\x95\x8feb\xe9F\x11\x8a{\x1c>\x9cCF=\xaa\xcb\r\xc4\xf3\xc5zD?\x06\xac\xe2\x00\rJ\xe0\xff\x00\xc0\x16\xa5\x1f\x08\xac\xc0#\xfbBs\xf5QW\x1c-U\xd0\xceX\xaaL\xf2\xc5\xf9%\xc7\x1fZ\xb0b\xde\xb9\x07\x18\xafF\x1f\x06\xed\x03n\xfe\xd1\x9c\xe7\xb1E\xa9G\xc2K@1\xf6\xf9\xbf\xef\x85\xae\x8faW\xb1\x9a\xc4Au<\xde y\xe7""\xa5M\xea\x8c\xc4c\x8a\xf4t\xf8Sh\x83\x1fo\x9c\xff\x00\xc0EK\xff\x00\n\xc2\xd4\xa9_\xb6\xcd\xcf\xfb""\xab\xd8N\xfb\x12\xf1\x14\xdfS\xc7\xe7\xba\x0cOPEb\xdc\xcc\x1eL\xee?\x8d{|\x9f\x07\xacd\x07\x17\xf3\x8c\xff\x00\xb0\xb5JO\x81\x9a|\x9c\xb6\xa3?\xfd\xf0\xb4K\r6\xcd#\x8b\xa6\x91\xe2s<B""N\x07\xbda\xdd\xce-\xe2wS\x9c\x8cs\xde\xbe\x80\x9f\xf6}\xd3\xa6\x18:\xad\xd6=\x91j\x8d\xd7\xec\xd3\xa6\xdc\xc7\xb0\xebW\x8a=\xa3Z!BQz\x98\xd4\xc4)\xad\x0f\x97t}3\xe1\xef\xc2\x1d/T\xf1\x06\xa7mo\xa7\xc0\xf3\xfd\xb1\xdd\xfeg\x92\xe0\xe0|\x80\xe4\x96\xf4\x02\xad\xcf\xe1\xddg\xe3-\xee\x9b\xe2;\x9d[\xfe\x10m\x1e\x02\xed\xa7Evs6\x0eG\xda\n\x12\x06\xe0\xb8#<\x8a\xf5\xa6\xfd\x84t\x1dO\xc7\xd6\xfe%\xd7\xbcQ\xa9\xeb\xd1\xd9\x90\xd6:]\xcc1\x8b[f\x07!\x82\x81\xf37\xb9\xae\xef\xc7\x1f\xb2\xd7\x85\xbe""Ae\x0e\xb9\xba\xf6+M\xe65\x95\x01\x03p\xc1\xe8Ez\x91\xd1jyrM\xecxM\x87\xec\x9f\xa2\xcc\xad}s\xac\xaf\x8ed\x9dL\xa5\xfcD^Uf\xc0\xc6\xd6F\xc0\x04\xf3\xc0\xef]\x17\x84~\x1fx^\xdbQ\xfb&\x9be?\x81|Ue\x1b\xb7\x91\xa7\xce\xc6\x19\x14\xa8\x01\xc2\x9f\x96T\xcfb85\xf4\x0f\x86>\x12\xe9\x9e\x13\xd0\xac\xb4\x9d:W\x86\xc6\xd2%\x86(\xd5F\x02\x8e\x94\xcd_\xe1>\x9f\xab\xdc\xd9\xdd}\xaeX.\xed$\xf3""\x9e5]\xc0te>\xa0\x8e\rn\xa6\xb61T\xda>i\xf8\x8bc\xaax\xb2\xfa\xebG\xd4c\xb7Y\xad\xe2Kx\xa5\x132-\xe3\x1f\x98\xb9P>PWw\x198 \xd7\xa3\xf8gD\xb0\xd0\xfc;kk\x13\xed\x10\xa0DfbO\x07\x1f\x96+\xac\xb8\xfd\x9e\xad.\xbcYw\xae\\k\xb7\xb3K3\x83\x1c\x0c\x8b\xb2\x15\x08\x17j\xfe\xa7\xf15v\xe7\xe0\x7f\x9byk,\x1e \xbb\xb5\x86\x16\xdd$)\n\x11(\xf4$\xf2?\n\x1c\xd3\xd8\xc7\xd9J\xe7\x95|Q\x97AO\x08\xca\xba\xca\xc1>\x92\xe0\xa5\xcaO\xbb\r\xc7\x00\xe0\x1c\x0e\xbc\xd7\x8a^i\x7f\x03\xbe\x1cxwG\xd2\xc5\xc0\xd2$\xd5e\xfbm\x8c\xe1\xc9*\xfb\xc6>n\xc3\x04\xd7\xdaR|\x1e\xb0\x9a\x06\x8ak\xb9&\x8d\x86\nI\x1a\x90\x7f\n\xe2|]\xfb\x1b|=\xf1\xd5\xc5\x9c\xfa\xce\x9a\x97r\xd9\x8cBLJ\x02\x0c\xe7\x00\x0e\xde\xd4)E\x15\xec\xe4|\xf5\xf03\xc3gQ\xf8\x8f\xe2\x7f\x16]\xea\xeb}{\xbc\xd9\x08\xa29O(\x1f\xdd\xb8\xf7+\x8a\xfa\x1f\xe0\xfe\xbe\xda\x97\xc5\x9dsOG\x06\x0b\x1d60\xc3\xfd\xb6\x93?\xca\xafx\x7f\xf6c\xf0\xff\x00\x855\xeb\x9dKJ\xbb\x9a\xc5nc\x11\xcbm\x12(C\x8e\x87\xd8\xe2\xbao\x00\xfc!\xb2\xf0\x17\x8a5\xcdn\x0b\xd9\xae\xeeu]\xa1\xd6U\x00F\x14\x0c\x01\x8f\xa5\x13\x94^\xc2\xa7NQ\x95\xd9\xe8\x94QEdw\x88zW\x19\xf1""k\x8b=\x1e\x1b\xbf\xf8I\x13\xc2\xfa]\xbc\xdef\xa1{\xb1ZV\x8bi\xda\x91\x96\x04\x02\\\xafbH\xc8\x1c\x9a\xec\xcfJ\xe4\xbco\xf0\xfe\xc3\xc7?\xd9f\xf6\xea\xf6\xd8\xe9\xd7B\xf2\x0f\xb3H\xa0y\xa0\x10\xac\xca\xca\xca\xd8\xc9##\x83\xcfZ\x00\xf2/\r\xf8\x8b\xc7\x9e*\xb6\x96\xca\xe7\xc4\x17Z,\xb6\x1aU\xc6\xa5\x14\xf2ZD\x97\x17h\xd7\x12\xad\xab\xcc\x85p\xbf\xba\x8dK(\x00\xe5\xb9\xc1\xe2\xb6\xed<u\xe3\x1dS\xc4\x1f\r\xee\x9ak+-\x0fZ\x81\x85\xc41\xa1ig\x9b\xec\xcc\xe4\xe4\xfd\xc4V\x1c\x01\xc9\xcdu\xda\xc7\xc2m;[x\xa6\xbb\xd6usz {Io#\xb8H\xe5\xb9\xb7v\xcbC!T\x00\xaes\x82\x00a\xce\rm\\\xf8+C\xb8:\x101*G\xa3n\xfb\x1cH\xf8U\x063\x19\x04w\x1bN(\x15\xcf\x1e\xd4<e\xe3o\x07\xf8\x95\xb4\xd3\xac\x1dF\xf2]""\xf2\xe4\xbe\xb5n\xb6\xb6\x12\xdd!C\x1f\xd9]W%UY\xb7)<\x80\xbd\xc95\xc4|?\xf8\x89\xe3;\xfdkE\xd2\xed\xfcY\xab\xddiw\x1a\x14z\xb2\xcfu\xfd\x99\xe7\xb9yG\xdef\x1c.\x1b\xee\x9f\x98~\x15\xee\xb6?\x05\xbc3mql\xd7s\xdekV\xf6q<\x166Z\xac\xe2x,\xd1\xf1\xb8""\xe0\x13\x9c\x01\x97,@\x18\x04TK\xf0\'\xc1+\xe3\x16\xd7\x86\x91\xa7\x05\xfe\xcf\xfb\x07\xd8>\xcd\x1f\x93\x8f0?\x99\xd3;\xb8\xc7\xd2\x81\x9c\x15\xcf\xc4'"
    thispacket1 = PacketData(line1, line2)
    print('测试1:', thispacket1.predict())
    print(thispacket1.predict_npy())