<commit_before>+++
date = "2017-05-10T15:04:18+02:00"
slug = "itunes-mitm"
title = "Downloading older iOS app versions with iTunes"
+++

I recently held a talk about reverse engineering iOS apps at [Mobile Camp 2017](https://mobilecamp.de). There will be another post about said talk soon, since I'll be holding it again at our local Cocoaheads meetup in a few days, this time with a video recording 😊.

One of my topics was taking a look into an app's bundle, for which I had an app in mind that bundled an interesting SQLite database[^1]. I remembered stumbling across this a little while ago and thought it'd be something nice and small to show. On redownloading the current version of the app I noticed that the SQLite db was still there, but now encrypted 😿. Not wanting to look around for something else to demo I chose to force iTunes to just download an older version of the app instead. Doing so turned out to be rather easy if you're at least somewhat familiar with *man-in-the-middle* attacking yourself, something I also went over in my talk.

I'm using a tool called [Charles](https://www.charlesproxy.com) for this. I can also recommend the very popular [mitmproxy](https://mitmproxy.org). The idea is the same for both of them, but I'll reference Charles here.

Run your tool of choice and start iTunes. Search for the app you want and click download. Since you don't want the current version you can cancel the download right after that. Now check Charles for a request to `*-buy.itunes.apple.com`. Since this request is TLS encrypted we're going to enable Charles' SSL Proxying (right-click the request and do so). Let iTunes re-send the request by starting the download again (we still just need it to start, not actually finish downloading). Charles should now show the request in its unencrypted form.

If you view the server's response you'll see a plist file (Apple's XML based "property list" file format). You're looking for a section that looks like the following.

```xml
<key>softwareVersionExternalIdentifiers</key>
<array>
<integer>813164182</integer>
<integer>813305098</integer>
<integer>814184616</integer>
<integer>814214406</integer>
<integer>814369260</integer>
<integer>814850256</integer>
<integer>817722935</integer>
</array>
```
<commit_msg>Update itunes-mitm w/ current ipa downloading tips<commit_after>+++
date = "2017-05-10T15:04:18+02:00"
slug = "itunes-mitm"
title = "Downloading older iOS app versions with iTunes"
+++

**Update** (2017-09-23):
Apple recently removed the App Store entirely from iTunes (a welcome move), which kinda broke the entire workflow here. It is however still possible to download IPA files to your Mac through the use of [Apple Configurator 2](https://itunes.apple.com/de/app/apple-configurator-2/id1037126344?l=en&mt=12). 

1. Buy and download the app via your iOS device
2. Open Apple Configurator and login under "Account"
3. Connect your device, then go to "Add" > "Application" and choose the app in question from your purchase history
4. A dialog will open asking you if you want to overwrite the app or continue in another fashion. As long as this dialog is open, the IPA file will be cached in `~/Library/Group Containers/K36BKF7T3D.group.com.apple.configurator/Library/Caches/Assets/TemporaryItems/MobileApps/`. 

This process at least helps with downloading current IPA files. The act of downloading older versions is left as an exercise to the reader. I have to add that I haven't checked if it's still possible, I'm just guessing that it doesn't differ too much from the process outlined below.

---

I recently held a talk about reverse engineering iOS apps at [Mobile Camp 2017](https://mobilecamp.de). There will be another post about said talk soon, since I'll be holding it again at our local Cocoaheads meetup in a few days, this time with a video recording 😊.

One of my topics was taking a look into an app's bundle, for which I had an app in mind that bundled an interesting SQLite database[^1]. I remembered stumbling across this a little while ago and thought it'd be something nice and small to show. On redownloading the current version of the app I noticed that the SQLite db was still there, but now encrypted 😿. Not wanting to look around for something else to demo I chose to force iTunes to just download an older version of the app instead. Doing so turned out to be rather easy if you're at least somewhat familiar with *man-in-the-middle* attacking yourself, something I also went over in my talk.

I'm using a tool called [Charles](https://www.charlesproxy.com) for this. I can also recommend the very popular [mitmproxy](https://mitmproxy.org). The idea is the same for both of them, but I'll reference Charles here.

Run your tool of choice and start iTunes. Search for the app you want and click download. Since you don't want the current version you can cancel the download right after that. Now check Charles for a request to `*-buy.itunes.apple.com`. Since this request is TLS encrypted we're going to enable Charles' SSL Proxying (right-click the request and do so). Let iTunes re-send the request by starting the download again (we still just need it to start, not actually finish downloading). Charles should now show the request in its unencrypted form.

If you view the server's response you'll see a plist file (Apple's XML based "property list" file format). You're looking for a section that looks like the following.

```xml
<key>softwareVersionExternalIdentifiers</key>
<array>
<integer>813164182</integer>
<integer>813305098</integer>
<integer>814184616</integer>
<integer>814214406</integer>
<integer>814369260</integer>
<integer>814850256</integer>
<integer>817722935</integer>
</array>
```

{'fraction_non_alphanumeric': 0.07190342897130861, 'fraction_numerical': 0.035339398180545836, 'mean_word_length': 4.671626984126984, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 40, 'https://': 7, 'lorem ipsum': 0, 'www.': 2, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 19, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '488578', 'n_tokens_mistral': 1697, 'n_tokens_neox': 1489, 'n_words': 836}