<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>kilko.de - iOS</title>
    <subtitle>Kilian&#x27;s homepage and public feed</subtitle>
    <link rel="self" type="application/atom+xml" href="https://kilko.de/tags/ios/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://kilko.de"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2017-05-30T12:30:38+02:00</updated>
    <id>https://kilko.de/tags/ios/atom.xml</id>
    <entry xml:lang="en">
        <title>Reverse Engineering iOS Apps</title>
        <published>2017-05-30T12:30:38+02:00</published>
        <updated>2017-05-30T12:30:38+02:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://kilko.de/blog/reverse-engineering-ios/"/>
        <id>https://kilko.de/blog/reverse-engineering-ios/</id>
        
        <content type="html" xml:base="https://kilko.de/blog/reverse-engineering-ios/">&lt;iframe width=&quot;100%&quot; height=&quot;500&quot; src=&quot;https:&#x2F;&#x2F;www.youtube-nocookie.com&#x2F;embed&#x2F;lArXWiVWImk?rel=0&amp;amp;showinfo=0&quot; frameborder=&quot;0&quot; allowfullscreen&gt;&lt;&#x2F;iframe&gt;
&lt;p&gt;As promised in my &lt;a href=&quot;&#x2F;itunes-mitm&quot;&gt;last post&lt;&#x2F;a&gt; I wanted to write a post about a talk I recently held at &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;mobilecamp.de&quot;&gt;Mobile Camp 2017&lt;&#x2F;a&gt;. I also held the talk again at our local Cocoaheads Meetup on May 24th 2017, this time being recorded on video (Thanks, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;benchr&quot;&gt;Ben&lt;&#x2F;a&gt;!). But since the talk is in German, I promised to publish an English summary here as well, so here we go 😊&lt;&#x2F;p&gt;
&lt;p&gt;The slides are online as well and can be found on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;git.io&#x2F;reverse-ios&quot;&gt;GitHub Pages&lt;&#x2F;a&gt;. I&#x27;ve linked to most things as well, everything in orange is clickable 😉&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-is-reverse-engineering&quot;&gt;What is Reverse Engineering?&lt;&#x2F;h2&gt;
&lt;p&gt;According to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Reverse_engineering&quot;&gt;Wikipedia&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Reverse engineering, also called back engineering, is the processes of extracting knowledge or design information from anything man-made and re-producing it or re-producing anything based on the extracted information. The process often involves disassembling something (a mechanical device, electronic component, computer program, or biological, chemical, or organic matter) and analyzing its components and workings in detail.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;That&#x27;s exactly what we&#x27;re going to do. We have an app that we didn&#x27;t write ourselves and want to find out what it&#x27;s &lt;em&gt;doing&lt;&#x2F;em&gt; under the hood. Maybe we&#x27;re interested in how a certain behavior is built. Or we want to have a look at how the API the app talks to works or what kind of data is being sent to it (perhaps a little too much?). Or we might even be interested in finding out why a certain bug may be occuring.&lt;&#x2F;p&gt;
&lt;p&gt;Whatever our intent, there&#x27;s a few things we can do to achieve this.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;inside-an-app&quot;&gt;Inside an App&lt;&#x2F;h2&gt;
&lt;p&gt;There&#x27;s a few things to find in an app. Obviously we have the app itself, meaning some kind of executable and possibly a list of frameworks. Additionally there&#x27;s some metadata, which in the iOS world mostly comes down to the info.plist. I&#x27;d add NSUserDefaults to this as well, although they&#x27;re not really included within the app, but stored elsewhere. But especially on macOS this is highly interesting, as a lot of apps offer a lot more customization than seemingly possible via their GUI. And finally we also have assets, e.g. bundled images, videos, sounds, fonts, strings and whatever else.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-s-possible&quot;&gt;What&#x27;s Possible&lt;&#x2F;h2&gt;
&lt;p&gt;I&#x27;m going to split this up into two cases, one being while the app is running and the other while it isn&#x27;t.&lt;&#x2F;p&gt;
&lt;p&gt;If the app is running we can on one hand start monitoring the network and intercept everything the app sends and receives. This is where we can figure out how an API the app might be talking to is working. On the other hand we can try and inject code into the app and bend it to our will.&lt;&#x2F;p&gt;
&lt;p&gt;When not having a running app at our disposal we can open it up and see what kind of stuff is lying around in the bundle. We can also dump the binary to gain a lot more insight into what kind of code the app is actually running behind the scenes.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;intercepting-network-calls&quot;&gt;Intercepting Network Calls&lt;&#x2F;h2&gt;
&lt;p&gt;For this we&#x27;re going to be using a fantastic tool called &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.charlesproxy.com&quot;&gt;Charles&lt;&#x2F;a&gt;, but there are also &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;mitmproxy.org&quot;&gt;alternatives&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;There are &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;codewithchris.com&#x2F;tutorial-using-charles-proxy-with-your-ios-development-and-http-debugging&#x2F;&quot;&gt;plenty&lt;&#x2F;a&gt; of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.facebot.org&#x2F;charles-basics&#x2F;&quot;&gt;tutorials&lt;&#x2F;a&gt; for this online, so I&#x27;m not going to go through this step by step.&lt;&#x2F;p&gt;
&lt;p&gt;The idea is that we can use Charles to intercept anything an app sends to &lt;em&gt;the internet&lt;&#x2F;em&gt; and receives from said &lt;em&gt;internet&lt;&#x2F;em&gt;. Charles has a pretty nifty feature called breakpoints that let us stop on both events and modify the request and response contents inline.
It becomes a bit trickier if the app is using transport encryption, which any sane app should at the very least be doing. If there are no additional measures like certificate pinning at play though we can just tell Charles to use its SSL proxying mode to use our own SSL certificate instead of the original. That way we can just as well listen in on any encrypted requests.&lt;&#x2F;p&gt;
&lt;p&gt;As mentioned though if the app pins to a specific certificate (meaning their app is expecting a specific one, not just &lt;em&gt;any&lt;&#x2F;em&gt; SSL certificate), we&#x27;re kinda stuck here. &lt;strong&gt;And cert pinning is definitely something any app handling sensitive information should be looking in to if not already doing. Man-in-the-middle attacks are commonplace and it&#x27;s always a good idea to protect your users. There&#x27;s more than your reputation at stake 😉&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-bundle&quot;&gt;The Bundle&lt;&#x2F;h2&gt;
&lt;p&gt;Apps usually bundle more than just their executable. So why not have a look, even if it&#x27;s just to satisfy our curiosity.&lt;&#x2F;p&gt;
&lt;p&gt;Go ahead and download whatever app you&#x27;re interested in via iTunes. If you&#x27;re looking for a specific (older) version, check out my &lt;a href=&quot;&#x2F;itunes-mitm&quot;&gt;last post&lt;&#x2F;a&gt; on how to do just that. Right click the app in iTunes and select &quot;Show in Finder&quot;. Here we can just rename the .ipa file to end in .zip and unpack it. Then we can have a look inside \o&#x2F; (Right click an .app and select &quot;Show package contents&quot; to open it).&lt;&#x2F;p&gt;
&lt;p&gt;For most apps there&#x27;s not all too much we can discover here. You&#x27;ll most likely be seeing icons and maybe some other media files. Possibly fonts and sounds as well. Obviously depends on the app.&lt;&#x2F;p&gt;
&lt;p&gt;The two apps I looked into in my talk were both related to public transport in Dresden, &#x27;cause I love myself some good public transport data. The first one, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;itunes.apple.com&#x2F;us&#x2F;app&#x2F;fahrinfo-dresden&#x2F;id314790387?mt=8&quot;&gt;Fahrinfo Dresden&lt;&#x2F;a&gt;, bundles an SQLite db containing a list of all stops in Dresden (for autocompletion) including their coordinates. This was definitely a cool resource to stumble across (especially since these coordinates were somewhat hard to gather elsewhere).&lt;&#x2F;p&gt;
&lt;p&gt;The second app, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;itunes.apple.com&#x2F;us&#x2F;app&#x2F;dvb-mobil&#x2F;id1174905421?mt=8&quot;&gt;DVB mobil&lt;&#x2F;a&gt;, is the official app our public transport provider publishes. As you might be able to tell by using the app and the performance that shows, this app is not a native app, but although I&#x27;d love to very much, this isn&#x27;t the place to argue about that... The app is built with &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;ionicframework.com&quot;&gt;Ionic&lt;&#x2F;a&gt; (previously known as Cordova - more or less), which means the core logic and pretty much everything is written in JavaScript and not compiled into a native binary. Interestingly enough this means that we&#x27;re going to be running across the actual source of the app in the bundle. Unfortunately though the app doesn&#x27;t do all that much that&#x27;s very interesting to look at, but it&#x27;s definitely cool to poke around a bit.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;code-injection&quot;&gt;Code Injection&lt;&#x2F;h2&gt;
&lt;p&gt;This was the coolest part of the talk in my mind at least. Unfortunately it requires your device to be jailbroken. But once you&#x27;ve stepped past that hurdle, the fun begins.&lt;&#x2F;p&gt;
&lt;p&gt;We&#x27;re going to be using a fantastic tool called &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.cycript.org&quot;&gt;cycript&lt;&#x2F;a&gt; to basically give us a live REPL into an app of our choice. This is suprisingly easy to do and surprisingly powerful as well.&lt;&#x2F;p&gt;
&lt;p&gt;For the talk I ran an app called Jodel, which, if you&#x27;re unfamiliar with it, is basically a German equivalent of YikYak. I ran the app on my jailbroken iPhone 4 (running a rather old iOS 7.1.2, but that shouldn&#x27;t be an issue here) and to then get up and running we just have to SSH into our iPhone and run the following.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; cycript&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Jodel&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;-p&lt;&#x2F;code&gt; flag tells cycript to look through all running processes and find the one with the given name. Cycript will now present us with a prompt where we can use its mix of JS and Objective-C to do whatever we want.&lt;&#x2F;p&gt;
&lt;p&gt;One way of getting started is having a look at the current recursive description of the view hierarchy for example.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; UIApp&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;keyWindow&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;recursiveDescription&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;toString&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Cycript has a pretty nice way of accessing anything you know a the memory address of.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; var&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; table&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; new&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Instance&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;0xDEADBEEF&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; use an actual memory address, duh :P&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I used this to get a handle to the &lt;code&gt;JDLLoadingTableView&lt;&#x2F;code&gt; I found in the recursive description above, which is the main table view showing all &quot;jodels&quot;. Then I wanted to find the top-most cell and see if I can change its displayed text and vote count.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; var&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; idx&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;NSIndexPath&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; indexPathForRow&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; inSection&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; var&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; cell&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;table&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; cellForRowAtIndexPath&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;idx&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; cell&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;hidden&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant&quot;&gt; YES&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; this worked, so we have a reference to the correct cell&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; cell&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;hidden&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant&quot;&gt; NO&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; cell&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;recursiveDescription&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;toString&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; we see there&amp;#39;s a `contentLabel`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; cell&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;contentLabel&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;text&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;foobar&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; yay, it works \o&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; cell&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;voteCountLabel&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;text&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;156&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; works as well :)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Obviously this only changes the display of things though. Once we send an upvote or trigger a refresh in any other way, our changes are obviously going to be reset. For trying to get around that it would make sense to see if we can change things directly in the models the app stores internally, but that&#x27;s something for another rainy day 😊&lt;&#x2F;p&gt;
&lt;p&gt;Another way of accessing any running instance of whatever class in cycript is the &lt;code&gt;choose&lt;&#x2F;code&gt; function. You just provide it with a name and it hands you all instances of that class it currently finds. And since Jodel uses Fabric, we can just do the following.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; var&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; crashlytics&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; choose&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;CLSAnalyticsController&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;crash&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; fabricAPIKey&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It&#x27;s also worth noting at this point that cycript is a fantastic way of getting around that pesky certificate pinning mentioned previously, since we can just go ahead and disable that if it&#x27;s getting in our way. It&#x27;s especially easy if the app is using a framework like &lt;code&gt;AFNetworking&lt;&#x2F;code&gt;, where we can just set the &lt;code&gt;SSLPinningMode&lt;&#x2F;code&gt; to &lt;code&gt;None&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;If you&#x27;re a developer you might want to think about this. Anything you do on a user&#x27;s device is something the user can influence. If your app is talking directly to several third-party services and authenticating itself against them, the user of your app will probably be able to find out your API keys (or similar). It might be worth putting something like that behind your own API, so that you can play somewhat of a gatekeeper for most stuff at least. Also please make sure that you&#x27;re not throwing around sensitive information everywhere. Anything your app can access is something cycript (or similar and&#x2F;or more malicious tools) can access. Anything that&#x27;s just lying around unencrypted and way beyond its lifetime is something that will be read by someone unauthorized. It&#x27;s a &lt;em&gt;terrible&lt;&#x2F;em&gt; idea to store passwords in NSUserDefaults for example. But it&#x27;s maybe not quite as obvious that things like encryption keys should not be stored in memory indefinitely either, but just when you need them. It&#x27;s worth talking to someone with a bit more experience regarding this stuff if you want to take it seriously.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;dumping-the-binary&quot;&gt;Dumping the Binary&lt;&#x2F;h2&gt;
&lt;p&gt;To find out more of what kind of data an app stores and what it&#x27;s &lt;em&gt;really&lt;&#x2F;em&gt; doing we&#x27;re going to have to decrypt the actual executable, arguably the most &lt;em&gt;involved&lt;&#x2F;em&gt; part of this post, but it&#x27;s actually rather straight-forward in acomplishing. The &quot;hard&quot; part lies in interpreting the results.&lt;&#x2F;p&gt;
&lt;p&gt;First off we&#x27;re going to want to find the location of the app on our device so that we can tell dumpdecrypted where to look. I&#x27;m using a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;conradev&#x2F;dumpdecrypted&quot;&gt;fork of dumpdecrypted&lt;&#x2F;a&gt; which also dumps all frameworks, which can come in handy.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; find&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &#x2F;var&#x2F;mobile&#x2F;Applications&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Jodel&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; DYLD_INSERT_LIBRARIES=dumpdecrypted.dylib&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &#x2F;var&#x2F;mobile&#x2F;Applications&#x2F;[...]&#x2F;Jodel.app&#x2F;Jodel&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; [...] is a placeholder for the app&amp;#39;s ID :P&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;After doing so we&#x27;ll see a Jodel.encrypted file lying around. This we can now pull over to our Mac and throw into a tool like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.hopperapp.com&quot;&gt;Hopper&lt;&#x2F;a&gt; (there&#x27;s a free trial, which is rather neat) where can look at pretty much everything and try to see what happens where and how by looking at the generated pseudo-code (awesome feature!) or we can dump the encrypted file using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nygard&#x2F;class-dump&quot;&gt;class-dump&lt;&#x2F;a&gt; into a header listing everything that exists. This is useful if you already have a faint idea of what you&#x27;re looking for. In my case this was to find out some stuff about how Jodel generates the HMAC it uses to &quot;sign&quot; every request making it harder to tamper with their API 😉 Props to them for doing it this way by the way!&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; class-dump&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Jodel.decrypted&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Jodel.h&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;By the way, there&#x27;s the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nst&#x2F;iOS-Runtime-Headers&quot;&gt;iOS-Runtime-Headers&lt;&#x2F;a&gt; repo on GitHub which lists header info on all (including private) frameworks in iOS. It&#x27;s regularly updated when new versions of iOS emerge. Apple has followed the practice of adding frameworks as private variants before publicizing them in future versions, so it&#x27;s neat to see hints to some upcoming stuff before it actually gets announced at WWDC 😊&lt;&#x2F;p&gt;
&lt;p&gt;Soooo, that more or less brings us to the end of the talk. Thanks for being there, having a look at the video recording or reading this post. You&#x27;re awesome! I hope that at least some of the information gathered here was of use to you, I definitely learned some stuff when putting it all together. Cheers!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tl-dr&quot;&gt;TL;DR&lt;&#x2F;h2&gt;
&lt;p&gt;If your code is running on somebody else&#x27;s device, they can do whatever they want with it. And there&#x27;s not really anything you can do to stop that. Make sure to think about this when building your app, but don&#x27;t worry about it all too much, it&#x27;s normal 😜&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Downloading older iOS app versions with iTunes</title>
        <published>2017-05-10T15:04:18+02:00</published>
        <updated>2017-05-10T15:04:18+02:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://kilko.de/blog/itunes-mitm/"/>
        <id>https://kilko.de/blog/itunes-mitm/</id>
        
        <content type="html" xml:base="https://kilko.de/blog/itunes-mitm/">&lt;p&gt;&lt;strong&gt;Update&lt;&#x2F;strong&gt; (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 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;itunes.apple.com&#x2F;de&#x2F;app&#x2F;apple-configurator-2&#x2F;id1037126344?l=en&amp;amp;mt=12&quot;&gt;Apple Configurator 2&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Buy and download the app via your iOS device&lt;&#x2F;li&gt;
&lt;li&gt;Open Apple Configurator and login under &quot;Account&quot;&lt;&#x2F;li&gt;
&lt;li&gt;Connect your device, then go to &quot;Add&quot; &amp;gt; &quot;Application&quot; and choose the app in question from your purchase history&lt;&#x2F;li&gt;
&lt;li&gt;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 &lt;code&gt;~&#x2F;Library&#x2F;Group Containers&#x2F;K36BKF7T3D.group.com.apple.configurator&#x2F;Library&#x2F;Caches&#x2F;Assets&#x2F;TemporaryItems&#x2F;MobileApps&#x2F;&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;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&#x27;t checked if it&#x27;s still possible, I&#x27;m just guessing that it doesn&#x27;t differ too much from the process outlined below.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;I recently held a talk about reverse engineering iOS apps at &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;mobilecamp.de&quot;&gt;Mobile Camp 2017&lt;&#x2F;a&gt;. There will be another post about said talk soon, since I&#x27;ll be holding it again at our local Cocoaheads meetup in a few days, this time with a video recording 😊.&lt;&#x2F;p&gt;
&lt;p&gt;One of my topics was taking a look into an app&#x27;s bundle, for which I had an app in mind that bundled an interesting SQLite database&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. I remembered stumbling across this a little while ago and thought it&#x27;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&#x27;re at least somewhat familiar with &lt;em&gt;man-in-the-middle&lt;&#x2F;em&gt; attacking yourself, something I also went over in my talk.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m using a tool called &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.charlesproxy.com&quot;&gt;Charles&lt;&#x2F;a&gt; for this. I can also recommend the very popular &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;mitmproxy.org&quot;&gt;mitmproxy&lt;&#x2F;a&gt;. The idea is the same for both of them, but I&#x27;ll reference Charles here.&lt;&#x2F;p&gt;
&lt;p&gt;Run your tool of choice and start iTunes. Search for the app you want and click download. Since you don&#x27;t want the current version you can cancel the download right after that. Now check Charles for a request to &lt;code&gt;*-buy.itunes.apple.com&lt;&#x2F;code&gt;. Since this request is TLS encrypted we&#x27;re going to enable Charles&#x27; 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.&lt;&#x2F;p&gt;
&lt;p&gt;If you view the server&#x27;s response you&#x27;ll see a plist file (Apple&#x27;s XML based &quot;property list&quot; file format). You&#x27;re looking for a section that looks like the following.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;key&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;softwareVersionExternalIdentifiers&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;key&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;integer&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;813164182&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;integer&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;integer&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;813305098&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;integer&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;integer&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;814184616&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;integer&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;integer&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;814214406&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;integer&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;integer&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;814369260&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;integer&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;integer&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;814850256&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;integer&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;integer&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;817722935&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;integer&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is a list of all versions of the app (or more precisely their IDs), starting with the oldest. Obviously your IDs will most likely differ.&lt;&#x2F;p&gt;
&lt;!--Unfortunately these version IDs aren&#x27;t directly convertible to the version string used by the app. You&#x27;re going to have to guess. For my case this was fine, since I just needed *any* old version. Otherwise you can of course just try a few times and see if you can find a specific one you&#x27;re looking for.--&gt;
&lt;p&gt;Unfortunately there&#x27;s no direct way to correlate all of these version identifiers with the app&#x27;s actual version strings. Apple&#x27;s servers only tell you the version string when requesting one of these specifically, but more on that in a pinch.&lt;&#x2F;p&gt;
&lt;p&gt;Go ahead and copy an ID. Now check the request tab of that same request. You should be able to find a section that specifies which version iTunes wants to download.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;key&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;appExtVrsId&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;key&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;822037669&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The easiest way in Charles is to now set a breakpoint on this request (right-click → Breakpoints). Restart the download in iTunes and Charles will pop up allowing you to edit the request iTunes sends to Apple before it goes through. This is where you can now insert your copied ID as the value for the just mentioned &lt;code&gt;appExtVrsId&lt;&#x2F;code&gt; field. After clicking &quot;Execute&quot; Charles will also stop the incoming response before allowing iTunes to read it. This includes a field named &lt;code&gt;bundleShortVersionString&lt;&#x2F;code&gt; which contains the human-readable ID. You can abort the response and try again if this wasn&#x27;t the app version you&#x27;re looking for.&lt;&#x2F;p&gt;
&lt;img style=&quot;display: block; margin: 0 auto;&quot; src=&quot;https:&#x2F;&#x2F;cloud.githubusercontent.com&#x2F;assets&#x2F;2625584&#x2F;25902476&#x2F;e85fca08-3599-11e7-9643-78d41095f4c1.png&quot; &#x2F;&gt;
&lt;p&gt;If it is a version that works for you, great! That&#x27;s it 🎉. iTunes is downloading the app as we speak and you can then do whatever you want with it. Be aware that any current versions of the app need to be removed from your device if you want to sync it to one.&lt;&#x2F;p&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;I&#x27;m referring to the app &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;itunes.apple.com&#x2F;us&#x2F;app&#x2F;fahrinfo-dresden&#x2F;id314790387?mt=8&quot;&gt;FahrInfo&lt;&#x2F;a&gt; for Dresden. The bundled SQLite db contains a list of all public transport stops including their coordinates, which was used by the app for autocompletion. And if you know me, you know that I&#x27;m a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kiliankoe&#x2F;vvo&quot;&gt;sucker&lt;&#x2F;a&gt; for local public transport data. &lt;a href=&quot;#fr-1-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;section&gt;
</content>
        
    </entry>
</feed>
