Useful Cydia Apps for pentesting

For pentesting iPhone applications, we need to download a lot of tools from Cydia. Some of the necessary  tools are –

  • OpenSSH – Allows to connect to the iPhone remotely over SSH
  • Adv-cmds : Comes with a set of process commands like ps, kill, finger…
  • Sqlite3 : Sqlite database client
  • GNU Debugger: For run time analysis & reverse engineering
  • Syslogd : To view iPhone logs
  • Veency: Allows to view the phone on the workstation with the help of veency client
  • Tcpdump: To capture network traffic on phone
  • com.ericasadun.utlities: plutil to view property list files
  • Grep: For searching
  • Odcctools (Darwin CC tools): otool – object file displaying tool
  • Crackulous: Decrypt iPhone apps
  • Hackulous: To install decrypted apps
  • Cycript: Run time analysis & reverse engineering

    * To install crackulous and hackulous add to Cydia sources.
    * To install GNU Debugger on iOS 5 view –

Posted by on February 7, 2012 in iPhone

1 Comment

Tags: , , , , ,

Blind Sql Injection – Data Extraction Part 1

Article below will provide you with overview of how to extract data when any application has blind sql injection vulnerability.

Assuming that, you already have some knowledge on Sql Injection ( SQLi ) and identifying sql injection. I will jump straight to the data extraction.

As you all know SQL Injection is attack where user provided sql statements can executed to perform unintented operation, blah blah… For proper defination, please refer OWASP Website. 🙂

In blind sql injection, an attacker can inject sql statements and steal data by asking a series of True or False questions through Sql Statements.


Let us suppose a application takes the user input and tries to build a sql query as below

Sqlquery = “select * from users where username = ‘” + txtusername.text + “’”            

If the user enters “john’ and 1=1–“ ( no double quotes in input )

The final query will look something like this

select * from users where username = ‘john’ and 1=1–

this will still return the results for user john.

In the above example if the user enters “john’ and 1=0” in the search text box then the query will be:  select * from users where username = ‘john’ and 1=0–

So here we have 2 queries, one of them will return the data for user “john” and another will not. Using these 2 conditions the user will be able to extract the data from the database.

Data Extraction

Now question comes, how can we extract data from database by just using true or false conditions.  To answer that, first we need to get understanding of how computers handle data internally.

In computer, all the data is handled in 1’s and 0’s i.e binary. Character “A” is represented by ascii value 65. Binary representation of 65 is 01000001

In Blind Sql injection, we try to determine the value of each bit with one request and try to construct the character after we get all the 8 bits value. So we need 8 requests in here to get one character from database.

Let us see how we perform this to get the information.

Assuming that we are working on Sql Server database and want to extract the database user name under which the sql queries and being run.

Sql server provides built in variable to get this information, it can be retrieved by using

Select user query.

Let us assume that the above query will return “scott” ( this is just for better understanding, in actual we will not be knowing what the query will return )

To get the first character of user the query can be written as below

select substring(user,1,1)

I got the first character, now how to get the ascii value to first character?

select ascii(substring(user,1,1))

ascii value of “s” is 115. Binary representation is 01110011

we try to do some exclusive or operations on the ascii value and see what the results are:

115 XOR 1 = 114  ( 01110010 )

115 XOR 2 = 113 ( 01110001)

115 XOR 4 = 119 ( 01110111)

115 XOR 8 = 123 ( 01111011)

115 XOR 16 = 99 ( 01100011)

115 XOR 32 = 83 ( 01010011)

115 XOR 64 = 51 ( 00110011)

115 XOR 128 = 243 (11110011)

The reason we have taken 1,2,4,8 etc for XOR here is that, if you see the binary representation of these numbers, they will have 0’s in all the positions except one and that position will determine the bit position for which we are trying to retrieve the bit value.

If you observe the XOR output above, you will see that whenever the actual ascii value had 1 in the bit position then the final XORed value has decreased than 115 and when the bit value is 0 then the XORed value has increased more than 115. Based  on the above inference I can build my query as

select case when ascii(substring(user,1,1)) ^ 1 > ascii(substring(user,1,1)) then 0 else 1 end

^ denotes XOR operation in Sql Server.

So in the search field in the application we will enter following search string

john’ and 1= select case when ascii(substring(user,1,1)) ^ 1 > ascii(substring(user,1,1)) then 0 else 1 end–

if you see the condition above, 1=0 or 1=1 condition in the query will depend on the bit value of the
data that we are trying to retrieve.

If we send the below search strings to database

john’ and 1= select case when ascii(substring(user,1,1)) ^ 1 > ascii(substring(user,1,1)) then 0 else 1 end–

john’ and 1= select case when ascii(substring(user,1,1)) ^ 2 > ascii(substring(user,1,1)) then 0 else 1 end–

john’ and 1= select case when ascii(substring(user,1,1)) ^ 4 > ascii(substring(user,1,1)) then 0 else 1 end–

john’ and 1= select case when ascii(substring(user,1,1)) ^ 8 > ascii(substring(user,1,1)) then 0 else 1 end–

john’ and 1= select case when ascii(substring(user,1,1)) ^ 16 > ascii(substring(user,1,1)) then 0 else 1 end–

john’ and 1= select case when ascii(substring(user,1,1)) ^ 32 > ascii(substring(user,1,1)) then 0 else 1 end–

john’ and 1= select case when ascii(substring(user,1,1)) ^ 64 > ascii(substring(user,1,1)) then 0 else 1 end–

john’ and 1= select case when ascii(substring(user,1,1)) ^ 128 > ascii(substring(user,1,1)) then 0 else 1 end—

we should be able to determine all the 8 bits, once we retrieve all the 8 bits then we can get the ascii value and from ascii value get the character.

Once we get the first character we can tweak the substring function to substring(user,2,1) to get the 2nd character and repeat the steps.

In this fashion we can do bit by bit data extraction from the database. So need to have lot’s of patience…next part is going to cover the quick way of data extraction…wait for part 2  🙂


Posted by on January 31, 2012 in web application hacking

1 Comment

Tags: , , , , ,

iPhone: keychain dumper – killed 9 problem

In iPhone, keychain is a sqllite database which stores sensitive data on the device. Apple’s keychain service is a library/API provided by Apple that developers can use to store sensitive information on an iOS device securely.  Instead of storing sensitive information in plaintext configuration files, developers can leverage the keychain services to have the operating system store sensitive information securely on their behalf.

Keychain is encrypted with a hardware key.  Hardware key is unique per device and not even accessible to OS running on the device. So even if some one get access to the keychain db file in a remote attack (Remember android malware, which steal sqlite.db files and sent it to the remote server), they cannot decrypt and view the content. Keychain also restricts the application access to the stored data.  Each application on your device has a unique application-identifier (also called as entitlements).  The keychain service restricts which data an application can access based on this identifier. By default, applications can only access data associated with their own application-identifier. Later apple introduced keychain groups. Now applications which belong to same group can share the keychain items.

On a jailbroken device, all keychain entries can be accessed by writing an application and making it as a member of all application group.

One such tool designed to grab all the keychain entries is  keychain dumper –

Copy keychain_dumper to iPhone over ssh. Run the below command on SSH Terminal. This extracts all the keychain groups from keychain-2.db and stores in an xml file.

./keychain_dumper -e /var/tmp/entitlements.xml

Using ldid and entitlement xml file, we can make keychain_dumper program as a member of all keychain groups.

ldid -S/var/tmp/entitlements.xml keychain_dumper

Now running keychain dumper reads all the entries from keychain and displays it on the terminal.


On the newer versions of iOS (v5) running this tool ends up with killed 9 error.

The problem here is iOS kernel signature checks the binary file at several places. Jailbreak tools cannot patch all these signature checks because it is difficult for them to patch each and every signature check. When we copy keychaindumper to iPhone, it does not have a signature. So running the binary exits with killed 9 message because iOS kernel does not have the signature of keychain_dumper.

To get rid of this problem add the signature of keychain_dumper to kernel cache (list of hashes) by running the below command. After adding the signature, you can run the rest of commands to dump the keychain entries.

ldid -S keychain_dumper

But in the newer versions (5.0.1), this workaround is not working. Because we have to run ldid command twice with -S option. This tries to overwrite the binary hash on kernel cache and fails. So follow the below listed steps to use the keychain_dumper on newer versions of iOS.

1. Copy keychain_dumper to iPhone over SSH.
2. Manually dump keychain groups with the help of sqlite3 command.
>  Sqlite3 /var/Keychains/keychain-2.db “select agrp from genp”
Running this command on my phone listed three access groups.
–   apple,,
3. Create a XML file similar to the sample shown below with all the keychain groups listed  by above command
(paste the keychain group name in the string tags).


<?xml version=”1.0″ encoding=”UTF-8″?>
<!DOCTYPE plist PUBLIC “-//Apple//DTD PLIST 1.0//EN” ““><plist version=”1.0”>

4. Copy sample.xml to /var/tmp folder on iPhone.
5. Run below commands to dump the keychain entries.
> ldid –S/var/tmp/ent.xml keychian_dumper
> ./keychain_dumper

To run the keychain_dumper again, follow all the steps.

[Update: 31-Jan-2012]
New version of keychaindumper has released. So you will not face killed 9 problem any more.
More details are available at –


Posted by on January 21, 2012 in iPhone


Tags: , , , , ,

iPhone Forensics – on iOS 5

iPhone Forensics goal is extracting data and artifacts from iPhone without altering the information on the device.
iPhone forensics can be performed on the backups made by iTunes (escrow key attack) or directly on the live device. This article explains the technical procedure and the challenges involved in extracting data from the live iPhone.

The techniques explained in the article only works for iPhone 3gs, iPhone 4 & iPad1. It does not work for iPhone 4s, iPad 2,  iPad 3 and iPad mini.

Techniques explained in the article also works for iOS 6 (Use iOS 5.1.1 ipsw file iOS 6 devices).

Forensics on Live Device:

Jean Sigwald a researcher at Sogeti ESEC Labs has released open source forensic tools (with the support of iOS 5) to recover low level data from the iPhone. Below details outline their research and gives an overview on usage of iPhone forensic tools.

iPhone 4 GSM model, running with iOS 5.1.1 is used for the demos.

Steps involved in iPhone forensics:

  • Creating & Loading forensic toolkit on to the device without damaging the evidence
  • Establishing a communication between the device and the computer
  • Bypassing the iPhone passcode restrictions
  • Reading the encrypted file system
  • Recovering the deleted files


1. Creating & Loading forensic toolkit

Imagine a computer which is protected with OS level password –  we can still access the hard disk data by booting a live CD or by removing the hard disk and connecting it to other machine. When we compare computers to the iPhone, it is an embedded device. So it is not easy to take out the chips (hard disk) and dump data in it. iPhone makes chip dumping even more complicated by encrypting the data during storage. In order to perform iPhone forensics, we use Live CD approach. As the iPhone has only one serial port, we are going to load custom OS over USB to access hard disk (NAND chip) of the device. But the problem here is, iPhone only loads the firmware which is signed by Apple.

In order to create and load forensic toolkit, first we need to understand iPhone functions at operating system level.  iOS (previously known as iPhone OS) is the operating system that runs on all Apple devices like iPhone, iPod, Apple TV and iPad.  iOS is a zip file (ships as an .ipsw file) that contains boot loaders, kernel, system software, shared libraries & built in applications.

When an iPhone boots up, it walks through a chain of trust which is a series of RSA signature checks among software components in a specific order as shown in Figure 1.

The BootRom is a Read only memory (ROM) and it is the first stage of booting an iOS device. BootRom contains the Apple root certificates to signature check the next stage.

iPhone operates in 3 modes – Normal Mode, Recovery Mode, DFU mode

In Normal mode, BootRom start off some initialization stuff and loads the low level boot loader (LLB) by verifying its signature. LLB signature checks and loads the stage 2 boot loader (iBoot). iBoot signature checks the kernel & device tree and kernel signature checks all the user applications.

In DFU mode, iPhone follows the boot sequence with a series of signature checks as shown in
Figure 2. BootRom signature checks the second level boot loaders (iBSS, iBEC). Boot loader signature checks the kernel and kernel signature checks the Ramdisk.

During iOS update, Ramdisk gets loaded into RAM and it loads all other OS components. In Forensics, we will create a custom Ramdisk with all our forensic tool kit and load it on iPhone volatile memory. Signature checks implemented at various stages in the boot sequence does not allow loading our custom Ramdisk. To load our custom Ramdisk we have to bypass all these signature checks. In the chain of trust boot sequence, if we compromise one link, we can fully control all the links that follow it. The hacker community have found several vulnerabilities in BootRom using which we can flash our own boot loader and patch all other signature checks in all the subsequent stages. Apart from signature checks, every stage is also encrypted. These encryption keys can be grabbed from JailBreaking tools.

Building custom Ramdisk

First we will build a custom Ramdisk with all our forensic tools and patch the Ramdisk signature checks in kernel. Later, we use jailbreak tools to load our kernel by patching BootRom signature checks.

With the open source forensic toolkit released by Sogeti Labs, we can build Ramdisk only on MAC OS X. During this article, Ramdisk is built on MAC OS X 10.6. The entire forensic toolkit contains python scripts, few binaries and few shell scripts.

In order to run the tools, first we need to install all the dependencies (Use the below listed commands from OS X terminal).

Download and install Xcode 4. It installs the required compilers (ex: gcc).

Download ldid, grant execute permissions and move it to /usr/bin directory. ldid is used for signing the binaries.

curl -O
chmod +x ldid
sudo mv ldid /usr/bin/

Download and install OSXFuse. OSXFUSE allows to extend Mac OS X’s native file handling capabilities via third-party file system.

curl -O -L
hdiutil mount OSXFUSE-2.3.4.dmg
sudo installer -pkg /Volumes/FUSE for OS X/Install OSXFUSE 2.3.pkg -target /
hdiutil eject /Volumes/FUSE for OS X/

Download & install python modules – pycrypto, M2crypto, construct and progressbar.

sudo ARCHFLAGS='-arch i386 -arch x86_64' easy_install pycrypto
sudo easy_install M2crypto construct progressbar

Download and install Mercurial ( to check out the source code from the repository.

hg clone
cd iphone-dataprotection

Compile img3fs.c which is located in img3fs folder. This script is used to encrypt and decrypt Ramdisk and kernel. If you run into a problem while running this command, edit the makefile in img3fs folder and change the compiler path.

make -C img3fs/

Download redsn0w which is a famous JailBreaking tool. Keys.plist file inside redsn0w contains the encryption keys to decrypt Ramdisk and Kernel.

curl -O -L
cp redsn0w_mac_0.9.14b2/ .

To patch the signature checks in kernel, supply iOS 5.1.1 ipsw file to iOS 5.1.1 ipsw file can be downloaded from which maintains all iOS versions for all Apple devices.

python python_scripts/ iPhone3,1_5.1.1_9B208_Restore.ipsw

The above python script creates a patched kernel and a shell script to create Ramdisk.

sh ./

Running the shell script downloads the forensic tool kit (ssh.tar.gz) and adds it to the Ramdisk. The Ramdisk image is just a plain HFS+ file system which is native to Mac OS, making it fairly simple to add files to it. All the steps mentioned above create a patched kernel and a custom Ramdisk with forensic tools.

Note: I have created the patched kernel and the custom Ramdisk for iPhone 4. You can directly download these files and skip all the above steps.

Download Link –

Loading Forensic Toolkit

In order to load forensic toolkit, supply iOS 5.1.1 ipsw file, patched kernel and custom Ramdisk to redsn0w tool. Connect the device to computer using USB cable and run the below command. Follow the steps displayed by redsn0w to boot the device in DFU mode. In DFU mode, redsn0w exploits the BootRom vulnerability and loads patched kernel & custom Ramdisk on to the device.

./redsn0w_mac_0.9.14b2/ -i iPhone3,1_5.1.1_9B208_Restore.ipsw -r myramdisk.dmg -k kernelcache.release.n88.patched

If the process fails with the No identifying data fetched error, make sure that the host computer is connected to the internet. After redsn0w is done, the Ramdisk boots in verbose mode. Upon successful boot up, iPhone displays ‘OK’ message.

2. Establishing device to computer communication

Once booted with custom Ramdisk, networking capabilities (like WI-FI) are not enabled by default. So a different way is chosen to communicate with the device by following the approach that Apple took with iTunes. USBMUX is a protocol used by iTunes to talk to the booted iPhone and coordinate access to its iPhone services by other applications. USB multiplexing provides TCP like connectivity over a USB port using SSL. Over this channel iTunes uses AFC service to transfer files. But here we use this channel to establish a SSH connection and get shell access to the device.

SSH works on port 22. script redirects port 22 traffic to 2222 port.

python usbmuxd-python-client/ -t 22:2222 1999:1999

SSH is now accessible at localhost:2222.

ssh -p 2222 root@localhost
password: alpine

At this point, we get access to the file system. To make things even more complicated, every file is encrypted with its own unique encryption key tied to particular iOS device. Furthermore, data protection mechanism introduced with iOS 4 adds another layer of encryption that does not give access to the protected files & keychain items when the device is locked. Data protection is the combination of using hardware based encryption along with a software key.  Every iPhone (>3gs) contains a special piece of hardware (AES processor) which handles the encryption with a set of hardcoded keys (UID, GID). OS running on the device cannot read the hardcoded keys but it can use the keys generate by UID (0x835 and 0x89B) for encryption and decryption. Software key is protected by a passcode and is also used to unlock the device every time the user wants to make use of the device. So in order to access the protected files, first we have to bypass the passcode.

3. Bypassing the iPhone passcode restrictions

Initially (< iOS 4), passcode is stored in a file which can be removed directly over SSH. Since the introduction of data protection (from iOS 4), passcode is used to encrypt protected files and keychain items on the device. So in order to decrypt the data, we have to supply the valid passcode.

Passcode validation is performed at two levels one at springboard and another one at kernel level. Brute force attack performed at springboard level locks the device, introduces delays and may lead to data wipe-out. However these protection mechanisms are not applicable at kernel level (AppleKeyStore method) and it leads to brute force attacks.  To make brute force attacks less practical, passcode key derived from the user passcode is tied to hardware UID key.  So the brute force can only be performed on the device and it is not possible to prepare pre compute values (like rainbow tables) offline. script can be used to brute force the 4 digit passcode.

python python_scripts/

Port 1999 opened with is used by the brute force script. It connects to the custom restored_external daemon on the Ramdisk, collects basic device information (serial number, UDID, etc.), unique device keys (keys 0x835 and 0x89B), downloads the system keybag and tries to brute force the passcode (4 digits only).

Table 1 illustrates the time required to brute force different types of passcodes.

4. Reading the encrypted file system

Upon successful passcode brute force, the script automatically downloads the keychain. Keychain is a SQLite database which stores sensitive data on your device.  Keychain is encrypted with hardware key.  Keychain also restrict which applications can access the stored data.  Each application on your device has a unique application-identifier (also called as entitlements).  The keychain service restricts which data an application can access based on this identifier. By default, applications can only access data associated with their own application-identifier.  Later apple introduced keychain groups. Now applications which belong to same group can share the keychain items.  There are two ways to access all the keychain items. One way is, by writing an application and making it as a member of all application groups. The other way is by writing an application and granting entitlement.

Keychain database contents can be extracted using

python python_scripts/ -d [UDID]/keychain-2.db [UDID]/[DATAVOLUMEID].plist

To dump the iPhone file system execute the dump_data_partition shell script.


The script reads the file system from the device and copies it to UDID directory as an image (.dmg) file. The image file can be opened using the modified HFSExplorer that will decrypt the files on the fly. To decrypt it permanently, script can be used.

python python_scripts/ [UDID]/[data_DATE].dmg decrypts all files in the file system image. To view the decrypted files, mount the file system with below command.

Hdituil mount [UDID]/[data_DATE].dmg

As soon as the file system is decrypted, there are various files of interest available such as the mail database, the SMS database and location history, etc…

5. Recovering the deleted files

Deleting a file on iPhone, only deletes the file reference. So it is possible to recover the deleted files. To recover the deleted files run script.

python python_scripts/ [UDID]/[data_DATE].dmg

With this technique it is possible to recover valuable data like call logs, deleted images, deleted SMS, deleted contacts, deleted voicemail and deleted emails.

With the techniques illustrated in the article it is clear that iPhone Forensics is still possible on the latest version of iOS.

Techniques used in the article are explained and demonstrated in the video.




I wrote this article for infosecinstitute.


  1.  iPhone data protection in depth by Jean-Baptiste Bédrune, Jean Sigwald
  2. iPhone data protection tools
  3. ‘Handling iOS encryption in forensic investigation’ by Jochem van Kerkwijk
  4. iPhone Forensics by Jonathan Zdziarski
  5. iPhone forensics white paper
  6. Keychain dumper
  7. 25C3: Hacking the iPhone
  8. iPhone wiki

Posted by on January 10, 2012 in iPhone


Tags: , , , , , , , , , , ,

Pentesting Web Applications

I use these slides for my training. Initially I thought of not sharing with anyone. Later I felt, even if someone use my slides, they cannot teach like me 🙂



Posted by on November 21, 2011 in web application hacking


Tags: , , , ,

iPhone 4- Gevey sim unlock useful tips

If you are using Gevey unlock and want to upgrade your iPhone to ios 5 , do not directly update it through iTunes. Use redsnow and create a custom os bundle which preserves the old baseband. Detailed steps can be found at – Update to iOS 5 by preserving baseband

After installing iOS 5 you need to activate the phone. Activation is different from unlocking . To activate the phone you will require an original sim (carrier to which the phone is locked). If you do not have the original sim, close iTunes and use redsnow to jailbreak the phone. After jailbreaking, open iTunes and activate the phone.

Now insert your Gevey sim to unlock the iPhone. It works perfectly on iOS 5 and baseband 4.10.1.

Gevey sim problems that I have faced and the solutions

– After the sync with iTunes (over USB), Gevey sim stopped working (you will see no service message). It seems Apple is sending some instructions to phone to disable the Gevey sim. I removed the sim and inserted it again. Then Gevey sim started working.

– To get rid of this problem, I am disconnecting the internet from my machine (on which iTunes is running) while syncing the phone. So far, I did not face any problem with this method.

– After syncing the phone with iTunes over Wi-Fi, Gevey sim stopped working and I spent a lot of time to make it work. One solution that I found is – sync the phone with iTunes (disconnect internet from laptop) over USB then remove the sim and insert it again. Hereafter Gevey sim worked well .

– After downloading GPRS or 3G settings, those settings did not work. To make it work, I restarted the phone, removed the sim and inserted it again.

– If none of those techniques work or if you see invalid sim message: Remove & insert the sim. After few minutes you will see No service message. Dial 112 and end the call in a minute. Turn on airpot and off it in a minute. It will show SIM Failure message. You might get signal by this time. If not, it might have shown you invalid sim message. Now remove the sim and insert it again. And do not do anything. You will see the signal in few minutes.

– If you have jailbroken iOS 5 (currently only tethered jailbreak is available), when you restart the phone you have to use redsnow just boot option to make the phone work. If you Want to restart your phone without connecting it to laptop, one alternative is, use of software restart called respring. Download sbsettings from Cydia and it will show respring option. Now on-wards whenever you want to restart the phone, use respring option.

– Turning on 3g may drops the signal, then remove and insert the sim, gevey displays accept message. Click on it. Wait for 1 minute and dial 112 and hangup. Turn on airplane mode till you see no sim card installed message. Turn off airplane mode. It displays the signal now (even for gevey ultra sim, you have to follow all the steps).

– This technique worked for all kind of signal problems: Remove the sim card when you notice no service message. If you see other messages like invalid sim, turn on and off airplane mode until you see no service message. Insert sim, then gevey displays accept message. Click on it. Wait for 1 minute (you may notice no service message) and dial 112 and hangup. Turn on airplane mode till you see no sim card installed message. Turn off airplane mode. Wait for few seconds. You will notice sim failure, invalid sim message. Later it starts searching for signal and displays the full signal (all the steps are necessary even for gevey ultra sim) .

– Turning on 3g sometimes may show only one signal bar and slowly drops the signal. To get rid of this problem, always first turn on cellular data then turn on 3g.

[Update: 01-Feb-2012]
Gevey sim is working with iOS 5.0.1 (base band 4.10.01). Preserver base band before updating it – Update iOS 5.0.1 by preserving baseband

It is good to update to 5.0.1 because untether jailbreak is available. Which means you can turn on/off phone happily.

[Update: 14-Feb-2012]
When you want to use internet, Turning on cellular data may not work. If it does not work turn on cellular data and data roaming.

[Update: 26-Apr-2012]
Gevey sim is no more required. You can directly unlock your iPhone running on any baseband with SAM unlock method. Details are available at –

No more gevey sim problems …..

[Update: 03-May-2012]
SAM unlock is no more working. Now the only unlock solution available is Gevey sim. Latest version of gevey sim (Ultra S) also supports iPhone4 – 4.11.08 baseband.


Posted by on October 31, 2011 in iPhone


Tags: , , , , , , ,