Module: Msf::Post::Hardware::Zigbee::Utils

Defined in:
lib/msf/core/post/hardware/zigbee/utils.rb

Constant Summary collapse

DOT154_FCF_TYPE_MASK =

Constants for packet decoding fields Frame Control Field

0x0007
DOT154_FCF_SEC_EN =

: Frame type mask

0x0008
DOT154_FCF_FRAME_PND =

: Set for encrypted payload

0x0010
DOT154_FCF_ACK_REQ =

: Frame pending

0x0020
DOT154_FCF_INTRA_PAN =

: ACK request

0x0040
DOT154_FCF_DADDR_MASK =

: Intra-PAN activity

0x0C00
DOT154_FCF_VERSION_MASK =

: Destination addressing mode mask

0x3000
DOT154_FCF_SADDR_MASK =

: Frame version

0xC000
DOT154_FCF_TYPE_MASK_SHIFT =

Frame Control Field Bit Shifts

0
DOT154_FCF_DADDR_MASK_SHIFT =

: Frame type mask mode shift

10
DOT154_FCF_VERSION_MASK_SHIFT =

: Destination addressing mode mask

12
DOT154_FCF_SADDR_MASK_SHIFT =

: Frame versions mask mode shift

14
DOT154_FCF_ADDR_NONE =

Address Mode Definitions

0x0000
DOT154_FCF_ADDR_SHORT =

: Not sure when this is used

0x0002
DOT154_FCF_ADDR_EXT =

: 4-byte addressing

0x0003
DOT154_FCF_TYPE_BEACON =

: 8-byte addressing

0
DOT154_FCF_TYPE_DATA =

: Beacon frame

1
DOT154_FCF_TYPE_ACK =

: Data frame

2
DOT154_FCF_TYPE_MACCMD =

: Acknowledgement frame

3
DOT154_CRYPT_NONE =

: MAC Command frame

0x00
DOT154_CRYPT_MIC32 =

: No encryption, no MIC

0x01
DOT154_CRYPT_MIC64 =

: No encryption, 32-bit MIC

0x02
DOT154_CRYPT_MIC128 =

: No encryption, 64-bit MIC

0x03
DOT154_CRYPT_ENC =

: No encryption, 128-bit MIC

0x04
DOT154_CRYPT_ENC_MIC32 =

: Encryption, no MIC

0x05
DOT154_CRYPT_ENC_MIC64 =

: Encryption, 32-bit MIC

0x06
DOT154_CRYPT_ENC_MIC128 =

: Encryption, 64-bit MIC

0x07

Instance Method Summary collapse

Instance Method Details

#dot154_packet_decode(packet) ⇒ Hash

Breaks up the packet into different sections. Also provides Some decoding information. This method relates to Killerbee's Pktchop method and Returns a similar array structure PktChop. If it's a beacon data you will also have A BEACONDATA array of raw beacon related packets. You can pull other decoded portions from the returned hash such as

FSF
SEQ
SPAN_ID
SOURCE
SUPERFRAME
GTS
PENDING_ADDRESS_COUNT
PROTOCOL_ID
STACK_PROFILE
CAPABILITY
EXT_PAN_ID
TX_OFFSET
UPDATE_ID

Parameters:

  • packet (String)

    Raw data from recv

Returns:

  • (Hash)

    { PktChop => [Array of data], ..


145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
# File 'lib/msf/core/post/hardware/zigbee/utils.rb', line 145

def dot154_packet_decode(packet)
  result = {}
  offset = 0
  pktchop = ['', '', '', '', '', '', [], '']
  pktchop[0] = packet[0,2]
  # Sequence number
  pktchop[1] = packet[2]
  # Byte swap
  fcf = pktchop[0].reverse.unpack("H*")[0].hex
  result["FSF"] = fcf
  result["SEQ"] = pktchop[1]
  # Check if we are dealing with a beacon frame
  if (fcf & DOT154_FCF_TYPE_MASK) == DOT154_FCF_TYPE_BEACON
    beacondata = ["", "", "", "", "", "", "", "", "", ""]
    # 802.15.4 fields, SPAN and SA
    pktchop[4] = packet[3,2]
    pktchop[5] = packet[5,2]
    result["SPAN_ID"] = pktchop[4].reverse.unpack("H*")[0]
    result["SOURCE"] = pktchop[5].reverse.unpack("H*")[0]
    offset = 7

    # Superframe specification
    beacondata[0] = packet[offset,2]
    result["SUPERFRAME"] = beacondata[0]
    offset+=2

    # GTS data
    beacondata[1] = packet[offset]
    result["GTS"] = beacondata[1]
    offset+=1

    # Pending address count
    beacondata[2] = packet[offset]
    result["PENDING_ADDRESS_COUNT"] = beacondata[2]
    offset+=1

    # Protocol ID
    beacondata[3] = packet[offset]
    result["PROTOCOL_ID"] = beacondata[3]
    offset+=1

    # Stack Profile version
    beacondata[4] = packet[offset]
    result["STACK_PROFILE"] = beacondata[4]
    offset+=1

    # Capability information
    beacondata[5] = packet[offset]
    result["CAPABILITY"] = beacondata[5]
    offset+=1

    # Extended PAN ID
    beacondata[6] = packet[offset,8]
    result["EXT_PAN_ID"] = beacondata[6].reverse.unpack("H*")[0]
    offset+=8

    # TX Offset
    beacondata[7] = packet[offset,3]
    result["TX_OFFSET"] = beacondata[7]
    offset+=3

    # Update ID
    beacondata[8] = packet[offset]
    result["UPDATE_ID"] = beacondata[8]
    offset+=1
    pktchop[6] = beacondata
    result["BEACONDATA"] = beacondata
  else
    # Not a beacon frame

    # DPAN
    pktchop[2] = packet[3,2]
    offset = 5

    # Examine the destination addressing mode
    daddr_mask = (fcf & DOT154_FCF_DADDR_MASK) >> 10
    if daddr_mask == DOT154_FCF_ADDR_EXT
      pktchop[3] = packet[offset,8]
      offset += 8
    elsif daddr_mask == DOT154_FCF_ADDR_SHORT
      pktchop[3] = packet[offset,2]
      offset += 2
    end

    # Examine the Intra-PAN flag
    if (fcf & DOT154_FCF_INTRA_PAN) == 0
      pktchop[4] = packet[offset,2]
      offset += 2
    end

    # Examine the source addressing mode
    saddr_mask = (fcf & DOT154_FCF_SADDR_MASK) >> 14
    if daddr_mask == DOT154_FCF_ADDR_EXT
      pktchop[5] = packet[offset,8]
      offset += 8
    elsif daddr_mask == DOT154_FCF_ADDR_SHORT
      pktchop[5] = packet[offset,2]
      offset += 2
    end
  end
  # Append remaining payload
  pktchop[7] = packet[offset,packet.size] if offset < packet.size
  result["PktChop"] = pktchop
  return result
end

#get_target_deviceString

Retrieves the target Zigbee device. This is typically set by the user via the interactive HWBridge command line

Returns:

  • (String)

    Zigbee device ID


64
65
66
67
# File 'lib/msf/core/post/hardware/zigbee/utils.rb', line 64

def get_target_device
  return unless is_zigbee_hwbridge_session?
  return client.zigbee.get_target_device
end

#inject(device, data) ⇒ Object

Inject raw packets. Need firmware on the zigbee device that supports transmission.

Parameters:

  • device (String)

    Zigbee device ID

  • data (String)

    Raw binary data sent as a string


90
91
92
93
94
95
# File 'lib/msf/core/post/hardware/zigbee/utils.rb', line 90

def inject(device, data)
  return {} unless is_zigbee_hwbridge_session?
  device = client.zigbee.target_device unless device
  return {} unless verify_device(device)
  client.zigbee.inject(device, data)
end

#is_zigbee_hwbridge_session?Boolean

Infer if the current session is for a ZigBee device.

Returns:

  • (Boolean)

    true if session is for a ZigBee device, false otherwise


47
48
49
50
51
# File 'lib/msf/core/post/hardware/zigbee/utils.rb', line 47

def is_zigbee_hwbridge_session?
  return true if client.zigbee
  print_error("Not a ZigBee hwbridge session")
  false
end

#recv(device) ⇒ String

Recieves data from the Zigbee device

Parameters:

  • device (String)

    Zigbee device ID

Returns:

  • (String)

    Binary blob of returned data


100
101
102
103
104
105
# File 'lib/msf/core/post/hardware/zigbee/utils.rb', line 100

def recv(device)
  return {} unless is_zigbee_hwbridge_session?
  device = client.zigbee.target_device unless device
  return {} unless verify_device(device)
  client.zigbee.recv(device)
end

#set_channel(device, channel) ⇒ Object

Sets the Zigbee Channel

Parameters:

  • device (String)

    Zigbee device ID

  • channel (Integer)

    Channel number, typically 11-25


80
81
82
83
84
85
# File 'lib/msf/core/post/hardware/zigbee/utils.rb', line 80

def set_channel(device, channel)
  return {} unless is_zigbee_hwbridge_session?
  device = client.zigbee.target_device unless device
  return {} unless verify_device(device)
  client.zigbee.set_channel(device, channel)
end

#set_target_device(device) ⇒ Object

Sets the target default Zigbee Device. This command typically isn't called via a script Instead the user is expected to set this via the interactive HWBridge commandline

Parameters:

  • device (String)

    Zigbee device ID


72
73
74
75
# File 'lib/msf/core/post/hardware/zigbee/utils.rb', line 72

def set_target_device(device)
  return unless is_zigbee_hwbridge_session?
  client.zigbee.set_target_device device
end

#sniffer_off(device) ⇒ Object

Turn off Zigbee receiving

Parameters:

  • device (String)

    Zigbee device ID


109
110
111
112
113
114
# File 'lib/msf/core/post/hardware/zigbee/utils.rb', line 109

def sniffer_off(device)
  return {} unless is_zigbee_hwbridge_session?
  device = client.zigbee.target_device unless device
  return {} unless verify_device(device)
  client.zigbee.sniffer_off(device)
end

#sniffer_on(device) ⇒ Object

Turn on Zigbee receiving

Parameters:

  • device (String)

    Zigbee device ID


118
119
120
121
122
123
# File 'lib/msf/core/post/hardware/zigbee/utils.rb', line 118

def sniffer_on(device)
  return {} unless is_zigbee_hwbridge_session?
  device = client.zigbee.target_device unless device
  return {} unless verify_device(device)
  client.zigbee.sniffer_on(device)
end

#verify_device(device) ⇒ Boolean

Verify if a device has been specified.

Returns:

  • (Boolean)

    true if device is specified, false otherwise


55
56
57
58
59
# File 'lib/msf/core/post/hardware/zigbee/utils.rb', line 55

def verify_device(device)
  return true if device
  print_line("No target device set, use 'target' or specify bus via the options.")
  false
end