Cracking Alchemy on the iPhone

Someone asked me how I got all of the Recipes for Alchemy on the IPhone. The answer – I cheated. I hacked the system.

Let me describe how I did this. There is some simple perl scripting involved, which might be useful to people.

Step 1 – Jailbreak the  iPhone

I’m a hacker. What can I say.

Step 2 – Getting the Alchemy Files

Find where the Alchemy application is stored.

You can open a terminal window, run find, and look for some file that has Alchemy in the name.

find / -name Alchemy*

Instead of a terminal window, you might find it easier to ssh into the iPhone. You do have to use Cydia to install the various extra programs. I had the following installed

  • Bourne-Again shell
  • Openssh

Once OpenSSH is installed, you have to use your iPhone, check the settings, and find your IP address. Say it’s 192.168.1.222. The iPhone has a habit of shutting down its IP address if not in use. So refresh the IP address using the DHCP refresh, and then type

ssh -l mobile 192.168.1.222

The password for the user “mobile” is “alpine”

Then use ‘find’ to locate the file. Once you have found this, grab all of the Alchemy files by typing the following on your Linux (ofr Windows with Cygwin)

Copying the Alchemy files onto your Linux machine

scp -r mobile@192.168.1.181:/var/mobile/Applications/9E1E4FC0-B6CE-4036-8DFB-BCB5666D4741/Alchemy.app .

This will copy all of the files onto your computer.
The string above is on my machine. Your mileage may vary.
You can examine the files to see what they contain using “string” “od”,  “emacs”, or whatever. It turns out that the file you want is Sparing.plist.

Next you want to decode the resource file that contains the recipes. I use perl. Looking at the various packages, the one that makes the most sense is the Mac::PropertyList module. Looking at the Dependency, it requires the XML::Entities module. Therefore, after you install perl, download and install the two Perl modules.

Step 3 – Getting Ready to use perl

Making it easier to install perl modules

I prefer to make sure /usr/local belongs to a certain UNIX group(5), such as adm, and that all of the subdirectories have group write permission.

In other words, type the following commands as root

chgrp  -R adm /usr/local
chmod -r g+w /usr/local

Installing the two perl Modules

This way you can install modules without requiring root access. To make the modules, after you download them, type

tar xfz XML-Entities*
cd XML-Entities
perl Makefile.pl
make
make install
cd ..
# And now do the next one
tar xfz Mac-Properties*
cd Mac-Properties*
perl Makefile.pl
make
make install
cd ..

Step 4-Extracting the Alchemy data from the Resource file

The Mac::PropertyList module creates a complex data structure with all of the information. The elegant thing to do is to write one perl program that reads the data and prints the results you want to get. But that takes more work. I prefer the “get the job done as easy as possible” school of programming. Rather than try to figure out the format of the complex data, the simplest thing to to is to let perl decode the binary information for you. The program to use is Data::Dumper which outputs the structure of complex data. This is essential for the Perl programmer. You just give it a pointer to a complex piece of data, and Data::Dumper will describe it. The code to read the file and dump the results is below:

#!/usr/bin/perl
my $filename="./Alchemy.app/Sparing.plist";
use Mac::PropertyList qw( :all );
use Data::Dumper;
my $data  = parse_plist_file( $filename );
my $text  = plist_as_string( $data );
print Dumper($data);

Call this program List,  add the +x attribute with chmod, and they type

./List >List.out

If you look at the output of this file, you will see something that looks like this

VAR1 = bless( {
    'Metal+Electricity' => bless( do{(my $o = 'Aluminium')}, 'Mac::PropertyList::string' ),
    'Oil+Tool' => bless( do{(my $o = 'Petrol')}, 'Mac::PropertyList::string' ),

etc.

Aha! Clearly, Metal+Electricity creates Aluminum. Let’s write a perl script that reads this file, and outputs the recipe.

But some of the lines, like the first one, is a different format. Well, perl can handle this very easily.

Parsing ASCII in perl

I usually use the following template to do string parsing

#!/usr/bin/perl -w
use strict;
#my filename="List.out";
my $line;

while (defined($line=<>)) {
# 'Metal+Electricity' => bless( do{(my $o = 'Aluminium')}, 'Mac::PropertyList::string' ),

     if ($line =~ /complexstring/) {
     } elsif ($line =~ /string/){

          printf("You didn't match this line: $linen");
     } else {
          printf("Can't parse line: $linen");
     }
}

I include the string I am trying to parse as a comment, to help me get the regular expression correct.

The second string is how I debug the first string

First attempt at matching an ASCII line  in perl. I replace the strings I am tring to match ‘Metal+Electricity’ and ‘Aluminum’ with “.*”

if ($line =~ /'.*' => bless( do{(my $o = '.*')}, 'Mac::PropertyList::string'/) {
 } elsif ($line =~ /bless/){

But I want to remember the strings found within the ‘…’, so I need to add parenthesis around them, so perl will remember them. This would be

if ($line =~ /'(.*)' => bless( do{(my $o = '(.*)')}, 'Mac::PropertyList::string'/) {
   printf("$1 => $2n");
 } elsif ($line =~ /bless/){

This is a start, but there is a problem. When I use sed, I need to put backslashes before the parenthesis to mark them as special. Perl is the opposite. A backslash means the character is NOT  special, or NOT a metacharacter.

So I need to put backslashes around the other parenthesis

if ($line =~ /'(.*)' => bless( do{\(my $o = '(.*)')}, 'Mac::PropertyList::string'/){

I also needed to put a backslash before the backslash. Running this gives me the error

Global symbol "$o" requires explicit package name at ./ParseBug.pl line 6.

(Smack forehead) I also need to put before the ‘$’

Sometimes I need to experiment with the regex, and the second line, where the ‘/bless/ is show, is a guess. Note that this also prints out lines that don;t match anything.
Eventually, I get this right. The final version is

-
#!/usr/bin/perl -w
use strict;
#my filename="List.out";
my $line;
while (defined($line=<>)) {
 if ($line =~ /'(.*)' => bless( do{\(my $o = '(.*)')}, 'Mac::PropertyList::string'/){
   printf("%s=%sn", $2, $1);
 } elsif ($line =~ /bless/) {
   printf("missed line: $linen");
 } elsif ($line =~ /VAR1/) {
 } elsif ($line =~ /Mac::PropertyList::dict/) {
 }else {
   printf("Can't parse line: $linen");
 }
}

This prints out all of the recipes

Advertisements
This entry was posted in Hacking, Shell Scripting and tagged , , , , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s