RSS

Use frida and objection to penetration test iOS app security

A quick and detail guide with examples about how to use frida and objection to penetration test your iOS app security without a jailbroken device. A quick cheat sheet of objection usage examples on iOS.

Introduction

What is frida?

frida is a dynamic code instrumentation toolkit. It lets you inject snippets of JavaScript or your own library into native apps on Windows, macOS, GNU/Linux, iOS, Android, and QNX. Frida also provides you with some simple tools built on top of the Frida API.

What is objection?

objection is a runtime mobile exploration toolkit, powered by Frida, built to help you assess the security posture of your mobile applications, without needing a jailbreak. objection supports both iOS and Android.

objection for iOS key features :

  • Patch iOS applications, embedding a Frida gadget that can be used with objection or just Frida itself.
  • Interact with the filesystem, listing entries as well as upload & download files where permitted.
  • Perform various memory related tasks, such as listing loaded modules and their respective exports.
  • Attempt to bypass and simulate jailbroken or rooted environments.
  • Discover loaded classes and list their respective methods.
  • Perform common SSL pinning bypasses.
  • Dynamically dump arguments from methods called as you use the target application.
  • Interact with SQLite databases inline without the need to download the targeted database and use an external tool.
  • Execute custom Frida scripts.
  • Dump the iOS keychain, and export it to a file.
  • Dump data from common storage such as NSUserDefaults and the shared NSHTTPCookieStorage.
  • Dump various formats of information in human readable forms.
  • Bypass certain forms of TouchID restrictions.
  • Watch for method executions by targeting all methods in a class, or just a single method.
  • Monitor the iOS pasteboard.
  • Dump encoded .plist files in a human readable format without relying on external parsers.

Install frida and objection

Both frida and objection can be installed from pip (I use python3):

$ pip3 install frida-tools
$ pip3 install objection

After installation, you get a batch of command line tools:

frida             frida-create      frida-kill        frida-ps          frida-rm
frida-apk         frida-discover    frida-ls          frida-pull        frida-trace
frida-compile     frida-join        frida-ls-devices  frida-push
objection

Setup frida on iOS

Frida supports two modes of operation: jailbroken or not jailbroken. This article focus on how to use frida and objection on not jailbroken iOS devices.

Frida is able to instrument debuggable apps, and will inject Gadget automatically as of Frida 12.7.12.

Only a few requirements to be aware of:

  • The iOS device should ideally be running iOS 13 or newer.
  • The Developer Disk Image must be mounted. Xcode will mount it automatically as soon as it discovers the iOS USB device, but you can also do it manually by using ideviceimagemounter.
  • Latest Gadget (Can download from https://github.com/frida/frida/releases ) must be present in the user’s cache directory. On macOS this is ~/.cache/frida/gadget-ios.dylib.

Use frida on iOS

To use frida, first you need connect your device with a usb cable.

List running processes / apps

frida-ps is a command-line tool for listing processes, which is very useful when interacting with a remote system.

$ frida-ps -h
usage: frida-ps [options]

optional arguments:
  -h, --help            show this help message and exit
  -D ID, --device ID    connect to device with the given ID
  -U, --usb             connect to USB device
  -R, --remote          connect to remote frida-server
  -H HOST, --host HOST  connect to remote frida-server on HOST
  --certificate CERTIFICATE
                        speak TLS with HOST, expecting CERTIFICATE
  --origin ORIGIN       connect to remote server with “Origin” header set to ORIGIN
  --token TOKEN         authenticate with HOST using TOKEN
  --keepalive-interval INTERVAL
                        set keepalive interval in seconds, or 0 to disable (defaults to -1 to auto-select based on
                        transport)
  --p2p                 establish a peer-to-peer connection with target
  --stun-server ADDRESS
                        set STUN server ADDRESS to use with --p2p
  --relay address,username,password,turn-{udp,tcp,tls}
                        add relay to use with --p2p
  -O FILE, --options-file FILE
                        text file containing additional command line options
  --version             show program's version number and exit
  -a, --applications    list only applications
  -i, --installed       include all installed applications
  -j, --json            output results as JSON

List all running processes

To list all running processes, use frida-ps -U. Example:

$ frida-ps -U
  PID  Name
-----  --------------------------------------------------------
  631  AMDEngagementExtension
  523  AMPIDService
14447  ANECompilerService
 4939  ANEStorageMaintainer
14339  ASPCarryLog
11699  AccountSubscriber
11706  AccountSubscriber
 6859  Telegram
...

To list all running apps (not include system processes), use frida-ps -Ua. For example:

$ frida-ps -Ua
  PID  Name                           Identifier
-----  -----------------------------  ----------------------------
10205  App Store                      com.apple.AppStore
 6302  Calendar                       com.apple.mobilecal
  637  Clock                          com.apple.mobiletimer
 5980  Firefox                        org.mozilla.ios.Firefox
 8954  Google                         com.google.GoogleMobile
  321  Mail                           com.apple.mobilemail
 5485  Maps                           com.apple.Maps
  318  Notes                          com.apple.mobilenotes
 5308  Photos                         com.apple.mobileslideshow
 9423  Podcasts                       com.apple.podcasts
13559  PosterBoard                    com.apple.PosterBoard
 6248  Safari                         com.apple.mobilesafari
  571  Settings                       com.apple.Preferences
 6859  Telegram                       ph.telegra.Telegraph
11181  TestFlight                     com.apple.TestFlight
...

List all installed applications

To list all installed applications, use frida-ps -Uai. For example:

$ frida-ps -Uai                                                                                                   1  PID  Name                           Identifier
-----  -----------------------------  ---------------------------------------------
10205  App Store                      com.apple.AppStore
 6302  Calendar                       com.apple.mobilecal
  637  Clock                          com.apple.mobiletimer
 5980  Firefox                        org.mozilla.ios.Firefox
  321  Mail                           com.apple.mobilemail
 5485  Maps                           com.apple.Maps
  318  Notes                          com.apple.mobilenotes
 5308  Photos                         com.apple.mobileslideshow
 9423  Podcasts                       com.apple.podcasts
13559  PosterBoard                    com.apple.PosterBoard
 6248  Safari                         com.apple.mobilesafari
  571  Settings                       com.apple.Preferences
 6859  Telegram                       ph.telegra.Telegraph
11181  TestFlight                     com.apple.TestFlight
    -  Books                          com.apple.iBooks
    -  Calculator                     com.apple.calculator
    -  Camera                         com.apple.camera
...

Use objection on iOS

objection usage:

$ objection --help                                                                                                2Usage: objection [OPTIONS] COMMAND [ARGS]...

       _   _         _   _
   ___| |_|_|___ ___| |_|_|___ ___
  | . | . | | -_|  _|  _| | . |   |
  |___|___| |___|___|_| |_|___|_|_|
        |___|(object)inject(ion)

       Runtime Mobile Exploration
          by: @leonjza from @sensepost

  By default, communications will happen over USB, unless the --network option
  is provided.

Options:
  -N, --network            Connect using a network connection instead of USB.
  -h, --host TEXT          [default: 127.0.0.1]
  -p, --port INTEGER       [default: 27042]
  -ah, --api-host TEXT     [default: 127.0.0.1]
  -ap, --api-port INTEGER  [default: 8888]
  -g, --gadget TEXT        Name of the Frida Gadget/Process to connect to.
                           [default: Gadget]
  -S, --serial TEXT        A device serial to connect to.
  -d, --debug              Enable debug mode with verbose output. (Includes
                           agent source map in stack traces)
  --help                   Show this message and exit.

Commands:
  api          Start the objection API server in headless mode.
  device-type  Get information about an attached device.
  explore      Start the objection exploration REPL.
  patchapk     Patch an APK with the frida-gadget.so.
  patchipa     Patch an IPA with the FridaGadget dylib.
  run          Run a single objection command.
  signapk      Zipalign and sign an APK with the objection key.
  version      Prints the current version and exists.

explore start an interactive command line to interaction with app. For example:

$ objection -g 19978 explore
Using USB device `iPhone`
Agent injected and responds ok!

     _   _         _   _
 ___| |_|_|___ ___| |_|_|___ ___
| . | . | | -_|  _|  _| | . |   |
|___|___| |___|___|_| |_|___|_|_|
      |___|(object)inject(ion) v1.11.0

     Runtime Mobile Exploration
        by: @leonjza from @sensepost

[tab] for command suggestions
com.example.foobar on (iPhone: 16.0) [usb] #

Use -g <pid> to attach an exist app. Can also use -g <bundle id> to launch app and attach it. For example:

$ objection -g com.example.foobar explore

ios info binary

com.example.foobar on (iPhone: 16.0) [usb] # ios info binary
Name              Type     Encrypted  PIE    ARC    Canary  Stack Exec  RootSafe
----------------  -------  ---------  -----  -----  ------  ----------  --------
Foobar            execute  False      True   True   False   False       False
FoobarReport      dylib    False      False  False  False   False       False

Get app bundle info

Use ios bundles to list app frameworks and bundles. For example:

com.example.foobar on (iPhone: 16.0) [usb] # ios bundles list_frameworks
Executable        Bundle                       Version  Path
----------------  ---------------------------  -------  -------------------------------------------
FoobarReport  com.example.FoobarReport               1  ...pp/Frameworks/FoobarReport.framework
                                                        ...rivateFrameworks/AppleCVAPhoto.framework

com.example.foobar on (iPhone: 16.0) [usb] # ios bundles list_bundles
Executable        Bundle                            Version  Path
----------------  --------------------------------  -------  -------------------------------------------
                                                             /usr/lib/system
                                                             ...eFrameworks/WebCore.framework/Frameworks
                                                             /usr/lib/log
BoundingPathData  com.apple.uikit.BoundingPathData  1.0      ...itCore.framework/BoundingPathData.bundle
Foobar         com.example.foobar                  1.0      ...240-4B53-8D7A-0403A37E2D4A/Foobar.app
                                                             /usr/lib/swift
                                                             /usr/lib
RawCamera         com.apple.RawCamera.bundle        9.13.0   ...em/Library/CoreServices/RawCamera.bundle

List app directories

com.example.foobar on (iPhone: 16.0) [usb] # env

Name               Path
-----------------  ---------------------------------------------------------------------------------------------
BundlePath         /private/var/containers/Bundle/Application/83F9204D-7240-4B53-8D7A-0403A37E2D4C/Foobar.app
CachesDirectory    /var/mobile/Containers/Data/Application/BA1D1280-9900-439E-BEC3-0442B27E177C/Library/Caches
DocumentDirectory  /var/mobile/Containers/Data/Application/BA1D1280-9900-439E-BEC3-0442B27E177C/Documents
LibraryDirectory   /var/mobile/Containers/Data/Application/BA1D1280-9900-439E-BEC3-0442B27E177C/Library

List files in app directory

Use ls to list files in app directory, use cd to check working directory, for example:

com.example.foobar on (iPhone: 16.0) [usb] # ls
NSFileType  Perms  NSFileProtection  Read  Write  Owner           Group           Size       Creation                   Name
----------  -----  ----------------  ----  -----  --------------  --------------  ---------  -------------------------  ------------------------
Directory     493  None              True  False  _installd (33)  _installd (33)  96.0 B     1970-01-01 00:00:00 +0000  PlugIns
Directory     493  None              True  False  _installd (33)  _installd (33)  128.0 B    1970-01-01 00:00:00 +0000  Base.lproj
Directory     493  None              True  False  _installd (33)  _installd (33)  96.0 B     1970-01-01 00:00:00 +0000  _CodeSignature
Directory     493  None              True  False  _installd (33)  _installd (33)  64.0 B     1970-01-01 00:00:00 +0000  META-INF
Directory     493  None              True  False  _installd (33)  _installd (33)  96.0 B     1970-01-01 00:00:00 +0000  Frameworks
Regular       420  None              True  False  _installd (33)  _installd (33)  1.6 KiB    2022-03-14 16:08:02 +0000  Info.plist
Regular       420  None              True  False  _installd (33)  _installd (33)  8.0 B      2022-03-14 16:08:02 +0000  PkgInfo
Regular       420  None              True  False  _installd (33)  _installd (33)  265.4 KiB  2022-03-14 15:57:10 +0000  embedded.mobileprovision
Regular       493  None              True  False  _installd (33)  _installd (33)  422.9 KiB  2022-03-14 16:15:12 +0000  Foobar

Readable: True  Writable: False

com.example.foobar on (iPhone: 16.0) [usb] # cd PlugIns
com.example.foobar on (iPhone: 16.0) [usb] # ls
NSFileType  Perms  NSFileProtection  Read  Write  Owner           Group           Size     Creation                   Name
----------  -----  ----------------  ----  -----  --------------  --------------  -------  -------------------------  ----------------------------
Directory     493  None              True  False  _installd (33)  _installd (33)  224.0 B  1970-01-01 00:00:00 +0000  foobar-shareextension.appex

Readable: True  Writable: False

com.example.foobar on (iPhone: 16.0) [usb] # pwd
Current directory: /private/var/containers/Bundle/Application/83F9204D-7240-4B53-8D7A-0403A37E2D4C/Foobar.app/PlugIns

View file content

Use file cat to view file content. It will download file then cat it locally. For example:

[usb] # file cat Info.plist

For plist type file, can also use ios plist cat <plist file path> to decode plist file. For example:

[usb] # ios plist cat Info.plist

Download file from device

Use file download <file path> to download a file from device. For example:

com.example.foobar on (iPhone: 16.0) [usb] # file download Info.plist
Downloading /private/var/containers/Bundle/Application/83F9204D-7240-4B53-8D7A-0403A37E2D4C/Foobar.app/Info.plist to Info.plist
Streaming file from device...
Writing bytes to destination...
Successfully downloaded /private/var/containers/Bundle/Application/83F9204D-7240-4B53-8D7A-0403A37E2D4C/Foobar.app/Info.plist to Info.plist

Use ios cookies get to get cookies. For example:

com.example.foobar on (iPhone: 16.0) [usb] # ios cookies get
No cookies found

Dump all of the credentials

Use ios nsurlcredentialstorage dump to dump all of the credentials in the shared NSURLCredentialStorage. For example:

com.example.foobar on (iPhone: 16.0) [usb] # ios nsurlcredentialstorage dump
Protocol  Host  Port  Authentication Method  User  Password
--------  ----  ----  ---------------------  ----  --------

Dump userdefaults

Use ios nsuserdefaults get to get all of the entries. For example:

com.example.foobar on (iPhone: 16.0) [usb] # ios nsuserdefaults get
{
    AKLastEmailListRequestDateKey = "2022-08-20 16:01:39 +0000";
    AKLastIDMSEnvironment = 0;
    ...
}

List all loaded frameworks/modules

Use memory list modules to list all the loaded modules in the current process. For example:

com.example.foobar on (iPhone: 16.0) [usb] # memory list modules
Save the output by adding `--json modules.json` to this command
Name                                   Base         Size                  Path
-------------------------------------  -----------  --------------------  ------------------------------------------------------------------------------
Foobar                                 0x10010c000  131072 (128.0 KiB)    /private/var/containers/Bundle/Application/83F9204D-7240-4B53-8D7A-0403A37E...
FoobarShare                            0x100200000  65536 (64.0 KiB)      /private/var/containers/Bundle/Application/83F9204D-7240-4B53-8D7A-0403A37E...
Foundation                             0x1cffb8000  9744384 (9.3 MiB)     /System/Library/Frameworks/Foundation.framework/Foundation
libobjc.A.dylib                        0x1cef28000  277568 (271.1 KiB)    /usr/lib/libobjc.A.dylib
libSystem.B.dylib                      0x222101000  8192 (8.0 KiB)        /usr/lib/libSystem.B.dylib
Combine                                0x1de138000  1376248 (1.3 MiB)     /System/Library/Frameworks/Combine.framework/Combine
CoreFoundation                         0x1d5b24000  4083712 (3.9 MiB)     /System/Library/Frameworks/CoreFoundation.framework/CoreFoundation
UIKit                                  0x24785a000  12288 (12.0 KiB)      /System/Library/Frameworks/UIKit.framework/UIKit
libswiftCore.dylib                     0x1cfa1d000  5672960 (5.4 MiB)     /usr/lib/swift/libswiftCore.dylib
libswiftCoreFoundation.dylib           0x203615000  32756 (32.0 KiB)      /usr/lib/swift/libswiftCoreFoundation.dylib
libswiftCoreGraphics.dylib             0x1f8310000  28672 (28.0 KiB)      /usr/lib/swift/libswiftCoreGraphics.dylib
libswiftCoreImage.dylib                0x2353d1000  4096 (4.0 KiB)        /usr/lib/swift/libswiftCoreImage.dylib
...

List module exports

Use memory list exports <module name> to list the exports of a module. module name list can get from memory list modules. For example:

com.example.foobar on (iPhone: 16.0) [usb] # memory list exports Pegasus
Save the output by adding `--json exports.json` to this command
Type      Name                                                                           Address
--------  -----------------------------------------------------------------------------  -----------
function  NSStringFromPGBackgroundPIPAuthorizationState                                  0x1fbc94d44
variable  OBJC_CLASS_$_PGBackgroundPIPAuthorization                                      0x22cdb76a8
variable  OBJC_CLASS_$_PGCommand                                                         0x22cdb6f50
variable  OBJC_CLASS_$_PGControlsViewModel                                               0x22cdb6f78
variable  OBJC_CLASS_$_PGControlsViewModelValues                                         0x22cdb6fa0
variable  OBJC_CLASS_$_PGInterruptionAssistant                                           0x22cdb6c58
variable  OBJC_CLASS_$_PGMenuItem                                                        0x22cdb7798
variable  OBJC_CLASS_$_PGPictureInPictureApplication                                     0x22cdb6c80
variable  OBJC_CLASS_$_PGPictureInPictureController                                      0x22cdb6d48
variable  OBJC_CLASS_$_PGPictureInPictureProxy                                           0x22c074fc8
variable  OBJC_CLASS_$_PGPictureInPictureViewController                                  0x22c0750e0
variable  OBJC_CLASS_$_PGPlaybackState                                                   0x22cdb7630
variable  OBJC_CLASS_$_PGPlaybackStatePrerollAttributes                                  0x22cdb7518
variable  OBJC_METACLASS_$_PGBackgroundPIPAuthorization                                  0x22cdb76d0
variable  OBJC_METACLASS_$_PGCommand                                                     0x22cdb6e60
variable  OBJC_METACLASS_$_PGControlsViewModel                                           0x22cdb7220
variable  OBJC_METACLASS_$_PGControlsViewModelValues                                     0x22cdb7248
variable  OBJC_METACLASS_$_PGInterruptionAssistant                                       0x22cdb6cd0
variable  OBJC_METACLASS_$_PGMenuItem                                                    0x22cdb77c0
variable  OBJC_METACLASS_$_PGPictureInPictureApplication                                 0x22cdb6cf8
variable  OBJC_METACLASS_$_PGPictureInPictureController                                  0x22cdb6d70
variable  OBJC_METACLASS_$_PGPictureInPictureProxy                                       0x22c074ff0
variable  OBJC_METACLASS_$_PGPictureInPictureViewController                              0x22c075248
variable  OBJC_METACLASS_$_PGPlaybackState                                               0x22cdb7680
variable  OBJC_METACLASS_$_PGPlaybackStatePrerollAttributes                              0x22cdb7540
variable  PGPegasusErrorDomain                                                           0x225d13168
variable  PGPictureInPictureProxyPictureInPictureActiveChangedNotification               0x225d12a48
variable  PGPictureInPictureViewControllerPrefersIdleTimerDisabledDidChangeNotification  0x225d125b0

Use can also write output in json format with --json <output file path>. For example:

com.example.foobar on (iPhone: 16.0) [usb] # memory list exports Pegasus --json Pegasus_exports.json
Writing exports as json to Pegasus_exports.json...
Wrote exports to: Pegasus_exports.json

Dump app memory

Use memory dump all <output file path> to dump app memory to. For example:

com.example.foobar on (iPhone: 16.0) [usb] # memory dump all appmem.dump
Will dump 111 rw- images, totalling 718.5 MiB
Dumping 512.0 MiB from base: 0x280000000  [####################################]  100%

After dump memory, you can use strings to check readable strings in memory, for example:

$ strings appmem.dump | grep -i username   # search is there any username string in memory.
$ strings appmem.dump | grep -i token   # search is there any token string in memory.

Dump/add/clear iOS key chain

Use ios keychain to add/dump/clear iOS keychain:

add       Add an entry to the iOS keychain
dump      Dump the keychain for the current app's entitlement group
clear     Delete all keychain entries for the current app's entitlement group

ios keychain examples:

com.example.foobar on (iPhone: 16.0) [usb] # ios keychain dump
Note: You may be asked to authenticate using the devices passcode or TouchID
Save the output by adding `--json keychain.json` to this command
Dumping the iOS keychain...
Created Accessible  ACL Type Account    Service Data

2022-08-16 04:06:05 +0000  WhenUnlockedThisDeviceOnly      None  Password  username foo
2022-08-16 04:06:05 +0000  WhenUnlockedThisDeviceOnly      None  Password  token token12345
...


com.example.foobar on (iPhone: 16.0) [usb] # ios keychain clear
Are you sure you want to clear the iOS keychain? [y/N]: y
Clearing the keychain...
Keychain cleared

monitor pasteboard

Use ios pasteboard monitor to monitor the iOS pasteboard. It will print pasteboard content after issue this command (it may take a few seconds). For example:

com.example.foobar on (iPhone: 16.0) [usb] # ios pasteboard monitor
com.example.foobar on (iPhone: 16.0) [usb] # (agent) [pasteboard-monitor] Data: loading this page

Disable sslpinning

Use ios sslpinning disable to disable ios sslpinning. For example:

com.example.foobar on (iPhone: 16.0) [usb] # ios sslpinning disable
(agent) Hooking common framework methods
(agent) Found NSURLSession based classes. Hooking known pinning methods.
(agent) Hooking lower level SSL methods
(agent) Hooking lower level TLS methods
(agent) Hooking BoringSSL methods
(agent) Registering job 759888. Type: ios-sslpinning-disable

Troubleshootings

Unable to connect to the frida server

Use objection and got following error:

$ objection -g 10204 explore
Checking for a newer version of objection...
Using USB device `iPhone`
Unable to connect to the frida server: need Gadget to attach on jailed iOS; its default location is: /Users/foobar/.cache/frida/gadget-ios.dylib

Frida is able to instrument debuggable apps, and will inject Gadget automatically. Gadget must be present in the user’s cache directory. On macOS this is ~/.cache/frida/gadget-ios.dylib.

Gadget can download from https://github.com/frida/frida/releases . The file name is frida-gadget--ios-universal.dylib.gz. Once download it, unzip and move to the default location.

Failed to enumerate applications: this feature requires an iOS Developer Disk Image to be mounted

Plugin a new iOS device and got following error:

$ frida-ps -Ua
Failed to enumerate applications: this feature requires an iOS Developer Disk Image to be mounted; run Xcode briefly or use ideviceimagemounter to mount one manually

To use frida, the Developer Disk Image must be mounted. Xcode will mount it automatically as soon as it discovers the iOS USB device, but you can also do it manually by using ideviceimagemounter.

In xcode, Click Window -> Devices and Simulators, check the device connection status, wait a few minutes should be good to go.

objection stuck

When use objection to launch app, it may stuck after app launched, the following:

$ objection -g com.example.foobar explore
Using USB device `iPhone`
...

To workaround this, launch app manually, then use frida-ps to find the process id and use objection to attach it. For example:

$ frida-ps -Ua                                                                                                    1  PID  Name                           Identifier
-----  -----------------------------  ----------------------------
19978  Foobar Example                 com.example.foobar          # <---- Get process id for objection
10205  App Store                      com.apple.AppStore
...

$ objection -g 19978 explorer
$ objection -g 19978  explore
Using USB device `iPhone`
Agent injected and responds ok!

     _   _         _   _
 ___| |_|_|___ ___| |_|_|___ ___
| . | . | | -_|  _|  _| | . |   |
|___|___| |___|___|_| |_|___|_|_|
      |___|(object)inject(ion) v1.11.0

     Runtime Mobile Exploration
        by: @leonjza from @sensepost

[tab] for command suggestions
com.example.foobar on (iPhone: 16.0) [usb] #

Unable to connect to the frida server: unable to attach to the specified process

Try to use objection to attach a process and failed with Unable to connect to the frida server: unable to attach to the specified process:

$ objection -g 9002 explore                                                                                       2Using USB device `iPhone`
Unable to connect to the frida server: unable to attach to the specified process

This may due to app is not debuggable. For example, app is installed from app store or TestFlight.

To attach any process, you need patch the exist iOS application .

Before you can use any of the objection commands on an iOS application (build in release mode), the application’s IPA itself needs to be patched and code signed to load the FridaGadget.dylib on start. To patch an IPA though, a few things need to be done in preparation, such as getting an embedded.mobileprovision file, as well as a code signing certificate from Apple. Once you have these, objection has a patchipa subcommand that will help you take care of the rest.

Related pages:

References

OmniLock - Block / Hide App on iOS

Block distractive apps from appearing on the Home Screen and App Library, enhance your focus and reduce screen time.

DNS Firewall for iOS and Mac OS

Encrypted your DNS to protect your privacy and firewall to block phishing, malicious domains, block ads in all browsers and apps

Ad