I’ve been getting a lot of complaints about my last article from the 10 Days of Hacking due to the sudden decrease of quality, and I want to apologize by creating a bonus day where I want to talk about some interesting hacks and developments.
Consider this the real Day 6 if you may.
ePSP is the term used to refer to the PSP sandbox emulated by the Vita, mainly used to play PSP games purchased from PSN.
One of the main selling points of the Vita was its backwards compatibility with PSP games, but there was a catch: only digital games could be played. Although this is bad for people with many UMDs, it’s a pretty logical situation, UMDs are bulky, noisy, slow and consume much more batteries than other physical media such as cartridges, or digital media.
But there was one question in everyone’s mind: how well did the Vita emulated the PSP? we’re here to find out.
BIT BY BIT
Not long after the Vita’s Japanese launch, scene developer Teck4 showcased a PSP Hello World running on the Vita, which is surprising as before it, a PSP Hello World was not possible on the PS3 under the same circumstances, so you’d think they would have that same security measures, but perhaps it breaks compatibility. Another scene developer, Wololo, soon started working on porting VHBL to the Vita. Wololo came across many new security measures and restrictions along the way, which ended up just being there to annoy hackers, but he eventually overcame them, here’s some of those restrictions and how he managed over them:
- it was no longer possible to create EBOOT.PBP files inside the ePSP, this was easily overthrown by using a different name (wololo used wmenu.bin).
- there was no possibility to freely copy content to ms0 from the outside other than using the savedata of the game, so we couldn’t install homebrews the old way, we now have to pack them into a zip inside the save and then unzip it once we gain control of the game.
- ePSP on Vita no longer has the “.” (current) and “..” (parent) directories, we now need to add them ourselves.
Soon after the announcement of VHBL, wololo created a method to distribute the name of the game to as many people as possible with very little risk of getting it patched by Sony, we know this method as the Ninja Release. Back then we really didn’t know how Sony would react to this, so it was best to keep it hidden for a while until many people got it and then make a public announcement containing the name of the game, but not the files to run the exploit.
As we had feared, Sony took the game down only hours after the public announcement, not only letting us know that the do watch the blogs, but they also don’t take to kindly to harmful usermode exploits that mean no real threat to piracy.
It was theorized that Sony patched the game not because of piracy but because it scared developers away, today we know this is bullsh*t, developers are moving away regardless of the existence of hacks or not.
Wololo soon released a second exploit, and the best so far because of how it was presented, you can read it here: http://wololo.net/2012/03/25/dear-sony/
Many more exploits using VHBL were release after that, which Sony kept patching, so it was the cat and mouse game all over again.
ECFW AND KERNEL EXPLOITS
Eventually, full fledge PSP Custom Firmwares were released on the ePSP of the Vita, first it was 6.60 TN-A by Total_Noob (updated up to TN-C), which worked with a leaked kernel exploit by Coldbird, sadly this also meant Coldbird’s departure from the scene, which gradually meant the departure of the entire Team PRO. Not long after that, another developer by the name frostegater released a usermode exploit in the game UNO and a kernel exploit residing in a wlan function, which I’ll talk about it now. Today, the only CFW maker we got is Total_Noob, who has just released the 4th to 7th iteration of his great TN-V CFW, which ports the PSP’s XMB to the emulated PSP on the Vita, basically turning your Vita into a full fledge PSP with two analog sticks and touch screens.
Of course Total_Noob had to release a kernel exploit to have his CFW work, but I can’t disclose its inner workings as that’s something Total_Noob himself will do after Sony patches it, but, do we know how the other two kernel exploits work?
It’s no mystery by now that kernel exploits exist because either there’s a stupid mistake made by the people in charge of security, or there was really clever hacks with lots of brains placed in it developed.
While anyone with knowledge on finding kernel exploits will tell you that the PSP security is a joke, we have to understand that this is because the system was opened once, and once opened, you have a way to get into the system to find easier and better hacks. With the PSP, as I explained on the first day of PSP hacking, the system wasn’t really initially secured, this broke the never ending loop of needing a kernel exploit to find a kernel exploit.
It doesn’t matter how much Sony improved security on the kernel side, there was always a whole they haven’t patched, and in the case of the PSP, to find more holes the best thing we do is look in newly added functions.
EGGSPLANATION
WARNING: really huge block of text with no pictures incoming.
When it comes to ePSP, more like newly added functions we got completely overwritten functions, we have to thank kermit for this. Kermit is a module responsible for being the communication bridge between the ePSP and the actual Vita software.
When it comes to things like wifi, GPS, USB, camera, buttons, memory stick and other peripherals, they are no longer located or accessible as they were on the PSP, so the ePSP kernel doesn’t really have access to them, it’s the Vita that must wrap them around into the actual Vita hardware, this is what kermit is used for, to wrap around previous functions and modules that accessed these hardware, so naturally these functions need to be completely rewritten, so it’s a nice place to start looking. I will save you the time and tell you that both the leaked kernel exploit and the one frostegater released are in the wlan module, kermit_wlan.prx, let’s do a brief recap on how PSP security works:
The PSP RAM is mainly separated into two areas: user RAM (24MB) and kernel RAM (8MB). Kernel addresses always start with the number 0×8, while user RAM always start with the number 0×0. Pointers are always unsigned numbers, sign numbers use the very first bit to indicate which sign it is, 0 mean positive, 1 means negative, the other bits are used to express the actual number, in the case of unsigned numbers the first bit is not used for sign as the number is always positive, so it’s used for the number too. Back to kernel pointers, if we treat it as that, a pointer, it’s unsigned, and the first number, 0×8, is treated like that, an 8, but if we treat it as a signed number, in binary 0×8 is 1000, since the first digit is 1, the number is negative, and since it’s in two’s complement, which is how computers encode signed numbers.
Knowing this, we can guess that by treating kernel and user pointers as signed numbers, kernel pointers will always be negative and user pointers will always be positive. Using this the system can easily filter out unwanted kernel pointers passed through from user RAM, so you can’t easily fool the kernel into killing itself, at least that’s the theory, but that only works when you implement it.
If you have such an efficient security measure available, it’s only logical that you use it, so if hackers find a way around it, you at least tried, but….why the hell didn’t they do this for kermit_wlan.prx?
Not only did they forget to do one or two checks, which can sometimes happen, they simply ignored this checks altogether.
This is what frostgater’s exploited function looks today:
; Subroutine sceWlanDrv_lib_51B0BBB8 - Address 0x00004618
; Exported in sceWlanDrv_lib
sceWlanDrv_lib_51B0BBB8:
addiu $sp, $sp, -192
sw $s6, 168($sp)
addiu $s6, $sp, 63
ins $s6, $zr, 0, 6
sw $s5, 164($sp)
move $s5, $a1
li $a1, 64
sw $s3, 156($sp)
move $s3, $a0
move $a0, $s6
sw $s2, 152($sp)
move $s2, $k1
sll $k1, $k1, 11
sw $s4, 160($sp)
move $s4, $a2
sw $s1, 148($sp)
move $s1, $a3
sw $s0, 144($sp)
sw $ra, 176($sp)
jal sceKernelDcacheInvalidateRange
sw $s7, 172($sp)
sra $a1, $s6, 31
addiu $a0, $a1, 2
sll $v0, $a0, 29
lui $v1, 0x0
and $a1, $k1, $s1
or $s0, $s6, $v0
bltz $a1, loc_00004780
lw $s6, 32636($v1)
lui $t0, 0x0
lw $a3, 32480($t0)
bnez $a3, loc_000046D8
li $t1, -1
move $k1, $s2
move $v1, $zr
sw $t1, 0($s1)
this function does a lot of things, but we can sum it up into this (omitting some stuff):
int sceWlanDrv_lib_51B0BBB8(u32 a0, u32 a1, u32 a2, u32 a3){
if ( (a3 & k1) < 0)
return ERROR;
some_code_here
*a3 = -1;
return something;
pretty standard stuff here, it checks that a3, a pointer, is not a kernel pointer, then proceeds to do stuff, one of them being storing -1 to the address pointed by a3, but this is how the function looked like back then:
; Subroutine sceWlanDrv_lib_51B0BBB8 - Address 0x00004618
; Exported in sceWlanDrv_lib
sceWlanDrv_lib_51B0BBB8:
addiu $sp, $sp, -192
sw $s6, 168($sp)
addiu $s6, $sp, 63
ins $s6, $zr, 0, 6
sw $s5, 164($sp)
move $s5, $a1
li $a1, 64
sw $s3, 156($sp)
move $s3, $a0
move $a0, $s6
sw $s2, 152($sp)
move $s2, $k1
sll $k1, $k1, 11
sw $s4, 160($sp)
move $s4, $a2
sw $s1, 148($sp)
move $s1, $a3
sw $s0, 144($sp)
sw $ra, 176($sp)
jal sceKernelDcacheInvalidateRange
sw $s7, 172($sp)
sra $a1, $s6, 31
addiu $a0, $a1, 2
sll $v0, $a0, 29
lui $v1, 0x0
or $s0, $s6, $v0
lw $s6, 32636($v1)
lui $t0, 0x0
lw $a3, 32480($t0)
bnez $a3, loc_000046D8
li $t1, -1
move $k1, $s2
move $v1, $zr
sw $t1, 0($s1)
as you can see, there are no checks, so it translates to this:
int sceWlanDrv_lib_51B0BBB8(u32 a0, u32 a1, u32 a2, u32 a3){
some_code_here
*a3 = -1;
return something;
the function still stored -1 to the address pointed by a3, which can be given from user ram and there is no check or control over it, so the function happily took a pointer, didn’t bother checking if it was going to overwrite a place in ram we don’t want to be overwritten, and stores the value there. For those of you who don’t know, -1 is encoded in two’s complement as 0xFFFFFFFF, which when using as an instruction it’s translated as vsync, so it can be used as a valid instruction that we can use to overwrite another instruction, normally we want to overwrite the second instruction in this function:
; Subroutine sceKernelLibcTime - Address 0x0000F718
; Exported in UtilsForUser
; Exported in UtilsForKernel
sceKernelLibcTime:
lui $v1, 0x4EB0
lw $a1, 22388($v1)
addiu $sp, $sp, -16
sw $s0, 0($sp)
sll $v1, $k1, 11
move $s0, $k1
sw $ra, 4($sp)
beqz $a1, loc_0000F750
move $a2, $zr
move $k1, $v1
and $v1, $v1, $a0
bgez $v1, loc_0000F764
nop
loc_0000F74C: ; Refs: 0x0000F76C
move $k1, $s0
loc_0000F750: ; Refs: 0x0000F734
lw $ra, 4($sp)
lw $s0, 0($sp)
move $v0, $a2
jr $ra
addiu $sp, $sp, 16
loc_0000F764: ; Refs: 0x0000F744
jalr $a1
nop
; Data ref 0x08003DD3
j loc_0000F74C
move $a2, $v0
by doing so we prevent the function from overwriting a1, so we can set a1 to whatever we want and have the system jump to it, we just set a1 to point to a payload we have in user RAM and OR it with 0×80000000 to give it kernel privileges.
The funny thing about this kermit_wlan exploit is that they forgot to do the checks on over 10 wlan functions, giving us more than 10 kernel exploits, most of them found by yosh/wth. Of course Sony figured this out and patched all of them at once, but it’s still funny how they made such as stupid mistake after years of perfecting the PSP security system, I guess they hired different people to do the kermit_wlan module? I don’t know.
CONCLUSION
I hope you guys have enjoyed this article as a nice replacement for the 360 one, and stay tuned for the upcoming ones, we still got two more consoles and the 10th day conclusion.