#!/usr/bin/python3 # -*- coding: utf-8 -*- # # script to read pcap file (communcation with khanat) # # Copyright (C) 2019 AleaJactaEst # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # Ex.: # sudo tcpdump -i docker0 -w capture2.pcap # ./spykhanat.py --pcap-file=../capture2.pcap --msg-xml=../khanat-opennel-code/code/ryzom/common/data_common/msg.xml # ./spykhanat.py -m ../khanat-opennel-code/code/ryzom/common/data_common/msg.xml --yaml capture-2020-07-08-00-33-khanatclient.yml -w ../khanat-opennel-code/code/ryzom/common/data_common/database.xml -p capture-2020-07-08-00-33-khanatclient.pcap --filter-host-service='172.17.0.2:47851' # # FILEDATA="capture-2020-07-08-00-33-khanatclient.pcap" # ./spykhanat.py -m ../khanat-opennel-code/code/ryzom/common/data_common/msg.xml --yaml ${FILEDATA::-5}.yml -w ../khanat-opennel-code/code/ryzom/common/data_common/database.xml -p $FILEDATA --filter-host-service='172.17.0.2:47851' # # install pcapfile # pip install pypcapfile import argparse import logging from pcapfile import savefile from pcapfile.protocols.linklayer import ethernet from pcapfile.protocols.network import ip from pcapfile.protocols.transport import udp from pcapfile.protocols.transport import tcp import binascii import re from tools import BitStream from tools import Enum from tools import CActionFactory from tools import CBitSet from tools import DecodeImpulse from tools import DecodeDatabase from tools import World from tools import CGenericMultiPartTemp from tools import CImpulseDecoder #from tools import CStringManager from tools import CAction from tools import Impulse from tools import CPropertyDecoder from tools import TVPNodeBase import xml.etree.ElementTree as ET from datetime import datetime LOGGER = 'SpyKhanat' #file = open('capture2.pcap' , 'rb') #pcapfile = savefile.load_savefile(file,verbose=True) #pkt = pcapfile.packets[0] #print(pkt.raw()) #print(pkt.timestamp) #eth_frame = ethernet.Ethernet(pkt.raw()) #print(eth_frame) #ip_packet = ip.IP(binascii.unhexlify(eth_frame.payload)) #print(ip_packet) def write_yaml_str_or_array(outyaml, nbspace, value): if type(value) == str: outyaml.write(" " * nbspace + "- %s\n" % (value)) else: for key in value: outyaml.write(" " * nbspace + "- %s\n" % (key)) outyaml.write(" " * nbspace + str(type(value)) + "\n") class SpyPcap(): def __init__(self, khanat_host_service, pcap_file, msg_xml, database_xml, filter_host_service, show_raw_packet, show_message_decoded, outyaml=None, outcsv=False): if khanat_host_service: self.khanat_host_service = re.compile(khanat_host_service) else: self.khanat_host_service = None self.pcap_file = pcap_file self.msg_xml = msg_xml if filter_host_service: self.filter_host_service = re.compile(filter_host_service) else: self.filter_host_service = None self.show_raw_packet = show_raw_packet self.show_message_decoded = show_message_decoded self.actionFactory = CActionFactory.CActionFactory(None) self.client_state = {} # msg.xml self.decodeImpulse = DecodeImpulse.DecodeImpulse() self.decodeImpulseSimple = Impulse.DecodeImpulseSimple() fp = open(msg_xml , 'rt') msgRawXml = fp.read() fp.close() self.msgXml = ET.fromstring(msgRawXml) self.decodeImpulse.loadMsg(self.msgXml) self.decodeImpulseSimple.loadMsg(self.msgXml) # database.xml #self.decodeDatabase = DecodeDatabase.DecodeDatabase() fp = open(database_xml, 'rt') databaseRawXml = fp.read() fp.close() self.databaseXml = ET.fromstring(databaseRawXml) #self.decodeImpulseSimple.loadDatabase(self.databaseXml) self.decodeDatabase = DecodeDatabase.DecodeDatabase() self.decodeDatabase.loadDatabase(self.databaseXml) self.decodeImpulseSimple.loadDatabase(self.decodeDatabase) # outyaml self.outyaml = outyaml self.outcsv = outcsv def readRaw(self): file = open( self.pcap_file , 'rb') pcapfile = savefile.load_savefile(file,verbose=False) for pkt in pcapfile.packets: #print("pkt:", dir(pkt)) #print("pkt.header:", dir(pkt.header)) #print("pkt.packet:", dir(pkt.packet)) logging.getLogger(LOGGER).debug("raw: %s" % pkt.raw()) logging.getLogger(LOGGER).debug("timestamp: %s (%s)" % (pkt.timestamp,datetime.fromtimestamp(pkt.timestamp).strftime("%Y/%m/%d %H:%M:%S"))) eth_frame = ethernet.Ethernet(pkt.raw()) logging.getLogger(LOGGER).debug("eth_frame: %s" % eth_frame) if eth_frame.type == 2048: ip_packet = ip.IP(binascii.unhexlify(eth_frame.payload)) logging.getLogger(LOGGER).debug("ip packet: %s" % ip_packet) #print("ip_packet:", dir(ip_packet)) logging.getLogger(LOGGER).debug("ip packet: %s ->%s" % (ip_packet.src.decode(), ip_packet.dst.decode()) ) if ip_packet.p == 17: # UDP logging.getLogger(LOGGER).debug("ip packet: protocol UDP (%s)" % ip_packet.p) udp_packet = udp.UDP(binascii.unhexlify(ip_packet.payload)) #print("udp_packet:", dir(udp_packet)) logging.getLogger(LOGGER).debug("UDP packet: %s" % udp_packet) data = udp_packet.payload #print("data:", dir(data)) logging.getLogger(LOGGER).debug("data packet: %s" % data) data = udp_packet.payload logging.getLogger(LOGGER).info("data packet: timestamp:%s src:%s:%d dst:%s:%d data:%s" % (pkt.timestamp, ip_packet.src.decode(), udp_packet.src_port, ip_packet.dst.decode(), udp_packet.dst_port, data.decode())) elif ip_packet.p == 6: # TCP logging.getLogger(LOGGER).debug("ip packet: protocol TCP (%s)" % ip_packet.p) tcp_packet = tcp.TCP(binascii.unhexlify(ip_packet.payload)) data = tcp_packet.payload logging.getLogger(LOGGER).info("data packet: timestamp:%s src:%s:%d dst:%s:%d data:%s" % (pkt.timestamp, ip_packet.src.decode(), tcp_packet.src_port, ip_packet.dst.decode(), tcp_packet.dst_port, data.decode())) else: logging.getLogger(LOGGER).debug("ip packet: protocol (%s)" % ip_packet.p) def detect_khanat_server(self, packets): hostdetected = {} for pkt in packets: eth_frame = ethernet.Ethernet(pkt.raw()) if eth_frame.type == 2048: ip_packet = ip.IP(binascii.unhexlify(eth_frame.payload)) if ip_packet.p == 17: # UDP udp_packet = udp.UDP(binascii.unhexlify(ip_packet.payload)) data = udp_packet.payload host = "%s:%d" % (ip_packet.src.decode(), udp_packet.src_port) hostdetected.setdefault(host, 0) if len(data) == 20: hostdetected[host] += 1 id = None max = 0 for host in hostdetected: if id: if max < hostdetected[host]: max = hostdetected[host] id = host else: max = hostdetected[host] id = host logging.getLogger(LOGGER).info(" host :%s" % id) return id def initialize_client(self, clientid): self.client_state.setdefault(clientid, {'CurrentReceivedNumber': 0, 'CurrentSendNumber': 0, 'LastReceivedAck': 0, 'AckBitMask': 0, 'RegisteredAction': {}, 'world': World.World(), 'GenericMultiPartTempServer': CGenericMultiPartTemp.GenericMultiPartTemp(), 'GenericMultiPartTempClient': CGenericMultiPartTemp.GenericMultiPartTemp(), 'CImpulseDecoder': None, 'CActionFactory': None, 'LastAck0': [-1], 'LastAck1': [-1, -1], 'LastAck2': [-1, -1, -1, -1]}) self.client_state[clientid]['CImpulseDecoder'] = CImpulseDecoder.CImpulseDecoder(self.client_state[clientid]['world']) self.client_state[clientid]['CActionFactory'] = CActionFactory.CActionFactory(self.client_state[clientid]['world']) def add_registered_action(self, clientid, action): self.client_state[clientid]['RegisteredAction'].setdefault(action.Code, []) self.client_state[clientid]['RegisteredAction'][action.Code].append(action) self.client_state[clientid]['PropertyDecoder'] = CPropertyDecoder.CPropertyDecoder() self.client_state[clientid]['VisualPropertyTreeRoot'] = TVPNodeBase.TVPNodeBase("_VisualPropertyTreeRoot") self.client_state[clientid]['VisualPropertyTreeRoot'].build_tree() # def decodeDiscreetProperties(self, clientid, msgin): # # khanat-opennel-code/code/ryzom/client/src/network_connection.h:148 void decodeDiscreetProperties( NLMISC::CBitMemStream& msgin ) # BranchHasPayload = msgin.readBool("BranchHasPayload") # if BranchHasPayload: # if self.client_state[clientid]['VisualPropertyTreeRoot'].isLeaf(): # PropIndex = self.client_state[clientid]['VisualPropertyTreeRoot'].PropIndex # self.client_state[clientid]['VisualPropertyTreeRoot'].decodeDiscreetProperty(msgin, PropIndex) #if ( BranchHasPayload ) # { # if ( isLeaf() ) # { # SlotContext.NetworkConnection->decodeDiscreetProperty( msgin, PropIndex ); # } # else # { # if ( a() ) a()->decodeDiscreetProperties( msgin ); # if ( b() ) b()->decodeDiscreetProperties( msgin ); # } # } def decodeVisualProperties(self, clientid, msgin): """ khanat-opennel-code/code/ryzom/client/src/network_connection.cpp:1512 void CNetworkConnection::decodeVisualProperties( CBitMemStream& msgin ) """ actions = [] properties = [] notices = {} try: while True: property = {} # if ( msgin.getPosInBit() + (sizeof(TCLEntityId)*8) > msgin.length()*8 ) return # if msgin.sizeRead() + (8*8 ) > msgin.sizeData() * 8: #if msgin.needRead() < (8*8): if msgin.needRead() < 8: logging.getLogger(LOGGER).debug("too small no decodeVisualProperties [{0} > {1}]".format(msgin.sizeRead() + (8*8 ), msgin.sizeData() * 8 )) logging.getLogger(LOGGER).debug("properties:%s" % str(properties)) return properties, notices logging.getLogger(LOGGER).debug("too small no decodeVisualProperties [{0} > {1}]".format(msgin.sizeRead() + (8*8 ), msgin.sizeData() * 8 )) slot = msgin.readUint8("Slot") property['slot'] = slot hearder = 'VisualProperty/Slot_'+str(slot) + '/' associationBits = msgin.readSerial(2, "associationBits") notices.setdefault(hearder + 'associationBits', associationBits) property['associationBits'] = associationBits logging.getLogger(LOGGER).debug("slot:{0} (associationBits:{1})".format(slot, associationBits)) if self.client_state[clientid]['PropertyDecoder'] .associationBitsHaveChanged( slot, associationBits ) and (slot==0): if self.client_state[clientid]['PropertyDecoder'] .isUsed( slot ): sheet = self.client_state[clientid]['PropertyDecoder'] .getSheet(slot) property['sheet'] = sheet notices.setdefault(hearder + 'sheet', sheet) logging.getLogger(LOGGER).debug("sheet:{0}".format(sheet)) # TODO - remove sheet found in the list timestampIsThere = msgin.readBool("timestampIsThere") if timestampIsThere: timestampDelta = msgin.readSerial(4, "timestampDelta") timestamp = self.client_state[clientid]['CurrentReceivedNumber'] - timestampDelta logging.getLogger(LOGGER).debug("timestamp:{0} (timestampDelta:{1})".format(timestamp, timestampDelta)) else: timestamp = self.client_state[clientid]['CurrentReceivedNumber'] logging.getLogger(LOGGER).debug("timestamp:{0}".format(timestamp)) property['timestamp'] = timestamp notices.setdefault(hearder + 'timestamp', timestamp) property.setdefault('Actions', []) # Tree # currentNode->a() BranchHasPayload = msgin.readBool("BranchHasPayload [_VisualPropertyTreeRoot.VPA]") logging.getLogger(LOGGER).debug("_VisualPropertyTreeRoot.VPA->BranchHasPayload:{0}".format(BranchHasPayload)) if BranchHasPayload: # _PropertyDecoder.receive( _CurrentReceivedNumber, ap ); # Create a new action cActionPosition = CAction.CActionPosition(slot, Enum.TActionCode.ACTION_POSITION_CODE, self.client_state[clientid]['world']) cActionPosition.set_name('POSITION_CODE') cActionPosition.set_header_notice(hearder + 'POSITION_CODE') self.client_state[clientid]['PropertyDecoder'] .receive(cActionPosition) cActionPosition.unpack(msgin) actions.append(cActionPosition) for key in cActionPosition.notice: notices.setdefault(key, cActionPosition.notice[key]) #notice.setdefault(hearder + 'POSITION_CODE', cActionPosition) property['Actions'] .append(cActionPosition) # currentNode->b() BranchHasPayload = msgin.readBool("BranchHasPayload [_VisualPropertyTreeRoot.VPB]") logging.getLogger(LOGGER).debug("_VisualPropertyTreeRoot.VPB->BranchHasPayload:{0}".format(BranchHasPayload)) if BranchHasPayload: # currentNode->b()->a() BranchHasPayload = msgin.readBool("BranchHasPayload [_VisualPropertyTreeRoot.VPB.VPA]") logging.getLogger(LOGGER).debug("_VisualPropertyTreeRoot.VPB.VPA->BranchHasPayload:{0}".format(BranchHasPayload)) if BranchHasPayload: # Create a new action -> PROPERTY_ORIENTATION cActionOrientation= CAction.CActionSint64(slot, Enum.TPropIndex.PROPERTY_ORIENTATION, self.client_state[clientid]['world']) cActionOrientation.set_header_notice(hearder + 'Sint64') cActionOrientation.setNbBits(Enum.TPropIndex.PROPERTY_ORIENTATION, 'PROPERTY_ORIENTATION') cActionOrientation.set_name('PROPERTY_ORIENTATION') cActionOrientation.unpack(msgin) #self.client_state[clientid]['PropertyDecoder'] .receive(cActionPosition) actions.append(cActionOrientation) for key in cActionOrientation.notice: notices.setdefault(key, cActionOrientation.notice[key]) property['Actions'] .append(cActionOrientation) # Discreet properties # _VisualPropertyTreeRoot->b()->b() actions, addnotices = self.client_state[clientid]['VisualPropertyTreeRoot'].decodeDiscreetPropertiesVpbVpb(clientid, msgin, slot, self.client_state[clientid]['world']) for key in addnotices: notices.setdefault(hearder + key, addnotices[key]) for action in actions: property['Actions'] .append(action) #self.decodeDiscreetProperties(clientid, msgin) properties.append(property) except Exception as e: raise e except: # Detect end of stream (little hard to close) pass return properties, notices def decode_server(self, clientid, msgin, receivedPacket, receivedAck, nextSentPacket=0): """ khanat-opennel-code/code/ryzom/client/src/network_connection.cpp:1312 void CNetworkConnection::receiveNormalMessage(CBitMemStream &msgin) khanat-opennel-code/code/ryzom/client/src/impulse_decoder.cpp:38 void CImpulseDecoder::decode(CBitMemStream &inbox, TPacketNumber receivedPacket, TPacketNumber receivedAck, TPacketNumber nextSentPacket, vector &actions) khanat-opennel-code/code/ryzom/client/src/network_connection.cpp:1512 void CNetworkConnection::decodeVisualProperties( CBitMemStream& msgin ) """ actions = [] for level in range(0, 3): if level == 0: lAck = self.client_state[clientid]['LastAck0'] channel = 0 elif level == 1: lAck = self.client_state[clientid]['LastAck1'] channel = receivedPacket & 1 elif level == 2: lAck = self.client_state[clientid]['LastAck2'] channel = receivedPacket & 3 keep = True checkOnce = False num = 0 #logging.getLogger(LOGGER).debug("level:%d channel:%d lAck:%s" %(level, channel, ':'.join([str(x) for x in lAck]))) # lastAck = lAck[channel] while True: next = msgin.readBool('next:' + str(level) + ':' + str(channel)) if not next: break if not checkOnce: checkOnce = True keep = receivedAck >= lAck[channel] logging.getLogger(LOGGER).debug("keep:%s [%d => %d]" % (str(keep), receivedAck, lAck[channel])) if keep: lAck[channel] = nextSentPacket logging.getLogger(LOGGER).debug("lAck:%s" % ':'.join([str(x) for x in lAck])) pass num += 1 #actionFactory = CAction.CActionFactory(None) logging.getLogger(LOGGER).debug("[decode_server] (%s)" % (msgin.showAllData())) try: action = self.actionFactory.unpack(msgin) except Exception as e: logging.getLogger(LOGGER).debug("[decode_server] (%s)" % (msgin.showAllData())) raise e logging.getLogger(LOGGER).debug("action:%s" % action) #action = self._CActionFactory.unpack(msgin) if keep: logging.getLogger(LOGGER).debug("keep Code:%s" % str(action.Code)) actions.append(action) elif action: logging.getLogger(LOGGER).debug("append Code:%s" % str(action.Code)) self.add_registered_action(clientid, action) # khanat-opennel-code/code/ryzom/client/src/network_connection.cpp:1512 void CNetworkConnection::decodeVisualProperties( CBitMemStream& msgin ) properties, notices = self.decodeVisualProperties(clientid, msgin) return actions, properties, notices def decode_client_send_normal_message(self, msgin, clientid, dst, sequenceid, name, Reference): ''' khanat-opennel-code/code/ryzom/client/src/network_connection.cpp:2029 void CNetworkConnection::sendNormalMessage() khanat-opennel-code/code/ryzom/common/src/game_share/action_block.cpp:36 void CActionBlock::serial(CBitMemStream &msg) ''' #actions = self.client_state[clientid]['CImpulseDecoder'].decode(msgin, self.client_state[clientid]['CurrentReceivedNumber'], self.client_state[clientid]['LastReceivedAck'], self.client_state[clientid]['CurrentSendNumber'] ) actions = [] impulses = [] noerror = True msgin.disable_LogErrorOnStreamOverflow() while noerror: try: cycle = msgin.readUint32("Cycle") num = msgin.readUint8("num") logging.getLogger(LOGGER).debug("[Client -> Server] Cycle:%u num:%u" % (cycle, num)) for i in range(0, num): actions.append(self.client_state[clientid]['CActionFactory'].unpack(msgin, Reference, name)) pass except BitStream.OverflowError: noerror = False except RuntimeError: noerror = False except TypeError as e: logging.getLogger(LOGGER).debug("[Client -> Server] Impossible to decode %s (not read:%u, msg:%s)" % (e.__class__, msgin.needRead(), msgin.showAllData())) #raise e except Exception as e: logging.getLogger(LOGGER).debug("[Client -> Server] end %s (not read:%u)" % (e.__class__, msgin.needRead())) raise e msgin.enable_LogErrorOnStreamOverflow() ids = 0 for action in actions: try: impulse = action.decodeImpulseSimple( self.decodeImpulseSimple, self.client_state[clientid]['world'], self.client_state[clientid]['GenericMultiPartTempClient'], Reference = name ) #, Reference = Parent, Name = "%s_%d" % (target, 0)) if impulse: impulses.append(impulse) except BitStream.OverflowError as e: logging.getLogger(LOGGER).debug("[Client -> Server] error:%s : %s"% (e.__class__, msgin.showAllData())) except AttributeError as e: logging.getLogger(LOGGER).debug("[Client -> Server] error:%s : %s"% (e.__class__, msgin.showAllData())) #raise "Bad message" except Impulse.ImpulseNoElement: pass ids += 1 logging.getLogger(LOGGER).debug("[Client -> Server] detail actions [%d] => %s" % ( len(actions), ', '.join([str(x) for x in actions]))) # decodeVisualProperties( msgin ); return actions, impulses def decode_client_message(self, msgin, clientid, dst, sequenceid, name, Parent, Source): importantinfo = {} target = "%s_%s" % (Source, Parent[7:]) CurrentReceivedNumber = msgin.readSint32('CurrentReceivedNumber') SystemMode = msgin.readBool('SystemMode') logging.getLogger(LOGGER).debug("[Client -> Server] {CurrentReceivedNumber:%d, SystemMode:%d, src:%s, dst:%s}" % (CurrentReceivedNumber, SystemMode, clientid, dst)) self.initialize_client(clientid) self.client_state[clientid]['CurrentReceivedNumber'] = CurrentReceivedNumber actions = [] impulses = [] databases = [] if not SystemMode: ''' khanat-opennel-code/code/ryzom/client/src/network_connection.cpp:2029 void CNetworkConnection::sendNormalMessage() ''' LastReceivedAck = msgin.readSint32('LastReceivedAck') self.client_state[clientid]['LastReceivedAck'] = LastReceivedAck AckBitMask = msgin.readUint32('AckBitMask') self.client_state[clientid]['AckBitMask'] = AckBitMask logging.getLogger(LOGGER).info("[Client -> Server] Normal Mode {CurrentReceivedNumber:%d, src:%s, dst:%s, LastReceivedAck:%d}" % (CurrentReceivedNumber, clientid, dst, LastReceivedAck)) # self.decode_server(msgin, _CurrentReceivedNumber, _CurrentReceivedNumber-1) actions, impulses = self.decode_client_send_normal_message(msgin, clientid, dst, sequenceid, "%s_%d" % (target, 0), Parent) else: message = msgin.readUint8('message') try: typeMessage = Enum.CLFECOMMON(message).name except ValueError: typeMessage = "Unknown" if message == Enum.CLFECOMMON.SYSTEM_LOGIN_CODE: UserAddr = msgin.readUint32('UserAddr') UserKey = msgin.readUint32('UserKey') UserId = msgin.readUint32('UserId') LanguageCode = msgin.readString('LanguageCode') logging.getLogger(LOGGER).info("[Client -> Server] System Mode:%s {CurrentReceivedNumber:%d, src:%s, dst:%s, UserAddr:%d, UserId:%d, UserAddr:%d LanguageCode:%s}" % (typeMessage, CurrentReceivedNumber, clientid, dst, UserAddr, UserKey, UserId, LanguageCode)) action = CAction.CActionFake('SYSTEM_LOGIN_CODE', msgin, Reference=Parent, Name = "%s_%d" % (target, 0)) actions.append(action) elif message == Enum.CLFECOMMON.SYSTEM_PROBE_CODE: LatestProbe = msgin.readSint32('LatestProbe') logging.getLogger(LOGGER).info("[Client -> Server] System Mode:%s probe:%d {CurrentReceivedNumber:%d, src:%s, dst:%s}" % (typeMessage, LatestProbe, CurrentReceivedNumber, clientid, dst)) action = CAction.CActionFake('SYSTEM_PROBE_CODE', msgin, Reference=Parent, Name = "%s_%d" % (target, 0)) actions.append(action) elif message == Enum.CLFECOMMON.SYSTEM_SYNC_CODE: Synchronize = msgin.readUint32('Synchronize') stime = msgin.readSint64('stime') LatestSync = msgin.readUint32('LatestSync') MsgData = msgin.readArrayUint8(16, 'MsgData') md5Msg = bytes(MsgData) DatabaseData = msgin.readArrayUint8(16, 'DatabaseData') md5Database = bytes(DatabaseData) logging.getLogger(LOGGER).info("[Client -> Server] System Mode:%s {CurrentReceivedNumber:%d, src:%s, dst:%s, Synchronize:%d, stime:%d, LatestSync:%d, MsgData:%s, DatabaseData:%s}" % ( typeMessage, CurrentReceivedNumber, clientid, dst, Synchronize, stime, LatestSync, binascii.hexlify(md5Msg).decode(), binascii.hexlify(md5Database).decode())) action = CAction.CActionFake('SYSTEM_SYNC_CODE', msgin, Reference=Parent, Name = "%s_%d" % (target, 0)) actions.append(action) elif message == Enum.CLFECOMMON.SYSTEM_ACK_SYNC_CODE: LastReceivedNumber = msgin.readSint32('LastReceivedNumber') LastAckInLongAck = msgin.readSint32('LastAckInLongAck') LongAckBitField = CBitSet.CBitSet() LongAckBitField.readSerial(msgin, 'LongAckBitField') LatestSync = msgin.readSint32('LatestSync') logging.getLogger(LOGGER).info("[Client -> Server] System Mode:%s {CurrentReceivedNumber:%d, src:%s, dst:%s, LastReceivedNumber:%d, LastAckInLongAck:%d, LatestSync:%d, LongAckBitField:%s}" % ( typeMessage, CurrentReceivedNumber, clientid, dst, LastReceivedNumber, LastAckInLongAck, LatestSync, LongAckBitField)) action = CAction.CActionFake('SYSTEM_ACK_SYNC_CODE', msgin, Reference=Parent, Name = "%s_%d" % (target, 0)) actions.append(action) elif message == Enum.CLFECOMMON.SYSTEM_ACK_PROBE_CODE: SizeLatestProbes = msgin.readSint32('SizeLatestProbes') LatestProbes = [] for data in range(0, SizeLatestProbes): LatestProbes.append(msgin.readSint32('LatestProbes')) logging.getLogger(LOGGER).info("[Client -> Server] System Mode:%s (%d) {CurrentReceivedNumber:%d, src:%s, dst:%s, SizeLatestProbes:%d, LatestProbes:%s}" % (typeMessage, message, CurrentReceivedNumber, clientid, dst, SizeLatestProbes, str(LatestProbes))) action = CAction.CActionFake('SYSTEM_ACK_PROBE_CODE', msgin, Reference=Parent, Name = "%s_%d" % (target, 0)) actions.append(action) else: logging.getLogger(LOGGER).info("[Client -> Server] System Mode:%s (%d) {CurrentReceivedNumber:%d, src:%s, dst:%s}" % (typeMessage, message, CurrentReceivedNumber, clientid, dst)) logging.getLogger(LOGGER).debug("[Client -> Server] msg:%s" % msgin.showAllData()) return actions, impulses, databases, importantinfo def decode_khanat_message(self, msgin, src, dst, sequenceid, clientname, Parent, Source): target = "%s_%s" % (Source, Parent[7:]) actions = [] properties = [] impulses = [] databases = [] notices = {} CurrentSendNumber = msgin.readSint32('CurrentSendNumber') logging.getLogger(LOGGER).debug("[Server -> Client] {CurrentSendNumber:%d, src:%s, dst:%s}" % (CurrentSendNumber, src, dst)) SystemMode = msgin.readBool('SystemMode') self.initialize_client(dst) self.client_state[dst]['CurrentSendNumber'] = CurrentSendNumber id = 0 if not SystemMode: _LastReceivedAck = msgin.readSint32('LastReceivedAck'); logging.getLogger(LOGGER).debug("[Server -> Client] Normal Mode {CurrentSendNumber:%d, src:%s, dst:%s, _LastReceivedAck:%d}" % (CurrentSendNumber, src, dst, _LastReceivedAck)) actions, properties, notices = self.decode_server(dst, msgin, CurrentSendNumber, CurrentSendNumber-1) if actions: logging.getLogger(LOGGER).debug('list actions: [' + str(len(actions)) + '] ' +','.join( [ str(x) for x in actions] ) ) else: logging.getLogger(LOGGER).debug('list actions: None') # Decode the actions received in the impulsions logging.getLogger(LOGGER).debug('=' * 80) actionsbis = [] logging.getLogger(LOGGER).debug("size[actions] %d" % len(actions)) for action in actions: referenceBis = "%s_%d" % (target, id) action.add_reference(Parent) action.set_name(referenceBis) logging.getLogger(LOGGER).debug('-' * 80) logging.getLogger(LOGGER).debug('Analyse actions:%s', action) logging.getLogger(LOGGER).debug("size[actions] %d" % len(actions)) if action.Code == Enum.TActionCode.ACTION_DISCONNECTION_CODE: #action.add_reference(Parent) logging.getLogger(LOGGER).debug("Action : ACTION_DISCONNECTION_CODE") actionsbis.append(CAction.CActionFake('ACTION_DISCONNECTION_CODE', self.client_state[dst]['GenericMultiPartTempServer'].data[id].read())) # , Reference = Parent, Name = "%s_%d" % (target, 0) elif action.Code == Enum.TActionCode.ACTION_GENERIC_CODE: #action.add_reference(Parent) #action.genericAction(self.decodeImpulse, self.client_state[dst]['world'], self.client_state[dst]['GenericMultiPartTempServer']) #, Reference = Parent, Name = "%s_%d" % (target, 0)) try: impulse = action.decodeImpulseSimple( self.decodeImpulseSimple, self.client_state[dst]['world'], self.client_state[dst]['GenericMultiPartTempServer'], Reference = [Parent, ], Name = "%s_%d" % (target, 0) ) #, Reference = Parent, Name = "%s_%d" % (target, 0)) #logging.getLogger(LOGGER).info("impulse:%s" % str(impulse)) if impulse: logging.getLogger(LOGGER).debug("type impulse:%s" % str(type(impulse))) database = None #database = impulse.readDatabases(self.client_state[dst]['world'], self.decodeDatabase) if database: databases.append(database) impulses.append(impulse) except Impulse.ImpulseNoElement: pass logging.getLogger(LOGGER).info("[Server -> Client] ACTION_GENERIC_CODE : {CurrentSendNumber:%d, src:%s, dst:%s, _LastReceivedAck:%d, action:%s}" % (CurrentSendNumber, src, dst, _LastReceivedAck, action)) elif action.Code == Enum.TActionCode.ACTION_GENERIC_MULTI_PART_CODE: #action.genericAction(self.decodeImpulse, self.client_state[dst]['world'], self.client_state[dst]['GenericMultiPartTempServer'], Reference = referenceBis) #, Reference = Parent, Name = "%s_%d" % (target, 0)) try: logging.getLogger(LOGGER).debug("[Server -> Client] ACTION_GENERIC_MULTI_PART_CODE : %s OKKKKKKKK " % action) impulse = action.decodeImpulseSimple( self.decodeImpulseSimple, self.client_state[dst]['world'], self.client_state[dst]['GenericMultiPartTempServer'], Reference = Parent, Name = "%s_%d" % (target, 0) ) #, Reference = Parent, Name = "%s_%d" % (target, 0)) logging.getLogger(LOGGER).debug("impulse:%s" % str(impulse)) if impulse: logging.getLogger(LOGGER).debug("type impulse:%s" % str(type(impulse))) impulses.append(impulse) except Impulse.ImpulseNoElement: pass logging.getLogger(LOGGER).debug("[Server -> Client] ACTION_GENERIC_MULTI_PART_CODE : %s" % action) for id in self.client_state[dst]['GenericMultiPartTempServer'].data: logging.getLogger(LOGGER).info("[Server -> Client] ACTION_GENERIC_MULTI_PART_CODE {id:%d, available:%s NbBlock:%d/%d, isDecoded:%s, FirstRead:%s}" % ( id, self.client_state[dst]['GenericMultiPartTempServer'].data[id].isAvailable(), self.client_state[dst]['GenericMultiPartTempServer'].data[id].getNbCurrentBlock(), self.client_state[dst]['GenericMultiPartTempServer'].data[id].NbBlock, self.client_state[dst]['GenericMultiPartTempServer'].data[id].isDecoded(), self.client_state[dst]['GenericMultiPartTempServer'].data[id].FirstRead )) if self.client_state[dst]['GenericMultiPartTempServer'].data[id].isAvailable(): logging.getLogger(LOGGER).info("[Server -> Client] ACTION_GENERIC_MULTI_PART_CODE {CurrentSendNumber:%d, src:%s, dst:%s, _LastReceivedAck:%d, id:%d, msg:%s}" % ( CurrentSendNumber, src, dst, _LastReceivedAck, id, self.client_state[dst]['GenericMultiPartTempServer'].data[id].read().showAllData())) ## temp = CAction.CActionFake('ACTION_GENERIC_MULTI_PART_CODE', ## self.client_state[dst]['GenericMultiPartTempServer'].data[id].read(), ## # {'coucou': ', '.join(self.client_state[dst]['GenericMultiPartTemp'].data[id].Reference)}, ## # Reference = self.client_state[dst]['GenericMultiPartTemp'].data[id].Reference, ## Name = "impulse_%s_%s" % (Parent[7:], 0) ## ) ## temp.Reference = self.client_state[dst]['GenericMultiPartTempServer'].data[id].Reference ## #actionsbis.append(temp) msg = self.client_state[dst]['GenericMultiPartTempServer'].data[id].MsgDecoded msg.reset_read() # #print("------->", msg.needRead(), "/", msg.sizeData()) # #print("------>", type(self.client_state[dst]['GenericMultiPartTempServer'].data[id])) action = CAction.CActionFake('ACTION_GENERIC_MULTI_PART_CODE', msg, # {'coucou': ', '.join(self.client_state[dst]['GenericMultiPartTemp'].data[id].Reference)}, Reference = self.client_state[dst]['GenericMultiPartTempServer'].data[id].Reference, Name = "impulse_%s_%s" % (Parent[7:], 0) ) try: impulse = action.decodeImpulseSimple( self.decodeImpulseSimple, self.client_state[dst]['world'], self.client_state[dst]['GenericMultiPartTempServer'], Reference = self.client_state[dst]['GenericMultiPartTempServer'].data[id].Reference, Name = "%s_%d" % (target, 0) ) #, Reference = Parent, Name = "%s_%d" % (target, 0)) if impulse: logging.getLogger(LOGGER).debug("type impulse:%s" % str(type(impulse))) impulses.append(impulse) except Impulse.ImpulseNoElement: pass actionsbis.append(action) # try: # impulse = {"Type": "CActionFake.ACTION_GENERIC_MULTI_PART_CODE"} # impulse["state"] = "message partially decoded" # tmp = self.decodeImpulseSimple.execute(msg, self.client_state[dst]['world']) # print("-"*80) # print(tmp) # print("-"*80) # impulse['Message'] = msg.extractAllData() # impulse['Reference'] = self.client_state[dst]['GenericMultiPartTempServer'].data[id].Reference # impulse['Name'] = "Impulse_%s_%d" % (target, 0) ## impulse = action.decodeImpulseSimple( ## self.decodeImpulseSimple, ## self.client_state[dst]['world'], ## self.client_state[dst]['GenericMultiPartTempServer'], ## Reference = Parent, ## Name = "%s_%d" % (target, 0) ## ) #, Reference = Parent, Name = "%s_%d" % (target, 0)) # print("-"*80) # logging.getLogger(LOGGER).info("impulse:%s" % str(impulse)) # if impulse: # print("spykhanat.py:473", type(impulse)) # impulses.append(impulse) # except Impulse.ImpulseNoElement: # pass # print(impulses) #raise "quoi" else: logging.getLogger(LOGGER).info("[Server -> Client] ACTION_GENERIC_MULTI_PART_CODE {CurrentSendNumber:%d, src:%s, dst:%s, _LastReceivedAck:%d, id:%d}" % ( CurrentSendNumber, src, dst, _LastReceivedAck, id)) elif action.Code == Enum.TActionCode.ACTION_DUMMY_CODE: #action.add_reference(Parent) logging.getLogger(LOGGER).info("Action : ACTION_DUMMY_CODE") actionsbis.append(CAction.CActionFake('ACTION_DUMMY_CODE', self.client_state[dst]['GenericMultiPartTempServer'].data[id].read(), Reference=Parent, Name = "%s_%d" % (target, 0))) self.add_registered_action(dst, action) id += 1 # # remove all old actions that are acked # while self._Actions and self._Actions[0].FirstPacket != 0 and self._Actions[0].FirstPacket < self._LastReceivedAck: # logging.getLogger(LOGGER).debug("remove old action [%d/%d] : %s" % (self._Actions[0].FirstPacket, self._LastReceivedAck, self._Actions[0])) # self._Actions.pop(0) logging.getLogger(LOGGER).debug("size[actions] %d" % len(actions)) for action in actionsbis: actions.append(action) logging.getLogger(LOGGER).debug("impulses:%s" % str(impulses)) else: message = msgin.readUint8('message') #referenceBis = "%s_%d" % (Parent, id) logging.getLogger(LOGGER).debug("[Server -> Client] System Mode {CurrentSendNumber:%d, src:%s, dst:%s, message:%d" % (CurrentSendNumber, src, dst, message)) if message == Enum.CLFECOMMON.SYSTEM_SYNC_CODE: logging.getLogger(LOGGER).debug("[Server -> Client] Synchronize") Synchronize = msgin.readUint32('Synchronize') stime = msgin.readSint64('stime') LatestSync = msgin.readUint32('LatestSync') MsgData = msgin.readArrayUint8(16, 'MsgData') DatabaseData = msgin.readArrayUint8(16, 'DatabaseData') logging.getLogger(LOGGER).info("[Server -> Client] System Mode / Synchronize {CurrentSendNumber:%d, src:%s, dst:%s, message:%d, Synchronize:%d, stime:%d, LatestSync:%d, MsgData:%s, DatabaseData:%s}" % (CurrentSendNumber, src, dst, message, Synchronize, stime, LatestSync, str(MsgData), str(DatabaseData))) action = CAction.CActionFake('SYSTEM_SYNC_CODE', msgin, Reference=Parent, Name = "%s_%d" % (target, 0)) actions.append(action) elif message == Enum.CLFECOMMON.SYSTEM_STALLED_CODE: logging.getLogger(LOGGER).debug("[Server -> Client] Stalled") logging.getLogger(LOGGER).info("[Server -> Client] System Mode / Stalled {CurrentSendNumber:%d, src:%s, dst:%s, message:%d}" % (CurrentSendNumber, src, dst, message)) action = CAction.CActionFake('SYSTEM_STALLED_CODE', msgin, Reference=Parent, Name = "%s_%d" % (target, 0)) actions.append(action) elif message == Enum.CLFECOMMON.SYSTEM_PROBE_CODE: logging.getLogger(LOGGER).debug("[Server -> Client] Probe") LatestProbe = msgin.readSint32('LatestProbe') logging.getLogger(LOGGER).info("[Server -> Client] System Mode / Probe {CurrentSendNumber:%d, src:%s, dst:%s, message:%d, LatestProbe:%d}" % (CurrentSendNumber, src, dst, message, LatestProbe)) action = CAction.CActionFake('SYSTEM_PROBE_CODE', msgin, Reference=Parent, Name = "%s_%d" % (target, 0)) actions.append(action) elif message == Enum.CLFECOMMON.SYSTEM_SERVER_DOWN_CODE: logging.getLogger(LOGGER).info("[Server -> Client] System Mode / BACK-END DOWN {CurrentSendNumber:%d, src:%s, dst:%s, message:%d}" % (CurrentSendNumber, src, dst, message)) action = CAction.CActionFake('SYSTEM_SERVER_DOWN_CODE', msgin, Reference=Parent, Name = "%s_%d" % (target, 0)) actions.append(action) else: logging.getLogger(LOGGER).warning("CNET: received system %d in state Login" % message) #cActionFactory = CAction.CActionFactory(None) #cActionFactory.unpack(msgin) logging.getLogger(LOGGER).debug("[Server -> Client] msg:%s" % msgin.showAllData()) #logging.getLogger(LOGGER).info("impulses:%s" % str(impulses)) return actions, impulses, databases, properties, notices def read(self): logging.getLogger(LOGGER).info("Conversion => Start") fullconverted = True file = open( self.pcap_file , 'rb') pcapfile = savefile.load_savefile(file,verbose=False) khanat_host = self.detect_khanat_server(pcapfile.packets) clientid = 1 serverid = 1 list_host = {} sequenceid = 1 sequencenum = 1 if self.outyaml: self.outyaml.write("# Generated : %s\n\n" % (datetime.now().strftime("%Y-%m-%d %H:%M:%S"))) if self.outcsv: self.outcsv.write("Date,Packet Id,Source,Destination,Key,Value\n") for pkt in pcapfile.packets: eth_frame = ethernet.Ethernet(pkt.raw()) if eth_frame.type == 2048: ip_packet = ip.IP(binascii.unhexlify(eth_frame.payload)) if ip_packet.p == 17: # UDP udp_packet = udp.UDP(binascii.unhexlify(ip_packet.payload)) data = udp_packet.payload if udp_packet.src_port == 53 or udp_packet.dst_port == 53: continue if udp_packet.src_port == 5353 and ip_packet.src.decode() == "224.0.0.251": continue if udp_packet.dst_port == 5353 and ip_packet.dst.decode() == "224.0.0.251": continue if not self.filter_host_service or self.filter_host_service.match("%s:%d" % (ip_packet.src.decode(), udp_packet.src_port)) or self.filter_host_service.match("%s:%d" % (ip_packet.dst.decode(), udp_packet.dst_port)): Reference = "packet_%d" % sequenceid logging.getLogger(LOGGER).debug("-" * 80) actions_clients = [] actions_servers = [] impulses_servers = [] impulses_clients = [] properties_servers = [] if self.show_raw_packet: logging.getLogger(LOGGER).debug("[raw packet] timestamp:%s [%s] src:%s:%d dst:%s:%d data:%s" % (pkt.timestamp, datetime.fromtimestamp(pkt.timestamp).strftime("%Y/%m/%d %H:%M:%S"), ip_packet.src.decode(), udp_packet.src_port, ip_packet.dst.decode(), udp_packet.dst_port, data.decode())) msgin = BitStream.BitStream() msgin.fromBytes(binascii.unhexlify(data)) src = "%s:%d" % (ip_packet.src.decode(), udp_packet.src_port) dst = "%s:%d" % (ip_packet.dst.decode(), udp_packet.dst_port) if (self.khanat_host_service and self.khanat_host_service.match(src)) or ( not self.khanat_host_service and khanat_host == src): if src not in list_host: name = "Server%d" % serverid list_host.setdefault(src, name) serverid += 1 else: if src not in list_host: name = "Client%d" % clientid list_host.setdefault(src, name) clientid += 1 if (self.khanat_host_service and self.khanat_host_service.match(dst)) or ( not self.khanat_host_service and khanat_host == dst): if dst not in list_host: name = "Server%d" % serverid list_host.setdefault(dst, name) serverid += 1 else: if dst not in list_host: name = "Client%d" % clientid list_host.setdefault(dst, name) clientid += 1 if (self.khanat_host_service and self.khanat_host_service.match(src)) or ( not self.khanat_host_service and khanat_host == src): _provenance = 'Server -> Client' logging.getLogger(LOGGER).debug("[%s] (message received) [%s] %s" % (_provenance, datetime.fromtimestamp(pkt.timestamp).strftime("%Y/%m/%d %H:%M:%S"), msgin.showAllData())) actions_servers, impulses_servers, databases_servers, properties_servers, notices = self.decode_khanat_message(msgin, src, dst, sequenceid, list_host[dst], Reference, list_host[src]) else: _provenance = 'Client -> Server' logging.getLogger(LOGGER).debug("[%s] (message received) [%s] %s" % (_provenance, datetime.fromtimestamp(pkt.timestamp).strftime("%Y/%m/%d %H:%M:%S"), msgin.showAllData())) actions_clients, impulses_clients, databases_clients, notices = self.decode_client_message(msgin, src, dst, sequenceid, list_host[dst], Reference, list_host[src]) if not msgin.checkOnlyZeroAtEnd(): # msgin.needRead() > 7: moredata = "message partially decoded" fullconverted = False else: moredata = 'message decoded' if self.show_message_decoded: logging.getLogger(LOGGER).debug("[%s] (%s) %s" % (_provenance, moredata, msgin.showAllData())) if notices: havedata = True else: havedata = False if not havedata: for action in actions_servers: if action.get_notice(): havedata = True break if not havedata: for action in actions_clients: if action.get_notice(): havedata = True break if not havedata: for impulse_data in impulses_servers: if impulse_data.get_notice(): havedata = True break if not havedata: for impulse_data in impulses_clients: if impulse_data.get_notice(): havedata = True break if havedata: print(datetime.fromtimestamp(pkt.timestamp).strftime("%Y/%m/%d %H:%M:%S"), "[", Reference, "]", list_host[src], "->", list_host[dst]) for key in notices: print(" " * 3, key, ":", notices[key]) for action in actions_servers: data = action.get_notice() for key in data: print(" " * 3, key, ":", data[key]) for action in actions_clients: data = action.get_notice() for key in data: print(" " * 3, key, ":", data[key]) for impulse_data in impulses_servers: data = impulse_data.get_notice() for key in data: print(" " * 3, key, ":", data[key]) for impulse_data in impulses_clients: data = impulse_data.get_notice() for key in data: print(" " * 3, key, ":", data[key]) print("") if self.outcsv: for key in notices: self.outcsv.write("%s,%s,%s,%s,%s,%s\n" % (datetime.fromtimestamp(pkt.timestamp).strftime("%Y/%m/%d %H:%M:%S"), Reference, list_host[src], list_host[dst], key, notices[key])) for action in actions_servers: data = action.get_notice() for key in data: self.outcsv.write("%s,%s,%s,%s,%s,%s\n" % (datetime.fromtimestamp(pkt.timestamp).strftime("%Y/%m/%d %H:%M:%S"), Reference, list_host[src], list_host[dst], key, data[key])) for action in actions_clients: data = action.get_notice() for key in data: self.outcsv.write("%s,%s,%s,%s,%s,%s\n" % (datetime.fromtimestamp(pkt.timestamp).strftime("%Y/%m/%d %H:%M:%S"), Reference, list_host[src], list_host[dst], key, data[key])) for impulse_data in impulses_servers: data = impulse_data.get_notice() for key in data: self.outcsv.write("%s,%s,%s,%s,%s,%s\n" % (datetime.fromtimestamp(pkt.timestamp).strftime("%Y/%m/%d %H:%M:%S"), Reference, list_host[src], list_host[dst], key, data[key])) for impulse_data in impulses_clients: data = impulse_data.get_notice() for key in data: self.outcsv.write("%s,%s,%s,%s,%s,%s\n" % (datetime.fromtimestamp(pkt.timestamp).strftime("%Y/%m/%d %H:%M:%S"), Reference, list_host[src], list_host[dst], key, data[key])) if self.outyaml: self.outyaml.write("\n%s:\n sequence: %d\n time: %s\n source: %s\n destination: %s\n function: %s\n adress_source: %s\n adress_destination: %s\n state: %s\n message:\n" % ( Reference, sequencenum, datetime.fromtimestamp(pkt.timestamp).strftime("%Y/%m/%d %H:%M:%S"), list_host[src], list_host[dst], _provenance, src, dst, moredata )) for key in msgin.extractAllData(): self.outyaml.write(" - %s\n" % key) if actions_servers: self.outyaml.write("\nblock_%s_%d:\n" %(list_host[src], sequenceid)) id = 0 for action in actions_servers: params = action.get_parameter() self.outyaml.write(" %s:\n" % (action.get_name())) # if "parent" in params: # self.outyaml.write(" parent: %s\n" % (params['parent'])) # elif "Reference" in params: # #self.outyaml.write(" parents: %s\n" % (', '.join(params['Reference']))) # self.outyaml.write(" parents:\n") # for key in params['Reference']: # self.outyaml.write(" - %s\n" % (key)) # else: # self.outyaml.write(" parent: udp_%s\n" % (sequenceid)) self.outyaml.write(" receivedby: client\n") self.outyaml.write(" sequence: %s\n" % (sequencenum)) self.outyaml.write(" source: %s\n" % (list_host[src])) self.outyaml.write(" destination: %s\n" % (list_host[dst])) for key in params: if key == 'Message': self.outyaml.write(" %s:\n" % (key)) for key2 in params[key]: self.outyaml.write(" - %s\n" % key2) elif key == "Reference": self.outyaml.write(" parents:\n") for key in params['Reference']: self.outyaml.write(" - %s\n" % (key)) #elif key != 'parent': else: self.outyaml.write(" %s: %s\n" % (key, params[key])) #self.outyaml.write(" %s: %s\n" % (key, params[key])) id += 1 # if databases_servers: # self.outyaml.write("\ndatabaseserver_%s_%d:\n" %(list_host[src], sequenceid)) # id = 0 # for databases in databases_servers: # params = impulse_data.get_parameter() # self.outyaml.write(" %s:\n" % (impulse_data.get_name())) # for key in params: # if key == 'Message': # self.outyaml.write(" %s:\n" % (key)) # for key2 in params[key]: # self.outyaml.write(" - %s\n" % key2) # elif key == "Reference": # self.outyaml.write(" parents:\n") # for key in params['Reference']: # self.outyaml.write(" - %s\n" % (key)) # #elif key != 'parent': # else: # self.outyaml.write(" %s: %s\n" % (key, params[key])) # #self.outyaml.write(" %s: %s\n" % (key, params[key])) # id += 1 # #print("-"*30) if impulses_servers: self.outyaml.write("\nimpulseserver_%s_%d:\n" %(list_host[src], sequenceid)) id = 0 #print("-"*30) #print(impulses_servers) #print(impulses_servers) for impulse_data in impulses_servers: #print("-"*80) #print(Impulse) #print(impulse_data) params = impulse_data.get_parameter() self.outyaml.write(" %s:\n" % (impulse_data.get_name())) for key in params: if key == 'Message': self.outyaml.write(" %s:\n" % (key)) for key2 in params[key]: self.outyaml.write(" - %s\n" % key2) elif key == "Reference": self.outyaml.write(" parents:\n") for key in params['Reference']: self.outyaml.write(" - %s\n" % (key)) #elif key != 'parent': else: self.outyaml.write(" %s: %s\n" % (key, params[key])) #self.outyaml.write(" %s: %s\n" % (key, params[key])) id += 1 #print("-"*30) if properties_servers: self.outyaml.write("\nvisual_properties_%s_%d:\n" %(list_host[src], sequenceid)) for property in properties_servers: self.outyaml.write(" slot: %d\n" % (property['slot'])) self.outyaml.write(" parents: %s\n" % Reference) self.outyaml.write(" associationBits: %d\n" % (property['associationBits'])) self.outyaml.write(" timestamp: %d\n" % (property['timestamp'])) for action in property['Actions']: try: action.print_yaml(self.outyaml, " ") #self.outyaml.write(" %s: %s\n" % (action.get_name(), str(action.get_property()))) except AttributeError: # TODO - change print if CAtion is Position or other (and not CActionSint64) params = action.get_parameter() self.outyaml.write(" %s:\n" % (action.get_name())) for key in params: if key == "Reference": pass elif key == "GameCycle": pass elif key == "Slot": pass else: self.outyaml.write(" %s: %s\n" % (key, params[key])) if actions_clients: self.outyaml.write("\nblock_%s_%d:\n" %(list_host[src], sequenceid)) id = 0 for action in actions_clients: self.outyaml.write(" %s:\n" % (action.get_name())) self.outyaml.write(" receivedby: server\n") self.outyaml.write(" sequence: %s\n" % (sequencenum)) self.outyaml.write(" source: %s\n" % (list_host[src])) self.outyaml.write(" destination: %s\n" % (list_host[dst])) params = action.get_parameter() for key in params: if key == 'Message': self.outyaml.write(" %s:\n" % (key)) for key2 in params[key]: self.outyaml.write(" - %s\n" % key2) elif key == "Reference": self.outyaml.write(" parents:\n") for key in params['Reference']: self.outyaml.write(" - %s\n" % (key)) else: self.outyaml.write(" %s: %s\n" % (key, params[key])) #self.outyaml.write(" %s: %s\n" % (key, params[key])) id += 1 # if impulses_clients: # self.outyaml.write("\nImpulseclient_%s_%d:\n" %(list_host[src], sequenceid)) # id = 0 # for Impulse in impulses_clients: # params = Impulse.get_parameter() # self.outyaml.write(" %s:\n" % (Impulse.get_name())) # id += 1 #if Reference == 'packet_409': # raise "STOP" sequenceid += 1 sequencenum += 1 for client in self.client_state: logging.getLogger(LOGGER).debug("%s [server tick:%d, client tick:%d]" %(client, self.client_state[client]['CurrentSendNumber'], self.client_state[client]['CurrentReceivedNumber'])) if fullconverted: logging.getLogger(LOGGER).info("Full converted") print("\nEnd : Full converted") else: logging.getLogger(LOGGER).info("Partially converted") print("\nEnd : Partially converted") logging.getLogger(LOGGER).info("Conversion => End") def main(): FORMAT = '%(asctime)-15s %(levelname)s %(filename)s:%(lineno)d %(message)s' logging.basicConfig(format=FORMAT) logger = [] logger.append(logging.getLogger(LOGGER)) # logger.append(logging.getLogger(CImpulseDecoder.LOGGER)) # #logger.append(logging.getLogger(DecodeImpuls.LOGGER)) #logger.append(logging.getLogger(BitStream.LOGGER)) # logger.append(logging.getLogger(CStringManager.LOGGER)) #logger.append(logging.getLogger(CAction.LOGGER)) #logger.append(logging.getLogger(CActionFactory.LOGGER)) #logger.append(logging.getLogger(BitStream.LOGGER)) #logger.append(logging.getLogger(DecodeDatabase.LOGGER)) #logger.append(logging.getLogger(Impulse.LOGGER)) #logger.append(logging.getLogger(TVPNodeBase.LOGGER)) # CImpulseDecoder # logger.append(logging.getLogger('CGenericMultiPartTemp')) #logger.append(logging.getLogger(DecodeDatabase.LOGGER)) parser = argparse.ArgumentParser() parser.add_argument("--khanat-host-service", help="filter to detect khanat host:service (FES)") parser.add_argument("--filter-host-service", help="filter host:service") parser.add_argument("-d", "--debug", help="show debug message", action='store_true') parser.add_argument("-v", "--verbose", help="show verbose message", action='store_true') parser.add_argument("-p", "--pcap-file", help="file pcap to read", required=True) parser.add_argument("-m", "--msg-xml", help="file msg.xml (from server khanat)", required=True) parser.add_argument("-w", "--database-xml", help="file database.xml (from server khanat)", required=True) parser.add_argument("-r", "--raw", help="show message raw", action='store_true') parser.add_argument("--yaml", help="generate YAML file (decode all message)", type=argparse.FileType('w'), default=None) parser.add_argument("--csv", help="generate CSV file (essential message)", type=argparse.FileType('w'), default=None) parser.add_argument("--show-raw-packet", help="show packet (raw data)", action='store_true') parser.add_argument("--show-message-decoded", help="show packet (raw data)", action='store_true') args = parser.parse_args() if args.debug: level = logging.getLevelName('DEBUG') elif args.verbose: level = logging.getLevelName('INFO') else: level = logging.getLevelName('WARNING') for logid in logger: logid.setLevel(level) logging.getLogger(LOGGER).info("Begin") spy = SpyPcap(khanat_host_service=args.khanat_host_service, pcap_file=args.pcap_file, msg_xml=args.msg_xml, database_xml=args.database_xml, filter_host_service=args.filter_host_service, show_raw_packet=args.show_raw_packet, show_message_decoded=args.show_message_decoded, outyaml=args.yaml, outcsv=args.csv) if args.raw: spy.readRaw() else: spy.read() logging.getLogger(LOGGER).info("End") if __name__ == "__main__": main()