6 ways to crash the wipeout browser...

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

th0mas
Posts: 43
Joined: Sun Apr 24, 2005 1:59 am
Location: Canada
Contact:

Post by th0mas »

if we could access those registers, we could be running the shellcode - all you can do at this point is tell the thread "your next instruction is at memory x", and we don't know where that location is.

and I'm glad you're case-insensitive ;).
Galfpart
Posts: 9
Joined: Wed Jun 01, 2005 8:32 pm

Post by Galfpart »

th0mas wrote:if we could access those registers, we could be running the shellcode
I'm not sure if I correctly understand you but you can access the registers
if you overwrite the return address (which - according to tmbinc - one can)
with the address of a code-location redirecting program flow to the content
of a register (read: to an address a register is pointing to) - which is
hopefully our overwritten stack. of course, there is a lot of patience and
a little bit of luck involved ;-)
th0mas wrote:and I'm glad you're case-insensitive ;).
IDA is, not me ;-)
th0mas
Posts: 43
Joined: Sun Apr 24, 2005 1:59 am
Location: Canada
Contact:

Post by th0mas »

Galfpart wrote:I'm not sure if I correctly understand you but you can access the registers
if you overwrite the return address (which - according to tmbinc - one can)
with the address of a code-location redirecting program flow to the content
of a register
ooOOHHH, you're saying hope to find a static point in the binary that contains the assembly instruction "jr $sp" or equivalent. Sorry, I didn't follow that part. *shuts his mouth* :)
Galfpart
Posts: 9
Joined: Wed Jun 01, 2005 8:32 pm

Post by Galfpart »

th0mas wrote: ooOOHHH, you're saying hope to find a static point in the binary that contains the assembly instruction "jr $sp" or equivalent. Sorry, I didn't follow that part. *shuts his mouth* :)
exactly. and if just ANY register points to our overwritten stack,
chances are VERY high that you're soon holding a working exploit
for wipeout in your hands (of course this task isn't trivial).
and the code seems to be at a static memory location if you read
earlier posts of this thread.
0xdeadface
Posts: 62
Joined: Tue May 31, 2005 5:11 am

Post by 0xdeadface »

Hmmmm....you might find a jr a0 or a1....I've seen them.

That would be kinda interesting as they are often used for variable passing to other functions, so chances are they'd be pointers to an area in the stack.

0xdf
Galfpart
Posts: 9
Joined: Wed Jun 01, 2005 8:32 pm

Post by Galfpart »

a few locations of the "jr" instruction:

.text:00000000 08 00 E0 03 jr $31

.text:00002068 08 00 20 00 jr $1

.text:001E072C 08 00 40 00 jr $2

.text:001024E0 08 00 80 00 jr $4


The problem is that "jr" seems to use $1, $2, $4 and $31 only.
I couldn't find any more "jr" instructions using any other register.

Unfortunately I am not into MIPS assembly but there should be a
few more instructions using registers to modify program flow.
A call or any other jump should do it.

Happy investigating ;-)
Galfpart
Posts: 9
Joined: Wed Jun 01, 2005 8:32 pm

Post by Galfpart »

http://www.phrack.org/show.php?p=56&a=15
----| Intro

Writing shellcode for the MIPS/Irix platform is not much different from writing
shellcode for the x86 architecture. There are, however, a few tricks worth
knowing when attempting to write clean shellcode (which does not have any NULL
bytes and works completely independent from it's position).

This small paper will provide you with a crash course on writing IRIX
shellcode for use in exploits. It covers the basic stuff you need to know to
start writing basic IRIX shellcode.
EDIT: Added a brief quote on what the link contains.
LiquidIce
Posts: 55
Joined: Mon Apr 04, 2005 1:15 am
Contact:

Post by LiquidIce »

Is this the kind of shellcode we need to be able to inject into the memory then execute?:

http://forums.ps2dev.org/viewtopic.php?p=11973#11973
emily
Posts: 2
Joined: Sat Jun 04, 2005 9:59 pm

Post by emily »

so, you can search for absolute addresses that contain specific opcodes (don't know how you did that). Also, you can load the stack with values using the buffer overrun.
Why don't you find a known address that contains a return from interrupt instruction ("ei" I think) & 'return' to that address. When the routine exits, it will jump to the "ei" instruction. This will pull values off the stack to restore registers - which you will have carefully loaded to be useful parameter values. It also pulls the PC off the stack, which was loaded to be a library function call, which seems handy.
IFF you can do this a couple of times, you can essentially do what the code-fragment pointed to by the previous post was doing. Even if you can only do it once, you might be able to call something useful.
Galfpart
Posts: 9
Joined: Wed Jun 01, 2005 8:32 pm

Post by Galfpart »

sounds like a good idea. i hope someone can try it, i don't have any
hardware to test it on ;-)
LiquidIce
Posts: 55
Joined: Mon Apr 04, 2005 1:15 am
Contact:

Post by LiquidIce »

nem told me he tried a few different things with this, but he could not get it to work. If anyone has code they would like me to try, I have the hardware and game to test on.

Just so that we're all on the same page, there are two steps to this exploit,

The first step is to find a spot in memory where there is a jump instruction as the return address. We overwrite that memory position with a pointer to our own code

The second part is putting our own code in memory in a spot where we know it will exist and be able to run. This code might need to be written to have 0 null bytes.

Once those two things are in place, we construct a link that changes the pointer, injects our own code to a spot in memory, then jumps to that position.

If this is even possible up to this point, what can we really do with shell code? It is unlikely that we will be able to launch any of the homebrew software that is out, because it is still not signed by sony. One possibility is to write code that overwrites files in the flash and modifies the certificates which do the signing checks. This is very risky, and I don't know too many people that are going to risk making their PSP a brick to figure this one out.

It sounds like there is still much work that needs to be done to make this a reality. If there is anything I can do to help test, let me know.
0xdeadface
Posts: 62
Joined: Tue May 31, 2005 5:11 am

Post by 0xdeadface »

No, if the exploit would work, you would use it to install a loader that loads unencrypted code and loads it in the running process, doing the relocations yourself and jump to the start of it.

As long as the crash is not in kernel mode, you'd not be able to do much more than that.

0xdf
emily
Posts: 2
Joined: Sat Jun 04, 2005 9:59 pm

Post by emily »

[quote]The first step is to find a spot in memory where there is a jump instruction as the return address. We overwrite that memory position with a pointer to our own code[/quote]

you can already replace a return address to run code from the location of your choice. problem is you can't locate or inject any interesting code to run. the sleep function has apparently already been run, but it's not too useful.
replacing the return address with the location of an 'ei' and filling the stack appropriately lets you call kernel functions and pass arguments. if you can do it several times (a big but not impossible if), you could

open a file
load it into memory (fixed, known address)
create a thread, pointing to known address
start thread
voila

it seems the locations of these kernel functions and their parameters are known already.
mrbrown
Site Admin
Posts: 1537
Joined: Sat Jan 17, 2004 11:24 am

Post by mrbrown »

The eret instruction (return from exception, not ei) is only used inside the kernel. You can't overwrite kernel memory because it's protected from access via the MMU. Interrupt handlers that live in userspace use a syscall instruction to return control to the kernel.
0xdeadface
Posts: 62
Joined: Tue May 31, 2005 5:11 am

Post by 0xdeadface »

I was afraid of that. Does that mean that the only feasible way would be brute force? (ie, determining what address on the passed string is actually the return address fetched, then figure out the amount of stackspace we have for shellcode and determine where the stack lies at that moment by inserting different return addresses?)

That's a lot of brute-force to do.

There are quite some addiu a0,sp,0 and the likes but of course those are not usually followed by a jr a0 :\ (who woulda thought) and it seems the return code isn't preceded by a load into a register that might be useful as far as I understood (still haven't looked into it myself, without any wipeout, and currently even without a disassembler). If there'd be any register set with a pointer to a variable in the stack it would of course be a lot easier.

0xdf
LiquidIce
Posts: 55
Joined: Mon Apr 04, 2005 1:15 am
Contact:

Post by LiquidIce »

If anyone is having problems following this thread, I'd suggest taking a look at this article:

http://www.hxdef.org/knowhow/stackover.txt

It explains in great details, how a stack works, the concepts behind a buffer overflow, examples on how to write shell code, and how to bring everything together using NOPs to get to the right place in memory. It has helped me a lot with understanding the concepts talked about in this thread, and hopefully will help someone else figure out how to get our own code working in there. It is not PSP specific, but the concepts are the same.
`smash the stack` [C programming] n. On many C implementations
it is possible to corrupt the execution stack by writing past
the end of an array declared auto in a routine. Code that does
this is said to smash the stack, and can cause return from the
routine to jump to a random address. This can produce some of
the most insidious data-dependent bugs known to mankind.
DrEggman
Posts: 28
Joined: Tue Mar 22, 2005 1:29 pm

Post by DrEggman »

One note on using this. Its been tested by me an tmbinc that you have to link to the html code almost directly. Going through a portal that has you enter the URL completely changes how the code reacts. In one case, tmbinc had it setup to kill the browser, thus disabling all the face buttons, but it kept the home button and related funtions active. When using the same HTML insert, we got a completely different outcome by using a different portal with a URL insert. Just so you know.
Shine
Posts: 728
Joined: Fri Dec 03, 2004 12:10 pm
Location: Germany

Post by Shine »

LiquidIce wrote:If anyone is having problems following this thread, I'd suggest taking a look at this article:

http://www.hxdef.org/knowhow/stackover.txt
Thanks. Nothing really new, but I've tried the idea, that the stack is always nearly at the same position. Now that I have a 1.0 PSP, I wrote a program, which displays the SP and it was 0x09fbfe50 all the time :-)

And some code, which increments all vram bytes in an endless loop and which doesn't contain 0x00, 0x09, 0x0a or 0x0d (which might cause problems when using as URL parameters). With this code you can see, if your code is executed. In the 16 bit color mode, like in nem's hello world, it cycles through all colors and in RGB mode (if there is an RGB mode on PSP) it should cycle through gray scale. I'm not very good at MIPS assembler, but it works at least:

Code: Select all

start:  xor $t7, $t7, $t7
        xor $t0, $t0, $t0
        lui $t4, 0x4040
        lui $t0, 0x405e
        lui $t7, 0x041f
        xor $t0, $t0, $t4     # results in t7=0x041f0000 and t0=0x001e0000 and 
next:   lbu $t4, 0x4040($t7)  # load byte
        add $t4, -1           # add something
        sb $t4, 0x4040($t7)   # store back
        subu $t7, 1           # decrement vram pointer
        sub $t0, 1            # decrement loop
        bgez $t0, next        # jump while >= 0
        lui $t4, 0x4040       # nop without 0
        bgez $t7, start       # unconditional jump (endless outer loop)
        lui $t4, 0x4040       # nop without 0
I've tested it with this C code on my 1.0 PSP:

Code: Select all

const unsigned char colorIncrement[] = {
        0x26, 0x78, 0xEF, 0x01, 0x26, 0x40, 0x08, 0x01, 
        0x40, 0x40, 0x0C, 0x3C, 0x5E, 0x40, 0x08, 0x3C, 
        0x1F, 0x04, 0x0F, 0x3C, 0x26, 0x40, 0x0C, 0x01, 
        0x40, 0x40, 0xEC, 0x91, 0xFF, 0xFF, 0x8C, 0x21, 
        0x40, 0x40, 0xEC, 0xA1, 0xFF, 0xFF, 0xEF, 0x25, 
        0xFF, 0xFF, 0x08, 0x21, 0xFA, 0xFF, 0x01, 0x05, 
        0x40, 0x40, 0x0C, 0x3C, 0xF2, 0xFF, 0xE1, 0x05, 
        0x40, 0x40, 0x0C, 0x3C };

typedef void (*pfv) ();
pfv colorIncrementFunction;

int xmain(void) {
        ...
        colorIncrementFunction = (pfv) colorIncrement;
        (*colorIncrementFunction)();
        return 0;
}
The next step is to write something more useful, like loading a binary from memory stick. I don't know how the kernel calls are implemented, but looks like the kernel loader has to adjust the kernel calls in the program, so just loading a binary and executing it is not enough. Would be nice, if we could call a kernel function, which can load and execute an unencrypted ELF.
LiquidIce
Posts: 55
Joined: Mon Apr 04, 2005 1:15 am
Contact:

Post by LiquidIce »

I've made some attempts to run Shine's shellcode in the wipeout browser. My non-working code is below, what am I doing wrong?

(Remove linebreaks in the call= line, I had to add them so i didn't mess up the tables on this forum)

Code: Select all

<center>
This does not work yet
<br><br>
<script>
call= "\x26\x78\xEF\x01\x26\x40\x08\x01\x40\x40\x0C\x3C\x5E\x40\x08
\x3C\x1F\x04\x0F\x3C\x26\x40\x0C\x01\x40\x40\xEC\x91\xFF\xFF
\x8C\x21\x40\x40\xEC\xA1\xFF\xFF\xEF\x25\xFF\xFF\x08\x21\xFA
\xFF\x01\x05\x40\x40\x0C\x3C\xF2\xFF\xE1\x05\x40\x40\x0C\x3C";
big="";
for &#40;i = 0; i < 272; i++&#41; big = big + call;
document.links&#91;0&#93;.href="proc&#58;//upload/profile&#58;http&#58;//?" + big;
</script>
Also tried this javascript:

Code: Select all

<script>
call= "\x26\x78\xEF\x01\x26\x40\x08\x01\x40\x40\x0C\x3C\x5E\x40\x08
\x3C\x1F\x04\x0F\x3C\x26\x40\x0C\x01\x40\x40\xEC\x91\xFF\xFF
\x8C\x21\x40\x40\xEC\xA1\xFF\xFF\xEF\x25\xFF\xFF\x08\x21\xFA
\xFF\x01\x05\x40\x40\x0C\x3C\xF2\xFF\xE1\x05\x40\x40\x0C\x3C";
document.write&#40;"<a href='proc&#58;//upload/profile&#58;http&#58;//?" + call + "'>RUN CODE</a>"&#41;;
</script>

Also, does it matter if I have the wipeout update installed or not? Does the Wipeoue update upgrade the browser version?

I'm also thinking that I might need to execute two proc:// statements... one to inject the code and another to execute it.

Can anyone shed some light?

BTW, I am using MooPS as my DNS redirection. DrEggman said he experienced some problems when running this with certain portals. Which ones work best?
Galfpart
Posts: 9
Joined: Wed Jun 01, 2005 8:32 pm

Post by Galfpart »

First of all it's nice to see that somebody is actually trying this!

What did not work for you? Didn't the browser crash at all?

edit:

you need to modify the return address to jump to your code first, of course.
simply sending this code and overflowing the stack doesn't help at all.

stack looks similar to this:

Code: Select all

&#91;xxxxxxxxxxxxxxxx&#93;&#91;xxxx&#93;
 |                 |
local variable    return address

let's say if you send a lot of "A" characters
the stack might look like that&#58;

&#91;AAAAAAAAAAAAAAAA&#93;&#91;AAAA&#93;
 |                 |
local variable    return address
your aim is now to stuff a reasonable address into "return address".
a reasonable address would be a jump instruction, taking the
address out of a register. the register is supposed to point somewhere
into "local variable" - the location you can control (stuff with shellcode).

the "hard" task is to find out IF there is any register which points into
"local variable".

i hope this clears things up :)

cheers
Klimru
Posts: 34
Joined: Sat Apr 09, 2005 7:29 am

Post by Klimru »

Does anyone have a working example of this exploit? I saw somewhere up in the post that it was possible to call a function that put the PSP to sleep... has anyone been able to reproduce this? If so, is there any working HTML that could be posted to demonstrate?

Edit:
Also, I'm happy to try anything that anyone comes up with that they're affriad to try for fear of breaking something. lol. US 1.5 PSP.
Shine
Posts: 728
Joined: Fri Dec 03, 2004 12:10 pm
Location: Germany

Post by Shine »

Klimru wrote:Does anyone have a working example of this exploit? I saw somewhere up in the post that it was possible to call a function that put the PSP to sleep... has anyone been able to reproduce this? If so, is there any working HTML that could be posted to demonstrate?
I'm not sure, if the ThreadSleep function was acutally called, because much more could stop the browser thread, too, not only calling this sleep function.
LiquidIce wrote: I've made some attempts to run Shine's shellcode in the wipeout browser. My non-working code is below, what am I doing wrong?
Looks like the Wipeout browser sometimes uses some sort of w_char internally for japanese character set (try some >0xc0 bytes in the HTML text and you'll see some japanese characters, even if you specify ISO-8859-1 as encoding, which is simply ignored by the browser), which is 32 bit wide. Could be really difficult to find a shitf-jis byte string, which produce a valid MIPS-assembler-multibyte-string. Perhaps one should try to find a buffer overflow in more low-level code, which is not translated, for example the HTTP headers (but perhaps they are translated, too).
joe
Posts: 1
Joined: Tue Jun 07, 2005 3:01 am

Post by joe »

Creating a pspdif file that is greater than 8195 bytes and using something like proc://command/http://crash.pspdif to run it will crash the browser. This might be a little easier to exploit because it is not translated to wide chars.
Shine
Posts: 728
Joined: Fri Dec 03, 2004 12:10 pm
Location: Germany

Post by Shine »

joe wrote:Creating a pspdif file that is greater than 8195 bytes and using something like proc://command/http://crash.pspdif to run it will crash the browser. This might be a little easier to exploit because it is not translated to wide chars.
Yes, you are right. But it might be more difficult. I've tested it yesterday with some repeated sequences, like all 0 bytes for nops, followed by my code, followed by repeated 4 bytes for overwriting a stack return address and sometimes the browser crashs, but the music continues to play and sometimes the PSP shuts down. With some data it is even possible to download 64 MB and more, so there is somewhere a wrap, because otherwise the PSP would shut down on illegal memory access before finishing loading (if the file is loaded by user code and not by a kernel function, because the web server log showed that all data was loaded).

My idea was, that the PSPDIF file was loaded somewhere in the heap, hoping that the heap is behind the program and before the stack, but no luck.
zith
Posts: 4
Joined: Thu Apr 21, 2005 2:47 am

Post by zith »

I might be missing something, and i dont know any mips assembly or much about the psp at all, but why wouldnt it be possible to simply use a string like:

[NNNNNNNNNNNSSSSSSSSS][SSSS][RRRR]

Where N is NOP, S is the shellcode, R is the return address. Then as the value of the return address you take start_of_stack - offset (or + offset depending on if the stack grows up or down in this architechture), and simply try some offsets? If you fill up with as many NOP's as possible it shouldnt take very long finding a return address that works and with 0x420 bytes to write to you should have plenty of space for lots and lots of NOPS and still a quite large shellcode.

Is there something i should know about MIPS or the PSP that makes this impossible?
Post Reply