NOTICE: Contents subject to change.
UPDATE: Revised to include the new format for the latest iLiberty+ version.
NOTICE: New payload header is not compatible with old versions (prior 1.3.0) of iLiberty+. If you have made your own payloads for old version iLiberty+, you may have to change the header slightly to use it on new iLiberty+ version, but normally the script body doesn’t need to change.
With the release of iLiberty+ (Windows) and iLibertyX (OS X), iPhone hacking has become a really easy thing. With iLiberty+’s open structure, it’s pretty easy to implement customized functions into it. This article explains in detail the payload technique used in iLiberty+. NOTE: iLiberty+ and iLibertyX comply to the same payload calling conventions, so the payload written for iLiberty+ also works on iLibertyX.
What Is A Payload
A payload is a package which does a specific job. A payload can do many things to your iPhone, e.g. jailbreak, activate, unlock, system tuning, issue fixing, etc. In iLiberty+, a payload consists of two parts:
1. A payload script
2. A payload archive
The payload script is vital, it’s a must for a payload, the archive is optional. Both the script and the archive pack (if there is) must be put into the payload folder under the iLiberty+ application folder.
For most of the work, an archive is required. For example, to install the BSD Subsystem, you have to have the BSD_Subsystem.zip archive downloaded from its original site. However, in some cases, there’ll be no archive. For example, to fix some 3rd party application issues on 1.1.3, all you have to do is only to create a symbolic link, no need to create any file.
How Payloads Are Put On Device
When you have chosen some payloads to execute, iLiberty+ will pack them into a single ZIP archive and upload it to iPhone before ramdisk boot. In pass 2, the master script will extract the archive into user’s Media folder, after extraction, the Media folder has the following structure:
--Media
|
+- bin
+- do_payload.sh
+- iLiberty_Signature
+- payload/payload1.sh
+- payload/archive1.zip
+- payload/payload2.sh
+- payload/archive2.zip
.
.
.
The bin folder contains a minimal set of utilities that iLiberty+ requires. The do_payload.sh is the main script that calls each and every payload script in alphabetical order. The iLiberty_Signature is a footprint to help script determine the payload location. Please remember the above structure, knowing the payload location and structure will help you write your own payload.
Payload Script Naming
The script name does not need to follow any rules. But since the scripts are called one by one in their alphebetical order, so normally payload scripts are prefixed by a 2-digit number (range from 00 to 99). Because some special payload needs to be run before others, we have used the following rules in our payloads:
00 to 09 for important payloads that normally require some priviliges, activation, unlock, etc important payloads all fall into this range. For example, activation is normally the first thing to do, so it’s called 00Activate.
On the other hand, 3rd party payloads are just add-ons to iPhone system softwares, so they have the lowerest order, we would like to use 90 to 99 for them.
In order to make several payloads can be done in correct order, we have arranged some important payloads in this order:
00 - Activation, Baseband erase/reflash
01 - Bootloader upgrade/downgrade
02 - Unlock
10 - Patches
87 - Cydia
88 - Installer
89 - BSD
90 - 99 Apps
The above arrangement ensures when multiple payloads are checked, they can be executed in a reasonable manner. For example, suppose we want to downgrade our bootloader to 3.9, then unlock it with AnySIM. From the above order, we know the bootloader will be downgraded first, when it’s done, the unlock will follow, and it’s just the correct order. If we don’t follow the above order, i.e. the unlock comes before bootloader downgrade, then it’ll fail.
Of course you don’t have to follow the above rules, but knowing the rule is good, because it allows you to give a correct script name to your payload. Let’s say we have a very kewl payload and we want it to be the very first payload to execute, we can name it:
000VeryKewlPayload.sh
And it will be first executed. Similarly, if we want to let a script run last, then name it to:
99ZLastPayload.sh
This will make it the last payload to execute.
Payload Script Header
The new payload script header is not compatible with old versions of iLiberty+, so this section is devided into two parts.
New format (for iLiberty+ version 1.3.0 and later)
iLiberty+’s payload script must comply to some conventions in order to be detected by the iLiberty+ application executable. The script must contains a header that describes things like the payload name, the archive, etc. The script header is in the following format:
#!/bin/sh # # Id: similar to bundleIdentifier # Name: name of the payload # Author: author of payload # Version: payload version # Script: link to payload script # Pack: link to payload archive (can be empty if there's no zip archive needed) # URL: link to author's site # Desc: payload description line #1, you may # seperate descriptions into several lines # without problem #
The first line indicates the shell the script uses, normally it’s /bin/sh, but there’s no problem using others (e.g. /usr/bin/python as long as it’s installed). Other lines are pretty self-descriptive. If there’s no contents for a field, just leave the filed name there, like this:
# Pack:
There’s one thing needs to be mentioned, the Desc field must be the last field in header, it can contain multile lines, it ends in an blank link or an empty comment line. So all the following formats are correct:
Example 1: # Desc: This is a single line description # Example 2: # Desc: This description contains 2 lines # and it ends with an empty comment # Example 3: # Desc: This description ends with a blank line
We’ll see a real example, the following script header is from a bundled script:
#!/bin/sh # # Id: com.zjlotto.iLiberty.Unlock # Name: Unlock 03.14.08_G - 04.04.05_G # Author: George Zhu # Version: 1.1 # Script: http://iLiberty.zjlotto.com/Payloads2/02Unlock.sh # Pack: http://iLiberty.zjlotto.com/Payloads2/AnySIM_Unlock_BL39.zip # URL: http://george.insideiphone.com/ # Desc: This payload works on both bootloader 3.9 and 4.6, for bootloader # 4.6 it will change baseband to 04.02.13_G after unlock. #
The above is the unlock payload script header, you can see it’s pretty easy understand it.
Old format (for iLiberty+ version prior 1.3.0)
Old format is slightly simpler, it is in the following format:
#!/bin/sh # # Name: name of the payload # Pack: archive name (can be empty if there's no zip archive needed) # URL: link to download the archive (can be empty if there's no zip archive needed) # Desc: payload description line #1 # description continues to line #2 # the last line #3 #
NOTICE: Due to the different meaning of Pack and URL in new and old versions of iLiberty+, the new payload is not compatible with old iLiberty+ versions.
A real example:
#!/bin/sh # # Name: OpenSSH 4.6p1-2 # Pack: openssh-4.6p1-2.zip # URL: http://ste-repo.natetrue.com:15842/iphone-apps/zips/openssh-4.6p1-2.zip # Desc: OpenSSH Package
From the header we know, the payload is named OpenSSH 4.6p1-2, it requires an archive pack named openssh-4.6p1-2.zip, the archive pack can be downloaded from http://ste-repo.natetrue.com:15842/iphone-apps/zips/openssh-4.6p1-2.zip.
Payload Script Body
Following the script header, the script body begins. This is the real script you would like to execute on iPhone, you may write it in any way you prefer, but there are some points need to be considered:
Minimal BSD Tool Set
A newly jailbroken/activated iPhone doesn’t have BSD Subsystem installed, iLiberty+ has copied a very limited tool set onto phone. The utilities are packed in the BasePack.zip, when being extracted, they are put into the bin folder under user’s (mobile or root) Media folder. Here’s the list:
chmod chown cp dd dirname grep igsm ls mkdir plutil reboot rm sleep tar unzip
You should avoid modifying BasePack.zip by yourself because any further update may change this file and wipe out your modifications. If you need some special utilities that have not included in the BasePack.zip, please include them into your payload archive, in a sub-folder /bin. As an example, please check an AnySIM_XXX.zip archive.
Internal Functions
An internal function script named functions.inc is copied to /bin2. Your script should source it to get the basic environment setup correctly (e.g. PATH, DEBUG, etc). So the following line should be put at the very beginning of the script (after the header):
. /bin2/functions.inc(deprecated)
. $FUNCTIONS
After sourcing it, the following environment variables are set:
SIGNATURE - a signature file PL - payload folder name PL_DIR - full path to payload folder AFC_DIR - full path to user's media folder USER_DIR - full path to user's home directory OPTIONS - contains user selected options, mainly for master.sh DEBUG - 1 = on which logs all output, sent from GUI DEBUG_DELAY - time (in seconds) to delay for debug, sent from GUI DEBUG_LOG - debug log file name
There’re some internal functions defined in the functions.inc:
GetFirmwareVersion
Syntax: GetFirmwareVersion var_nameGetBasebandVersion
Syntax: GetBasebandVersion var_name default_versionGetBootloaderVersion
Syntax: GetBootloaderVersion var_nameGetEnvironment
Syntax: GetEnvironment hasBSD hasInstaller
The functions return the result into the variable you defined while calling the function. Here’s an example:
. $FUNCTIONS
GetFirmwareVersion var_fw_version
if [ ${var_fw_version} != "1.1.3" ]; then
echo "Error: not version 1.1.3"
exit 1
fi
GetBasebandVersion var_bb_version
if [ ${var_bb_version} != "04.03.13_G" ]; then
echo "Error: not baseband 04.03.13"
exit 1
fi
GetBasebandVersion var_bb_version DEFAULT_VALUE
if [ ${var_bb_version} = "DEFAULT_VALUE" ]; then
echo "Error: unable to determine baseband version"
exit 1
fi
GetBootloaderVersion var_bl_version
if [ ${var_bl_version} != "3.9_M3S2" ]; then
echo "Error: not bootloader 3.9"
exit 1
fi
GetEnvironment hasBSD hasInstaller
if [ ${hasBSD} = "BSD" ]; then
echo "Found BSD"
elif [ ${hasBSD} = "CYDIA" ]; then
echo "Found Cydia"
else
echo "No BSD/Cydia installed"
fi
if [ ${hasInstaller} = "INSTALLER" ]; then
echo "Found Installer"
elif [ ${hasInstaller} = "CYDIA" ]; then
echo "Found Cydia"
else
echo "Installer not found"
fi
You script may call these internal functions in case your payload is for a specific firmware/baseband/bootloader version.
Examples
Here are some examples which may help you further understand the payload script.
Example 1: Activate 1.1.4
Activativation requires to patch /usr/lib/lockdownd, so the script to activate 1.1.4 is mainly replacing the old lockdownd with a patched one. First, the header, we have described it earlier, so we’ll just skip it:
Script header for latest iLiberty+
#!/bin/sh # # Id: com.zjlotto.iLiberty.Activate # Name: Activate 1.1.4 # Author: George Zhu # Version: 1.0 # Script: http://iLiberty.zjlotto.com/Payloads2/00Activate114.sh # Pack: http://iLiberty.zjlotto.com/Payloads2/Activate114.zip # URL: http://george.insideiphone.com/ # Desc: Activates iPhone firmware 1.1.4 with a patched lockdownd. #
Script header for old iLiberty+ versions (prior 1.3.0)
#!/bin/sh # # Name: Activate 1.1.4 # Pack: Activate114.zip # URL: http://iLiberty.zjlotto.com/Payloads/Activate114.zip # Desc: Activate iPhone firmware 1.1.4 with a patched lockdownd. #
Now the main script body, we first invoke the internal functions to examine the firmware version, if firmware version is not 1.1.4, we pause for a few seconds so that user can know what happens:
. $FUNCTIONS echo "Activating 1.1.4..." GetFirmwareVersion fw_version if [ ${fw_version} != "1.1.4" ]; then echo "Wrong firmware version: ${fw_version}" sleep 5 exit 1 fi
When version check succeeds, we can now extract our patched lockdownd to replace the old one, we also added some error detection and permission fix to make it fail-safe:
unzip -q -o ${PL_DIR}/Activate114.zip -d /usr/libexec/ if [ $? -ne 0 ]; then sleep 10 fi chmod 555 /usr/libexec/lockdownd
Last, we remove our archive:
rm -f ${PL_DIR}/Activate114.zip echo "Done"
NOTE: Although master script will clean up the entire payload folder at the end of execution, it’s a good idea to clean up our own package before leaving, because if there’re many payloads to install, the payload folder may occupy quite some disk spaces.
Example 2: General Fix for 3rd Party Apps
This is an example about how to write a script-only payload. Notice, in script-only payload, the PACK and URL fields in script header must be left blank.
Since many 3rd party application issue can be solved by adding a symbolic link as below:
For latest iLiberty+ (version 1.3.0 and above)
#!/bin/sh # # Id: com.zjlotto.iLiberty.Fix3rdPartyApp # Name: General Fix for 3rd Party App Issues # Author: <author> # Version: 1.0 # Script: http://link.to.your.site/30Fix3rdPartyApp.sh # Pack: # URL: http://link.to.your.site/ # Desc: This tiny payload creates a symbolic link for libgcc_s.1.dylib, # this dynamic library is required by most 3rd party application. . $FUNCTIONS echo "Adding libgcc_s.1.dylib symbolic link..." GetFirmwareVersion fw_ver if [ ${fw_ver} != "1.1.3" -a ${fw_ver} != "1.1.4" ]; then echo "Lower versions need no fix" sleep 5 exit 0 fi mkdir -p /usr/local/arm-apple-darwin/lib ln -s /usr/lib/libgcc_s.1.dylib /usr/local/arm-apple-darwin/lib/.
For old iLiberty+ versions (prior 1.3.0)
/usr/local/arm-apple-darwin/lib/libgcc_s.1.dylib -> /usr/lib/libgcc_s.1.dylib
We can make a simple payload to fix it for us:
#!/bin/sh # # Name: General Fix for 3rd Party App Issues # Pack: # URL: # Desc: This tiny payload creates a symbolic link for libgcc_s.1.dylib, # this dynamic library is required by most 3rd party application. . $FUNCTIONS echo "Adding libgcc_s.1.dylib symbolic link..." GetFirmwareVersion fw_ver if [ ${fw_ver} != "1.1.3" -a ${fw_ver} != "1.1.4" ]; then echo "Lower versions need no fix" sleep 5 exit 0 fi mkdir -p /usr/local/arm-apple-darwin/lib ln -s /usr/lib/libgcc_s.1.dylib /usr/local/arm-apple-darwin/lib/.
NOTE: If there’s anything missing or not clearly explained in the article, please let me know. Comments are welcome.

27 Comments
I wonder if you could include a descriptive tutorial in just a simple jailbreak with adding the necessary payload, IE: Installer, OpenSSH, BSD Subsystem.
There are many people who use AT&T as their providers, thus we only need to jailbreak our phones and add installer..
My hat is off to you and your team on such an innovative tool for us who use Iphone. You for sure will be getting my donation in the sum of $100.00 when it is released today, great work~!
If u just need the jailbreak and Installer, then just check the Installer (jailbreak is checked by default), then click Go.
Downloading it now George… If you need a faster server for apps let me know… Thanks for the prompt reply..
George what apps does the installer install on it by default? If i need BSD SubSytem and SSH do it need to customize a payload?
Also do i need to be diconnected from itunes before i install? I am on 1.1.4 otb.. Do i just turn on iphone, connect to dock, then install?
Download failed, unexpected end of archive…
Server too busy, over 1000 concurrent downloads.
软件有个显示小问题
Advanced–Available Payloads(9)–Unlock for 3.14/04.01/04.02/04.03/04/05 最后的04/05应该是04.05 请大侠改下
Well all went fine for a bit, now i have lost my WiFi access, “unable to join Linksys”.
It use to work all the time before.. I have a 16GB Iphone with 1.1.4OTB, i did Jailbreak only with Installer.. Any ideas why i lost my WiFi?
I am trying to recover voicemails and text files in my Iphone, the screen is cracked and white lighted but I can see the music,photo itunes control files with touchcopy and ziphone. Is there a way to get at all the files in this thing and maybe run undelete software also? The phone now shows up in my vista network and sharing center as “home” it asks for user name and password, I have tried root /dottie and alpine but can’t get it open. I am new to this and kinda bouncing around trying things. Some stable guidance would sure be appreciated
Hi there :)
First of all thx for a all that time and efford you and the other guys has put into making this great piece of software :)
As I would like to be able to make my own payloads I have a few, prolly very noobish questions, but here we go:
When making the .sh file what editor do you recomend me to use?
If I use a link to a given software, lets say OpenSSH, would I also need to include the OpenSSH.zip into the payload or will iLiberty+ download it directly from the url given in the header?
Will every payload be installed in the media folder unless told otherwise, or do I need to specify where to install the payload, openSSH for instance?
Hopefully you will have time to help me abit on those questions :)
//M
Hi George
iLibertyX is perfect. I have created a couple of payloads but something seems to be wrong:
2008-03-27 17:04:23 +0100 Phase 2 starting
2008-03-27 17:04:23 +0100 Unpacking payload…
2008-03-27 17:04:27 +0100 /var/mobile/Media/payload/test.sh:.:9: no such file or directory: /bin2/functions.inc
2008-03-27 17:04:27 +0100 Installing test.app
2008-03-27 17:04:27 +0100 ———————
2008-03-27 17:04:27 +0100 /var/mobile/Media/payload/test.sh:19: command not found: GetFirmwareVersion
2008-03-27 17:04:27 +0100 /var/mobile/Media/payload/test.sh:20: parse error: condition expected: !=
Somehow /bin2/functions.inc cannot be called and hence the defined functions do not work.
I have tried with some of the payloads from your site, but get the same error. Commands like unzip etc. woks.
I am on mac os x 10.4, iPhone 1.1.4 3.9BL
/martin
Martin,
iLiberty+ and iLiberyX are developed by different people, we had communication problems in the past (we’re on different timezone and I had problem accessing the repo) so the two versions might not be exactly the same. The functions.inc is included in BasePack.zip (under /bin folder), which is extracted and moved to /bin2 on iLiberty+, but it might be moved to another place in iLibertyX (or might be missing). Please use the following syntax to source the functions.inc:
The $FUNCTIONS is set before calling payload so every payload is able to use it.
Another workaround is to check where functions.inc is moved or missing:
1. Check if there’s a file /bin/functions.inc in BasePack.zip
2. Check the /do_payload.sh in BackPack.zip to find out where it copies functions.inc to
When you have found the location of functions.inc, you may change accordingly in your script.
We’re working on the update and will try to make iLiberty+ and iLiberyX work in the exactly same way.
George,
It works with . $FUNCTIONS
/martin
’m trying to fix the WiFi problem. I’ve downloaded the payload pack made by macbug.de. I’m on a mac, I’m using Safari.
The pack is in .tar and I’ve decompressed it. Now I have the 4 .zip files with its .sh files. The problem is that I can’t to select them from iLiberty ( Apps Tab > Select a custom payload manually) . It appears grayed, as if the files is not supported. Sorry for my english. Thank you
Same problem as Flavio. How do I get the payload pack to be recognized by iLiberty+? I’ve read your instructions several times, buy no help.
Thanks in advance!
@Ariel, check This Link, Script/Pack URL parsing bug.
George,
after hours of debugging my custom payloads (none of them ever worked) it seems that iLiberty cant handle payload scripts edited with wordpad editor.
I just edited one char in a comment line of the youtube fix which comes with iLiberty, and this is the log after saving 10YouTubefix.sh with Wordpad and executing it with iLiberty:
2008-04-14 21:43:55 +0200 iLiberty+ - Pass 2 Starting
2008-04-14 21:43:55 +0200 Unpacking main payload…
2008-04-14 21:44:00 +0200
2008-04-14 21:44:00 +0200 /var/mobile/Media/payload/10YouTubeFix.sh:12: command not found: ^M
2008-04-14 21:44:00 +0200 /var/mobile/Media/payload/10YouTubeFix.sh:.:13: no such file or directory: /bin2/functions.inc^M
2008-04-14 21:44:01 +0200 /var/mobile/Media/payload/10YouTubeFix.sh:14: command not found: ^M
2008-04-14 21:44:01 +0200 YouTube Fix
2008-04-14 21:44:01 +0200 ———–
2008-04-14 21:44:01 +0200 /var/mobile/Media/payload/10YouTubeFix.sh:17: command not found: ^M
2008-04-14 21:44:01 +0200 /var/mobile/Media/payload/10YouTubeFix.sh:19: command not found: ^M
2008-04-14 21:44:01 +0200 Extracting package…
2008-04-14 21:44:01 +0200 /var/mobile/Media/payload/10YouTubeFix.sh:40: parse error near `\n’
2008-04-14 21:44:01 +0200
2008-04-14 21:44:01 +0200 Housekeeping…Done
2008-04-14 21:44:02 +0200 iLiberty+ - Pass 2 Completed
I would call that a bug.:)
Is there a editor for Windows I can use?
@Cassian, hmm…that’s an interesting thought. Do you think Unix is totally a bug because it can’t understand the end-of-line characters in Windows’ text files ?
There’re some editors that can handle Unix text files correctly, I’ve been using Vi for Windows, sometimes I also use UltraEdit and you may find many others through Google.
George,
ok so it looks like I’m the lonely windows fool jumped in this trap..:)
dont want to argue about this just thought it could be helpful to mention theres a problem in using windows editors .
I have iLiberty+ 1.51. I am trying to write a custom payload to install the Term-VT100 app. (I think this should be included as a standard option BTW)
I have created a script with the required header fields. Saved it as Terminal.sh but I can not select it from liberty+ as a custom payload. I rename it to .lby still not allowed.
I note that the .lby files in the payloads folder are not text files they are binary files.
So how do I get my script recognised?
Can I reference the script and pack on the mac filesystem without having to put them on my website ?
TIA
Quench.
Hi, George!
Wrote custom payloads for v1.2 - all was working. After installing v1.3 was changed header as you described, but iLiberty wont install my payload’s.
I have 1 uestion if iLiberty check script adress from the header and compares local script with this one n link?
Thank,
Andre
@Andre1C, good question :) iLiberty+ examines local payloads in the following steps:
1. Get all *.sh files in payload directory, and put them into a payload list
2. Check a *.sh file to get essential info
3. If the Pack field is not empty, check if the pack file (filename extracted from URL) exists in payload directory, if it does not exist, then remove it from payload list
4. Loop to step 2 till all scripts processed
5. Output the final payload list
From the above procedure, if you want a payload to be recognized by iLiberty+, it must be:
1. A single .sh script in payload directory, the Pack field in .sh script is empty
-or-
2. A .sh script and an archive described in Pack field both exist in payload directory
No, the problem was that iLiberty+ 1.3 recognize my ayloads, but won’t install them on iPhone.
So, the question is if the script file isn’t loaded on http server and header strng that describes script adress looks like “http:\\” iLiberty+ 1.3 will not add ths payload to ramdisk?
Andre
Why isn’t this recognised!!!?
I have a file Terminal.sh which starts
#!/bin/sh
#
# Id: 1
# Name: Terminal App
# Author: Stuart Gall
# Version: 0.1
# Script: /Terminal.sh
# Pack: /Term-vt100.zip
# URL: http://none.none
# Desc: Install Terminal app
When I try to select custom payload manually the file is greyed out. (ILiberty + 1.51)
TIA
George, I really need your help.
People asking me why my payloads won’t be installed under iLiberty+ 1.3 (they are recognized but not installed).
If you have an ICQ or MSN account please email me your contact info.
Thanks,
Andre
@Andre1C, if iL+ recognizes your payload, it will load it if you check it, same algo.
About the editors, you can use SciTE. Its free and light.
Free download from http://scintilla.sourceforge.net/ScintillaDownload.html