6 ways to crash the wipeout browser...
6 ways to crash the wipeout browser...
Hi,
I noticed the following ways to crash the wipeout browser:
1.) "<div>" * (large number, > ~500). you can use every other tag as well.
The html parser seems to be recursive. At least this slows down the parsing process until it finally crashes.
No big deal, i think, i don't think it can be exploited (but hey, people always told this and a month later, machines get rooted.)
2.) <a href="proc://buttons/http://bla?bla">CRASH ME</a
3.) <a href="proc://exists/http://bla?bla">CRASH ME</a
4.) <a href="proc://sound/http://bla?bla">CRASH ME</a
Looks just like some stupid *strchr(buffer, '<any-nonexisting-char>') =0; (which is damn stupid, yes, but doesn't look too exploitable, too.)
5.) "<" + '(any char)' * 1024
This looks more interesting. The crash boundary is exactly 1024 characters, which makes me feel that the developers of the wipeout browser are indeed damn stupid.
and finally my favourite one:
6.) "<a href="proc://upload/profile:http://?" + 'a' * ~980 + "">CRASH ME</a>"
this one seems to be related with the "%s&upload=profile&value=all&uid=%s" format string. No, they didn't used snprintf. How stupid.
Anyway, i tried something like "http://?" + "\xfc\x23\x91\x88" * (256+16) which should end up at 089123fc, which should be a "jr $ra" (can somebody please check this? i was told that game load to 08900000, and as \x08 seems to cause problems while parsing, i set the MSB. Is this valid for code like for data addresses, too?), and it didn't worked as expected (expected behaviour: "sounds continues, browser hangs", experienced behaviour: "like any other crash - sound hangs, browser hangs"). I don't have a bright idea anymore.
I've spent some disassembling the corresponding functions, but i couldn't find something i'm doing wrong. The buffer in question should be 0x400 bytes, plus 0x20 bytes of variables which are only touched after the sprintf(), and then the return address. So sending 0x420 bytes junk and the the return address should do it. Well, it doesn't.
I noticed the following ways to crash the wipeout browser:
1.) "<div>" * (large number, > ~500). you can use every other tag as well.
The html parser seems to be recursive. At least this slows down the parsing process until it finally crashes.
No big deal, i think, i don't think it can be exploited (but hey, people always told this and a month later, machines get rooted.)
2.) <a href="proc://buttons/http://bla?bla">CRASH ME</a
3.) <a href="proc://exists/http://bla?bla">CRASH ME</a
4.) <a href="proc://sound/http://bla?bla">CRASH ME</a
Looks just like some stupid *strchr(buffer, '<any-nonexisting-char>') =0; (which is damn stupid, yes, but doesn't look too exploitable, too.)
5.) "<" + '(any char)' * 1024
This looks more interesting. The crash boundary is exactly 1024 characters, which makes me feel that the developers of the wipeout browser are indeed damn stupid.
and finally my favourite one:
6.) "<a href="proc://upload/profile:http://?" + 'a' * ~980 + "">CRASH ME</a>"
this one seems to be related with the "%s&upload=profile&value=all&uid=%s" format string. No, they didn't used snprintf. How stupid.
Anyway, i tried something like "http://?" + "\xfc\x23\x91\x88" * (256+16) which should end up at 089123fc, which should be a "jr $ra" (can somebody please check this? i was told that game load to 08900000, and as \x08 seems to cause problems while parsing, i set the MSB. Is this valid for code like for data addresses, too?), and it didn't worked as expected (expected behaviour: "sounds continues, browser hangs", experienced behaviour: "like any other crash - sound hangs, browser hangs"). I don't have a bright idea anymore.
I've spent some disassembling the corresponding functions, but i couldn't find something i'm doing wrong. The buffer in question should be 0x400 bytes, plus 0x20 bytes of variables which are only touched after the sprintf(), and then the return address. So sending 0x420 bytes junk and the the return address should do it. Well, it doesn't.
Yo tmbinc !
Nice to see you joining from Gamecube development to PSP development ...
Finding overflows in the Wipeout browser is not the time worth for doing research. I personally think it's easier to find an overflow in the build in media player routines (jpeg viewer, mp3 player, mp4 player etc.)
It would also be more comfortable to turn on the psp and starting code over the build in viewers than booting wipeout from umd and typing hundreds of chars into the url line ...
Nice to see you joining from Gamecube development to PSP development ...
Finding overflows in the Wipeout browser is not the time worth for doing research. I personally think it's easier to find an overflow in the build in media player routines (jpeg viewer, mp3 player, mp4 player etc.)
It would also be more comfortable to turn on the psp and starting code over the build in viewers than booting wipeout from umd and typing hundreds of chars into the url line ...
sounds very promising for a buffer overflow :)
i have a few questions:
if the wipeout code is encrypted how do you decompile it?
and more generally when doing buffer overflows on console games, i was just thinking.. you must have to unregister all the callbacks the game has to be properly in control of the system right? is that what you meant by the sound continuing?
also surely its better to have a buffer overflow in a game that sony cant easily patch, rather than the firmware which most likely wont work anymore once it is updated, i think this direction is a very good idea.
i have a few questions:
if the wipeout code is encrypted how do you decompile it?
and more generally when doing buffer overflows on console games, i was just thinking.. you must have to unregister all the callbacks the game has to be properly in control of the system right? is that what you meant by the sound continuing?
also surely its better to have a buffer overflow in a game that sony cant easily patch, rather than the firmware which most likely wont work anymore once it is updated, i think this direction is a very good idea.
KiWi: i choosed the first thing which i had some binaries for, and that was wipeout. exploiting something without having binaries sounds nearly impossible for me, at least when doing stack-based overflows where you have to know the return-addr.
Sure an exploit in something else would be better, but at least i don't have any access to the binaries of the loader.
placasoft: Honestly, i don't know. I grepped through the binary, and found it.
tomt: The available rip contains EBOOT.BIN which is encrypted and BOOT.BIN which is unencrypted. I don't know for sure if this executable matches the one on my wipeout disc, but especially the 6.) behaves like i expected that from the code.
About the "sound-or-not":
The sound is played in one thread, the browser works in another thread.
Now, if a thread crashes, the whole game crashes. The exception handler probably halts the whole system (?). If some thread, however, would loop infinite, the other threads should continue. Thus, the sound should continue, while the browser hangs (but not crashes).
As said, it didn't worked. Maybe because i have to jump to 08xxxxxx and can't set any other bits? Sorry i'm not too familiar with this kseg-stuff. Can anybody enlighten me?
Or the binary is just a little bit different than the one on my disc (japanese vs. US?)
Does anybody know how to place something in the memory at a known location?
Sure an exploit in something else would be better, but at least i don't have any access to the binaries of the loader.
placasoft: Honestly, i don't know. I grepped through the binary, and found it.
tomt: The available rip contains EBOOT.BIN which is encrypted and BOOT.BIN which is unencrypted. I don't know for sure if this executable matches the one on my wipeout disc, but especially the 6.) behaves like i expected that from the code.
About the "sound-or-not":
The sound is played in one thread, the browser works in another thread.
Now, if a thread crashes, the whole game crashes. The exception handler probably halts the whole system (?). If some thread, however, would loop infinite, the other threads should continue. Thus, the sound should continue, while the browser hangs (but not crashes).
As said, it didn't worked. Maybe because i have to jump to 08xxxxxx and can't set any other bits? Sorry i'm not too familiar with this kseg-stuff. Can anybody enlighten me?
Or the binary is just a little bit different than the one on my disc (japanese vs. US?)
Does anybody know how to place something in the memory at a known location?
tmbinc: the homebrewed ELFs are statics and load to 0x08900000, but how can be you sure at all that the game load to 0x08900000 if the ELF is relocatable?tmbinc wrote:and finally my favourite one:
6.) "<a href="proc://upload/profile:http://?" + 'a' * ~980 + "">CRASH ME</a>"
this one seems to be related with the "%s&upload=profile&value=all&uid=%s" format string. No, they didn't used snprintf. How stupid.
Anyway, i tried something like "http://?" + "\xfc\x23\x91\x88" * (256+16) which should end up at 089123fc, which should be a "jr $ra" (can somebody please check this? i was told that game load to 08900000, and as \x08 seems to cause problems while parsing, i set the MSB. Is this valid for code like for data addresses, too?), and it didn't worked as expected (expected behaviour: "sounds continues, browser hangs", experienced behaviour: "like any other crash - sound hangs, browser hangs"). I don't have a bright idea anymore.
sobreviviendo en la tierra de los trolldev
I'm guessing he found it in Wipeout Pure's BOOT.BIN.placasoft wrote:lol....komm lieber mal in mein eigenes Forum...pg.de wurde mich zu dumm -.-GeKKo wrote:The 1. Way doesn't work for me : /.
Hey placa man sieht dich so selten auf pg.de :|
In which binary do you found this? @ TMBINC
Live free, prosper, and under my rule.
With help of #pspdev i was able to continously call "sceKernelSleepThread", so sound continued but browser crashed. yay.
The binary is in fact loaded to 08900000. That location seems to be "static", it isn't randomized or so.
Next big task is to place some more interesting code somewhere where we know the memory address of. I haven't succeeded here for now.
Damn, i wish i had a ramdump of the running game...
The binary is in fact loaded to 08900000. That location seems to be "static", it isn't randomized or so.
Next big task is to place some more interesting code somewhere where we know the memory address of. I haven't succeeded here for now.
Damn, i wish i had a ramdump of the running game...
-
- Posts: 62
- Joined: Tue May 31, 2005 5:11 am
Tres promising
If you managed to call the KernelSleepThread, how did you achieve that?
If you'd like to share please do :) but if not - Wouldn't it simply be possible to place your own code in the data you pass (except you'll have a pain to code it in such a way that it only uses allowed bytes)? That's at a known address (program counter - xx) which you can stuff in ra and jump to?
0xdf
If you'd like to share please do :) but if not - Wouldn't it simply be possible to place your own code in the data you pass (except you'll have a pain to code it in such a way that it only uses allowed bytes)? That's at a known address (program counter - xx) which you can stuff in ra and jump to?
0xdf
Re: Tres promising
perhaps by overwriting the return address, which is stored on stack.0xdeadface wrote:If you managed to call the KernelSleepThread, how did you achieve that?
@tmbinc: which disassembler did you use and how did you find the functions which parses the URL?
0xdeadface:
I overwrote the return address with the address of the sceKernelSleepThread function (or better, the wrapper).
Yes, i could pass my own code, but the problem is finding it in memory. I don't know where the stack is located nor any other place where i can upload code to. The only thing i know is that the binary itself is loaded to 08900000.
Basically only .data or .bss are fixed in memory, and i wasn't able to find anything useful which i could do to have specific data loaded there.
Making some "shellcode" which only contains allowed bytes is probably difficult but not impossible. so far i wrote some "put-something-to-vram" which doesn't have any nullbytes - but still, i don't know where i have to jump to.
@shine:
IDA Pro, as always. I'm a lucky employee who could convince his company that this piece of software is "absolutely required for my work". And well, it is. :)
Finding the stuff is easy. Just search for some sprintf()-like format strings, and look how they are used.
Or search for stack frames in the range of ~1kb or so (just search for the "addiu $sp, -0x400...0x500" or whatever - some binary wildcarding does it fine). That gives you a lot of interesting functions.
I overwrote the return address with the address of the sceKernelSleepThread function (or better, the wrapper).
Yes, i could pass my own code, but the problem is finding it in memory. I don't know where the stack is located nor any other place where i can upload code to. The only thing i know is that the binary itself is loaded to 08900000.
Basically only .data or .bss are fixed in memory, and i wasn't able to find anything useful which i could do to have specific data loaded there.
Making some "shellcode" which only contains allowed bytes is probably difficult but not impossible. so far i wrote some "put-something-to-vram" which doesn't have any nullbytes - but still, i don't know where i have to jump to.
@shine:
IDA Pro, as always. I'm a lucky employee who could convince his company that this piece of software is "absolutely required for my work". And well, it is. :)
Finding the stuff is easy. Just search for some sprintf()-like format strings, and look how they are used.
Or search for stack frames in the range of ~1kb or so (just search for the "addiu $sp, -0x400...0x500" or whatever - some binary wildcarding does it fine). That gives you a lot of interesting functions.
is the location random? or would it be the same place every time?
if it was fixed, and you could put enough nops in front of it, it would be possible to generate a batch of say 1000 possible locations..
i'm sure we could find enough volunteers to try them fairly quickly..
if it was fixed, and you could put enough nops in front of it, it would be possible to generate a batch of say 1000 possible locations..
i'm sure we could find enough volunteers to try them fairly quickly..
Chaosmachine Studios: High Quality Homebrew.
Are you sure that the kernel function was called? Freezing the browser is a known issue, see this topic. How does your URL look like? Perhaps with some JavaScript we can write some bytes, which cannot be parsed.tmbinc wrote:With help of #pspdev i was able to continously call "sceKernelSleepThread", so sound continued but browser crashed. yay.
-
- Posts: 62
- Joined: Tue May 31, 2005 5:11 am
Stack
tmbinc,
While I assume you already have done this, have you checked where with your own (meaning any homebrew) app the stack lies?
It'd be kinda safe to assume that the stack at that moment of crashing can't be *that* far away from that address. Surely it'll be a tad deeper, but most likely in the order of bytes, not Kb's.
If you have determined how long the string is you can pass (both before the jump address and after it you should be able to inject different fragments of code to and some cleverly guessed jump addresses to figure out where your stack lies exactly at that moment in time?
This is, by the way, assuming that the crash happens in usermode code. I don't know whether kernel code uses it's own stackspace.
Unfortunately I have no WipeOut....might want to get that :)
0xdf
(edited to make one thing a bit more readable'
While I assume you already have done this, have you checked where with your own (meaning any homebrew) app the stack lies?
It'd be kinda safe to assume that the stack at that moment of crashing can't be *that* far away from that address. Surely it'll be a tad deeper, but most likely in the order of bytes, not Kb's.
If you have determined how long the string is you can pass (both before the jump address and after it you should be able to inject different fragments of code to and some cleverly guessed jump addresses to figure out where your stack lies exactly at that moment in time?
This is, by the way, assuming that the crash happens in usermode code. I don't know whether kernel code uses it's own stackspace.
Unfortunately I have no WipeOut....might want to get that :)
0xdf
(edited to make one thing a bit more readable'
Perhaps loading an image could work. If the graphics mode has no unused bytes, like 3 bytes for true color per pixel instead of 4 bytes, then you can load a true color PNG image in the browser. But I don't know, if it is possible to execute code in VRAM.tmbinc wrote: Does anybody know how to place something in the memory at a known location?
Ok, now some code which may help to write arbitrary bytes on the stack:
Code: Select all
<center>"<a href="proc://upload/profile:http://?x">CRASH ME</a>"
<script>
/* use this for dumping
var properties = "";
for (var property in document.links[0])
properties = properties + property + "=" + document.links[0][property] + "<br>";
document.write(properties);
*/
// 0x9ACE131E,sceKernelSleepThread
call=unescape("%u131e%u9ace");
big="";
for (i = 0; i < 272; i++) big = big + call;
document.links[0].href="proc://upload/profile:http://?" + big;
</script>
You need to put the address of sceKernelSleepThread, not the ID. the address would be 0x08a39360. otherwise it would work, though i didn't tried with javascript. i had to use 0x48a39360 because 0x08 wouldn't be parsed, but maybe you have more luck with javascript!
i used Wipeout-USA (is there another version?)
0xdeadface: the problem is that each thread allocates a new stack, most threads have stack sized of ~64k. this gives a rather large space to search :/
i used Wipeout-USA (is there another version?)
0xdeadface: the problem is that each thread allocates a new stack, most threads have stack sized of ~64k. this gives a rather large space to search :/
-
- Posts: 62
- Joined: Tue May 31, 2005 5:11 am
tmbinc,
Have you already determined the correct position in the string where the return address should be placed?
I wonder how many bytes you can get stuffed behind it...it would, in case of a bruteforce search, at least limit the search space
I know it´d be a ridiculous venture but......if all else fails.....
0xdf
Have you already determined the correct position in the string where the return address should be placed?
I wonder how many bytes you can get stuffed behind it...it would, in case of a bruteforce search, at least limit the search space
I know it´d be a ridiculous venture but......if all else fails.....
0xdf
tmbinc, nice work so far.
tmbinc:
have you tried looking for a byte sequence in the wipeout
binary which will form an opcode to copy the current stack pointer
into the Program counter/ Instruction Pointer ?
something like
MOV PC, SP (ARM equivalent)
or
PUSH ESP (IA32 equivalent)
RET
From there you can continue your experiments ;-)
This might work, depending on the layout of the stack.
i'd love to try it out myself but i don't have a psp ;-)
any sponsors around ? ;-)
cheers
tmbinc:
have you tried looking for a byte sequence in the wipeout
binary which will form an opcode to copy the current stack pointer
into the Program counter/ Instruction Pointer ?
something like
MOV PC, SP (ARM equivalent)
or
PUSH ESP (IA32 equivalent)
RET
From there you can continue your experiments ;-)
This might work, depending on the layout of the stack.
i'd love to try it out myself but i don't have a psp ;-)
any sponsors around ? ;-)
cheers
i was thinking about this the other day but i didnt post it because i thought it was too dumb
but if you have a vague idea where the stack is you could just put it the return address, and then a huge list of no ops (like several K), followed by your code.
that way as long as the return address is within the list of no ops, it should just run all the way down them to your code, so you dont have to hit the first instruction spot on.
if you cant encode the no op instuction (does mips even have one?) you could always just put a huge list of adds that wont have any effect other than adding lots to a register
but if you have a vague idea where the stack is you could just put it the return address, and then a huge list of no ops (like several K), followed by your code.
that way as long as the return address is within the list of no ops, it should just run all the way down them to your code, so you dont have to hit the first instruction spot on.
if you cant encode the no op instuction (does mips even have one?) you could always just put a huge list of adds that wont have any effect other than adding lots to a register
That'd beGalfpart wrote: MOV PC, SP (ARM equivalent)
or
PUSH ESP (IA32 equivalent)
RET
Code: Select all
jr $sp
And that's the dword 0.if you cant encode the no op instuction (does mips even have one?) you could always just put a huge list of adds that wont have any effect other than adding lots to a register
pixel: A mischievous magical spirit associated with screen displays. The computer industry has frequently borrowed from mythology. Witness the sprites in computer graphics, the demons in artificial intelligence and the trolls in the marketing department.
http://wiki.nobis-crew.org/PlayStation/r3000
There's all the ressources you need to encode the instruction yourself, and even more of them. jr $sp would be 0x03a00008
There's all the ressources you need to encode the instruction yourself, and even more of them. jr $sp would be 0x03a00008
pixel: A mischievous magical spirit associated with screen displays. The computer industry has frequently borrowed from mythology. Witness the sprites in computer graphics, the demons in artificial intelligence and the trolls in the marketing department.
Thanks!
the bad news:
Searching down CASE-INSENSITIVELY for binary string 08 00 a0 03...
Search failed.
Command "AskBinaryText" failed
Gotta have a deeper look...
edit:
as MIPS processors have a lot of registers, there may be more
than just one register pointing to the stack. maybe someone is lucky
and can find any register pointing into his "shellcode". what does
the psp do when it crashes?
i want a coredump ;-)
the bad news:
Searching down CASE-INSENSITIVELY for binary string 08 00 a0 03...
Search failed.
Command "AskBinaryText" failed
Gotta have a deeper look...
edit:
as MIPS processors have a lot of registers, there may be more
than just one register pointing to the stack. maybe someone is lucky
and can find any register pointing into his "shellcode". what does
the psp do when it crashes?
i want a coredump ;-)
Last edited by Galfpart on Wed Jun 01, 2005 11:38 pm, edited 1 time in total.