each getData()
function seems to be calling pack()
. Example of NDRSTRUCT
class NDRSTRUCT(NDRCONSTRUCTEDTYPE):
def getData(self, soFar = 0):
data = b''
arrayPadding = b''
soFar0 = soFar
# 14.3.7.1 Structures Containing a Conformant Array
# A structure can contain a conformant array only as its last member.
# In the NDR representation of a structure that contains a conformant array,
# the unsigned long integers that give maximum element counts for dimensions of the array
# are moved to the beginning of the structure, and the array elements appear in place at
# the end of the structure.
# 14.3.7.2 Structures Containing a Conformant and Varying Array
# A structure can contain a conformant and varying array only as its last member.
# In the NDR representation of a structure that contains a conformant and varying array,
# the maximum counts for dimensions of the array are moved to the beginning of the structure,
# but the offsets and actual counts remain in place at the end of the structure,
# immediately preceding the array elements
lastItem = (self.commonHdr+self.structure)[-1][0]
if isinstance(self.fields[lastItem], NDRUniConformantArray) or isinstance(self.fields[lastItem], NDRUniConformantVaryingArray):
# So we have an array, first item in the structure must be the array size, although we
# will need to build it later.
if self._isNDR64:
arrayItemSize = 8
arrayPackStr = '<Q'
else:
arrayItemSize = 4
arrayPackStr = '<L'
# The size information is itself aligned according to the alignment rules for
# primitive data types. (See Section 14.2.2 on page 620.) The data of the constructed
# type is then aligned according to the alignment rules for the constructed type.
# In other words, the size information precedes the structure and is aligned
# independently of the structure alignment.
# We need to check whether we need padding or not
pad0 = (arrayItemSize - (soFar % arrayItemSize)) % arrayItemSize
if pad0 > 0:
soFar += pad0
arrayPadding = b'\\xee'*pad0
else:
arrayPadding = b''
# And now, let's pretend we put the item in
soFar += arrayItemSize
else:
arrayItemSize = 0
# Now we need to align the structure
# The alignment of a structure in the octet stream is the largest of the alignments of the fields it
# contains. These fields may also be constructed types. The same alignment rules apply
# recursively to nested constructed types.
alignment = self.getAlignment()
if alignment > 0:
pad = (alignment - (soFar % alignment)) % alignment
if pad > 0:
soFar += pad
data += b'\\xAB'*pad
for fieldName, fieldTypeOrClass in self.commonHdr+self.structure:
try:
if isinstance(self.fields[fieldName], NDRUniConformantArray) or isinstance(self.fields[fieldName], NDRUniConformantVaryingArray):
res = self.fields[fieldName].getData(soFar)
if isinstance(self, NDRPOINTER):
pointerData = data[:arrayItemSize]
data = data[arrayItemSize:]
data = pointerData + arrayPadding + pack(arrayPackStr ,self.getArrayMaximumSize(fieldName)) + data
else:
data = arrayPadding + pack(arrayPackStr, self.getArrayMaximumSize(fieldName)) + data
arrayPadding = b''
arrayItemSize = 0
else:
res = self.pack(fieldName, fieldTypeOrClass, soFar)
data += res
soFar = soFar0 + len(data) + len(arrayPadding) + arrayItemSize
if the base type for this class is NDR
,then the pack will point to Ndr.pack()
content of dcerpc\\v5\\ndr.py
def pack(self, fieldName, fieldTypeOrClass, soFar = 0):
if isinstance(self.fields[fieldName], NDR):
return self.fields[fieldName].getData(soFar)
## -
data = self.fields[fieldName]
# void specifier
if fieldTypeOrClass[:1] == '_':
return b''
## =
# code specifier
two = fieldTypeOrClass.split('=')
if len(two) >= 2:
try:
return self.pack(fieldName, two[0], soFar)
except:
self.fields[fieldName] = eval(two[1], {}, self.fields)
return self.pack(fieldName, two[0], soFar)
if data is None:
raise Exception('Trying to pack None')
## :
# literal specifier
if fieldTypeOrClass[:1] == ':':
if hasattr(data, 'getData'):
return data.getData()
return data
# struct like specifier
return pack(fieldTypeOrClass, data)
Noted the above specifier is what’s shown in the \\impacket\\[structure.py](<http://structure.py/>)