Skip to main content

What is special about roothide environments?

Roothide is a type of jailbreak distinct from rootful and rootless.


Differences from rootful/rootless

Unlike traditional jailbreaks, in roothide the "jailbreak root (jbroot)" and the "system root (rootfs)" are separate. jbroot is mounted inside rootfs at a random path, and rootfs is also bind-mounted back at jbroot/rootfs/.

System root (rootfs)

In roothide, the system root is the iOS root directory. It is unmodified and contains no extra paths.

Jailbreak root (jbroot)

In roothide, jbroot is mounted under rootfs at a random path, usually something like /var/containers/Bundle/Application/.jbroot-XXXXXXXXXXXXXXXX/ (X are random). Use the jbroot function to convert a normal path to its jbroot path. For example, to access /var/mobile/Media/1.txt inside jbroot, use jbroot("/var/mobile/Media/1.txt"). In a script, f = io.open(jbroot("/var/mobile/Media/1.txt"), "r") will actually open:

/var/containers/Bundle/Application/.jbroot-XXXXXXXXXXXXXXXX/var/mobile/Media/1.txt

Shell environment

As mentioned, jbroot is mounted at a random path inside rootfs. But in shell environments (e.g., deb install scripts), you cannot know where jbroot is mounted inside rootfs. Therefore, roothide sets the shell runtime root to jbroot. That is, /Applications/XXTExplorer.app in a deb will be installed to:

/var/containers/Bundle/Application/.jbroot-XXXXXXXXXXXXXXXX/Applications/XXTExplorer.app

This ensures jailbroken packages do not pollute the system root. However, it introduces a problem when using os.execute or io.popen in XXTouch scripts, since they execute via bash/zsh. For example, calling os.execute("/usr/bin/hidutil list") will actually run:

/var/containers/Bundle/Application/.jbroot-XXXXXXXXXXXXXXXX/usr/bin/hidutil list

This prevents direct access to rootfs paths from shell. To solve this, roothide bind-mounts the system root back to jbroot/rootfs/. Thus, os.execute("/rootfs/usr/bin/hidutil list") will actually run:

/usr/bin/hidutil list

File and directory mirrors

Certain files/directories inside jbroot are symlinked to the original rootfs:

Path inside jbroot
/dev
/private/preboot
/var/containers
/var/mobile/Containers
/usr/share/misc/trace.codes
/usr/share/zoneinfo
/etc/hosts.equiv
/etc/hosts
/var/run/utmpx
/var/db/timezone
/System/Library/CoreServices/SystemVersion.plist

In addition, XXTouch’s script root /var/mobile/Media/1ferver in jbroot is also symlinked into rootfs. These paths are accessible from both jbroot and rootfs. Reference

XXTouch in Bootstrap environments

No auto-start

On devices using Bootstrap-Roothide semi-jailbreak, after rebooting and re-activating Bootstrap, XXTouch daemon does not auto-start. Open the XXTouch app; it will auto-exit and display "Starting XXTouch Daemon...". Within 20 seconds the daemon should be running.

No SpringBoard injection

If Bootstrap is used without enabling SpringBoard injection via Serotonin, UI-related script features are unavailable. dialog and webview that create top-level UI will be affected. alerthelper cannot handle system alerts.

Use XXTouch to remove potentially detectable files in Bootstrap-Roothide

local noexecute = require('no_os_execute')

function remove_sys_app_caches(name)
noexecute.rm_rf('/var/root/Library/WebKit/'..name)
noexecute.rm_rf('/var/root/Library/Caches/'..name)
noexecute.rm_rf('/var/root/Library/HTTPStorages/'..name)
noexecute.rm_rf('/var/root/Library/SplashBoard/Snapshots/'..name)
noexecute.rm_rf('/var/root/Library/Saved Application State/'..name..'.savedState')
noexecute.rm_rf('/var/root/Library/Preferences/'..name..'.plist')

noexecute.rm_rf('/var/root/Library/WebKit/'..name)
noexecute.rm_rf('/var/mobile/Library/Caches/'..name)
noexecute.rm_rf('/var/mobile/Library/HTTPStorages/'..name)
noexecute.rm_rf('/var/mobile/Library/SplashBoard/Snapshots/'..name)
noexecute.rm_rf('/var/mobile/Library/Saved Application State/'..name..'.savedState')
noexecute.rm_rf('/var/mobile/Library/Preferences/'..name..'.plist')
end

remove_sys_app_caches('com.opa334.Dopamine')
remove_sys_app_caches('org.coolstar.SileoStore')
remove_sys_app_caches('ws.hbang.Terminal')
remove_sys_app_caches('pisshill.usprebooter')
remove_sys_app_caches('com.samiiau.loader')
remove_sys_app_caches('kr.xsf1re.vnodebypass')
remove_sys_app_caches('com.serena.Antoine')
remove_sys_app_caches('wiki.qaq.TrollFools')
remove_sys_app_caches('com.tigisoftware.Filza')
remove_sys_app_caches('com.tigisoftware.Filza000')
remove_sys_app_caches('com.tigisoftware.ADManager')
remove_sys_app_caches('com.ichitaso.otadisablerts')
remove_sys_app_caches('chaoge.ChargeLimiter')

noexecute.rm_rf('/private/var/mobile/Library/Filza')
noexecute.rm_rf('/private/var/mobile/.ssh')
noexecute.rm_rf('/private/var/root/.ssh')
noexecute.rm_rf('/private/var/mobile/offsets.txt')
noexecute.rm_rf('/private/var/mobile/offsets.txt')
noexecute.rm_rf('/private/var/mobile/Serotonin.jp2')
noexecute.rm_rf('/private/var/mobile/Documents/kfund_offsets.plist')
noexecute.rm_rf('/private/var/iomfb_bics_daemon')

Why do these files exist? Although roothide installs jailbreak apps under random jbroot paths, it does not confine their runtime to those paths. So after running, caches or other files may still be written to the corresponding locations in rootfs.

Apps may also detect the SSH port. If necessary, disable SSH in Bootstrap settings to avoid detection.