How to Crack iOS App Quickly with One Line of Code?

By | September 1, 2019

Preface

This article does not need you to know LLDB, IDA, Hopper and other analysis debugging tools, do not need you to know any ARM assembly knowledge! What do you need to know? That’s a good question! You just need to hit the command line!!

Step 1. Install Frida

Frida is a lightweight cross-platform Hook framework that supports all mainstream operating systems and helps reverse engineers analyze specified processes. It mainly provides a streamlined Python interface and a rich JS interface. In addition to using its own console interaction, it can also use Python to inject JS script libraries into the target process. Using Frida, you can get process details, intercept and call specified functions, inject code, modify parameters, dump class and class method information from iOS applications, etc.

The Frida source code is hosted in GitHub: https://github.com/frida/, and can be downloaded and read by interested readers.

Frida needs to install the control side (macOS side) and the controlled side (iOS side). The version numbers of both sides should be the same, otherwise it may not work properly.

a. IOS side

Open the jailbreak store and add the software source https://build.frida.re/. Search for “Frida” for installation. The latest version is 12.6.18, as shown below:

b. Control side (macOS side)

The control terminal can be installed on Windows, macOS, Linux and other platforms. This article only takes macOS platform as an example to explain.Using sudo privilege, install Frida and frida-tools with pip, as follows:

$ sudo pip install frida
$ sudo pip install frida-tools
$ frida --version
12.6.18

Step 2. Looking for a breakthrough point

Previous tutorials used IDA to find entry points, because this is a novice tutorial, then use frida-trace to test directly, because there is a free trial, so choose to use the FreeTrial keyword repeatedly to test, the command line is as follows:

$ frida-trace -U -f com.apalonapps.vpnapp -m "*[* *FreeTrial*]"
Instrumenting functions...
-[APMInAppPurchaseItem isFreeTrial]: Loaded handler at "/Users/piao/Desktop/__handlers__/__APMInAppPurchaseItem_isFreeTrial_.js"
-[APMInAppPurchaseItem setFreeTrial:]: Loaded handler at "/Users/piao/Desktop/__handlers__/__APMInAppPurchaseItem_setFreeTrial__.js"
+[APNInAppProduct localizedStartMyFreeTrial]: Loaded handler at "/Users/piao/Desktop/__handlers__/__APNInAppProduct_localizedStart_0b3c8fc5.js"
+[APNInAppProduct localizedJoinWithFreeTrial]: Loaded handler at "/Users/piao/Desktop/__handlers__/__APNInAppProduct_localizedJoinW_14c42d59.js"
+[APNInAppProduct localizedSubscribeWithFreeTrial]: Loaded handler at "/Users/piao/Desktop/__handlers__/__APNInAppProduct_localizedSubsc_3ef5833c.js"
+[APNInAppProduct localizedStartFreeTrialAndSubscribe]: Loaded handler at "/Users/piao/Desktop/__handlers__/__APNInAppProduct_localizedStart_-4b087cfa.js"
+[APNInAppProduct localizedEnrollWithFreeTrial]: Loaded handler at "/Users/piao/Desktop/__handlers__/__APNInAppProduct_localizedEnrol_-1c75f8e9.js"
-[APNInAppProduct localizedPeriodFreeTrialString]: Loaded handler at "/Users/piao/Desktop/__handlers__/__APNInAppProduct_localizedPerio_5aa8eee7.js"
-[APNInAppProduct localizedStartFreeTrialString]: Loaded handler at "/Users/piao/Desktop/__handlers__/__APNInAppProduct_localizedStart_-19f8503b.js"
-[APNInAppProduct localizedStartYourNdayFreeTrialString]: Loaded handler at "/Users/piao/Desktop/__handlers__/__APNInAppProduct_localizedStart_6bd91611.js"
-[APNInAppProduct localizedNDayFreeTrialRenews]: Loaded handler at "/Users/piao/Desktop/__handlers__/__APNInAppProduct_localizedNDayF_-63a0ffb1.js"
-[ICMusicSubscriptionStatus isInFreeTrial]: Loaded handler at "/Users/piao/Desktop/__handlers__/__ICMusicSubscriptionStatus_isIn_-1cb12cd0.js"
-[ICMusicSubscriptionStatus isEligibleForFreeTrial]: Loaded handler at "/Users/piao/Desktop/__handlers__/__ICMusicSubscriptionStatus_isEl_1207a9d0.js"
-[APNSubscriptionsManager isActiveSubscriptionInFreeTrialPeriod]: Loaded handler at "/Users/piao/Desktop/__handlers__/__APNSubscriptionsManager_isActi_-1800081e.js"
-[APNSubscriptionsManager isFreeTrial]: Loaded handler at "/Users/piao/Desktop/__handlers__/__APNSubscriptionsManager_isFreeTrial_.js"
-[APNSubscriptionsManager setIsFreeTrial:]: Loaded handler at "/Users/piao/Desktop/__handlers__/__APNSubscriptionsManager_setIsF_39d6e6dd.js"
-[SSVSubscriptionStatus setFreeTrialIneligible:]: Loaded handler at "/Users/piao/Desktop/__handlers__/__SSVSubscriptionStatus_setFreeT_06feffb6.js"
-[SSVSubscriptionStatus isFreeTrialIneligible]: Loaded handler at "/Users/piao/Desktop/__handlers__/__SSVSubscriptionStatus_isFreeTr_-0038832.js"
Started tracing 18 functions. Press Ctrl+C to stop.

At this point, a “__handles__” folder will be generated in the directory where the command line is located, which contains the generated JS files, regardless of them for the time being.

Now let’s explain a few key parameters:

  • -U: Represents a USB connection
  • -f: Represents starting a process (followed by the bundleId application)
  • -m: Track the Object-C method (you can also call it Hook), follow by various fuzzy matching and so on

Successful Hook has a bunch of methods (functions). Unfortunately, there are no related methods triggered until we enter the interface. So let’s try it on the inbound page, click “Order Set and Enjoy Trial” and then click “Cancel” in the payment window.

At this point, the console finally responded:

/* TID 0x403 */
215349 ms -[APNSubscriptionsManager isFreeTrial]

Very good, it seems that the previous analysis is very important!! Now track all the methods of the APNSubscriptionsManager class, as follows:

$ frida-trace -U -f com.apalonapps.vpnapp -m "*[APNSubscriptionsManager *]"
.
.
.
Started tracing 87 functions. Press Ctrl+C to stop.
/* TID 0x403 */
540 ms -[APNSubscriptionsManager initWithSegmentProductIDs:0x0 serverValidationConfig:0x28103c020 reachabilityHostname:0x103202d90 customIdParsing:0x281e5d5c0]
540 ms | -[APNSubscriptionsManager initWithSegmentProductIDs:0x0 serverValidationConfig:0x28103c020 reachabilityHostname:0x103202d90 customIdParsing:0x281e5d5c0 subscriptionStatusDidCheckedInCurrentSession:0x0]
541 ms | | -[APNSubscriptionsManager updateSegmentProductIDs:0x0]
541 ms | | -[APNSubscriptionsManager initializeStorePurchasesObserver]
541 ms | | -[APNSubscriptionsManager setInitialSubscriptionStatus]
541 ms | | | -[APNSubscriptionsManager activeSubscription]
541 ms | | -[APNSubscriptionsManager checkForActiveSubscriptionOnSessionStart]
541 ms | | | -[APNSubscriptionsManager purchaseInProgress]
541 ms | | | -[APNSubscriptionsManager setCheckIsInProgess:0x1]
541 ms | | | -[APNSubscriptionsManager checkForActiveSubscriptionWithCompletion:0x16d284b70]
548 ms -[APNSubscriptionsManager setErrorHandler:0x281205340]
548 ms -[APNSubscriptionsManager setSubscriptionStatusDidChanged:0x1031cb0d0]
548 ms -[APNSubscriptionsManager setSubscriptionPaymentDidMade:0x16d284d18]
548 ms -[APNSubscriptionsManager hasActiveSubscription]
556 ms -[APNSubscriptionsManager canMakeAppStorePurchase]
557 ms -[APNSubscriptionsManager setCanMakeAppStorePurchase:0x16d284f00]
.
.
.

Okay, this time many C functions are called. Let’s leave him alone. Click on the list of servers and continue to look at method calls:

168571 ms -[APNSubscriptionsManager hasActiveSubscription]
168572 ms -[APNSubscriptionsManager hasActiveSubscription]
168572 ms -[APNSubscriptionsManager hasActiveSubscription]
168572 ms -[APNSubscriptionsManager hasActiveSubscription]
168573 ms -[APNSubscriptionsManager hasActiveSubscription]
168573 ms -[APNSubscriptionsManager hasActiveSubscription]
168573 ms -[APNSubscriptionsManager hasActiveSubscription]
168574 ms -[APNSubscriptionsManager hasActiveSubscription]
168574 ms -[APNSubscriptionsManager hasActiveSubscription]
168574 ms -[APNSubscriptionsManager hasActiveSubscription]
168575 ms -[APNSubscriptionsManager hasActiveSubscription]
168575 ms -[APNSubscriptionsManager hasActiveSubscription]

The hasActiveSubscription method is called repeatedly here, literally to see if the “subscription” function is activated (developers say full-featured trial). At this point, of course, there is no activation! How about trying to activate it?

Step 3. The final summit

Since it is a novice tutorial, of course not to analyze its code implementation. By looking at the logs, we noticed that this method would be invoked when App started, so what’s next? Find the JS file generated by frida-trace and slightly add a line of code as shown in the following figure:

Don’t panic, these codes are automatically generated by frida-trace. As long as you know roughly that onEnter is executed when entering the function and onLeave is executed when leaving the function, then the retval. replace (1) that Piaoge just added means that the return value is changed to 1 (true) when leaving the function.

At this point, the process is started with explicit script calls, as follows:

$ frida-trace -U -f com.apalonapps.vpnapp -m "-[APNSubscriptionsManager hasActiveSubscription]"
Instrumenting functions...
-[APNSubscriptionsManager hasActiveSubscription]: Loaded handler at "/Users/piao/Desktop/__handlers__/__APNSubscriptionsManager_hasAct_14ba39f8.js"
Started tracing 1 function. Press Ctrl+C to stop.
/* TID 0x403 */
482 ms -[APNSubscriptionsManager hasActiveSubscription]
710 ms -[APNSubscriptionsManager hasActiveSubscription]
748 ms -[APNSubscriptionsManager hasActiveSubscription]
749 ms -[APNSubscriptionsManager hasActiveSubscription]
.
.

After some analysis, I entered the interface. At this time, I was very excited, because the advertisement bar at the bottom was gone, as follows:

Click on the list of servers and try to click on a server at will. It seems that all of them are available, as follows:

The click-and-try function is completely normal, as shown in the following figure:

Enjoy! If you have any problems,please commit your questions in the following!

Leave a Reply

Your email address will not be published. Required fields are marked *