In the process of daily work, youdao friends often chat with me privately and ask me if I can help him break the shell of xxAPP. Therefore, how to break the shell of APP in a simple and fast way is of course particularly important. This paper will describe how to achieve one-button shell breaking without pain and itching. Of course, according to the convention of this series, it will also tell the principle of smashing shells, how to solve the problems encountered in smashing shells and so on.

First look at the final result:

Before reading this article, I assume that you already know how to access your phone remotely. If you really don’t, please read iOS Reverse (10)- Jailbreak! Jailbreak principle! Log in to the mobile phone through remote connection

Before you know how to break the shell, you need to know what is the shell, what is the principle of breaking the shell.

Same release benefits before starting: actively load the framework that doesn’t start by default, and resolve the DecryptApp pain point of failed decrypts

What is a shell

The vast majority of APP developers believe that the iOS system is very secure and do not reinforce the APP, so the popular meaning of shell is the encryption of the APP by Apple when uploading the APP.

1, verify when to shell

(1) After Build

Start by creating a new default project, EncryptApp, with Xcode, without writing any code or writing anything arbitrary. Build the project and go to the project path after it is successful to see if the shell is added.

Displays the contents of the EncryptApp package in the directory shown above

Use the terminal to see if the MachO file EncryptApp has been wrapped

otool -l EncryptApp | grep crypt
Copy the code

You can see that the cryptid field is 0, indicating that the file is not encrypted.

(2) Run it into the mobile phone

Start by looking up the location of the EncryptApp in the phone. Without further ado, use SSH to connect your computer to your iPhone (which also works). Make sure the EncryptApp is running properly on the device before using the ps command to find the current process.

ps -ax | grep EncryptApp  
Copy the code

From the figure above, you can view the physical path of the current APP on the device. Then go to the path and export it to the PC desktop (iFunBox is recommended. If the root directory of the device cannot be viewed using iFunBox, it indicates that the device does not have the permission. You need to download the AFC2 plug-in of the corresponding version in Cydia). Or run commands to copy the files to the desktop

scp -r -P 12345 root@localhost:/var/containers/Bundle/Application/AD8F7993-260F-465D-B207-900F67195658/Youkui4Phone.app ~/Desktop/
Copy the code

Also use the otool command to check whether it is encrypted

Similarly, if the cryptid field is 0, the file is not encrypted.

(3) After local packaging

As a general operation, package the project into an IPA package using certificates and export it to a desktop directory. Also use the otool command to check whether it is encrypted

Similarly, if the cryptid field is 0, the file is not encrypted. There are two cryptid fields here that indicate that MachO is a multi-schema executable, arm7 and arm64, and they’re not shelled.

(4) Packages downloaded from AppStore

Download a brand new Youku from AppStore, run it, also use PS to check its directory address, use Otool to check whether encryption.

Export it to the desktop to check whether it is encrypted

In this case, the cryptid field is 1, indicating that the file is encrypted by the encryption scheme of 1.

It can be concluded from the above process that App shell was encrypted after our IPA was uploaded to apple background.

Two, how to smash the shell

To really understand what cracking is, it’s important to know what the system does when it launches an app.

1. The kernel loads MachO

Before we click the App, the App lies on the disk in the form of MachO and various resources. After clicking icon, the kernel starts to read MachO to check whether the MachO is encrypted. If it is not encrypted, it is handed directly to DyLD to load and run. If it has been encrypted, the kernel needs to decrypt it, get the decrypted MachO file, and then hand it to DyLD to load and run.

Dyld loading process can be seen in the article iOS Reverse (5)- I wonder how MachO can claim to understand dyLD

As can be seen from this step, it is impossible for an encrypted MachO to be fully encrypted. Otherwise, the kernel cannot know whether the MachO is encrypted, what type of file it is, and what architecture it is. The specific method can also be clicked on iOS Reverse (5)- I wonder how MachO dare say I understand DYLD view).

We are using otool -l EncryptApp | grep crypt cryptid the command of a demerit out of the field, as well as cryptoff and cryptsize field, These two fields represent the MachO’s 103153664 bytes encrypted from position 16384(base 10).

The general flow chart of MachO after kernel loading and shell is as follows:

2, shell smashing process

(1) Two kinds of shell smashing principle

Cracking the shell is like a decryption process. We humans are the kernel and memory, while MachO unshelled is the plaintext and MachO shelled is the ciphertext. For example, when Xiaoming saw aGVsbG8=, he didn’t know what it meant, but he knew that it was encrypted with Base64, so he only needed to decrypt base64 to know that it actually meant hello.

Since the App needs to be decrypted every time it is started, asymmetric encryption/decryption of the App will be very inefficient, which will seriously affect the user experience. Therefore, the encryption of the App must be encrypted by symmetric encryption.

So you can see that there are two kinds of cracking. Static cracking shell: decrypt the whole process, restore all the code. Dynamic shell smashing: because the kernel is running MachO which has been decrypted in the memory, so as long as the MachO in the memory is directly dumped to the disk, which is equivalent to xiaoming students in the decryption algorithm after seeing the plaintext, we directly ask Xiaoming students to tell us what the plaintext is the same.

Static decryption is extremely costly and requires reverse the entire kernel, while Apple is very strict about kernel hardening, and even if it comes to the whole encryption process, as long as Apple slightly changes the encryption method, it will have to start all over again, so this method is not recommended. The memory format of each manufacturer is unified, so the way to read data from memory is unified, so the dynamic shell smashing method is the ideal way at present.

(2) Manual dynamic shell smashing

Activate the internal phoneLLDBservice

As mentioned above, the principle of dynamic shell smashing is to dump the corresponding binary from memory. Then, what are we using to debug the App in memory during daily development? The answer, of course, is known as LLDB

Our Mac comes with LLDB, for example:

Using a terminal, type in the command LLDB (python2 script, but python3 by default)

Or when using Xcode, suspend the App and the App enters the LLDB debugging state.

This also proves that there are LLDB corresponding services in our mobile phones.

When I bought a new mobile phone, there was no such service on the mobile phone. When I connected xcode to the App for the first time, Xcode copied the service of the corresponding version of the mobile phone system into the mobile phone, and the name of the service was called DebugServer.

On a Mac, the debugServer for iOS 10.3 is located in:

/ Applications/Xcode. App/Contents/Developer/Platforms/iPhoneOS platform/DeviceSupport / 10.3Copy the code
../DeveloperDiskImage/usr/bin/debugserver
Copy the code

On the mobile phone, the location of the debugServer is:

usr/bin
Copy the code

We can use MD5 to verify whether the debugServer in the phone and the debugServer in the computer are the same thing.

Of course, the result may also be different, because the mobile phone debugServer may be copied from other computers, other versions of the system into, but all the LLDB instruction set is unified

To sum up, the role of the debugServer is to connect to the LLDB on the Mac, so that the Mac can use the LLDB to control the DEBUgServer, and the DebugServer can control the iPhone.

As shown in figure:

Since the DebugServer is a service, the service must open a port through which remote clients can connect to the service. We can enable this port with the following command after the Mac is connected to the phone:

// DebugServer *: indicates the end interface-aAPP name/process number DebugServer *:12346-a EncryptApp
// 或者
debugserver *:12346 -a 3657
Copy the code

The 12346 port number can be written freely, but be careful not to repeat it with other port numbers. If you do not know the APP name/process number, run the ps-ax command to find the APP name/process number. If you know the name of the APP or part of the name of the APP can be filtered additional grep command ps – ax | grep EncryptApp

If the following error occurs

error: failed to attach to process named: "" (os/kern) invalid task Exiting.
Copy the code

Verify that the APP has been occupied by the debugServer, try to check whether Xcode or terminal is connected to the phone.

After closing other debugServers that occupy the App, restart the port. If the following information is displayed, the port is successfully opened:

Then enable the LLDB mode on the PC and attach the port. The related commands are as follows

/ / open LLDB state > LLDB corresponding port > / / adsorption process connect connect: / / localhost: 12346 / / view all image corresponding process under the port address, The first one is the App's ASLR > image listCopy the code

Like Xcode, LLDB apps are suspended and cannot be manipulated. Use the c command to unsuspend the App, and use the exit command to exit the LLDB state. See the official instruction set for more instructions

Dumps the encrypted binary

Since the beginning of the actual operation hit shell, then it will certainly need a encrypted App as an object, we still use the old friend youku 😝. The parts can be divided into: 1. Start App, open port, and open LLDB state. Memory read-force command to Dump the binary file of the decrypted part of MachO 6. Change the cryptid in MachO file to 0

Step 1: Repeat the previous Step
Step 2. Check the position and size of the MachO encrypted part
> otool -l Youkui4Phone | grep crypt
Copy the code

Cryptoff 16384 // File offset cryptSize 103153664 // Encrypted file size cryptid 1 // EncryptedCopy the code
Step 3. Check the ASLR of the App in memory
> image list
Copy the code

ASLR: 0 x00000001000c0000

Step 4. Usememory read -forceThe command dumps the decrypted portion of the binary file
// memory read--force --outfile Directory name of the output file --binary --count Size of the encrypted file ASLR+ File offset > memoryread --force --outfile ./Desktop/decrypted.bin --binary --count 103153664 0x00000001000c0000+16384
Copy the code

At this point you can find a decrypted.bin file on your desktop.

Step 5. UseddThe MachO command overwrites the dumped binary into the original MachO file
// dd seek= file offset address bs= unit 1 subsection conv= conversion method (retain the uncut part of the content)ifOf = Output file address > DD seek=16384 BS =1 conv=notruncif=./decrypted.bin of=./Youkui4Phone.app/Youkui4Phone
Copy the code

Step 6 change the MachO filecryptidfor0

At this point, MachO has actually been decrypted successfully, but the cryptid field of MachO has not been changed, so the cryptid is still only 1 at this time.

Open MachO directly and manually change the cryptid field to 0.

Verify success

Using the principle of class-dump, if the shell smashing succeeds, the header file can be exported. If the shell smashing fails, the header file cannot be exported.

(3) the frida – ios – dump

In the real daily development, of course, it is impossible to hit the shell more than once every time, which is time-consuming and exhausting. Zhang has written a very simple and easy to use shell breaking tool, which can be configured to achieve a command to complete the shell breaking. For details, see frida-ios-dump.

Frida-ios-dump one-click shell-smashing chicken version frida-ios-dump one-click shell-smashing chicken version frida-ios-dump one-click shell-smashing chicken version

There are excellent configuration documents that I won’t repeat here.

Is frida-ios-dump unbeatable once configured?

Of course not.

Three, special shell

Remember the above mentioned principle of cracking the shell is to dump the decrypted files in memory, so if there are files in the App running out of memory?

There must be, for example, the dynamic library framework commonly used in iOS. Some dynamic libraries are only loaded into memory when their functions are used. When using Frida to crack shells, this part of the framework must fail, and when we re-sign it, it will fail. In the analysis of the time also increased the difficulty (first do not discuss the non-re-signature debugging mode), such as: a treasure, fat book, etc.. The following error is reported when using MonkeyDev to re-sign it:

/Users/xxx/Desktop/xxx/TargetApp/xxx.app/Frameworks/xxx.framework/xxx This file is encrypted! Both please use github.com/AloneMonkey… to decrypt!

Those of you who have read dyLD’s source code must know the steps dyLD takes over the startup of App: 4. Load the dynamic link library. 5. Link the main program. 6

Of course we can use some of dyld’s methods to get all the framework of the current App.

The code is visible in the BallFramework

Use method: 1, download a good project, Bulid project 2, Build the successful framework copy to the mobile phone Home directory

> scp -r -P 12345 libAllFramework.framework root@localhost:~/
Copy the code

Note that the Build environment should be a real machine environment and pay attention to the framework permissions

3. Use DYLD_INSERT_LIBRARIES to implement the libAllFramework

/ / checking Facebook address > ps - ax | grep Facebook / / insert our dynamic library > DYLD_INSERT_LIBRARIES = libAllFramework. The framework/libAllFramework  /var/containers/Bundle/Application/B4217EF2-9F16-453F-B1DE-9EC5D0E69B60/Facebook.app/FacebookCopy the code

Can see in the vast majority of dynamic libraries have been loaded correctly, there is only one called FBCardIOSDKWrapperFramework failure load of dynamic link library, the author has not found the reason why will fail, if you have to understand the way of friends please let us know, thank you very much.

But this does not affect the big picture, because we just put the FBCardIOSDKWrapperFramework deleted from the source file. After smashing its shell again, re-signature can be successful.

If you don’t want to download the source code, you can download the packaged framework (ARM64 architecture) and Copy it directly into your phone.

Four,

This article describes what is a shell in the traditional sense in iOS, that is, symmetric encryption of apps. When Apple encrypted it. Hit the shell principle, the actual operation manual hit the shell, using tools to hit the shell, and finally an example of a hit the shell will encounter some pits.

Hope in the future work will be a shell to add a relaxed and happy thing 😸

Five, the reference

1, TZLoadAllLibs 2, a command to complete the shell smashing