def parseApplePartitionMap(bytesData):

    # Based on description at:
    # https://en.wikipedia.org/wiki/Apple_Partition_Map#Layout
    # and code at:
    # https://opensource.apple.com/source/IOStorageFamily/IOStorageFamily-116/IOApplePartitionScheme.h
    # Variable naming mostly follows Apple's code. 

    # Set up elemement object to store extracted properties
    properties = ET.Element("applePartitionMap")
             
    addProperty(properties, "signature", bc.bytesToText(bytesData[0:2]))
    addProperty(properties, "numberOfPartitionEntries", bc.bytesToUInt(bytesData[4:8]))
    addProperty(properties, "partitionBlockStart", bc.bytesToUInt(bytesData[8:12]))
    addProperty(properties, "partitionBlockCount", bc.bytesToUInt(bytesData[12:16]))
    addProperty(properties, "partitionName", bc.bytesToText(bytesData[16:48]))
    addProperty(properties, "partitionType", bc.bytesToText(bytesData[48:80]))
    addProperty(properties, "partitionLogicalBlockStart", bc.bytesToUInt(bytesData[80:84]))
    addProperty(properties, "partitionLogicalBlockCount", bc.bytesToUInt(bytesData[84:88]))
    addProperty(properties, "partitionFlags", bc.bytesToUInt(bytesData[88:92]))
    addProperty(properties, "bootCodeBlockStart", bc.bytesToUInt(bytesData[92:96]))
    addProperty(properties, "bootCodeSizeInBytes", bc.bytesToUInt(bytesData[96:100]))
    addProperty(properties, "bootCodeLoadAddress", bc.bytesToUInt(bytesData[100:104]))
    addProperty(properties, "bootCodeJumpAddress", bc.bytesToUInt(bytesData[108:112]))
    addProperty(properties, "bootCodeChecksum", bc.bytesToUInt(bytesData[116:120]))
    addProperty(properties, "processorType", bc.bytesToText(bytesData[120:136]))
    return(properties)
def parsePrimaryVolumeDescriptor(bytesData):

    # Set up elemement object to store extracted properties
    properties = ET.Element("primaryVolumeDescriptor")
           
    addProperty(properties, "typeCode", bc.bytesToUnsignedChar(bytesData[0:1]))
    addProperty(properties, "standardIdentifier", bc.bytesToText(bytesData[1:6]))
    addProperty(properties, "version", bc.bytesToUnsignedChar(bytesData[6:7]))
    addProperty(properties, "systemIdentifier", bc.bytesToText(bytesData[8:40]))
    addProperty(properties, "volumeIdentifier", bc.bytesToText(bytesData[40:72]))

    # Fields below are stored as both little-endian and big-endian; only
    # big-endian values read here!
    
    # Number of Logical Blocks in which the volume is recorded
    addProperty(properties, "volumeSpaceSize", bc.bytesToUInt(bytesData[84:88]))
    # The size of the set in this logical volume (number of disks)
    addProperty(properties, "volumeSetSize", bc.bytesToUShortInt(bytesData[122:124]))
    # The number of this disk in the Volume Set
    addProperty(properties, "volumeSequenceNumber", bc.bytesToUShortInt(bytesData[126:128]))
    # The size in bytes of a logical block
    addProperty(properties, "logicalBlockSize", bc.bytesToUShortInt(bytesData[130:132]))
    # The size in bytes of the path table
    addProperty(properties, "pathTableSize", bc.bytesToUInt(bytesData[136:140]))
	# Location of Type-L Path Table (note this is stored as little-endian only, hence
	# byte swap!)
    addProperty(properties, "typeLPathTableLocation", bc.swap32(bc.bytesToUInt(bytesData[140:144])))
    # Location of Optional Type-L Path Table
    addProperty(properties, "optionalTypeLPathTableLocation", bc.swap32(bc.bytesToUInt(bytesData[144:148])))
    # Location of Type-M Path Table
    addProperty(properties, "typeMPathTableLocation", bc.bytesToUInt(bytesData[148:152]))
    # Location of Optional Type-M Path Table
    addProperty(properties, "optionalTypeMPathTableLocation", bc.bytesToUInt(bytesData[152:156]))

    # Following fields are all text strings
    addProperty(properties, "volumeSetIdentifier", bc.bytesToText(bytesData[190:318]))
    addProperty(properties, "publisherIdentifier", bc.bytesToText(bytesData[318:446]))
    addProperty(properties, "dataPreparerIdentifier", bc.bytesToText(bytesData[446:574]))
    addProperty(properties, "applicationIdentifier", bc.bytesToText(bytesData[574:702]))
    addProperty(properties, "copyrightFileIdentifier", bc.bytesToText(bytesData[702:740]))
    addProperty(properties, "abstractFileIdentifier", bc.bytesToText(bytesData[740:776]))
    addProperty(properties, "bibliographicFileIdentifier", bc.bytesToText(bytesData[776:813]))
    
    # Following fields are all date-time values    
    addProperty(properties, "volumeCreationDateAndTime", decDateTimeToDate(bytesData[813:830]))
    addProperty(properties, "volumeModificationDateAndTime", decDateTimeToDate(bytesData[830:847]))
    addProperty(properties, "volumeExpirationDateAndTime", decDateTimeToDate(bytesData[847:864]))
    addProperty(properties, "volumeEffectiveDateAndTime", decDateTimeToDate(bytesData[864:881]))
    
    addProperty(properties, "fileStructureVersion", bc.bytesToUnsignedChar(bytesData[881:882]))
    
    return(properties)
    def makeHumanReadable(self, remapTable={}):
        # Takes element object, and returns a modified version in which all
        # non-printable 'text' fields (which may contain numeric data or binary strings)
        # are replaced by printable strings
        #
        # Property values in original tree may be mapped to alternative (more user-friendly)
        # reportable values using a remapTable, which is a nested dictionary.

        for elt in self.iter():
            # Text field of this element
            textIn = elt.text

            # Tag name
            tag = elt.tag

            # Step 1: replace property values by values defined in enumerationsMap,
            # if applicable
            try:
                # If tag is in enumerationsMap, replace property values
                parameterMap = remapTable[tag]
                try:
                    # Map original property values to values in dictionary
                    remappedValue = parameterMap[textIn]
                except KeyError:
                    # If value doesn't match any key: use original value
                    # instead
                    remappedValue = textIn
            except KeyError:
                # If tag doesn't match any key in enumerationsMap, use original
                # value
                remappedValue = textIn

            # Step 2: convert all values to text strings.

            # First set up list of all numeric data types,
            # which is dependent on the Python version used

            if config.PYTHON_VERSION.startswith(config.PYTHON_2):
                # Python 2.x
                numericTypes = [int, long, float, bool]
                # Long type is deprecated in Python 3.x!
            else:
                numericTypes = [int, float, bool]

            # Convert

            if remappedValue != None:
                # Data type
                textType = type(remappedValue)

                # Convert text field, depending on type
                if textType == bytes:
                    textOut = bytesToText(remappedValue)
                elif textType in numericTypes:
                    textOut = str(remappedValue)
                else:
                    textOut = removeControlCharacters(remappedValue)

                # Update output tree
                elt.text = textOut
Exemple #4
0
def parseMasterDirectoryBlock(bytesData):
    # Based on description at:
    # https://developer.apple.com/legacy/library/documentation/mac/Files/Files-102.html

    # Set up elemement object to store extracted properties
    properties = ET.Element("masterDirectoryBlock")

    addProperty(properties, "signature", bc.bytesToText(bytesData[0:2]))
    addProperty(properties, "blockSize", bc.bytesToUShortInt(bytesData[18:20]))
    addProperty(properties, "blockCount", bc.bytesToUInt(bytesData[20:24]))
    return (properties)
Exemple #5
0
def parseApplePartitionMap(bytesData):

    # Based on description at:
    # https://en.wikipedia.org/wiki/Apple_Partition_Map#Layout
    # and code at:
    # https://opensource.apple.com/source/IOStorageFamily/IOStorageFamily-116/IOApplePartitionScheme.h
    # Variable naming mostly follows Apple's code.

    # Set up elemement object to store extracted properties
    properties = ET.Element("applePartitionMap")

    addProperty(properties, "signature", bc.bytesToText(bytesData[0:2]))
    addProperty(properties, "numberOfPartitionEntries",
                bc.bytesToUInt(bytesData[4:8]))
    addProperty(properties, "partitionBlockStart",
                bc.bytesToUInt(bytesData[8:12]))
    addProperty(properties, "partitionBlockCount",
                bc.bytesToUInt(bytesData[12:16]))
    addProperty(properties, "partitionName", bc.bytesToText(bytesData[16:48]))
    addProperty(properties, "partitionType", bc.bytesToText(bytesData[48:80]))
    addProperty(properties, "partitionLogicalBlockStart",
                bc.bytesToUInt(bytesData[80:84]))
    addProperty(properties, "partitionLogicalBlockCount",
                bc.bytesToUInt(bytesData[84:88]))
    addProperty(properties, "partitionFlags", bc.bytesToUInt(bytesData[88:92]))
    addProperty(properties, "bootCodeBlockStart",
                bc.bytesToUInt(bytesData[92:96]))
    addProperty(properties, "bootCodeSizeInBytes",
                bc.bytesToUInt(bytesData[96:100]))
    addProperty(properties, "bootCodeLoadAddress",
                bc.bytesToUInt(bytesData[100:104]))
    addProperty(properties, "bootCodeJumpAddress",
                bc.bytesToUInt(bytesData[108:112]))
    addProperty(properties, "bootCodeChecksum",
                bc.bytesToUInt(bytesData[116:120]))
    addProperty(properties, "processorType",
                bc.bytesToText(bytesData[120:136]))
    return (properties)
Exemple #6
0
	def makeHumanReadable(self, remapTable = {}):
		# Takes element object, and returns a modified version in which all
		# non-printable 'text' fields (which may contain numeric data or binary strings)
		# are replaced by printable strings
		#
		# Property values in original tree may be mapped to alternative (more user-friendly)
		# reportable values using a remapTable, which is a nested dictionary.

		for elt in self.iter():
			# Text field of this element
			textIn = elt.text
			
			# Tag name
			tag = elt.tag
			
			# Step 1: replace property values by values defined in enumerationsMap,
			# if applicable
			try:
				# If tag is in enumerationsMap, replace property values
				parameterMap = remapTable[tag]
				try:
					# Map original property values to values in dictionary
					remappedValue = parameterMap[textIn]
				except KeyError:
					# If value doesn't match any key: use original value instead
					remappedValue = textIn
			except KeyError:
				# If tag doesn't match any key in enumerationsMap, use original value
				remappedValue = textIn
			
			# Step 2: convert all values to text strings
			if remappedValue != None:
				# Data type
				textType = type(remappedValue)
		
				# Convert text field, depending on type
				if textType == bytes:
					textOut = bytesToText(remappedValue)
				elif textType in[int,float,bool]:
					textOut=str(remappedValue)
				else:
					textOut=remappedValue
	
				# Update output tree
				elt.text = textOut
def parseAppleZeroBlock(bytesData):

    # Based on code at:
    # https://opensource.apple.com/source/IOStorageFamily/IOStorageFamily-116/IOApplePartitionScheme.h

    # Set up elemement object to store extracted properties
    properties = ET.Element("appleZeroBlock")
            
    addProperty(properties, "signature", bc.bytesToText(bytesData[0:2]))
    addProperty(properties, "blockSize", bc.bytesToUShortInt(bytesData[2:4]))
    addProperty(properties, "blockCount", bc.bytesToUInt(bytesData[4:8]))
    addProperty(properties, "deviceType", bc.bytesToUShortInt(bytesData[8:10]))
    addProperty(properties, "deviceID", bc.bytesToUShortInt(bytesData[10:12]))
    addProperty(properties, "driverData", bc.bytesToUInt(bytesData[12:16])) 
    addProperty(properties, "driverDescriptorCount", bc.bytesToUShortInt(bytesData[80:82]))
    addProperty(properties, "driverDescriptorBlockStart", bc.bytesToUInt(bytesData[82:86]))
    addProperty(properties, "driverDescriptorBlockCount", bc.bytesToUShortInt(bytesData[86:88]))
    addProperty(properties, "driverDescriptorSystemType", bc.bytesToUShortInt(bytesData[88:90]))
    return(properties)
Exemple #8
0
def decDateTimeToDate(datetime):
    # Convert 17 bit dec-datetime field to formatted  date-time string
    # TODO: incorporate time zone offset into result
    try:
        year = int(bc.bytesToText(datetime[0:4]))
        month = int(bc.bytesToText(datetime[4:6]))
        day = int(bc.bytesToText(datetime[6:8]))
        hour = int(bc.bytesToText(datetime[8:10]))
        minute = int(bc.bytesToText(datetime[10:12]))
        second = int(bc.bytesToText(datetime[12:14]))
        hundrethSecond = int(bc.bytesToText(datetime[14:16]))
        timeZoneOffset = bc.bytesToUnsignedChar(datetime[16:17])
        dateString = "%d/%02d/%02d" % (year, month, day)
        timeString = "%02d:%02d:%02d" % (hour, minute, second)
        dateTimeString = "%s, %s" % (dateString, timeString)
    except ValueError:
        dateTimeString = ""
    return (dateTimeString)
def decDateTimeToDate(datetime):
    # Convert 17 bit dec-datetime field to formatted  date-time string
    # TODO: incorporate time zone offset into result
    try:
        year = int(bc.bytesToText(datetime[0:4]))
        month = int(bc.bytesToText(datetime[4:6]))
        day = int(bc.bytesToText(datetime[6:8]))
        hour = int(bc.bytesToText(datetime[8:10]))
        minute = int(bc.bytesToText(datetime[10:12]))
        second = int(bc.bytesToText(datetime[12:14]))
        hundrethSecond = int(bc.bytesToText(datetime[14:16]))
        timeZoneOffset = bc.bytesToUnsignedChar(datetime[16:17])
        dateString = "%d/%02d/%02d" % (year, month, day)
        timeString = "%02d:%02d:%02d" % (hour, minute, second)
        dateTimeString = "%s, %s" % (dateString, timeString)
    except ValueError:
        dateTimeString=""
    return(dateTimeString)
Exemple #10
0
def parseAppleZeroBlock(bytesData):

    # Based on code at:
    # https://opensource.apple.com/source/IOStorageFamily/IOStorageFamily-116/IOApplePartitionScheme.h

    # Set up elemement object to store extracted properties
    properties = ET.Element("appleZeroBlock")

    addProperty(properties, "signature", bc.bytesToText(bytesData[0:2]))
    addProperty(properties, "blockSize", bc.bytesToUShortInt(bytesData[2:4]))
    addProperty(properties, "blockCount", bc.bytesToUInt(bytesData[4:8]))
    addProperty(properties, "deviceType", bc.bytesToUShortInt(bytesData[8:10]))
    addProperty(properties, "deviceID", bc.bytesToUShortInt(bytesData[10:12]))
    addProperty(properties, "driverData", bc.bytesToUInt(bytesData[12:16]))
    addProperty(properties, "driverDescriptorCount",
                bc.bytesToUShortInt(bytesData[80:82]))
    addProperty(properties, "driverDescriptorBlockStart",
                bc.bytesToUInt(bytesData[82:86]))
    addProperty(properties, "driverDescriptorBlockCount",
                bc.bytesToUShortInt(bytesData[86:88]))
    addProperty(properties, "driverDescriptorSystemType",
                bc.bytesToUShortInt(bytesData[88:90]))
    return (properties)
Exemple #11
0
def parsePrimaryVolumeDescriptor(bytesData):

    # Set up elemement object to store extracted properties
    properties = ET.Element("primaryVolumeDescriptor")

    addProperty(properties, "typeCode", bc.bytesToUnsignedChar(bytesData[0:1]))
    addProperty(properties, "standardIdentifier",
                bc.bytesToText(bytesData[1:6]))
    addProperty(properties, "version", bc.bytesToUnsignedChar(bytesData[6:7]))
    addProperty(properties, "systemIdentifier",
                bc.bytesToText(bytesData[8:40]))
    addProperty(properties, "volumeIdentifier",
                bc.bytesToText(bytesData[40:72]))

    # Fields below are stored as both little-endian and big-endian; only
    # big-endian values read here!

    # Number of Logical Blocks in which the volume is recorded
    addProperty(properties, "volumeSpaceSize",
                bc.bytesToUInt(bytesData[84:88]))
    # The size of the set in this logical volume (number of disks)
    addProperty(properties, "volumeSetSize",
                bc.bytesToUShortInt(bytesData[122:124]))
    # The number of this disk in the Volume Set
    addProperty(properties, "volumeSequenceNumber",
                bc.bytesToUShortInt(bytesData[126:128]))
    # The size in bytes of a logical block
    addProperty(properties, "logicalBlockSize",
                bc.bytesToUShortInt(bytesData[130:132]))
    # The size in bytes of the path table
    addProperty(properties, "pathTableSize",
                bc.bytesToUInt(bytesData[136:140]))
    # Location of Type-L Path Table (note this is stored as little-endian only, hence
    # byte swap!)
    addProperty(properties, "typeLPathTableLocation",
                bc.swap32(bc.bytesToUInt(bytesData[140:144])))
    # Location of Optional Type-L Path Table
    addProperty(properties, "optionalTypeLPathTableLocation",
                bc.swap32(bc.bytesToUInt(bytesData[144:148])))
    # Location of Type-M Path Table
    addProperty(properties, "typeMPathTableLocation",
                bc.bytesToUInt(bytesData[148:152]))
    # Location of Optional Type-M Path Table
    addProperty(properties, "optionalTypeMPathTableLocation",
                bc.bytesToUInt(bytesData[152:156]))

    # Following fields are all text strings
    addProperty(properties, "volumeSetIdentifier",
                bc.bytesToText(bytesData[190:318]))
    addProperty(properties, "publisherIdentifier",
                bc.bytesToText(bytesData[318:446]))
    addProperty(properties, "dataPreparerIdentifier",
                bc.bytesToText(bytesData[446:574]))
    addProperty(properties, "applicationIdentifier",
                bc.bytesToText(bytesData[574:702]))
    addProperty(properties, "copyrightFileIdentifier",
                bc.bytesToText(bytesData[702:740]))
    addProperty(properties, "abstractFileIdentifier",
                bc.bytesToText(bytesData[740:776]))
    addProperty(properties, "bibliographicFileIdentifier",
                bc.bytesToText(bytesData[776:813]))

    # Following fields are all date-time values
    addProperty(properties, "volumeCreationDateAndTime",
                decDateTimeToDate(bytesData[813:830]))
    addProperty(properties, "volumeModificationDateAndTime",
                decDateTimeToDate(bytesData[830:847]))
    addProperty(properties, "volumeExpirationDateAndTime",
                decDateTimeToDate(bytesData[847:864]))
    addProperty(properties, "volumeEffectiveDateAndTime",
                decDateTimeToDate(bytesData[864:881]))

    addProperty(properties, "fileStructureVersion",
                bc.bytesToUnsignedChar(bytesData[881:882]))

    return (properties)