Giter VIP home page Giter VIP logo

ccl-bplist's Introduction

ccl_bplist is a small Python module for dealing with binary property lists (bplists). It also contains special helper functionality to simplify the processing of NSKeyedArchiver structures often found in binary property lists.

It converts the binary property list file contents into a native Python object.

Property List Type Returned Python Type
null None
true True
false False
integer int
real float
uid int
date datetime.datetime
string str
data bytes
array list
dict dict
set list

Quick-Start

Here's a quick overview of the module's features:

Opening Property Lists

At its most basic, just import the module, create a file-like object around your plist (here I'm opening a file, but often I find that I'm dealing with embedded plists, in which case io.BytesIO is very useful).

>>> import ccl_bplist
>>> f = open("plist.plist", "rb")
>>> plist = ccl_bplist.load(f)
>>> 
>>> plist
{'$objects': ['$null', {'apiKey': UID: 10, 'eventLog': UID: 7, 'locale': UID: 12, '$class': UID: 14, 'pauseTime': UID: 4, 'totalErrorCount': 0, 'internetAvailable': True, 'errors': UID: 9, 'userID': UID: 0, 'appVersion': UID: 11, 'latitude': 0.0, 'eventCounts': UID: 5, 'eventLogComplete': True, 'crashed': False, 'pageViewCount': 0, 'startTime': UID: 2, 'pauseIntervalMillis': 0, 'gender': -1, 'longitude': 0.0, 'serializationVersion': 1, 'timeZone': UID: 13, 'accuracy': 0.0}, {'$class': UID: 3, 'NS.time': 378032076.116256}, {'$classes': ['NSDate', 'NSObject'], '$classname': 'NSDate'}, {'$class': UID: 3, 'NS.time': 378032077.674404}, {'$class': UID: 6, 'NS.keys': [], 'NS.objects': []}, {'$classes': ['NSMutableDictionary', 'NSDictionary', 'NSObject'], '$classname': 'NSMutableDictionary'}, {'$class': UID: 8, 'NS.objects': []}, {'$classes': ['NSMutableArray', 'NSArray', 'NSObject'], '$classname': 'NSMutableArray'}, {'$class': UID: 8, 'NS.objects': []}, 'BMPNB5HT2H63KM42BB83', '4.0.1', 'en_GB', 'Europe/London', {'$classes': ['FlurrySession', 'NSObject'], '$classname': 'FlurrySession'}], '$top': {'root': UID: 1}, '$version': 100000, '$archiver': 'NSKeyedArchiver'}

The plist is converted to a native Python object (the translations of plist data-type to Python data-types are listed above).

Working with NSKeyedArchiver Files

In this case the plist is one that has been created by Apple's NSKeyedArchiver class which means it's not a whole lot of fun to work with. Luckily, ccl_bplist can deserialise the object and give you the actual structure of the data.

>>> ns_keyed_archiver_obj = ccl_bplist.deserialise_NsKeyedArchiver(plist)
>>> ns_keyed_archiver_obj
{'apiKey': UID: 10, 'eventLog': UID: 7, 'locale': UID: 12, '$class': UID: 14, 'eventLogComplete': True, 'crashed': False, 'pageViewCount': 0, 'startTime': UID: 2, 'pauseTime': UID: 4, 'totalErrorCount': 0, 'internetAvailable': True, 'errors': UID: 9, 'pauseIntervalMillis': 0, 'gender': -1, 'userID': UID: 0, 'appVersion': UID: 11, 'longitude': 0.0, 'serializationVersion': 1, 'latitude': 0.0, 'timeZone': UID: 13, 'accuracy': 0.0, 'eventCounts': UID: 5}

The module assumes that if the top-level dictionary structure is $top/root that the object that you want returning sits beneath top. You can override this behaviour is you prefer:

>>> ns_keyed_archiver_obj = ccl_bplist.deserialise_NsKeyedArchiver(plist, parse_whole_structure=True)
>>> ns_keyed_archiver_obj
{'root': UID: 1}

You'll notice in both of these cases that we have UID objects. This is because NSKeyedArchiver maintains an object-table, and in the structure the objects are referred by their position in the object-table (more details here: http://www.cclgroupltd.com/digital-forensics/rd/geek-post-nskeyedarchiver-files-%E2%80%93-what-are-they-and-how-can-i-use-them.html. The module doesn't look-up the objects until they are requested, both for speed and (mostly) because you can have infinitely recursing structures. If you access a UID object in a list or dictionary it will be looked up and returned:

>>> ns_keyed_archiver_obj["root"]
{'apiKey': UID: 10, 'eventLog': UID: 7, 'locale': UID: 12, '$class': UID: 14, 'eventLogComplete': True, 'crashed': False, 'pageViewCount': 0, 'startTime': UID: 2, 'pauseTime': UID: 4, 'totalErrorCount': 0, 'internetAvailable': True, 'errors': UID: 9, 'pauseIntervalMillis': 0, 'gender': -1, 'userID': UID: 0, 'appVersion': UID: 11, 'longitude': 0.0, 'serializationVersion': 1, 'latitude': 0.0, 'timeZone': UID: 13, 'accuracy': 0.0, 'eventCounts': UID: 5}

Automatic Conversion of Common NSObjects

NSKeyed Archiver contains serialisations of ObjectiveC objects which would usually require extra code to deal with, but in version 0.13 of the module we've added a set of convenience features to make dealing with these data types a lot simpler.

>>> ns_keyed_archiver_obj["root"]["eventLog"]
{'$class': UID: 8, 'NS.objects': []}

Here we've accessed an object in this plist, we can inspect the type of the object by looking at the "$class" key:

>>> ns_keyed_archiver_obj["root"]["eventLog"]["$class"]
{'$classes': ['NSMutableArray', 'NSArray', 'NSObject'], '$classname': 'NSMutableArray'}

We can see that this is a serialisation of an NSMutableArray. We could access the contents of the array in the NS.objects key (which in this case contains an empty list), alternatively we can set a converter function for the module to use, you can write your own, but the module comes with one built in which you can enable like this:

>>> ccl_bplist.set_object_converter(ccl_bplist.NSKeyedArchiver_common_objects_convertor)

(NB this enables the converter module-wide, not just for objects that you're currently working on)

If we access the same object now, it automatically gets converted into a nice, native Python list:

>>> ns_keyed_archiver_obj["root"]["eventLog"]
[]

If you want to turn this functionality off, just set the converter function to a pass-through function:

>>> ccl_bplist.set_object_converter(lambda x: x)

This built-in converter also works for NSDictionary:

>>> ns_keyed_archiver_obj["root"]["eventCounts"]
{'$class': UID: 6, 'NS.keys': [], 'NS.objects': []}

>>> ns_keyed_archiver_obj["root"]["eventCounts"]["$class"]
{'$classes': ['NSMutableDictionary', 'NSDictionary', 'NSObject'], '$classname': 'NSMutableDictionary'}

>>> ccl_bplist.set_object_converter(ccl_bplist.NSKeyedArchiver_common_objects_convertor)
>>> ns_keyed_archiver_obj["root"]["eventCounts"]
{}

>>> ccl_bplist.set_object_converter(lambda x: x)

NSDate:

>>> ns_keyed_archiver_obj["root"]["startTime"]
{'$class': UID: 3, 'NS.time': 378032076.116256}

>>> ns_keyed_archiver_obj["root"]["startTime"]["$class"]
{'$classes': ['NSDate', 'NSObject'], '$classname': 'NSDate'}

>>> ccl_bplist.set_object_converter(ccl_bplist.NSKeyedArchiver_common_objects_convertor)
>>> ns_keyed_archiver_obj["root"]["startTime"]
datetime.datetime(2012, 12, 24, 8, 54, 36, 116256)

>>> ccl_bplist.set_object_converter(lambda x: x)

and the way that NSKeyedArchiver serialises Null as a string containing "$null":

>>> ns_keyed_archiver_obj["root"]["userID"]
'$null'

>>> ccl_bplist.set_object_converter(ccl_bplist.NSKeyedArchiver_common_objects_convertor)
>>> print(ns_keyed_archiver_obj["root"]["userID"])
None

ccl-bplist's People

Contributors

cclgroupltd avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

ccl-bplist's Issues

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.