Thursday, 30 April 2015

Trawling for Windows Phone 8 App Permissions

Trawling for Windows Phone App Permissions can be an Adventure! (Fishnets not mandatory ;)

A recent case had monkey researching how to determine which Windows Phone apps might store location data. Rather than manually opening/searching tens of app directories, wouldn't it be handy if we could auto-magically find the apps which allow our behaviours of interest?

It turns out each Windows Phone app has its own Application Manifest file (called "WMAppManifest.xml") which amongst other things, declares its allowed "Capability" permissions.
So under the "Data" partitition's "Programs" directory, there will be a bunch of Application specific sub-directories (eg Facebook) with each sub-directory having its own "WMAppManifest.xml" file.

For more details on Windows Phone 8 Capabilities (SW, HW and Functional) see here.

For an example of an App Manifest file see here.

You can get the "WP8_AppPerms.py" script from here.

The Script

You can point this script ("WP8_AppPerms.py") at a single "WMAppManifest.xml" file or at a parent directory (eg "Programs") containing multiple app directories. The script figures out if the given argument is a file or a directory and then calls its internal "Parse_Capabilities" function for each detected "WMAppManifest.xml" file.
The "Parse_Capabilities" function prints out the App Name, ProductID, Version, Description, Author and any declared App Capabilities to the command line. If its being called on a directory, the script will also print out the total number of "WMAppManifest.xml" files it has parsed and each directory path as they are parsed.
The script lists each Capability by their tag (eg ID_CAP_LOCATION) so users can then go here for (marginally) more detailed information.

I used this StackOverflow post as the basis for the XML parsing part of the script. Because why write your own XML parser when Python already has (several) existing implementations to choose from?
For the purposes of this script, we can say an XML document (or "ElementTree") is comprised of child "Elements".
These "Elements" can then have attributes.
So for the following simplified XML example:
<App xmlns="" Title="NewPhoneAppWP8" Version="1.0.0.0" >

"App" is the Element and "Title" and "Version" are the attributes of that Element.

Using the Python xml.etree.ElementTree library/package is a multi-step process.
First you call the "parse" function to read the file, then you call "getroot" to find the root (top) element.
Once you have the root element, you can call "find" to return a particular child element and then call "get" to return the attribute of that element.
So in Python, we can say something like:
    tree = ET.parse(filename) # parses the file
    root = tree.getroot() # gets the root element
    AppTitle = root.find("App").get("Title") # finds "App" child element & retrieves the "Title" attribute value
Retrieving the "Capability"s is a little more complicated as they are nested further down and there are usually multiple "Capability"s declared. The "get" function as used above only returns the first attribute it finds - not all of them. Boo!
So instead, we can use the "iterfind" function combined with an XML path to tell Python that we want a list of elements which are stored under the "App/Capabilities/Capability" path. We can then loop thru this returned list and print the "Name" attribute for each.
This looks like:
    caps = root.iterfind("./App/Capabilities/Capability")
        for cap in caps:
            print(cap.get("Name"))
The "." at the beginning of "./App/Capabilities/Capability" just means its a relative path to the element calling the "iterfind" function (ie the "root" element).

There's probably other ways of doing it but these code snippets worked well during testing.

Testing

The script has been tested on Windows 7 Pro 64-bit running Python 2.7.6 and was not designed to work on a raw phone image file. Its meant to be run against file system extractions/individual files only.
The test image (not shown in this post) was from a factory fresh Nokia Lumia 530 Phone running Windows Phone 8.1 which was imaged via an ATF JTAG box. X-Ways Forensics was then used to parse the image and export the "Data" partition's "Programs" directory (located on partition 27 in this case). There were 19 App sub directories with over 4000 files (295 MB) contained therein. A lot of potential data to trawl through eh?
Only the logical contents of the files were exported. Due to the way the Python XML library function parses files, having NULLS in the fileslack seemed to cause problems.
To minimize complaints when the script tries to open the file path (on MS Windows anyway), enclose the file path in double quotes ("), do not have commas in the filepath and do not leave a trailing \ at the end of the file path. Otherwise you will probably see an Exception message complaining about "invalid mode or filename".

To make testing easier, I copied the script, the example MS App Manifest XML file and a recursive test directory to the c:\wp8perms directory on my machine. Because I also have Python 3.4 installed on my PC, I am using the explicit path to my Python 2.7 executable (ie c:\python27\python.exe).

Here's the help output:
c:\wp8perms>
c:\wp8perms>c:\python27\python.exe WP8_AppPerms.py -h
Running WP8_AppPerms.py v2015-04-24
usage: WP8_AppPerms.py [-h] target

Prints Windows phone 8 Capabilities from given App Manifest XML file (or directory of files).

positional arguments:
  target      File or directory of files to be parsed

optional arguments:
  -h, --help  show this help message and exit

c:\wp8perms>

Here's the output of running it against a single instance of the MS example file downloaded from here.

c:\wp8perms>
c:\wp8perms>c:\python27\python.exe WP8_AppPerms.py WMAppManifest.xml
Running WP8_AppPerms.py v2015-04-24

Attempting to open single file WMAppManifest.xml
App Name = NewPhoneAppWP8
App ProductID = {31a2f61a-4083-4250-9c0a-2d68740285b3}
App Version = 1.0.0.0
App Description = Sample description
App Author = NewPhoneAppWP8 author
App Capabilities =
ID_CAP_NETWORKING
ID_CAP_MEDIALIB_AUDIO
ID_CAP_MEDIALIB_PLAYBACK
ID_CAP_SENSORS
ID_CAP_WEBBROWSERCOMPONENT

For a list of Capability definitions see https://msdn.microsoft.com/en-us/library/windows/apps/jj206936%28v=vs.105%29.aspx

Exiting ...

c:\wp8perms>

And here's what happens when we run it against a directory which is simulating a "Program" directory with 3 applications installed (ie app1, app2, app3). Note: All 3 App manifests have the same attribute values except for the "App Name".

c:\wp8perms>
c:\wp8perms>c:\python27\python.exe WP8_AppPerms.py Test-App-Perms-Programs
Running WP8_AppPerms.py v2015-04-24

Attempting to open Test-App-Perms-Programs\app1\WMAppManifest.xml
App Name = NewPhoneAppWP8-1
App ProductID = {31a2f61a-4083-4250-9c0a-2d68740285b3}
App Version = 1.0.0.0
App Description = Sample description
App Author = NewPhoneAppWP8 author
App Capabilities =
ID_CAP_NETWORKING
ID_CAP_MEDIALIB_AUDIO
ID_CAP_MEDIALIB_PLAYBACK
ID_CAP_SENSORS
ID_CAP_WEBBROWSERCOMPONENT

Attempting to open Test-App-Perms-Programs\app2\WMAppManifest.xml
App Name = NewPhoneAppWP8-2
App ProductID = {31a2f61a-4083-4250-9c0a-2d68740285b3}
App Version = 1.0.0.0
App Description = Sample description
App Author = NewPhoneAppWP8 author
App Capabilities =
ID_CAP_NETWORKING
ID_CAP_MEDIALIB_AUDIO
ID_CAP_MEDIALIB_PLAYBACK
ID_CAP_SENSORS
ID_CAP_WEBBROWSERCOMPONENT

Attempting to open Test-App-Perms-Programs\app3\WMAppManifest.xml
App Name = NewPhoneAppWP8-3
App ProductID = {31a2f61a-4083-4250-9c0a-2d68740285b3}
App Version = 1.0.0.0
App Description = Sample description
App Author = NewPhoneAppWP8 author
App Capabilities =
ID_CAP_NETWORKING
ID_CAP_MEDIALIB_AUDIO
ID_CAP_MEDIALIB_PLAYBACK
ID_CAP_SENSORS
ID_CAP_WEBBROWSERCOMPONENT

Parsed 3 WMAppManifest.xml files

For a list of Capability definitions see https://msdn.microsoft.com/en-us/library/windows/apps/jj206936%28v=vs.105%29.aspx

Exiting ...

c:\wp8perms>

Final Thoughts

This script should help narrow down which Windows Phone 8 Apps are worthy of further investigation when faced with the question like "Can you find all the location data?" etc. Once you have found which apps require your permissions of interest, you can then go search for those app storage directories for the actual data of interest. Fun times!

While Windows Phone Store Apps store their program/install data in their respective directories on the "Data" partition under "\Programs", most of the user and/or app generated data will NOT be stored under that directory.
Instead, (on the "Data" partition) check the app specific directories under "\Users" and the "\SharedData" directory (data potentially shared between apps) as potential sources of app data. Also, don't forget to check any SD cards and think about any cloud based apps which might provide an alternative data source (they will probably require a subpoena/warrant however).
Analysts should also check the "MainOS" partition's "/Programs" directory for any app manifest files for programs which were installed by default (ie not via the Windows Phone Store).
Finally, just because an app has a certain Capability permission does not mean that it also logs/stores that data ... but we have to start somewhere right?

If this script helps you or if you have any comments/suggestions/other script ideas, please feel free to leave a comment below. Happy Trawling!