12
12
from __future__ import division
13
13
from __future__ import print_function
14
14
from struct import pack , unpack , calcsize
15
+
16
+ import six
15
17
from six import b , PY3
16
18
from binascii import hexlify
17
19
@@ -80,13 +82,19 @@ class is the class to use when unpacking ':' fields.
80
82
commonHdr = ()
81
83
structure = ()
82
84
debug = 0
85
+ # Encoding defaults to latin-1 which already was the de facto encoding for structures and works for most use cases.
86
+ # Now it can be configured to another encoding if needed.
87
+ ENCODING = 'latin-1' # https://github.com/fortra/impacket/pull/1958
83
88
84
89
def __init__ (self , data = None , alignment = 0 ):
85
90
if not hasattr (self , 'alignment' ):
86
91
self .alignment = alignment
87
92
88
93
self .fields = {}
89
94
self .rawData = data
95
+
96
+ self .b = lambda x : six .ensure_binary (x , encoding = self .ENCODING )
97
+
90
98
if data is not None :
91
99
self .fromString (data )
92
100
else :
@@ -197,7 +205,7 @@ def pack(self, format, data, field = None):
197
205
198
206
# quote specifier
199
207
if format [:1 ] == "'" or format [:1 ] == '"' :
200
- return b (format [1 :])
208
+ return self . b (format [1 :])
201
209
202
210
# code specifier
203
211
two = format .split ('=' )
@@ -245,26 +253,26 @@ def pack(self, format, data, field = None):
245
253
# "printf" string specifier
246
254
if format [:1 ] == '%' :
247
255
# format string like specifier
248
- return b (format % data )
256
+ return self . b (format % data )
249
257
250
258
# asciiz specifier
251
259
if format [:1 ] == 'z' :
252
260
if isinstance (data ,bytes ):
253
- return data + b ('\0 ' )
254
- return bytes (b (data )+ b ('\0 ' ))
261
+ return data + self . b ('\0 ' )
262
+ return bytes (self . b (data )+ self . b ('\0 ' ))
255
263
256
264
# unicode specifier
257
265
if format [:1 ] == 'u' :
258
- return bytes (data + b ('\0 \0 ' ) + (len (data ) & 1 and b ('\0 ' ) or b'' ))
266
+ return bytes (data + self . b ('\0 \0 ' ) + (len (data ) & 1 and self . b ('\0 ' ) or b'' ))
259
267
260
268
# DCE-RPC/NDR string specifier
261
269
if format [:1 ] == 'w' :
262
270
if len (data ) == 0 :
263
- data = b ('\0 \0 ' )
271
+ data = self . b ('\0 \0 ' )
264
272
elif len (data ) % 2 :
265
- data = b (data ) + b ('\0 ' )
273
+ data = self . b (data ) + self . b ('\0 ' )
266
274
l = pack ('<L' , len (data )// 2 )
267
- return b'' .join ([l , l , b ('\0 \0 \0 \0 ' ), data ])
275
+ return b'' .join ([l , l , self . b ('\0 \0 \0 \0 ' ), data ])
268
276
269
277
if data is None :
270
278
raise Exception ("Trying to pack None" )
@@ -279,7 +287,7 @@ def pack(self, format, data, field = None):
279
287
elif isinstance (data , int ):
280
288
return bytes (data )
281
289
elif isinstance (data , bytes ) is not True :
282
- return bytes (b (data ))
290
+ return bytes (self . b (data ))
283
291
else :
284
292
return data
285
293
@@ -288,7 +296,7 @@ def pack(self, format, data, field = None):
288
296
if isinstance (data , bytes ) or isinstance (data , bytearray ):
289
297
return pack (format , data )
290
298
else :
291
- return pack (format , b (data ))
299
+ return pack (format , self . b (data ))
292
300
293
301
# struct like specifier
294
302
return pack (format , data )
@@ -315,7 +323,7 @@ def unpack(self, format, data, dataClassOrCode = b, field = None):
315
323
# quote specifier
316
324
if format [:1 ] == "'" or format [:1 ] == '"' :
317
325
answer = format [1 :]
318
- if b (answer ) != data :
326
+ if self . b (answer ) != data :
319
327
raise Exception ("Unpacked data doesn't match constant value '%r' should be '%r'" % (data , answer ))
320
328
return answer
321
329
@@ -361,7 +369,7 @@ def unpack(self, format, data, dataClassOrCode = b, field = None):
361
369
362
370
# asciiz specifier
363
371
if format == 'z' :
364
- if data [- 1 :] != b ('\x00 ' ):
372
+ if data [- 1 :] != self . b ('\x00 ' ):
365
373
raise Exception ("%s 'z' field is not NUL terminated: %r" % (field , data ))
366
374
if PY3 :
367
375
return data [:- 1 ].decode ('latin-1' )
@@ -370,7 +378,7 @@ def unpack(self, format, data, dataClassOrCode = b, field = None):
370
378
371
379
# unicode specifier
372
380
if format == 'u' :
373
- if data [- 2 :] != b ('\x00 \x00 ' ):
381
+ if data [- 2 :] != self . b ('\x00 \x00 ' ):
374
382
raise Exception ("%s 'u' field is not NUL-NUL terminated: %r" % (field , data ))
375
383
return data [:- 2 ] # remove trailing NUL
376
384
@@ -524,11 +532,11 @@ def calcUnpackSize(self, format, data, field = None):
524
532
525
533
# asciiz specifier
526
534
if format [:1 ] == 'z' :
527
- return data .index (b ('\x00 ' ))+ 1
535
+ return data .index (self . b ('\x00 ' ))+ 1
528
536
529
537
# asciiz specifier
530
538
if format [:1 ] == 'u' :
531
- l = data .index (b ('\x00 \x00 ' ))
539
+ l = data .index (self . b ('\x00 \x00 ' ))
532
540
return l + (l & 1 and 3 or 2 )
533
541
534
542
# DCE-RPC/NDR string specifier
@@ -584,7 +592,7 @@ def zeroValue(self, format):
584
592
if format in ['z' ,':' ,'u' ]:
585
593
return b''
586
594
if format == 'w' :
587
- return b ('\x00 \x00 ' )
595
+ return self . b ('\x00 \x00 ' )
588
596
589
597
return 0
590
598
0 commit comments