def server_post_decrypt(self, buf): if self.raw_trans: return buf self.recv_buf += buf out_buf = b'' while len(self.recv_buf) > 2: length = struct.unpack('>H', self.recv_buf[:2])[0] if length >= 8192: self.raw_trans = True self.recv_buf = b'' if self.decrypt_packet_num == 0: logging.info('auth_simple: over size') return b'E' else: raise Exception('server_post_decrype data error') if length > len(self.recv_buf): break if (binascii.crc32(self.recv_buf[:length]) & 0xffffffff) != 0xffffffff: logging.info('auth_simple: crc32 error, data %s' % (binascii.hexlify(self.recv_buf[:length]),)) self.raw_trans = True self.recv_buf = b'' if self.decrypt_packet_num == 0: return b'E' else: raise Exception('server_post_decrype data uncorrect CRC32') pos = common.ord(self.recv_buf[2]) + 2 out_buf += self.recv_buf[pos:length - 4] if not self.has_recv_header: if len(out_buf) < 12: self.raw_trans = True self.recv_buf = b'' logging.info('auth_simple: too short') return b'E' utc_time = struct.unpack('<I', out_buf[:4])[0] client_id = struct.unpack('<I', out_buf[4:8])[0] connection_id = struct.unpack('<I', out_buf[8:12])[0] time_dif = common.int32((int(time.time()) & 0xffffffff) - utc_time) if time_dif < 60 * -3 or time_dif > 60 * 3 or common.int32(utc_time - self.server_info.data.startup_time) < 0: self.raw_trans = True self.recv_buf = b'' logging.info('auth_simple: wrong timestamp, time_dif %d, data %s' % (time_dif, binascii.hexlify(out_buf),)) return b'E' elif self.server_info.data.insert(client_id, connection_id): self.has_recv_header = True out_buf = out_buf[12:] self.client_id = client_id self.connection_id = connection_id else: self.raw_trans = True self.recv_buf = b'' logging.info('auth_simple: auth fail, data %s' % (binascii.hexlify(out_buf),)) return b'E' self.recv_buf = self.recv_buf[length:] if out_buf: self.server_info.data.update(self.client_id, self.connection_id) self.decrypt_packet_num += 1 return out_buf
def server_decode(self, buf): if self.handshake_status == -1: return (buf, True, False) if self.handshake_status == 8: ret = b'' self.recv_buffer += buf while len(self.recv_buffer) > 5: if ord(self.recv_buffer[0]) != 0x17 or ord( self.recv_buffer[1]) != 0x3 or ord( self.recv_buffer[2]) != 0x3: logging.info("data = %s" % (binascii.hexlify(self.recv_buffer))) raise Exception('server_decode appdata error') size = struct.unpack('>H', self.recv_buffer[3:5])[0] if len(self.recv_buffer) < size + 5: break ret += self.recv_buffer[5:size + 5] self.recv_buffer = self.recv_buffer[size + 5:] return (ret, True, False) if self.handshake_status == 3: self.recv_buffer += buf buf = self.recv_buffer verify = buf verify_len = 43 - 10 if len(buf) < 43: raise Exception('server_decode data error') if not match_begin(buf, b"\x14" + self.tls_version + b"\x00\x01\x01"): #ChangeCipherSpec raise Exception('server_decode data error') buf = buf[6:] if not match_begin( buf, b"\x16" + self.tls_version + b"\x00\x20"): #Finished raise Exception('server_decode data error') if hmac.new(self.server_info.key + self.client_id, verify[:verify_len], hashlib.sha1).digest( )[:10] != verify[verify_len:verify_len + 10]: raise Exception('server_decode data error') if len(buf) < 37: raise Exception('server_decode data error') self.recv_buffer = buf[37:] self.handshake_status = 8 return self.server_decode(b'') #raise Exception("handshake data = %s" % (binascii.hexlify(buf))) self.recv_buffer += buf buf = self.recv_buffer ogn_buf = buf if len(buf) < 3: return (b'', False, False) if not match_begin(buf, b'\x16\x03\x01'): return self.decode_error_return(ogn_buf) buf = buf[3:] if struct.unpack('>H', buf[:2])[0] > len(buf) - 2: return (b'', False, False) self.recv_buffer = self.recv_buffer[struct.unpack('>H', buf[:2])[0] + 5:] self.handshake_status = 2 buf = buf[2:] if not match_begin(buf, b'\x01\x00'): #client hello logging.info("tls_auth not client hello message") return self.decode_error_return(ogn_buf) buf = buf[2:] if struct.unpack('>H', buf[:2])[0] != len(buf) - 2: logging.info("tls_auth wrong message size") return self.decode_error_return(ogn_buf) buf = buf[2:] if not match_begin(buf, self.tls_version): logging.info("tls_auth wrong tls version") return self.decode_error_return(ogn_buf) buf = buf[2:] verifyid = buf[:32] buf = buf[32:] sessionid_len = ord(buf[0]) if sessionid_len < 32: logging.info("tls_auth wrong sessionid_len") return self.decode_error_return(ogn_buf) sessionid = buf[1:sessionid_len + 1] buf = buf[sessionid_len + 1:] self.client_id = sessionid sha1 = hmac.new(self.server_info.key + sessionid, verifyid[:22], hashlib.sha1).digest()[:10] utc_time = struct.unpack('>I', verifyid[:4])[0] time_dif = common.int32((int(time.time()) & 0xffffffff) - utc_time) if self.server_info.obfs_param: try: self.max_time_dif = int(self.server_info.obfs_param) except: pass if self.max_time_dif > 0 and (time_dif < -self.max_time_dif or time_dif > self.max_time_dif \ or common.int32(utc_time - self.server_info.data.startup_time) < -self.max_time_dif / 2): logging.info("tls_auth wrong time") return self.decode_error_return(ogn_buf) if sha1 != verifyid[22:]: logging.info("tls_auth wrong sha1") return self.decode_error_return(ogn_buf) if self.server_info.data.client_data.get(verifyid[:22]): logging.info("replay attack detect, id = %s" % (binascii.hexlify(verifyid))) return self.decode_error_return(ogn_buf) self.server_info.data.client_data.sweep() self.server_info.data.client_data[verifyid[:22]] = sessionid # (buffer_to_recv, is_need_decrypt, is_need_to_encode_and_send_back) return (b'', False, True)
def server_post_decrypt(self, buf): if self.raw_trans: return (buf, False) self.recv_buf += buf out_buf = b'' sendback = False if not self.has_recv_header: if len(self.recv_buf) >= 12 or len(self.recv_buf) in [7, 8]: recv_len = min(len(self.recv_buf), 12) mac_key = self.server_info.recv_iv + self.server_info.key md5data = hmac.new(mac_key, self.recv_buf[:4], self.hashfunc).digest() if md5data[:recv_len - 4] != self.recv_buf[4:recv_len]: return self.not_match_return(self.recv_buf) if len(self.recv_buf) < 12 + 24: return (b'', False) self.last_client_hash = md5data uid = struct.unpack('<I', self.recv_buf[12:16])[0] ^ struct.unpack( '<I', md5data[8:12])[0] self.user_id_num = uid uid = struct.pack('<I', uid) if uid in self.server_info.users: self.user_id = uid self.user_key = self.server_info.users[uid] self.server_info.update_user_func(uid) else: self.user_id_num = 0 if not self.server_info.users: self.user_key = self.server_info.key else: self.user_key = self.server_info.recv_iv md5data = hmac.new(self.user_key, self.recv_buf[12:12 + 20], self.hashfunc).digest() if md5data[:4] != self.recv_buf[32:36]: logging.error( '%s data uncorrect auth HMAC-MD5 from %s:%d, data %s' % (self.no_compatible_method, self.server_info.client, self.server_info.client_port, binascii.hexlify(self.recv_buf))) if len(self.recv_buf) < 36: return (b'', False) return self.not_match_return(self.recv_buf) self.last_server_hash = md5data encryptor = encrypt.Encryptor( to_bytes(base64.b64encode(self.user_key)) + self.salt, 'aes-128-cbc') head = encryptor.decrypt( b'\x00' * 16 + self.recv_buf[16:32] + b'\x00') # need an extra byte or recv empty self.client_over_head = struct.unpack('<H', head[12:14])[0] utc_time = struct.unpack('<I', head[:4])[0] client_id = struct.unpack('<I', head[4:8])[0] connection_id = struct.unpack('<I', head[8:12])[0] time_dif = common.int32(utc_time - (int(time.time()) & 0xffffffff)) if time_dif < -self.max_time_dif or time_dif > self.max_time_dif: logging.info('%s: wrong timestamp, time_dif %d, data %s' % (self.no_compatible_method, time_dif, binascii.hexlify(head))) return self.not_match_return(self.recv_buf) elif self.server_info.data.insert(self.user_id, client_id, connection_id): self.has_recv_header = True self.client_id = client_id self.connection_id = connection_id else: logging.info( '%s: auth fail, data %s' % (self.no_compatible_method, binascii.hexlify(out_buf))) return self.not_match_return(self.recv_buf) self.encryptor = encrypt.Encryptor( to_bytes(base64.b64encode(self.user_key)) + to_bytes(base64.b64encode(self.last_client_hash)), 'rc4') self.recv_buf = self.recv_buf[36:] self.has_recv_header = True sendback = True while len(self.recv_buf) > 4: mac_key = self.user_key + struct.pack('<I', self.recv_id) data_len = struct.unpack('<H', self.recv_buf[:2])[0] ^ struct.unpack( '<H', self.last_client_hash[14:16])[0] rand_len = self.rnd_data_len(data_len, self.last_client_hash, self.random_client) length = data_len + rand_len if length >= 4096: self.raw_trans = True self.recv_buf = b'' if self.recv_id == 0: logging.info(self.no_compatible_method + ': over size') return (b'E' * 2048, False) else: raise Exception('server_post_decrype data error') if length + 4 > len(self.recv_buf): break client_hash = hmac.new(mac_key, self.recv_buf[:length + 2], self.hashfunc).digest() if client_hash[:2] != self.recv_buf[length + 2:length + 4]: logging.info('%s: checksum error, data %s' % (self.no_compatible_method, binascii.hexlify(self.recv_buf[:length]))) self.raw_trans = True self.recv_buf = b'' if self.recv_id == 0: return (b'E' * 2048, False) else: raise Exception( 'server_post_decrype data uncorrect checksum') self.recv_id = (self.recv_id + 1) & 0xFFFFFFFF pos = 2 if data_len > 0 and rand_len > 0: pos = 2 + self.rnd_start_pos(rand_len, self.random_client) out_buf += self.encryptor.decrypt(self.recv_buf[pos:data_len + pos]) self.last_client_hash = client_hash self.recv_buf = self.recv_buf[length + 4:] if data_len == 0: sendback = True if out_buf: self.server_info.data.update(self.user_id, self.client_id, self.connection_id) return (out_buf, sendback)
def server_post_decrypt(self, buf): if self.raw_trans: return (buf, False) self.recv_buf += buf out_buf = b'' if not self.has_recv_header: if len(self.recv_buf) < 4: return (b'', False) crc = struct.pack( '<I', binascii.crc32(self.server_info.key) & 0xFFFFFFFF) if crc != self.recv_buf[:4]: if self.method == 'auth_sha1': return (b'E', False) else: self.raw_trans = True return (self.recv_buf, False) length = struct.unpack('>H', self.recv_buf[4:6])[0] if length > len(self.recv_buf): return (b'', False) sha1data = hmac.new( self.server_info.recv_iv + self.server_info.key, self.recv_buf[:length - 10], hashlib.sha1).digest()[:10] if sha1data != self.recv_buf[length - 10:length]: logging.error('auth_sha1 data uncorrect auth HMAC-SHA1') return (b'E', False) pos = common.ord(self.recv_buf[6]) + 6 out_buf = self.recv_buf[pos:length - 10] if len(out_buf) < 12: self.raw_trans = True self.recv_buf = b'' logging.info('auth_sha1: too short') return (b'E', False) utc_time = struct.unpack('<I', out_buf[:4])[0] client_id = struct.unpack('<I', out_buf[4:8])[0] connection_id = struct.unpack('<I', out_buf[8:12])[0] time_dif = common.int32(utc_time - (int(time.time()) & 0xffffffff)) if time_dif < -self.max_time_dif or time_dif > self.max_time_dif \ or common.int32(utc_time - self.server_info.data.startup_time) < -self.max_time_dif / 2: self.raw_trans = True self.recv_buf = b'' logging.info( 'auth_sha1: wrong timestamp, time_dif %d, data %s' % ( time_dif, binascii.hexlify(out_buf), )) return (b'E', False) elif self.server_info.data.insert(client_id, connection_id): self.has_recv_header = True out_buf = out_buf[12:] self.client_id = client_id self.connection_id = connection_id else: self.raw_trans = True self.recv_buf = b'' logging.info('auth_sha1: auth fail, data %s' % (binascii.hexlify(out_buf), )) return (b'E', False) self.recv_buf = self.recv_buf[length:] self.has_recv_header = True while len(self.recv_buf) > 2: length = struct.unpack('>H', self.recv_buf[:2])[0] if length >= 8192 or length < 7: self.raw_trans = True self.recv_buf = b'' if self.decrypt_packet_num == 0: logging.info('auth_sha1: over size') return (b'E', False) else: raise Exception('server_post_decrype data error') if length > len(self.recv_buf): break if struct.pack( '<I', zlib.adler32(self.recv_buf[:length - 4]) & 0xFFFFFFFF) != self.recv_buf[length - 4:length]: logging.info('auth_sha1: checksum error, data %s' % (binascii.hexlify(self.recv_buf[:length]), )) self.raw_trans = True self.recv_buf = b'' if self.decrypt_packet_num == 0: return (b'E', False) else: raise Exception( 'server_post_decrype data uncorrect checksum') pos = common.ord(self.recv_buf[2]) + 2 out_buf += self.recv_buf[pos:length - 4] self.recv_buf = self.recv_buf[length:] if out_buf: self.server_info.data.update(self.client_id, self.connection_id) self.decrypt_packet_num += 1 return (out_buf, False)
def server_decode(self, buf): if self.handshake_status == -1: return (buf, True, False) if self.handshake_status == 8: ret = b'' self.recv_buffer += buf while len(self.recv_buffer) > 5: if ord(self.recv_buffer[0]) != 0x17: logging.info("data = %s" % (binascii.hexlify(self.recv_buffer))) raise Exception('server_decode appdata error') size = struct.unpack('>H', self.recv_buffer[3:5])[0] if len(self.recv_buffer) < size + 5: break ret += self.recv_buffer[5:size+5] self.recv_buffer = self.recv_buffer[size+5:] return (ret, True, False) if self.handshake_status == 3: verify = buf verify_len = 43 - 10 if len(buf) < 43: raise Exception('server_decode data error') if not match_begin(buf, b"\x14" + self.tls_version + "\x00\x01\x01"): #ChangeCipherSpec raise Exception('server_decode data error') buf = buf[6:] if not match_begin(buf, b"\x16" + self.tls_version + "\x00\x20"): #Finished raise Exception('server_decode data error') if hmac.new(self.server_info.key + self.client_id, verify[:verify_len], hashlib.sha1).digest()[:10] != verify[verify_len:verify_len+10]: raise Exception('server_decode data error') if len(buf) < 37: raise Exception('server_decode data error') self.recv_buffer = buf[37:] self.handshake_status = 8 return self.server_decode(b'') #raise Exception("handshake data = %s" % (binascii.hexlify(buf))) self.handshake_status = 2 ogn_buf = buf if not match_begin(buf, b'\x16\x03\x01'): return self.decode_error_return(ogn_buf) buf = buf[3:] if struct.unpack('>H', buf[:2])[0] != len(buf) - 2: logging.info("tls_auth wrong tls head size") return self.decode_error_return(ogn_buf) buf = buf[2:] if not match_begin(buf, b'\x01\x00'): #client hello logging.info("tls_auth not client hello message") return self.decode_error_return(ogn_buf) buf = buf[2:] if struct.unpack('>H', buf[:2])[0] != len(buf) - 2: logging.info("tls_auth wrong message size") return self.decode_error_return(ogn_buf) buf = buf[2:] if not match_begin(buf, self.tls_version): logging.info("tls_auth wrong tls version") return self.decode_error_return(ogn_buf) buf = buf[2:] verifyid = buf[:32] buf = buf[32:] sessionid_len = ord(buf[0]) if sessionid_len < 32: logging.info("tls_auth wrong sessionid_len") return self.decode_error_return(ogn_buf) sessionid = buf[1:sessionid_len + 1] buf = buf[sessionid_len+1:] self.client_id = sessionid sha1 = hmac.new(self.server_info.key + sessionid, verifyid[:22], hashlib.sha1).digest()[:10] utc_time = struct.unpack('>I', verifyid[:4])[0] time_dif = common.int32((int(time.time()) & 0xffffffff) - utc_time) if time_dif < -self.max_time_dif or time_dif > self.max_time_dif \ or common.int32(utc_time - self.server_info.data.startup_time) < -self.max_time_dif / 2: logging.info("tls_auth wrong time") return self.decode_error_return(ogn_buf) if sha1 != verifyid[22:]: logging.info("tls_auth wrong sha1") return self.decode_error_return(ogn_buf) if self.server_info.data.client_data.get(verifyid[:22]): logging.info("replay attack detect, id = %s" % (binascii.hexlify(verifyid))) return self.decode_error_return(ogn_buf) self.server_info.data.client_data.sweep() self.server_info.data.client_data[verifyid[:22]] = sessionid # (buffer_to_recv, is_need_decrypt, is_need_to_encode_and_send_back) return (b'', False, True)
def server_decode(self, buf): if self.raw_trans_recv: return (buf, True, False) if self.has_recv_header: verify = buf verify_len = 43 - 10 if len(buf) < 43: raise Exception('server_decode data error') if not match_begin(buf, b"\x14" + self.tls_version + "\x00\x01\x01"): #ChangeCipherSpec raise Exception('server_decode data error') buf = buf[6:] if not match_begin(buf, b"\x16" + self.tls_version + "\x00\x20"): #Finished raise Exception('server_decode data error') if hmac.new(self.server_info.key + self.client_id, verify[:verify_len], hashlib.sha1).digest()[:10] != verify[verify_len:verify_len+10]: raise Exception('server_decode data error') if len(buf) < 37: raise Exception('server_decode data error') buf = buf[37:] self.raw_trans_recv = True return (buf, True, False) self.has_recv_header = True ogn_buf = buf if not match_begin(buf, b'\x16' + self.tls_version): return self.decode_error_return(ogn_buf) buf = buf[3:] if struct.unpack('>H', buf[:2])[0] != len(buf) - 2: return self.decode_error_return(ogn_buf) buf = buf[2:] if not match_begin(buf, b'\x01\x00'): #client hello return self.decode_error_return(ogn_buf) buf = buf[2:] if struct.unpack('>H', buf[:2])[0] != len(buf) - 2: return self.decode_error_return(ogn_buf) buf = buf[2:] if not match_begin(buf, self.tls_version): return self.decode_error_return(ogn_buf) buf = buf[2:] verifyid = buf[:32] buf = buf[32:] sessionid_len = ord(buf[0]) if sessionid_len < 32: logging.info("tls_auth wrong sessionid_len") return self.decode_error_return(ogn_buf) sessionid = buf[1:sessionid_len + 1] buf = buf[sessionid_len+1:] self.client_id = sessionid sha1 = hmac.new(self.server_info.key + sessionid, verifyid[:22], hashlib.sha1).digest()[:10] utc_time = struct.unpack('>I', verifyid[:4])[0] time_dif = common.int32((int(time.time()) & 0xffffffff) - utc_time) if time_dif < -self.max_time_dif or time_dif > self.max_time_dif \ or common.int32(utc_time - self.server_info.data.startup_time) < -self.max_time_dif / 2: logging.info("tls_auth wrong time") return self.decode_error_return(ogn_buf) if sha1 != verifyid[22:]: logging.info("tls_auth wrong sha1") return self.decode_error_return(ogn_buf) if self.server_info.data.client_data.get(verifyid[:22]): logging.info("replay attack detect, id = %s" % (binascii.hexlify(verifyid))) return self.decode_error_return(ogn_buf) self.server_info.data.client_data.sweep() self.server_info.data.client_data[verifyid[:22]] = sessionid # (buffer_to_recv, is_need_decrypt, is_need_to_encode_and_send_back) return (b'', False, True)
def server_post_decrypt(self, buf): if self.raw_trans: return (buf, False) self.recv_buf += buf out_buf = b'' if not self.has_recv_header: if len(self.recv_buf) <= 6: return (b'', False) crc = struct.pack('<I', binascii.crc32(self.recv_buf[:2] + self.salt + self.server_info.key) & 0xFFFFFFFF) if crc != self.recv_buf[2:6]: return self.not_match_return(self.recv_buf) length = struct.unpack('>H', self.recv_buf[:2])[0] if length > len(self.recv_buf): return (b'', False) sha1data = hmac.new(self.server_info.recv_iv + self.server_info.key, self.recv_buf[:length - 10], hashlib.sha1).digest()[:10] if sha1data != self.recv_buf[length - 10:length]: logging.error('auth_sha1_v4 data uncorrect auth HMAC-SHA1') return self.not_match_return(self.recv_buf) pos = common.ord(self.recv_buf[6]) if pos < 255: pos += 6 else: pos = struct.unpack('>H', self.recv_buf[7:9])[0] + 6 out_buf = self.recv_buf[pos:length - 10] if len(out_buf) < 12: logging.info('auth_sha1_v4: too short, data %s' % (binascii.hexlify(self.recv_buf),)) return self.not_match_return(self.recv_buf) utc_time = struct.unpack('<I', out_buf[:4])[0] client_id = struct.unpack('<I', out_buf[4:8])[0] connection_id = struct.unpack('<I', out_buf[8:12])[0] time_dif = common.int32(utc_time - (int(time.time()) & 0xffffffff)) if time_dif < -self.max_time_dif or time_dif > self.max_time_dif: logging.info('auth_sha1_v4: wrong timestamp, time_dif %d, data %s' % (time_dif, binascii.hexlify(out_buf),)) return self.not_match_return(self.recv_buf) elif self.server_info.data.insert(client_id, connection_id): self.has_recv_header = True out_buf = out_buf[12:] self.client_id = client_id self.connection_id = connection_id else: logging.info('auth_sha1_v4: auth fail, data %s' % (binascii.hexlify(out_buf),)) return self.not_match_return(self.recv_buf) self.recv_buf = self.recv_buf[length:] self.has_recv_header = True sendback = False while len(self.recv_buf) > 4: crc = struct.pack('<H', binascii.crc32(self.recv_buf[:2]) & 0xFFFF) if crc != self.recv_buf[2:4]: self.raw_trans = True logging.info('auth_sha1_v4: wrong crc') if self.decrypt_packet_num == 0: logging.info('auth_sha1_v4: wrong crc') return (b'E', False) else: raise Exception('server_post_decrype data error') length = struct.unpack('>H', self.recv_buf[:2])[0] if length >= 8192 or length < 7: self.raw_trans = True self.recv_buf = b'' if self.decrypt_packet_num == 0: logging.info('auth_sha1_v4: over size') return (b'E', False) else: raise Exception('server_post_decrype data error') if length > len(self.recv_buf): break if struct.pack('<I', zlib.adler32(self.recv_buf[:length - 4]) & 0xFFFFFFFF) != self.recv_buf[length - 4:length]: logging.info('auth_sha1_v4: checksum error, data %s' % (binascii.hexlify(self.recv_buf[:length]),)) self.raw_trans = True self.recv_buf = b'' if self.decrypt_packet_num == 0: return (b'E', False) else: raise Exception('server_post_decrype data uncorrect checksum') pos = common.ord(self.recv_buf[4]) if pos < 255: pos += 4 else: pos = struct.unpack('>H', self.recv_buf[5:7])[0] + 4 out_buf += self.recv_buf[pos:length - 4] self.recv_buf = self.recv_buf[length:] if pos == length - 4: sendback = True if out_buf: self.server_info.data.update(self.client_id, self.connection_id) self.decrypt_packet_num += 1 return (out_buf, sendback)
def server_post_decrypt(self, buf): if self.raw_trans: return (buf, False) self.recv_buf += buf out_buf = b'' sendback = False if not self.has_recv_header: if len(self.recv_buf) >= 12 or len(self.recv_buf) in [7, 8]: recv_len = min(len(self.recv_buf), 12) mac_key = self.server_info.recv_iv + self.server_info.key md5data = hmac.new(mac_key, self.recv_buf[:4], self.hashfunc).digest() if md5data[:recv_len - 4] != self.recv_buf[4:recv_len]: return self.not_match_return(self.recv_buf) if len(self.recv_buf) < 12 + 24: return (b'', False) self.last_client_hash = md5data uid = struct.unpack('<I', self.recv_buf[12:16])[0] ^ struct.unpack('<I', md5data[8:12])[0] self.user_id_num = uid uid = struct.pack('<I', uid) if uid in self.server_info.users: self.user_id = uid self.user_key = self.server_info.users[uid] self.server_info.update_user_func(uid) else: self.user_id_num = 0 if not self.server_info.users: self.user_key = self.server_info.key else: self.user_key = self.server_info.recv_iv md5data = hmac.new(self.user_key, self.recv_buf[12 : 12 + 20], self.hashfunc).digest() if md5data[:4] != self.recv_buf[32:36]: logging.error('%s data uncorrect auth HMAC-MD5 from %s:%d, data %s' % (self.no_compatible_method, self.server_info.client, self.server_info.client_port, binascii.hexlify(self.recv_buf))) if len(self.recv_buf) < 36: return (b'', False) return self.not_match_return(self.recv_buf) self.last_server_hash = md5data encryptor = encrypt.Encryptor(to_bytes(base64.b64encode(self.user_key)) + self.salt, 'aes-128-cbc') head = encryptor.decrypt(b'\x00' * 16 + self.recv_buf[16:32] + b'\x00') # need an extra byte or recv empty self.client_over_head = struct.unpack('<H', head[12:14])[0] utc_time = struct.unpack('<I', head[:4])[0] client_id = struct.unpack('<I', head[4:8])[0] connection_id = struct.unpack('<I', head[8:12])[0] time_dif = common.int32(utc_time - (int(time.time()) & 0xffffffff)) if time_dif < -self.max_time_dif or time_dif > self.max_time_dif: logging.info('%s: wrong timestamp, time_dif %d, data %s' % (self.no_compatible_method, time_dif, binascii.hexlify(head))) return self.not_match_return(self.recv_buf) elif self.server_info.data.insert(self.user_id, client_id, connection_id): self.has_recv_header = True self.client_id = client_id self.connection_id = connection_id else: logging.info('%s: auth fail, data %s' % (self.no_compatible_method, binascii.hexlify(out_buf))) return self.not_match_return(self.recv_buf) self.encryptor = encrypt.Encryptor(to_bytes(base64.b64encode(self.user_key)) + to_bytes(base64.b64encode(self.last_client_hash)), 'rc4') self.recv_buf = self.recv_buf[36:] self.has_recv_header = True sendback = True while len(self.recv_buf) > 4: mac_key = self.user_key + struct.pack('<I', self.recv_id) data_len = struct.unpack('<H', self.recv_buf[:2])[0] ^ struct.unpack('<H', self.last_client_hash[14:16])[0] rand_len = self.rnd_data_len(data_len, self.last_client_hash, self.random_client) length = data_len + rand_len if length >= 4096: self.raw_trans = True self.recv_buf = b'' if self.recv_id == 0: logging.info(self.no_compatible_method + ': over size') return (b'E'*2048, False) else: raise Exception('server_post_decrype data error') if length + 4 > len(self.recv_buf): break client_hash = hmac.new(mac_key, self.recv_buf[:length + 2], self.hashfunc).digest() if client_hash[:2] != self.recv_buf[length + 2 : length + 4]: logging.info('%s: checksum error, data %s' % (self.no_compatible_method, binascii.hexlify(self.recv_buf[:length]))) self.raw_trans = True self.recv_buf = b'' if self.recv_id == 0: return (b'E'*2048, False) else: raise Exception('server_post_decrype data uncorrect checksum') self.recv_id = (self.recv_id + 1) & 0xFFFFFFFF pos = 2 if data_len > 0 and rand_len > 0: pos = 2 + self.rnd_start_pos(rand_len, self.random_client) out_buf += self.encryptor.decrypt(self.recv_buf[pos : data_len + pos]) self.last_client_hash = client_hash self.recv_buf = self.recv_buf[length + 4:] if data_len == 0: sendback = True if out_buf: self.server_info.data.update(self.user_id, self.client_id, self.connection_id) return (out_buf, sendback)
def server_post_decrypt(self, buf): if self.raw_trans: return (buf, False) self.recv_buf += buf out_buf = b'' sendback = False if not self.has_recv_header: if len(self.recv_buf) >= 7 or len(self.recv_buf) in [2, 3]: recv_len = min(len(self.recv_buf), 7) mac_key = self.server_info.recv_iv + self.server_info.key sha1data = hmac.new(mac_key, self.recv_buf[:1], self.hashfunc).digest()[:recv_len - 1] if sha1data != self.recv_buf[1:recv_len]: return self.not_match_return(self.recv_buf) if len(self.recv_buf) < 31: return (b'', False) sha1data = hmac.new(mac_key, self.recv_buf[7:27], self.hashfunc).digest()[:4] if sha1data != self.recv_buf[27:31]: logging.error('%s data uncorrect auth HMAC-SHA1 from %s:%d, data %s' % (self.no_compatible_method, self.server_info.client, self.server_info.client_port, binascii.hexlify(self.recv_buf))) if len(self.recv_buf) < 31 + self.extra_wait_size: return (b'', False) return self.not_match_return(self.recv_buf) uid = self.recv_buf[7:11] if uid in self.server_info.users: self.user_id = uid self.user_key = self.hashfunc(self.server_info.users[uid]).digest() self.server_info.update_user_func(uid) else: if not self.server_info.users: self.user_key = self.server_info.key else: self.user_key = self.server_info.recv_iv encryptor = encrypt.Encryptor(to_bytes(base64.b64encode(self.user_key)) + self.salt, 'aes-128-cbc') head = encryptor.decrypt(b'\x00' * 16 + self.recv_buf[11:27] + b'\x00') # need an extra byte or recv empty length = struct.unpack('<H', head[12:14])[0] if len(self.recv_buf) < length: return (b'', False) utc_time = struct.unpack('<I', head[:4])[0] client_id = struct.unpack('<I', head[4:8])[0] connection_id = struct.unpack('<I', head[8:12])[0] rnd_len = struct.unpack('<H', head[14:16])[0] if hmac.new(self.user_key, self.recv_buf[:length - 4], self.hashfunc).digest()[:4] != self.recv_buf[length - 4:length]: logging.info('%s: checksum error, data %s' % (self.no_compatible_method, binascii.hexlify(self.recv_buf[:length]))) return self.not_match_return(self.recv_buf) time_dif = common.int32(utc_time - (int(time.time()) & 0xffffffff)) if time_dif < -self.max_time_dif or time_dif > self.max_time_dif: logging.info('%s: wrong timestamp, time_dif %d, data %s' % (self.no_compatible_method, time_dif, binascii.hexlify(head))) return self.not_match_return(self.recv_buf) elif self.server_info.data.insert(self.user_id, client_id, connection_id): self.has_recv_header = True out_buf = self.recv_buf[31 + rnd_len:length - 4] self.client_id = client_id self.connection_id = connection_id else: logging.info('%s: auth fail, data %s' % (self.no_compatible_method, binascii.hexlify(out_buf))) return self.not_match_return(self.recv_buf) self.recv_buf = self.recv_buf[length:] self.has_recv_header = True sendback = True while len(self.recv_buf) > 4: mac_key = self.user_key + struct.pack('<I', self.recv_id) mac = hmac.new(mac_key, self.recv_buf[:2], self.hashfunc).digest()[:2] if mac != self.recv_buf[2:4]: self.raw_trans = True logging.info(self.no_compatible_method + ': wrong crc') if self.recv_id == 0: logging.info(self.no_compatible_method + ': wrong crc') return (b'E'*2048, False) else: raise Exception('server_post_decrype data error') length = struct.unpack('<H', self.recv_buf[:2])[0] if length >= 8192 or length < 7: self.raw_trans = True self.recv_buf = b'' if self.recv_id == 0: logging.info(self.no_compatible_method + ': over size') return (b'E'*2048, False) else: raise Exception('server_post_decrype data error') if length > len(self.recv_buf): break if hmac.new(mac_key, self.recv_buf[:length - 4], self.hashfunc).digest()[:4] != self.recv_buf[length - 4:length]: logging.info('%s: checksum error, data %s' % (self.no_compatible_method, binascii.hexlify(self.recv_buf[:length]))) self.raw_trans = True self.recv_buf = b'' if self.recv_id == 0: return (b'E'*2048, False) else: raise Exception('server_post_decrype data uncorrect checksum') self.recv_id = (self.recv_id + 1) & 0xFFFFFFFF pos = common.ord(self.recv_buf[4]) if pos < 255: pos += 4 else: pos = struct.unpack('<H', self.recv_buf[5:7])[0] + 4 out_buf += self.recv_buf[pos:length - 4] self.recv_buf = self.recv_buf[length:] if pos == length - 4: sendback = True if out_buf: self.server_info.data.update(self.user_id, self.client_id, self.connection_id) return (out_buf, sendback)
def server_post_decrypt(self, buf): if self.raw_trans: return (buf, False) self.recv_buf += buf out_buf = b'' sendback = False if not self.has_recv_header: if len(self.recv_buf) >= 7 or len(self.recv_buf) in [2, 3]: recv_len = min(len(self.recv_buf), 7) mac_key = self.server_info['recv_iv'] + self.server_info['key'] sha1data = hmac.new(mac_key, self.recv_buf[:1], self.hashfunc).digest()[:recv_len - 1] if sha1data != self.recv_buf[1:recv_len]: return self.not_match_return(self.recv_buf) if len(self.recv_buf) < 39: return (b'', False) sha1data = hmac.new(mac_key, self.recv_buf[7:27], self.hashfunc).digest()[:4] if sha1data != self.recv_buf[27:31]: logging.error( '%s data uncorrect auth HMAC-SHA1 from %s:%d, data %s' % (self.no_compatible_method, self.server_info['client'], self.server_info['client_port'], binascii.hexlify(self.recv_buf))) if len(self.recv_buf) < 39 + self.extra_wait_size: return (b'', False) return self.not_match_return(self.recv_buf) uid = self.recv_buf[7:11] if self.user_key is None: self.user_key = self.server_info['key'] encryptor = encrypt.Encryptor( to_bytes(base64.b64encode(self.user_key)) + self.salt, 'aes-128-cbc') head = encryptor.decrypt( b'\x00' * 16 + self.recv_buf[11:27] + b'\x00') # need an extra byte or recv empty length = struct.unpack('<H', head[12:14])[0] if len(self.recv_buf) < length: logging.debug('len(self.recv_buf):%d,length:%d' % (len(self.recv_buf), length)) return (b'', False) utc_time = struct.unpack('<I', head[:4])[0] client_id = struct.unpack('<I', head[4:8])[0] connection_id = struct.unpack('<I', head[8:12])[0] rnd_len = struct.unpack('<H', head[14:16])[0] if hmac.new(self.user_key, self.recv_buf[:length - 4], self.hashfunc).digest()[:4] != self.recv_buf[length - 4:length]: logging.info('%s: checksum error, data %s' % (self.no_compatible_method, binascii.hexlify(self.recv_buf[:length]))) return self.not_match_return(self.recv_buf) time_dif = common.int32(utc_time - (int(time.time()) & 0xffffffff)) if time_dif < -self.max_time_dif or time_dif > self.max_time_dif: logging.info('%s: wrong timestamp, time_dif %d, data %s' % (self.no_compatible_method, time_dif, binascii.hexlify(head))) return self.not_match_return(self.recv_buf) else: self.has_recv_header = True out_buf = self.recv_buf[31 + rnd_len + 4:length - 4] logging.debug('out:%s' % out_buf) self.client_id = client_id self.connection_id = connection_id client_id = struct.pack('<I', client_id) self.recv_buf = self.recv_buf[length:] self.has_recv_header = True sendback = True #pack_data while len(self.recv_buf) > 2: mac_key = self.user_key + struct.pack('<I', self.recv_id) length = struct.unpack('<H', self.recv_buf[:2])[0] if length >= 8192 or length < 6: self.raw_trans = True self.recv_buf = b'' if self.recv_id == 0: logging.info(self.no_compatible_method + ': over size') return (b'E' * 2048, False) else: raise Exception('server_post_decrype data error') if length > len(self.recv_buf): raise Exception('length is error') break if hmac.new(mac_key, self.recv_buf[:length - 4], self.hashfunc).digest()[:4] != self.recv_buf[length - 4:length]: logging.info('%s: checksum error, data %s' % (self.no_compatible_method, binascii.hexlify(self.recv_buf[:length]))) self.raw_trans = True self.recv_buf = b'' if self.recv_id == 0: return (b'E' * 2048, False) else: raise Exception( 'server_post_decrype data uncorrect checksum') self.recv_id = (self.recv_id + 1) & 0xFFFFFFFF pos = common.ord(self.recv_buf[2]) if pos < 255: pos += 2 else: pos = struct.unpack('<H', self.recv_buf[3:5])[0] + 2 out_buf += self.recv_buf[pos:length - 4] self.recv_buf = self.recv_buf[length:] if pos == length - 4: sendback = True return (out_buf, sendback)
def server_decode(self, buf): if self.deobfs_stage == -1: return (buf, True, False) if self.deobfs_stage == 1: ret = b'' self.recv_buffer += buf while len(self.recv_buffer) > 5: if ord(self.recv_buffer[0]) != 0x17 or ord( self.recv_buffer[1]) != 0x3 or ord( self.recv_buffer[2]) != 0x3: logging.info("data = %s" % (binascii.hexlify(self.recv_buffer))) raise Exception('server_decode appdata error') size = struct.unpack('>H', self.recv_buffer[3:5])[0] if len(self.recv_buffer) < size + 5: break ret += self.recv_buffer[5:size + 5] self.recv_buffer = self.recv_buffer[size + 5:] return (ret, True, False) #raise Exception("handshake data = %s" % (binascii.hexlify(buf))) self.recv_buffer += buf buf = self.recv_buffer ogn_buf = buf if len(buf) < 5: return (b'', False, False) if not match_begin(buf, b'\x16\x03\x01'): return self.decode_error_return(ogn_buf) buf = buf[3:] header_len = struct.unpack('>H', buf[:2])[0] if header_len > len(buf) - 2: return (b'', False, False) self.recv_buffer = self.recv_buffer[header_len + 5:] self.deobfs_stage = 1 buf = buf[2:header_len + 2] if not match_begin(buf, b'\x01\x00'): #client hello logging.info("tls_auth not client hello message") return self.decode_error_return(ogn_buf) buf = buf[2:] if struct.unpack('>H', buf[:2])[0] != len(buf) - 2: logging.info("tls_auth wrong message size") return self.decode_error_return(ogn_buf) buf = buf[2:] if not match_begin(buf, self.tls_version): logging.info("tls_auth wrong tls version") return self.decode_error_return(ogn_buf) buf = buf[2:] verifyid = buf[:32] buf = buf[32:] sessionid_len = ord(buf[0]) if sessionid_len < 32: logging.info("tls_auth wrong sessionid_len") return self.decode_error_return(ogn_buf) sessionid = buf[1:sessionid_len + 1] buf = buf[sessionid_len + 1:] self.client_id = sessionid utc_time = struct.unpack('>I', verifyid[:4])[0] time_dif = common.int32((int(time.time()) & 0xffffffff) - utc_time) if self.server_info.obfs_param: try: self.max_time_dif = int(self.server_info.obfs_param) except: pass if self.max_time_dif > 0 and (time_dif < -self.max_time_dif or time_dif > self.max_time_dif \ or common.int32(utc_time - self.server_info.data.startup_time) < -self.max_time_dif / 2): logging.info("tls_auth wrong time") return self.decode_error_return(ogn_buf) if self.server_info.data.client_data.get(verifyid[:22]): logging.info("replay attack detect, id = %s" % (binascii.hexlify(verifyid))) return self.decode_error_return(ogn_buf) self.server_info.data.client_data.sweep() self.server_info.data.client_data[verifyid[:22]] = sessionid # (buffer_to_recv, is_need_decrypt, is_need_to_encode_and_send_back) buf = buf[62:] if not match_begin(buf, b'\x00\x23'): logging.info("ext header error") return self.decode_error_return(ogn_buf) buf = buf[2:] ext_length = struct.unpack('>H', buf[:2])[0] buf = buf[2:] ret = buf[:ext_length] if len(self.recv_buffer) > 0: ret += self.server_decode(b'')[0] buf = buf[ext_length:] host_name = b'' buf = buf[7:] host_name_len = struct.unpack('>H', buf[:2])[0] buf = buf[2:] hostname = buf[:host_name_len] host_name = common.to_str(hostname) return (ret, True, False, host_name)
def server_post_decrypt(self, buf): if self.raw_trans: return buf self.recv_buf += buf out_buf = b'' if not self.has_recv_header: if len(self.recv_buf) < 4: return b'' crc = struct.pack('<I', binascii.crc32(self.server_info.key) & 0xFFFFFFFF) if crc != self.recv_buf[:4]: if self.method == 'auth_sha1': return b'E' else: self.raw_trans = True return self.recv_buf length = struct.unpack('>H', self.recv_buf[4:6])[0] if length > len(self.recv_buf): return b'' sha1data = hmac.new(self.server_info.recv_iv + self.server_info.key, self.recv_buf[:length - 10], hashlib.sha1).digest()[:10] if sha1data != self.recv_buf[length - 10:length]: logging.error('auth_sha1 data uncorrect auth HMAC-SHA1') return b'E' pos = common.ord(self.recv_buf[6]) + 6 out_buf = self.recv_buf[pos:length - 10] if len(out_buf) < 12: self.raw_trans = True self.recv_buf = b'' logging.info('auth_sha1: too short') return b'E' utc_time = struct.unpack('<I', out_buf[:4])[0] client_id = struct.unpack('<I', out_buf[4:8])[0] connection_id = struct.unpack('<I', out_buf[8:12])[0] time_dif = common.int32((int(time.time()) & 0xffffffff) - utc_time) if time_dif < -self.max_time_dif or time_dif > self.max_time_dif \ or common.int32(utc_time - self.server_info.data.startup_time) < -self.max_time_dif / 2: self.raw_trans = True self.recv_buf = b'' logging.info('auth_sha1: wrong timestamp, time_dif %d, data %s' % (time_dif, binascii.hexlify(out_buf),)) return b'E' elif self.server_info.data.insert(client_id, connection_id): self.has_recv_header = True out_buf = out_buf[12:] self.client_id = client_id self.connection_id = connection_id else: self.raw_trans = True self.recv_buf = b'' logging.info('auth_sha1: auth fail, data %s' % (binascii.hexlify(out_buf),)) return b'E' self.recv_buf = self.recv_buf[length:] self.has_recv_header = True while len(self.recv_buf) > 2: length = struct.unpack('>H', self.recv_buf[:2])[0] if length >= 8192 or length < 7: self.raw_trans = True self.recv_buf = b'' if self.decrypt_packet_num == 0: logging.info('auth_sha1: over size') return b'E' else: raise Exception('server_post_decrype data error') if length > len(self.recv_buf): break if struct.pack('<I', zlib.adler32(self.recv_buf[:length - 4]) & 0xFFFFFFFF) != self.recv_buf[length - 4:length]: logging.info('auth_sha1: checksum error, data %s' % (binascii.hexlify(self.recv_buf[:length]),)) self.raw_trans = True self.recv_buf = b'' if self.decrypt_packet_num == 0: return b'E' else: raise Exception('server_post_decrype data uncorrect checksum') pos = common.ord(self.recv_buf[2]) + 2 out_buf += self.recv_buf[pos:length - 4] self.recv_buf = self.recv_buf[length:] if out_buf: self.server_info.data.update(self.client_id, self.connection_id) self.decrypt_packet_num += 1 return out_buf
def server_post_decrypt(self, buf): if self.raw_trans: return buf self.recv_buf += buf out_buf = b'' while len(self.recv_buf) > 2: length = struct.unpack('>H', self.recv_buf[:2])[0] if length >= 8192 or length < 7: self.raw_trans = True self.recv_buf = b'' if self.decrypt_packet_num == 0: logging.info('auth_simple: over size') return b'E' else: raise Exception('server_post_decrype data error') if length > len(self.recv_buf): break if (binascii.crc32(self.recv_buf[:length]) & 0xffffffff) != 0xffffffff: logging.info('auth_simple: crc32 error, data %s' % (binascii.hexlify(self.recv_buf[:length]), )) self.raw_trans = True self.recv_buf = b'' if self.decrypt_packet_num == 0: return b'E' else: raise Exception('server_post_decrype data uncorrect CRC32') pos = common.ord(self.recv_buf[2]) + 2 out_buf += self.recv_buf[pos:length - 4] if not self.has_recv_header: if len(out_buf) < 12: self.raw_trans = True self.recv_buf = b'' logging.info('auth_simple: too short') return b'E' utc_time = struct.unpack('<I', out_buf[:4])[0] client_id = struct.unpack('<I', out_buf[4:8])[0] connection_id = struct.unpack('<I', out_buf[8:12])[0] time_dif = common.int32((int(time.time()) & 0xffffffff) - utc_time) if time_dif < -self.max_time_dif or time_dif > self.max_time_dif \ or common.int32(utc_time - self.server_info.data.startup_time) < 0: self.raw_trans = True self.recv_buf = b'' logging.info( 'auth_simple: wrong timestamp, time_dif %d, data %s' % ( time_dif, binascii.hexlify(out_buf), )) return b'E' elif self.server_info.data.insert(client_id, connection_id): self.has_recv_header = True out_buf = out_buf[12:] self.client_id = client_id self.connection_id = connection_id else: self.raw_trans = True self.recv_buf = b'' logging.info('auth_simple: auth fail, data %s' % (binascii.hexlify(out_buf), )) return b'E' self.recv_buf = self.recv_buf[length:] if out_buf: self.server_info.data.update(self.client_id, self.connection_id) self.decrypt_packet_num += 1 return out_buf
def server_post_decrypt(self, buf): if self.raw_trans: return (buf, False) self.recv_buf += buf out_buf = b'' sendback = False if not self.has_recv_header: if len(self.recv_buf) <= 6: return (b'', False) crc = struct.pack('<I', binascii.crc32(self.recv_buf[:2] + self.salt + self.server_info.key) & 0xFFFFFFFF) if crc != self.recv_buf[2:6]: return self.not_match_return(self.recv_buf) length = struct.unpack('>H', self.recv_buf[:2])[0] if length > len(self.recv_buf): return (b'', False) sha1data = hmac.new(self.server_info.recv_iv + self.server_info.key, self.recv_buf[:length - 10], hashlib.sha1).digest()[:10] if sha1data != self.recv_buf[length - 10:length]: logging.error('auth_sha1_v4 data uncorrect auth HMAC-SHA1') return self.not_match_return(self.recv_buf) pos = common.ord(self.recv_buf[6]) if pos < 255: pos += 6 else: pos = struct.unpack('>H', self.recv_buf[7:9])[0] + 6 out_buf = self.recv_buf[pos:length - 10] if len(out_buf) < 12: logging.info('auth_sha1_v4: too short, data %s' % (binascii.hexlify(self.recv_buf),)) return self.not_match_return(self.recv_buf) utc_time = struct.unpack('<I', out_buf[:4])[0] client_id = struct.unpack('<I', out_buf[4:8])[0] connection_id = struct.unpack('<I', out_buf[8:12])[0] time_dif = common.int32(utc_time - (int(time.time()) & 0xffffffff)) if time_dif < -self.max_time_dif or time_dif > self.max_time_dif: logging.info('auth_sha1_v4: wrong timestamp, time_dif %d, data %s' % (time_dif, binascii.hexlify(out_buf),)) return self.not_match_return(self.recv_buf) elif self.server_info.data.insert(client_id, connection_id): self.has_recv_header = True out_buf = out_buf[12:] self.client_id = client_id self.connection_id = connection_id else: logging.info('auth_sha1_v4: auth fail, data %s' % (binascii.hexlify(out_buf),)) return self.not_match_return(self.recv_buf) self.recv_buf = self.recv_buf[length:] self.has_recv_header = True sendback = True while len(self.recv_buf) > 4: crc = struct.pack('<H', binascii.crc32(self.recv_buf[:2]) & 0xFFFF) if crc != self.recv_buf[2:4]: self.raw_trans = True logging.info('auth_sha1_v4: wrong crc') if self.decrypt_packet_num == 0: logging.info('auth_sha1_v4: wrong crc') return (b'E'*2048, False) else: raise Exception('server_post_decrype data error') length = struct.unpack('>H', self.recv_buf[:2])[0] if length >= 8192 or length < 7: self.raw_trans = True self.recv_buf = b'' if self.decrypt_packet_num == 0: logging.info('auth_sha1_v4: over size') return (b'E'*2048, False) else: raise Exception('server_post_decrype data error') if length > len(self.recv_buf): break if struct.pack('<I', zlib.adler32(self.recv_buf[:length - 4]) & 0xFFFFFFFF) != self.recv_buf[length - 4:length]: logging.info('auth_sha1_v4: checksum error, data %s' % (binascii.hexlify(self.recv_buf[:length]),)) self.raw_trans = True self.recv_buf = b'' if self.decrypt_packet_num == 0: return (b'E'*2048, False) else: raise Exception('server_post_decrype data uncorrect checksum') pos = common.ord(self.recv_buf[4]) if pos < 255: pos += 4 else: pos = struct.unpack('>H', self.recv_buf[5:7])[0] + 4 out_buf += self.recv_buf[pos:length - 4] self.recv_buf = self.recv_buf[length:] if pos == length - 4: sendback = True if out_buf: self.server_info.data.update(self.client_id, self.connection_id) self.decrypt_packet_num += 1 return (out_buf, sendback)