29
29
from kasa .protocol import DEFAULT_CREDENTIALS , get_default_credentials
30
30
31
31
32
+ def _get_seq_from_query (packet ):
33
+ """Return sequence number for the query."""
34
+ query = packet .http .get ("request_uri_query" )
35
+ if query is None :
8000
36
+ raise Exception ("No request_uri_query found" )
37
+ # use regex to get: seq=(\d+)
38
+ seq = re .search (r"seq=(\d+)" , query )
39
+ if seq is not None :
40
+ return int (seq .group (1 ))
41
+ raise Exception ("Unable to find sequence number" )
42
+
43
+
32
44
def _is_http_response_for_packet (response , packet ):
33
45
"""Return True if the *response* contains a response for request in *packet*.
34
46
@@ -41,10 +53,7 @@ def _is_http_response_for_packet(response, packet):
41
53
):
42
54
return True
43
55
# tshark 4.4.0
44
- if response .http .request_uri == packet .http .request_uri :
45
- return True
46
-
47
- return False
56
+ return response .http .request_uri == packet .http .request_uri
48
57
49
58
50
59
class MyEncryptionSession (KlapEncryptionSession ):
@@ -244,71 +253,59 @@ def main(
244
253
if packet .ip .src != source_host :
245
254
continue
246
255
# we only care about http packets
247
- if hasattr (
248
- packet , "http"
249
- ): # this is redundant, as pyshark is set to only load http packets
250
- if hasattr (packet .http , "request_uri_path" ):
251
- uri = packet .http .get ("request_uri_path" )
252
- elif hasattr (packet .http , "request_uri" ):
253
- uri = packet .http .get ("request_uri" )
254
- else :
255
- uri = None
256
- if hasattr (packet .http , "request_uri_query" ):
257
- query = packet .http .get ("request_uri_query" )
258
- # use regex to get: seq=(\d+)
259
- seq = re .search (r"seq=(\d+)" , query )
260
- if seq is not None :
261
- operator .seq = int (
262
- seq .group (1 )
263
- ) # grab the sequence number from the query
264
- data = (
265
- # Windows and linux file_data attribute returns different
266
- # pretty format so get the raw field value.
267
- packet .http .get_field_value ("file_data" , raw = True )
268
- if hasattr (packet .http , "file_data" )
269
- else None
270
- )
271
- match uri :
272
- case "/app/request" :
273
- if packet .ip .dst != device_ip :
274
- continue
275
- assert isinstance (data , str ) # noqa: S101
276
- message = bytes .fromhex (data )
277
- try :
278
- plaintext = operator .decrypt (message )
279
- payload = json .loads (plaintext )
280
- print (json .dumps (payload , indent = 2 ))
281
- packets .append (payload )
282
- except ValueError :
283
- print ("Insufficient data to decrypt thus far" )
284
-
285
<
8000
span class="diff-text-marker">- case "/app/handshake1" :
286
- if packet .ip .dst != device_ip :
287
- continue
288
- assert isinstance (data , str ) # noqa: S101
289
- message = bytes .fromhex (data )
290
- operator .local_seed = message
291
- response = None
292
- print (
293
- f"got handshake1 in { packet_number } , "
294
- f"looking for the response"
295
- )
296
- while (
297
- True
298
- ): # we are going to now look for the response to this request
299
- response = capture .next ()
300
- if _is_http_response_for_packet (response , packet ):
301
- print (f"found response in { packet_number } " )
302
- break
303
- data = response .http .get_field_value ("file_data" , raw = True )
304
- message = bytes .fromhex (data )
305
- operator .remote_seed = message [0 :16 ]
306
- operator .remote_auth_hash = message [16 :]
307
-
308
- case "/app/handshake2" :
309
- continue # we don't care about this
310
- case _:
256
+ # this is redundant, as pyshark is set to only load http packets
257
+ if not hasattr (packet , "http" ):
258
+ continue
259
+
260
+ uri = packet .http .get ("request_uri_path" , packet .http .get ("request_uri" ))
261
+ if uri is None :
262
+ continue
263
+
264
+ operator .seq = _get_seq_from_query (packet )
265
+
266
+ # Windows and linux file_data attribute returns different
267
+ # pretty format so get the raw field value.
268
+ data = packet .http .get_field_value ("file_data" , raw = True )
269
+ <
A3DB
div class="diff-text-inner">
270
+ match uri :
271
+ case "/app/request" :
272
+ if packet .ip .dst != device_ip :
273
+ continue
274
+ message = bytes .fromhex (data )
275
+ try :
276
+ plaintext = operator .decrypt (message )
277
+ payload = json .loads (plaintext )
278
+ print (json .dumps (payload , indent = 2 ))
279
+ packets .append (payload )
280
+ except ValueError :
281
+ print ("Insufficient data to decrypt thus far" )
282
+
283
+ case "/app/handshake1" :
284
+ if packet .ip .dst != device_ip :
311
285
continue
286
+ message = bytes .fromhex (data )
287
+ operator .local_seed = message
288
+ response = None
289
+ print (
290
+ f"got handshake1 in { packet_number } , "
291
+ f"looking for the response"
292
+ )
293
+ while (
294
+ True
295
+ ): # we are going to now look for the response to this request
296
+ response = capture .next ()
297
+ if _is_http_response_for_packet (response , packet ):
298
+ print (f"found response in { packet_number } " )
299
+ break
300
+ data = response .http .get_field_value ("file_data" , raw = True )
301
+ message = bytes .fromhex (data )
302
+ operator .remote_seed = message [0 :16 ]
303
+ operator .remote_auth_hash = message [16 :]
304
+
305
+ case "/app/handshake2" :
306
+ continue # we don't care about this
307
+ case _:
308
+ continue
312
309
except StopIteration :
313
310
break
314
311
0 commit comments