Top Menu

A Brief History Lesson

Lets quickly rewind to 11 years ago (2006) and refresh our memory of the very first custom firmware: 2.71 SE-A. Dark_AleX and team designed this custom firmware based on Devhook, a piece of software that allowed you to load the latest PSP firmware from the memory stick. Devhook provided the basic foundation for loading non-host firmware and 2.71 SE-A exploited this knowledge and combined both 1.50 and 2.71 to create a hybrid firmware. This technique was implemented through SE, OE and the start of M33. Beyond this, a custom IPL was used for custom firmware.

The custom IPL method worked fantastically until newer PSP models started shipping with patched bootroms. The first hack for these newer devices was a simple homebrew enabler (HEN) on 5.03, called ChickHEN. You might remember the dramas and the struggle of constantly crashing when accessing photo menu. This was really the first stage of “new-era” homebrew/cfw since the departure of Dark_AleX and team M33. This stage onward, the primary source of homebrew was from HENs, which were non-persistent custom firmwares. These HENs were typically invoked using a kernel exploit and a user exploit in a game or third party library (libtiff, mainly…).

When the PS3 was hacked and a selection of PSP encryption keys were released, this allowed us to sign our own userland applications. This functionality brought us two great improvements:

  • HEN/CFW can be loaded much faster through a signed application
  • rather than loading a game and we can now sign our own vshmain and replace a step in the bootchain

kgsws first demonstrated this bootchain injection back in 2011 and lead to the creation of 6.20 permanent custom firmware. Sony did patch this up in later firmware by applying an ECDSA signature to PRX files in the bootchain which we cannot forge.

So, for Infinity to work we need one single crucial component: Find an exploit in the bootchain. This is easier said than done, of course. First we need to analyse how the PSP bootchain works.

PSP bootchain
PSP bootchain

First step in the PSP bootchain is the CPU bootrom which loads the IPL from NAND. The bootrom is obviously ROM and cannot be modified, so there is nothing we can control here. The IPL is formatted in a very primitive block structure of KIRK CMD 1 blocks. Unfortunately, we cannot decrypt the blocks of newer PSP models as the bootrom performs a XOR over the encryption key. This makes it incredibly difficult to forge IPL blocks. Additionally, in these newer models each IPL block has 0x20 bytes of hash data in the footer of the block. These 0x20 bytes are an encrypted MAC and would require knowledge of the bootrom to forge. These issues make breaking IPL loading very difficult.

The IPL is mostly used for seeding the system and initialising hardware devices. It loads and decrypts only three files: the bootconfig, sysmem.prx and loadcore.prx.

The bootconfig is a binary file that details the bootchain under certain modes. There are different bootchains for running a game and loading the XMB. The IPL decrypts this file and verifies the signcheck and header hash of all the modules in the current bootchain. It also loads all these files into memory to be loaded later.

Sysmem is a fairly benign module and mostly used for managing the PSP memory resources and UIDs. It’s role in the boot process is minimal, but provides utilities and functionality to later modules that will be loaded. This is an encrypted PRX and the IPL must be able to decrypt, decompress and load it.

Loading loadcore is the last stage of the IPL and is where responsibility is handed to load the rest of the firmware. Loadcore’s role in the OS is specifically the task of loading executables. It manages decryption, decompression, import/export linking and tracking loaded modules. In boot-time, it manages loading upto init.prx.

Init.prx is a very simple module which loads the rest of the bootchain specified by the bootconfig from the IPL. Init.prx also resolves the anchors in the bootconfig for apps which aren’t located in the NAND, such as games, homebrew, apps, etc. Init.prx doesn’t do the loading itself, it works as a proxy for modulemgr.prx which in turn utilises loadcore.

Of course, there are other vectors beyond init.prx as the system becomes more active. This could be malformed firmware for the ME processor, breaking assets and resources in the XMB, and many more. However, for an early as possible boot-time hack, we need to look at PRX loading. An early boot-time exploit is preferred, as it both provides greater flexibility in terms of recovery should a user accidentally delete or corrupt files in the firmware and allows custom firmware to run unaltered. If custom firmware is loaded later, patches need to be applied retroactively.

The Giraffe Bug

Infinity is based off a bug in PRX loading. It turns out loadcore is a bit indecisive about what it does with the optional and rarely used ~SCE header. This header is 64 bytes long and mostly unused other than a 32 bit size/offset field (lets call it sce_size) at +4 in the header. The main PRX decryption function sceKernelCheckExecFile just skips past the 64 bytes when it detects that sce_size is positive. sceKernelLoadExecutableObject, the actual ELF loading aspect of loadcore does the same thing. However, sceKernelProbeExecutableObject, which is used to get information about the PRX meta-data, skips past sce_size bytes. This inconsistency leads to the loading of an unencrypted PRX.

Lets quickly talk about how loadcore loads the first set of boot modules.

// decrypt prx
sceKernelCheckExecFile(prx_data, &info);

if (info.compressed) {
   // allocate memory for decompression buffer, etc
   // need to decrypt/decompress
   sceKernelCheckExecFile(prx_data, &info);

// get meta data
sceKernelProbeExecutableObject(info->base, &info);

When sceKernelCheckExecFile is invoked the first time, it will skip past the ~SCE header if present and attempt to do various operations. I’ve simplified down the operation, but below is a flowchart describing the basic tasks.

sceKernelCheckExecFile flowchart
sceKernelCheckExecFile flowchart

First off, if we provide an unencrypted PRX it will actually succeed to get through sceKernelCheckExecFile. sceKernelCheckExecFile isn’t here to validate that the PRX or ELF being checked is valid for the context – it only checks that the executable is consistent. Since under certain circumstances an unencrypted ELF/PRX can be valid (such as early release game titles), there is a path that succeeds. The problem is the internal flags such as is_decrypted will not be set so sceKernelProbeExecutable will fail.

sceKernelProbeExecutable is the function that checks an executable is valid for the context. So for a boot executable it must be encrypted. So how do we get through sceKernelCheckExecFile with an unencrypted PRX, but still somehow set flags that can only be set with an encrypted PRX? Lets talk about how sceKernelProbeExecutableObject works. Firstly it does the ~SCE header skip by sce_size bytes. After this, it will check the if the is_decompressed and is_decrypted flags are false. If they are both false, it will call sceKernelCheckExecFile again, then continue normally.

Spotted the bug yet?

What if we have an ~SCE header followed by an unencrypted PRX and finally followed by an official 100% legit encrypted PRX? If we set sce_size to point to the encrypted PRX, we can force sceKernelProbeExecutableObject to call sceKernelCheckExecFile on an encrypted PRX which will in turn set the is_decrypted flag to true! The very observant of you will notice a problem we just laid in front of ourselves: the compression buffer is not set. Amazingly, when processing an unencrypted PRX or ELF Sony uses the compression buffer variable to store some data for calculating the size of the executable. Thus a crafted ELF can set the decryption buffer by correctly setting a program header p_vaddr. Perfect.

The smartest of readers would also figure out that the decrypted PRX would be stored in this compression buffer and not at the location of the encrypted PRX. However, sceKernelProbeExecutableObject expects the decrypted result to be in the same location of the encrypted PRX. This may be an oversight from the Sony engineers, but it means we must store an ELF header where encrypted data exists. Although, we can just repeat the exercise and use another ~SCE header. Since the data is not used and sceKernelCheckExecFile uses a constant offset, we can store an ELF header too in there as long as the sce_size is positive. As for the contents of the header, we can just offset them back to the ELF above it.

All we need to do now is load our PRX and sceKernelProbeExecutableObject does just that thanks to the constant offset for an ~SCE header. Finally, for it to be accepted by the IPL/bootconfig you need to copy the signcheck from the encrypted module to the location it would expect it to at, so +0x80. Then you have a bootable PRX that passes decryption and ECDSA.

This bug exists in 6.31 and below, it was mysteriously patched in 6.35 – not much longer after I discovered it. For this reason E1000 (PSP street) is not supported.

A touch of the old magic

So you might be wondering: “How does a patched 6.31 exploit and brief history lesson translate into 6.61 permanent patch?”. 6.61 Infinity goes back to the old SE/OE days and uses the same technique done back then. Instead of a 1.50/2.71 hybrid firmware we use 6.31 and 6.61. The catalyst for this hybrid firmware is the giraffe bug applied to systimer.prx. I chose this specific module only due to its size. Weighing in at only 3 KB compressed and 7 KB uncompressed it is the smallest PRX before init.prx. Size is important here – the PSP NAND is nearly at capacity under normal circumstances so we have to make savings.  In fact, on the original phat PSP the NAND cannot contain both 6.61 and the 6.31 subset firmware. The infinity installer actually excludes some features (location free TV) so everything important can be installed.

With a giraffe’d systimer on the PSP we can inject a payload and take control of the system. Due to the way the hack works, relocations are not applied correctly. This means that code execution is not as clean as loading an ELF. The installer instead just slams some MIPS assembly at the entry location of systimer. The payload then locates loadcore by doing some calculations based on arguments passed to the module. With this information we can patch the kernel decryption routine and clear the caches. We also do a small patch to the module loading routine that passes the bootconfig as an argument. Afterwards, it cleans up and returns to loadcore.

Here we have a compromised (and unstable) system that is now patched to load unencrypted PRX. How infinity takes advantage of this situation is by replacing init.prx with a custom module that acts as our bootloader. Our bootloader has three key roles:

  • Restore system stability
  • Provide a recovery system
  • Load 6.61 firmware

Restoring system stability is done by modifying the bootconfig to load an original copy of systimer.prx and init.prx. These modifications will allow the system to continue the boot process as normal. We need to do this as we need services further down the boot chain for detecting button presses, rebooting the system and loading from memory stick.

Recovery is implemented by doing a check for L trigger when the memory stick driver is loaded. If pressed, the file ms0:/infinity/recovery.prx is loaded and started. Currently, there is no official recovery implementation. Those wishing to unbrick a device that still has access to the memory stick must first implement their own recovery. This executable is run under the 6.31 kernel and does not have any typical services of a normal kernel PRX. No NID resolver, no screen and no systemctrl. Additionally, since we wait for the memory stick driver any damage to the boot chain before this module is a permanent brick.

In the typical case where L trigger is not held, the bootloader will automatically reboot into 6.61. It does this by patching NAND decryption keys, patching prx decryption keys and redirecting flash0/kd to flash0/kn and flash0/vsh to flash0/vsn. These folders are where infinity has installed the 6.61 firmware.

At this point, the system reboots into 6.61 much like a normal system. Infinity keeps itself hidden in the background to maintain NAND redirection but is ultimately silent. It uses clever patches in order to work alongside both PRO and ME and provides the necessary compatibility modules to load them on start. This design keeps infinity agnostic to the running CFW and allows users to choose whichever they prefer. This design also allows developers to create their own CFW and take advantage of infinity’s permanent patches.

An end of an era

Infinity left some open ended questions regarding the state of PSP development. I used the flexible CFW agnostic design to gauge health for homebrew development in this area. Whilst I had a few bites that were interested; it ultimately ended with nothing. Likewise the lack of recovery implementation further solidified that people have moved on from the PSP. This is, of course, no surprise to me.

There are still some unfulfilled hacking goals for the PSP. PSP street has no permanent hack and KIRK is still mostly unbroken. The crypto engine has had some leaks of keys from the PS3 but has ultimately been secure from the PSP side. Likewise the bootrom has not been dumped for the newer models. If I were to make a prediction I’d say that these goals will never be met. The PSP is over 12 years old (at time of writing) and development has dwindled into the abyss.

Whilst not perfect, Infinity is probably the final nail in the coffin for PSP.

Infinity 6.61 WebsiteInfinity 6.61 Source Code

Follow me on twitter: @DaveeFTW

About The Author


  1. Waiting for sony to release PSP ofw 6.66 (the number of the beast) to increase system stability

  2. Hey, thanks for the writeup was a very interesting history lesson and read.

  3. For ppl like me that have been active since the early hack days of the PSP, this article was not only a trip down to memory lane, but also a very needed information aquisition. Thank you. =)

  4. Amazing explanation, so you pretty much used the header glitch to spoof a decrypted PRX as an encrypted? Brilliant, and the clarity of the explanation as well, very impressive. Hope to see more hacks from you in the near future. Cheers.

  5. Agreed. Satan is not beast enough if Sony doesn’t prove it by evolving their relationship beyond reasons of agreeing eventually constantly without knowing why. So they work together fighting for the cream because of seeing at last where the dot will stand basically defines the needle in the haystack theory. equals sony.s.atan Create to be Creator and have opinions about it. Then see them shattered to understand sata and n and see sata 3 and 802.11n as both the limit in what hdd is for wifi. We have ssd now and n to define the lightspeed. How about redefining limits in the future ? Can only the pro being neo at the beginning shatter the idea of a fifth ? Will a sixth sense emerge to tell us ? Will a seventh reality really appear ? How far can we push the limits ? Do we believe in Einstein ? He put it that way so we can only guess the square is just a idea of ac truly means the value it has for showing the truth when claiming 2,4 is value beyond reason of acceptance ? We believe or we don’t believe the equal in rules is really meant for us to follow or not to follow but only one is the decision ? It’s what changes that defines the rules. Think in flops. How many flops will have the fifth as oppossed to neo ? 5 times that ? Can you put a price on that ? Sure, says S. It’s the s in the middle that says it all. S is 5 because ac is the limit of 5. bUt Sony fails to deliver and sees the love in the creampie of the neo. Satan fails to decide the color of the cream. FAIL equals LIE so thruth is DEAD and ALIVE but it needs the limit to define it. The worker will choose the color for them and that’s the big lie in which we all live. Stop. Rules. It has all but something different in the middle. The colour of the needle everybody deems so necessary to chose. It began with capital it ended with it but in the middle it failed. It stops the way you want it, just yhat you have to find reachable the last digit of pi is it because it’s a lie seeing the colour shape emotions for you, and seeing the rule of DNA being programmed with light, it’s just that it will always fail to be understandable as a result of SATAN not SEXTING with SONY but only SEEN, without dots ? Understandable, it’s the love the black man sees the white cream will follow in defining right as close to justness as close as the DNA can explain that to him without killing the reason but with the power of unlimited thoughts about it saying just that based on his own dna and not fake proxies mirroring the same truth he’s failing to see the dots that ultimately cannot be seen in dns at first but only in dna not the second time. The reason of that is the beginning of love, white chicks will always love big black love coming straight from the source, proving acceptance by seeing the lack of black dots just by showing there’s real proof based of the same reason there is DNS to mirror DNA, the point of it. Will you believe can you hack the website will you may or you shall not ? This ip has points to prove my name is hidden for a reason but it will always be the same as long the email associated is active so do points in ip prove activity or identity in choosing being a hacker and be hacked to prove it you won because you have learned the point of it ? You’re beyond reason to hack ! Try to hack your own DNA placing dots like you did with DNS. Abomination ! New idea coming straight from your own DNA, emotion of life as sole moment of expectancy moment in determining on sight what is more, so close to enough or so far away, what really matters in choosing. The point of questions when you reach the dot and the message is stop. When you read it it’s different. Spelling the opposite way is help. Just for you to get the point of it. The reason DNA is anti-hate and understanding racism before you get it. There’s nothing gay or lesbian thinking about doing it in 3. It’s just biology tells you the rule of life she has to folow with each of us, that she’s pervert about it before telling us to have the entire eternity left to convince her she’s wrong in changing us, she struggles to understand the condition of a shemale. It’s the point of it, He or She or whatever the 0 choses before it gets closer to 1 demanding understandable needs is granted full acceptance only once so you can decide to love and to hate but the ocurence of that happening only you decide. For the point of it, Satan Is really Sony if there’s a tiny little dot left to argue about forever ? One will epic fail leading the other to define the experience he got in following his own opinions, for the reason or the ransom or the reward or the bribe or anything there’s left to argue about when a dot that’s keeping them from sexting each other right being wrong from the beginning with both of them expresses that in a common manner for both of them and that they don’t feel like they use full language so they wait and see if the light eventually is 3 and not 3 and 1 and 4 for the point that there is like that but simply for the point you understand that or both or none or zero or one or rule or point or the meaning of everything as opossed to containing all is what defines the battle. Express your feelings about : 3,14 and 3,14159265 and see that if go beyond limits you’ll be the s in shemale. The big S that’s missing from Satan when throwing valuable dirt out in order to fall because he chose so simply by not knowing if wondering if is a rule he must or must not understand the hard way must be followed. He lacks pride, he just doesn’t regrets the power he had because he lost it without getting that the big S is small and a has nothing to say about greatness in capitals as opossed to strength in numbers, He has given Satan all but he failed the Truth in his Command, Capitals the message, reason to follow or not any rule beyond reach for others. It’s the message that gets the stack corruption wanted by all in this good evil game of chess. King is gOD but it’s getting the message of chess that’s certainly a mortal kombat fatality depending on the conbination of time and moves but it’s like fear lacks and evil is not always good to win if so, it’s the message and the reason you get deeper you eventually fail and why you retry you cannot tell you clearly know. G from god or g from God but always choosing as close as the dice tells you to feel about deceipt when you see opportunity. Is this the longest message you failed to understand, being maybe the last one or maybe first ? Whatever, you’ll see in the end the meaning of everything, i am small for HE is strong letting me know that, if you get his message now and now YOU understand, act and choose. Anything.

  6. Very interesting article. Can you point us to a write up about the original dev hook? Thanks

  7. VSH has an elevated user level which allows loading modules from the memory card. Thus, the *smartest* of readers would have realized that this means Davee had an easy kernel exploit for a good chunk of firmwares 😉

  8. Are you going to release a fixed 1.02? I’d like to use pause feature on my PSP GO.

  9. Thanks, 6.61 Infinity in my PSP work

  10. Interesting indeed. I’d like to know more about the differences between Infinity 1.00 and 1.02, how did you fix the pause feature on PSP GO and broke the loading of isos’. I’ve seen that you still use a PSP GO from time to time, did you fix these bugs on it? Thanks

  11. Here’s for hoping for a 1.03 release with correctly fixed Pause/Resume ! Thank you so much for all your work on contributions, Davee! It means so much!!

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>