def parse(self, packet): # dissect fixed header try: fixed_header = unpack("!BBHHHH", packet[:10]) except struct.error: raise ParseException("s7comm", "malformed fixed packet header structure") self.magic = int(fixed_header[0]) if self.magic != 0x32: raise ParseException( "s7comm", "bad magic number, expected 0x32 but got {0}.".format(self.magic), ) self.pdu_type = fixed_header[1] self.reserved = fixed_header[2] self.request_id = fixed_header[3] self.param_length = fixed_header[4] self.data_length = fixed_header[5] # dissect variable header if self.pdu_type in (2, 3): # type 2 and 3 feature an additional RESULT INFORMATION header self.result_info = unpack("!H", packet[10:12]) header_offset = 2 else: header_offset = 0 self.parameters = packet[ 10 + header_offset : 10 + header_offset + self.param_length ] self.data = packet[ 10 + header_offset + self.param_length : 10 + header_offset + self.param_length + self.data_length ] try: self.param = unpack("!B", self.parameters[:1])[0] except: raise ParseException("s7comm", "invalid packet") return self
def request_diagnostics(self): # semi-check try: unpack('!BBBBBBBB', self.parameters[:8]) except struct.error: raise ParseException('s7comm', 'malformed SSL/SZL parameter structure') chunk = self.data chunk_id = 0 while chunk: try: ssl_chunk_header = unpack('!BBH', chunk[:4]) except struct.error: raise ParseException('s7comm', 'malformed SSL/SZL data structure') # dissect data blocks data_error_code = ssl_chunk_header[0] data_data_type = ssl_chunk_header[1] data_next_bytes = ssl_chunk_header[2] data_ssl_id = '' data_ssl_index = '' data_ssl_unknown = '' if data_next_bytes > 0: data_ssl_id = unpack('!H', chunk[4:6])[0] if data_next_bytes > 1: data_ssl_index = unpack('!H', chunk[6:8])[0] if data_next_bytes > 2: data_ssl_unknown = chunk[8:4 + data_next_bytes] # map request ssl to method if hasattr(self, 'request_ssl_{0}'.format(data_ssl_id)): m = getattr(self, 'request_ssl_{0}'.format(data_ssl_id)) description, params, data = m(data_ssl_index) return params, data chunk = chunk[4 + data_next_bytes:] chunk_id += 1 return 0x00, 0x00
def request_diagnostics(self): # semi-check try: unpack("!BBBBBBBB", self.parameters[:8]) except struct.error: raise ParseException("s7comm", "malformed SSL/SZL parameter structure") chunk = self.data chunk_id = 0 while chunk: try: ssl_chunk_header = unpack("!BBH", chunk[:4]) except struct.error: raise ParseException("s7comm", "malformed SSL/SZL data structure") # dissect data blocks # data_error_code = ssl_chunk_header[0] # data_data_type = ssl_chunk_header[1] data_next_bytes = ssl_chunk_header[2] data_ssl_id = "" data_ssl_index = "" # data_ssl_unknown = "" if data_next_bytes > 0: data_ssl_id = unpack("!H", chunk[4:6])[0] if data_next_bytes > 1: data_ssl_index = unpack("!H", chunk[6:8])[0] if data_next_bytes > 2: # data_ssl_unknown = chunk[8 : 4 + data_next_bytes] pass # map request ssl to method if hasattr(self, "request_ssl_{0}".format(data_ssl_id)): m = getattr(self, "request_ssl_{0}".format(data_ssl_id)) _, params, data = m(data_ssl_index) return params, data chunk = chunk[4 + data_next_bytes :] chunk_id += 1 return 0x00, 0x00
def dissect(self, packet): # dissect fixed header try: fixed_header = unpack("!HHB", packet[:5]) except struct.error: raise ParseException("s7comm", "malformed fixed header structure") self.dst_ref = fixed_header[0] self.src_ref = fixed_header[1] self.opt_field = fixed_header[2] # dissect variable header chunk = packet[5:] while len(chunk) > 0: chunk_param_header = unpack("!BB", chunk[:2]) chunk_param_code = int(chunk_param_header[0]) chunk_param_length = chunk_param_header[1] if chunk_param_length == 1: param_unpack_structure = "!B" elif chunk_param_length == 2: param_unpack_structure = "!H" else: raise ParseException("s7comm", "malformed variable header structure") chunk_param_data = unpack(param_unpack_structure, chunk[2:2 + chunk_param_length]) if chunk_param_code == 0xC1: self.src_tsap = chunk_param_data[0] elif chunk_param_code == 0xC2: self.dst_tsap = chunk_param_data[0] elif chunk_param_code == 0xC0: self.tpdu_size = chunk_param_data[0] else: raise ParseException("s7comm", "unknown parameter code") # remove this part of the chunk chunk = chunk[2 + chunk_param_length:] return self
def parse(self, packet): # packet = cleanse_byte_string(packet) try: # try to extract the header by pattern to find malformed header data header = unpack('!BBH', packet[:4]) except struct.error: raise ParseException('s7comm', 'malformed packet header structure') # extract header data and payload self.version = header[0] self.reserved = header[1] self.packet_length = header[2] self.payload = packet[4:4 + header[2]] return self
def parse(self, packet): try: header = unpack('!BBB', packet[:3]) except struct.error: raise ParseException('s7comm', 'malformed packet header structure') self.packet_length = header[0] self.tpdu_type = int(header[1]) self.trailer = packet[1 + self.packet_length:] if self.tpdu_type == 0xf0: # the DT DATA TPDU features another header byte that shifts our structure self.opt_field = header[2] self.payload = packet[3:1 + self.packet_length] else: self.payload = packet[2:1 + self.packet_length] return self
def request_not_implemented(self): raise ParseException('s7comm', 'request not implemented in honeypot yet.')
def request_not_implemented(self): raise ParseException("s7comm", "request not implemented in honeypot yet.")