def handle(self, data, address): session = conpot_core.get_session('bacnet', address[0], address[1]) logger.info('New Bacnet connection from %s:%d. (%s)', address[0], address[1], session.id) session.add_event({'type': 'NEW_CONNECTION'}) # I'm not sure if gevent DatagramServer handles issues where the # received data is over the MTU -> fragmentation if data: pdu = PDU() pdu.pduData = data apdu = APDU() npdu = NPDU() bvlpdu = BVLPDU() try: bvlpdu.decode(pdu) npdu.decode(bvlpdu) apdu.decode(npdu) except DecodingError as e: logger.error("DecodingError: %s", e) logger.error("PDU: " + format(pdu)) return self.bacnet_app.indication(apdu, address, self.thisDevice) self.bacnet_app.response(self.bacnet_app._response, npdu, bvlpdu, address) logger.info('Bacnet client disconnected %s:%d. (%s)', address[0], address[1], session.id)
def handle(self, data, address): session = conpot_core.get_session( "bacnet", address[0], address[1], get_interface_ip(address[0]), self.server.server_port, ) logger.info("New Bacnet connection from %s:%d. (%s)", address[0], address[1], session.id) session.add_event({"type": "NEW_CONNECTION"}) # I'm not sure if gevent DatagramServer handles issues where the # received data is over the MTU -> fragmentation if data: pdu = PDU() pdu.pduData = bytearray(data) apdu = APDU() try: apdu.decode(pdu) except DecodingError: logger.warning("DecodingError - PDU: {}".format(pdu)) return self.bacnet_app.indication(apdu, address, self.thisDevice) # send an appropriate response from BACnet app to the attacker self.bacnet_app.response(self.bacnet_app._response, address) logger.info("Bacnet client disconnected %s:%d. (%s)", address[0], address[1], session.id)
def response(self, response_apdu, npdu, bvlpdu, address): if response_apdu is None: return apdu = APDU() response_apdu.encode(apdu) apdu.encode(npdu) npdu.encode(bvlpdu) pdu = PDU() bvlpdu.bvlciLength = len(bvlpdu.pduData) + 4 bvlpdu.encode(pdu) apdu_type = apdu_types.get(response_apdu.apduType) if isinstance(response_apdu, RejectPDU) or isinstance( response_apdu, ErrorPDU): self.datagram_server.sendto(pdu.pduData, address) logger.info('Bacnet Error or Reject response sent to %s (%s:%s)', response_apdu.pduDestination, apdu_type.__name__, self._response_service) else: if pdu.pduDestination == '*:*': # broadcast # sendto operates under lock self.datagram_server.sendto(pdu.pduData, ('', address[1])) else: # sendto operates under lock self.datagram_server.sendto(pdu.pduData, address) logger.info('Bacnet response sent to %s (%s:%s)', response_apdu.pduDestination, apdu_type.__name__, self._response_service)
def response(self, response_apdu, address): if response_apdu is None: return apdu = APDU() response_apdu.encode(apdu) pdu = PDU() apdu.encode(pdu) if isinstance(response_apdu, RejectPDU) or isinstance( response_apdu, ErrorPDU): self.datagram_server.sendto(pdu.pduData, address) else: apdu_type = apdu_types.get(response_apdu.apduType) if pdu.pduDestination == "*:*": # broadcast # sendto operates under lock self.datagram_server.sendto(pdu.pduData, ("", address[1])) else: # sendto operates under lock self.datagram_server.sendto(pdu.pduData, address) logger.info( "Bacnet response sent to %s (%s:%s)", response_apdu.pduDestination, apdu_type.__name__, self._response_service, )
def test_readProperty(self): request = ReadPropertyRequest( objectIdentifier=("analogInput", 14), propertyIdentifier=85 ) request.apduMaxResp = 1024 request.apduInvokeID = 101 apdu = APDU() request.encode(apdu) pdu = PDU() apdu.encode(pdu) buf_size = 1024 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.sendto(pdu.pduData, self.address) data = s.recvfrom(buf_size) s.close() received_data = data[0] expected = ReadPropertyACK() expected.pduDestination = GlobalBroadcast() expected.apduInvokeID = 101 expected.objectIdentifier = 14 expected.objectName = "AI 01" expected.propertyIdentifier = 85 expected.propertyValue = Any(Real(68.0)) exp_apdu = APDU() expected.encode(exp_apdu) exp_pdu = PDU() exp_apdu.encode(exp_pdu) self.assertEqual(exp_pdu.pduData, received_data)
def test_whoIs(self): request = WhoIsRequest( deviceInstanceRangeLowLimit=500, deviceInstanceRangeHighLimit=50000 ) apdu = APDU() request.encode(apdu) pdu = PDU() apdu.encode(pdu) buf_size = 1024 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.sendto(pdu.pduData, self.address) data = s.recvfrom(buf_size) s.close() received_data = data[0] expected = IAmRequest() expected.pduDestination = GlobalBroadcast() expected.iAmDeviceIdentifier = 36113 expected.maxAPDULengthAccepted = 1024 expected.segmentationSupported = "segmentedBoth" expected.vendorID = 15 exp_apdu = APDU() expected.encode(exp_apdu) exp_pdu = PDU() exp_apdu.encode(exp_pdu) self.assertEqual(exp_pdu.pduData, received_data)
def test_whoHas(self): request_object = WhoHasObject() request_object.objectIdentifier = ('binaryInput', 12) request = WhoHasRequest(object=request_object) apdu = APDU() request.encode(apdu) pdu = PDU() apdu.encode(pdu) buf_size = 1024 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.sendto(pdu.pduData, ('127.0.0.1', self.bacnet_server.server.server_port)) data = s.recvfrom(buf_size) received_data = data[0] expected = IHaveRequest() expected.pduDestination = GlobalBroadcast() expected.deviceIdentifier = 36113 expected.objectIdentifier = 12 expected.objectName = 'BI 01' exp_apdu = APDU() expected.encode(exp_apdu) exp_pdu = PDU() exp_apdu.encode(exp_pdu) self.assertEquals(exp_pdu.pduData, received_data)
def test_whoHas(self): request_object = WhoHasObject() request_object.objectIdentifier = ("binaryInput", 12) request = WhoHasRequest(object=request_object) apdu = APDU() request.encode(apdu) pdu = PDU() apdu.encode(pdu) buf_size = 1024 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.sendto(pdu.pduData, self.address) data = s.recvfrom(buf_size) s.close() received_data = data[0] expected = IHaveRequest() expected.pduDestination = GlobalBroadcast() expected.deviceIdentifier = 36113 expected.objectIdentifier = 12 expected.objectName = "BI 01" exp_apdu = APDU() expected.encode(exp_apdu) exp_pdu = PDU() exp_apdu.encode(exp_pdu) self.assertEqual(exp_pdu.pduData, received_data)
def handle(self, data, address): session = conpot_core.get_session('bacnet', address[0], address[1], get_interface_ip(address[0]), self.server.server_port) logger.info('New Bacnet connection from %s:%d. (%s)', address[0], address[1], session.id) session.add_event({'type': 'NEW_CONNECTION'}) # I'm not sure if gevent DatagramServer handles issues where the # received data is over the MTU -> fragmentation if data: pdu = PDU() pdu.pduData = bytearray(data) apdu = APDU() try: apdu.decode(pdu) except DecodingError: logger.warning("DecodingError - PDU: {}".format(pdu)) return self.bacnet_app.indication(apdu, address, self.thisDevice) # send an appropriate response from BACnet app to the attacker self.bacnet_app.response(self.bacnet_app._response, address) logger.info('Bacnet client disconnected %s:%d. (%s)', address[0], address[1], session.id)
def handle(self, data, address): session = conpot_core.get_session('bacnet', address[0], address[1]) logger.info('New Bacnet connection from %s:%d. (%s)', address[0], address[1], session.id) session.add_event({'type': 'NEW_CONNECTION'}) # I'm not sure if gevent DatagramServer handles issues where the # received data is over the MTU -> fragmentation if data: pdu = PDU() pdu.pduData = data apdu = APDU() try: apdu.decode(pdu) except DecodingError as e: logger.error("DecodingError: %s", e) logger.error("PDU: " + format(pdu)) return self.bacnet_app.indication(apdu, address, self.thisDevice) self.bacnet_app.response(self.bacnet_app._response, address) logger.info('Bacnet client disconnected %s:%d. (%s)', address[0], address[1], session.id)
def response(self, response_apdu, address): if response_apdu is None: return apdu = APDU() response_apdu.encode(apdu) pdu = PDU() apdu.encode(pdu) if isinstance(response_apdu, RejectPDU) or isinstance(response_apdu, ErrorPDU): self.datagram_server.sendto(pdu.pduData, address) else: apdu_type = apdu_types.get(response_apdu.apduType) if pdu.pduDestination == '*:*': # broadcast # sendto operates under lock self.datagram_server.sendto(pdu.pduData, ('', address[1])) else: # sendto operates under lock self.datagram_server.sendto(pdu.pduData, address) logger.info('Bacnet response sent to %s (%s:%s)', response_apdu.pduDestination, apdu_type.__name__, self._response_service)
def response(self, response_apdu, address): if response_apdu is None: return apdu = APDU() response_apdu.encode(apdu) pdu = PDU() apdu.encode(pdu) if isinstance(response_apdu, RejectPDU) or isinstance(response_apdu, ErrorPDU): self.sock.sendto(pdu.pduData, address) else: apdu_type = apdu_types.get(response_apdu.apduType) if pdu.pduDestination == '*:*': # broadcast self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) self.sock.sendto(pdu.pduData, ('', address[1])) else: # unicast self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 0) self.sock.sendto(pdu.pduData, address) logger.info('Bacnet response sent to %s (%s:%s)', response_apdu.pduDestination, apdu_type.__name__, self._response_service)
def test_readProperty(self): request = ReadPropertyRequest(objectIdentifier=('analogInput', 14), propertyIdentifier=85) request.apduMaxResp = 1024 request.apduInvokeID = 101 apdu = APDU() request.encode(apdu) pdu = PDU() apdu.encode(pdu) buf_size = 1024 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.sendto(pdu.pduData, ('127.0.0.1', self.bacnet_server.server.server_port)) data = s.recvfrom(buf_size) received_data = data[0] expected = ReadPropertyACK() expected.pduDestination = GlobalBroadcast() expected.apduInvokeID = 101 expected.objectIdentifier = 14 expected.objectName = 'AI 01' expected.propertyIdentifier = 85 expected.propertyValue = Any(Real(68.0)) exp_apdu = APDU() expected.encode(exp_apdu) exp_pdu = PDU() exp_apdu.encode(exp_pdu) self.assertEquals(exp_pdu.pduData, received_data)
def confirmation(self, pdu): if _debug: SnifferStateMachine._debug("confirmation(%s) %r", self.name, pdu) # it's an NPDU npdu = NPDU() npdu.decode(pdu) # filter out network layer traffic if there is any, probably not if npdu.npduNetMessage is not None: if _debug: SnifferStateMachine._debug(" - network message: %r", npdu.npduNetMessage) return # decode as a generic APDU apdu = APDU() apdu.decode(npdu) # "lift" the source and destination address if npdu.npduSADR: apdu.pduSource = npdu.npduSADR else: apdu.pduSource = npdu.pduSource if npdu.npduDADR: apdu.pduDestination = npdu.npduDADR else: apdu.pduDestination = npdu.pduDestination # make a more focused interpretation atype = apdu_types.get(apdu.apduType) if _debug: SnifferStateMachine._debug(" - atype: %r", atype) xpdu = apdu apdu = atype() apdu.decode(xpdu) if _debug: SnifferStateMachine._debug(" - apdu: %r", apdu) # pass to the state machine self.receive(apdu)
def test_whoIs(self): request = WhoIsRequest(deviceInstanceRangeLowLimit=500, deviceInstanceRangeHighLimit=50000) apdu = APDU() request.encode(apdu) pdu = PDU() apdu.encode(pdu) buf_size = 1024 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.sendto(pdu.pduData, ('127.0.0.1', self.bacnet_server.server.server_port)) data = s.recvfrom(buf_size) received_data = data[0] expected = IAmRequest() expected.pduDestination = GlobalBroadcast() expected.iAmDeviceIdentifier = 36113 expected.maxAPDULengthAccepted = 1024 expected.segmentationSupported = 'segmentedBoth' expected.vendorID = 15 exp_apdu = APDU() expected.encode(exp_apdu) exp_pdu = PDU() exp_apdu.encode(exp_pdu) self.assertEquals(exp_pdu.pduData, received_data)
from bacpypes.apdu import WhoIsRequest, WhoHasObject, WhoHasRequest # code for generating adpu - who-is # request = WhoIsRequest(deviceInstanceRangeLowLimit=500, deviceInstanceRangeHighLimit=50000) # test_pdu = PDU() # test_apdu = APDU() # request.encode(test_apdu) # test_apdu.encode(test_pdu) # bacnet_app = BACnetApp(test.thisDevice, test) # bacnet_app.get_objects_and_properties(test.dom) # bacnet_app.indication(test_apdu, ('127.0.0.1', 9999), test.thisDevice) # print(bacnet_app._response) # bacnet_app.response(bacnet_app._response, ('127.0.0.1', 9999)) # # logger.debug('Starting BACnet Server! at {}:{}'.format('localhost', 9999)) # # test.start('127.0.0.1', 9999) # testing who-has request_object = WhoHasObject() request_object.objectIdentifier = ('binaryInput', 12) request = WhoHasRequest(object=request_object) test_apdu = APDU() request.encode(test_apdu) test_pdu = PDU() test_apdu.encode(test_pdu) bacnet_app = BACnetApp(test.thisDevice, test) bacnet_app.get_objects_and_properties(test.dom) bacnet_app.indication(test_apdu, ('127.0.0.1', 9999), test.thisDevice) print(bacnet_app._response) bacnet_app.response(bacnet_app._response, ('127.0.0.1', 9999)) except KeyboardInterrupt: logger.debug('Stopping BACnet server') test.stop()
npdu = NPDU() npdu.decode(pdu) if _debug: decode_packet._debug(" - npdu: %r", npdu) except Exception, err: if _debug: decode_packet._debug(" - decoding Error: %r", err) return None # application or network layer message if npdu.npduNetMessage is None: if _debug: decode_packet._debug( " - not a network layer message, try as an APDU") # decode as a generic APDU try: xpdu = APDU() xpdu.decode(npdu) if _debug: decode_packet._debug(" - xpdu: %r", xpdu) apdu = xpdu except Exception, err: if _debug: decode_packet._debug(" - decoding Error: %r", err) return npdu # "lift" the source and destination address if npdu.npduSADR: apdu.pduSource = npdu.npduSADR else: apdu.pduSource = npdu.pduSource if npdu.npduDADR: apdu.pduDestination = npdu.npduDADR else:
def decode_packet(data, destination): """decode the data, return some kind of PDU.""" if _debug: decode_packet._debug("decode_packet %r %r", data, destination) # build a PDU pdu = PDU(data, destination=destination) # check for a BVLL header if pdu.pduData[0] == 0x84: if _debug: decode_packet._debug(" - BVLL header found") xpdu = BVLPDU() xpdu.decode(pdu) pdu = xpdu # make a more focused interpretation atype = bvl_pdu_types.get(pdu.bvlciFunction) if not atype: if _debug: decode_packet._debug(" - unknown BVLL type: %r", pdu.bvlciFunction) return pdu # decode it as one of the basic types try: xpdu = pdu bpdu = atype() bpdu.decode(pdu) if _debug: decode_packet._debug(" - bpdu: %r", bpdu) pdu = bpdu # source address in the packet pdu.pduSource = pdu.bvlciAddress # no deeper decoding for some if atype not in (OriginalUnicastNPDU, OriginalBroadcastNPDU): return pdu except Exception as err: if _debug: decode_packet._debug(" - decoding Error: %r", err) return xpdu # check for version number if pdu.pduData[0] != 0x01: if _debug: decode_packet._debug( " - not a version 1 packet: %s...", btox(pdu.pduData[:30], ".") ) return None # it's an NPDU try: npdu = NPDU() npdu.decode(pdu) except Exception as err: if _debug: decode_packet._debug(" - decoding Error: %r", err) return None # application or network layer message if npdu.npduNetMessage is None: if _debug: decode_packet._debug(" - not a network layer message, try as an APDU") # decode as a generic APDU try: xpdu = APDU() xpdu.decode(npdu) apdu = xpdu except Exception as err: if _debug: decode_packet._debug(" - decoding Error: %r", err) return npdu # "lift" the source and destination address if npdu.npduSADR: apdu.pduSource = npdu.npduSADR else: apdu.pduSource = npdu.pduSource if npdu.npduDADR: apdu.pduDestination = npdu.npduDADR else: apdu.pduDestination = npdu.pduDestination # make a more focused interpretation atype = apdu_types.get(apdu.apduType) if not atype: if _debug: decode_packet._debug(" - unknown APDU type: %r", apdu.apduType) return apdu # decode it as one of the basic types try: xpdu = apdu apdu = atype() apdu.decode(xpdu) except Exception as err: if _debug: decode_packet._debug(" - decoding Error: %r", err) return xpdu # decode it at the next level if isinstance(apdu, ConfirmedRequestPDU): atype = confirmed_request_types.get(apdu.apduService) if not atype: if _debug: decode_packet._debug( " - no confirmed request decoder: %r", apdu.apduService ) return apdu elif isinstance(apdu, UnconfirmedRequestPDU): atype = unconfirmed_request_types.get(apdu.apduService) if not atype: if _debug: decode_packet._debug( " - no unconfirmed request decoder: %r", apdu.apduService ) return apdu elif isinstance(apdu, SimpleAckPDU): atype = None elif isinstance(apdu, ComplexAckPDU): atype = complex_ack_types.get(apdu.apduService) if not atype: if _debug: decode_packet._debug( " - no complex ack decoder: %r", apdu.apduService ) return apdu elif isinstance(apdu, SegmentAckPDU): atype = None elif isinstance(apdu, ErrorPDU): atype = error_types.get(apdu.apduService) if not atype: if _debug: decode_packet._debug(" - no error decoder: %r", apdu.apduService) return apdu elif isinstance(apdu, RejectPDU): atype = None elif isinstance(apdu, AbortPDU): atype = None if _debug: decode_packet._debug(" - atype: %r", atype) # deeper decoding try: if atype: xpdu = apdu apdu = atype() apdu.decode(xpdu) except Exception as err: if _debug: decode_packet._debug(" - decoding error: %r", err) return xpdu # success return apdu else: # make a more focused interpretation ntype = npdu_types.get(npdu.npduNetMessage) if not ntype: if _debug: decode_packet._debug( " - no network layer decoder: %r", npdu.npduNetMessage ) return npdu if _debug: decode_packet._debug(" - ntype: %r", ntype) # deeper decoding try: xpdu = npdu npdu = ntype() npdu.decode(xpdu) except Exception as err: if _debug: decode_packet._debug(" - decoding error: %r", err) return xpdu # success return npdu
test_server = ServerStateMachine() # bind everything together bind(test_application, test_asap, test_smap, test_server) # ============================================================================== who_is_request = WhoIsRequest( deviceInstanceRangeLowLimit=0, deviceInstanceRangeHighLimit=4194303, ) print("who_is_request") who_is_request.debug_contents() print("") test_apdu = APDU() who_is_request.encode(test_apdu) print("test_apdu") test_apdu.debug_contents() print("") print("modify test_apdu") test_apdu.pduData = test_apdu.pduData[:-1] # test_apdu.pduData = xtob('7509006869207468657265') # CharacterString("hi there") test_apdu.debug_contents() print("") # make a send transition from start to success test_server.start_state.send(test_apdu).success()
def confirmation(self, pdu): if _debug: SnifferNode._debug("confirmation(%s) %r", self.name, pdu) # it's an NPDU npdu = NPDU() npdu.decode(pdu) # decode as a generic APDU apdu = APDU() apdu.decode(npdu) # "lift" the source and destination address if npdu.npduSADR: apdu.pduSource = npdu.npduSADR else: apdu.pduSource = npdu.pduSource if npdu.npduDADR: apdu.pduDestination = npdu.npduDADR else: apdu.pduDestination = npdu.pduDestination # make a more focused interpretation atype = apdu_types.get(apdu.apduType) if _debug: SnifferNode._debug(" - atype: %r", atype) xpdu = apdu apdu = atype() apdu.decode(xpdu) print(repr(apdu)) apdu.debug_contents() print("")