Analyzing the PSX emulator on the Xperia Play

I’ve been playing around with the new Xperia Play (well, with the speed of these Android phone releases, it’s already old). I’ve decided it would be a challenge to try to figure out how the PSOne emulator works and eventually be able to inject any ISO and play it with Sony superior PS1 emulator. Just to be clear, nothing is done yet, and this is just a technical post to aid whoever else is trying to do the same thing. Also, because information should be free.

Decompiling and disassembling

Before we can do any analyzing, we need to break everything open. I found a couple of useful tools to aid with reverse engineering Android applications. First up is apktool, which is like an all-in-one Android app decompression and decompilation tool. It uses various other tools to do stuff like decompress resources, convert the meta files to be readable, and use baksmali to disassemble Dalvik bytecode to assembly code. Another useful tool is dex2jar, which converts Dalvik bytecode to regular Java bytecode and generates a jar that can be decompiled to Java code using a decompiler like, my favorite, JD-GUI. Last, but not least, we have the big guns: IDA Pro, which I’ve used religiously for many projects. If you don’t know, it can disassemble almost any binary, including native ARM libraries.

Stepping through

The first thing to do once we reversed all the code is to read it. A good way to start is to follow an application from start to finish through the code. Looking in the Android manifest file, we find the main activity that is started is com.sony.android.psone.BootActivity. We open that up, look at onCreate() and read what it does, follow whatever methods it calls and read through all those too. It may get a bit complicated, so I suggest thinking like a stack. From what I can understand, the first thing the app does is check if the data is downloaded. “Crash Bandicoot” is a 500MB game, so it would use up all the system space, so what Sony did is pack the binaries into the APK installed on the system, and the game data (textures, images, etc) is a ZPAK (renamed PKZIP) file that is downloaded from their servers if deleted. Once the data is verified to exist or downloaded from Sony’s servers, the baton is passed to a native JNI library to do the actual work.

Native code

Sony sees the Xperia Play not as just an Android phone, but a game platform. They call it “zplatform”, or as I guess: Zeus Platform (Zeus was the codename for the Xperia Play). The platform APIs is found on libzplatform.so, which is linked by all platform compliant (read: only on Play) games. It contains functions for extracting/creating ZPAK files as well as a lot of encryption/decryption commands and other stuff like networking. Another library is libjava-activity.so, which contains the actual emulator. Well, sort of. libjava-activity.so contains almost 2MB worth of crypto-security functions. It’s sole purpose is to decrypt and load into memory, three files (two of which are stored encrypted inside libjava-activity.so). They are: image_ps_toc (I can only guess it relates to the ROM file, image.ps), ps1_rom.bin (the PS1 BIOS, found in the data ZPAK), and libdefault.so (the main executable, aka: the emulator).

ZPAK files

The ZPAK file is basically a ZIP file that stores the game data. I only looked through “Bruce Lee” and “Crash Bandicoot”, but from what I can see there, all ZPAK files contain a metadata XML and one or more encrypted data files. For example, Crash Bandicoot’s ZPAK data contains image.ps, which I can guess from the size, is the ROM file for the game. I do not know if it’s an ISO or if it’s compressed, but that’s not important right now. There’s also ps1_rom.bin, which I can say for certain after reading the code to decrypt it, is the PS1 BIOS file, compressed using zlib. There’s also pages from the manual named for their page number and have no extensions. I can assume that they’re encrypted too because they contain no image header and the first two bytes are not the same throughout. The main thing I need to figure out is if the encryption key is common or not.

The white box

The main executable, libdefault.so, is completely encrypted and obfuscated by libjava-activity.so, which implements a white box security. If you read anything about white box cryptography (Google), you’ll see that it’s sole purpose in existence is to prevent itself from being reverse engineered. It hides the decryption key in a giant table or an even bigger finite-sized key. Nevertheless, it would take someone, a group of people smarter than me (not that that’s hard to find) to crack this file.

What’s next

Unfortunately, that’s all I know for now. Why? Because the CDMA version of the Xperia Play has not been rooted yet, and any farther analysis would require client access. I’m in the process to locating a R800i model of the Play to test with, but for now, I hope that someone who knows what they’re doing reads this and continue where I left off.

There are two giant problems that’s preventing us from injecting any PS1 image into the emulator. First of all, everything is encrypted. My hope is that it’s a single key used in zplatform (seeing that there’s functions such as zpCryptDecrypt and zpCryptEncrypt in the platform APIs) is used by Sony to encrypt image.ps and the manuals. Second of all, we need libdefault.so, the emulator. This may be easier then imagined. White box cryptography is used to hide the decryption key, not the decrypted content. My hope is that libdefault.so is loaded into RAM after libjava-activity.so decrypts it. There is a high chance of that because it would be hard to hide an executable and run it at the same time. If that is the case, disassembling the emulator will produce more results. If you have a rooted Xperia Play, set up USB debugging, and open up Crash Bandicoot. Connect the Play, and call “adb shell dd if=/dev/mem > memdump.bin” and then “adb shell dd if=/dev/kmem >> memdump.bin” (I don’t know which one would work, so try both). That will (hopefully) produce a memory dump that will contain the emulator executable. Once we have this, even if we cannot decrypt image.ps, it may be possible to write an alternative wrapper application that will load ISOs or something.

Porting Kindle 3.1: Part 2 – Update encryption

Overview

So, on the topic of Kindle (I swear, it’s becoming an obsession). I am currently in the process of porting the Kindle 3.1 software to Kindle 2 and DX. I will make a series of posts describing my process while describing how various parts of the Kindle operating system works. Now I’ve tested 3.1 on my Kindle 2 and it works perfectly fine. All features work (audio, TTS, book reading), and the new features also work without major slowdowns (new PDF reader, new browser, etc).

Where’s part one you ask? Well, part one was getting the 3.1 OS to work on the Kindle 2, the rest is making an easy installer. That is a long story that involves custom partition tables, manually creating tar files (checksums are a pain), remote debugging, and more. It’s a lot of stuff and most aren’t very useful because nobody should have to repeat the process, which is why I’m creating a easy to use installer. If I have time one day, I may write it down for documentation purposes.

First of all, I will write down the game plan. What I plan to do is create an installer with the least amount of steps for the user. I’m hoping for a two part or three part installer. (Can’t be one part because you need a copy of the OS, and distributing it is most likely frowned upon by Amazon). How the installer should work is:

  1. User copies a image-creator package on a jail-broken Kindle 2. This package will backup the original OS, and generate a new ext3 image with some required files from the Kindle 2 (drivers and such). It will also update the kernel to support recovery packages.
  2. User keeps backup in a safe place and copies the image-creator package and the image generated from the K2 on a jail-broken Kindle 3 and runs the package. The image-creator will scan the filesystem making sure all files exist are are unmodified, then copies the files to the ext3 image. It will then take the ext3 image and generate a Kindle 2 recovery package with the 3.1 OS.
  3. User copies the recovery package generated from the Kindle 3 and copies it to the Kindle 2 and restarts. The Kindle will write the ext3 image to the root partition.

Update Encryption

Now, Igor Skochinsky wrote a nice post a couple of years ago on the Kindle update encryption algorithm. Basically, to encrypt an update, you take each byte of the file and shift the bits four to the left and OR it with the same bits shifted four to the right. Then you AND the result by 0xFF and XOR it by 0x7A. (Sounds like some computer dance move). Well, Igor also wrote a nice Python script that does the encrypting and decrypting, but I didn’t want to port Python to Kindle, so I decided to modify Amazon’s update decryption script “dm” and reverse it to make a encryption script “md”. I opened up IDA Pro and looked for the encryption. Here it is nicely commented by me into psudocode:

BL getchar // get byte to modify

EOR R3, R0, #0x7A // R3 = R0 ^ 0x7A

CMN R0, #1 // if !(R0 == 1), we are at the end of the file …

MOV R0, R3,LSR#4 // R0 = R3 >> 4

AND R0, R0, #0xF // R0 = R0 & 0xF

ORR R0, R0, R3,LSL#4 // R0 = R0 | R3 << 4

BNE loc_8470 // … then jump to end of program

MOV R0, #0 // clear R0 register

ADD SP, SP, #4 // don’t care

LDMFD SP!, {PC} // don’t care

It was a simple matter of reversing the instructions and registers, but like I said before, IDA Pro does not allow changing instructions directly, so I had to mess around with the machine code in the hex editor until I made the instructions I want. Here’s the modified function nicely commented by me in human.

BL getchar // get byte to modify

CMN R0, #1 // if byte is 0×01, then …

MOV R3, R0,LSR#4 // set R0 to R0 right shift 4

AND R3, R3, #0xF // set R4 to R4 logical AND 0xF

ORR R3, R3, R0,LSL#4 // set R3 to R3 logical OR ( R0 left shift 4 )

EOR R0, R3, #0x7A // set R0 to R3 logical exclusive OR 0x7A

BNE loc_8470 // … exit program

MOV R0, #0 // clear register R0

ADD SP, SP, #4 // don’t care

LDMFD SP!, {PC} // don’t care

If you want to try it out, here’s the bspatch from “dm” to “md”. MD5 of dm is 6725ac822654b97355facd138f86d438 and after patching, md should be 3b650bcf4021b41d70796d93e1aad658. You can copy md to your Kindle’s /usr/sbin and test it out:

echo ‘hello world’ | md > hello.bin # “md” encrypt ‘hello world’ and output to hello.bin

cat hello.bin | dm # “dm” decrypt hello.bin and it should output ‘hello world’

Now that we can create update packages from the Kindle, I can start working on the Kindle 2 image-creator script.