Join Us and become a Member for a Verified Badge on Discord to access private areas with the latest PS4 PKGs.
PS4 Jailbreaking       Thread starter PSXHAX       Start date Dec 18, 2021 at 3:41 PM       14,398       48      
As the PS4Scene releases even more PS4 PKG 9.00 Game Dumps this month via the pOOBs4 Exploit, following the PS4 PKG / Keys Information and his PKG_PFS_Tool: PS4 PKG / PFS / Save Games Unpacker Tool developer @flatz disclosed on Twitter a PS4 Crypto CoProcessor (CCP) Kernel Bug that allows bruteforcing key slots from the Secure Asset Management Unit (SAMU) Processor, which he details in ccp_crypto_bug.c how the AES / HMAC Keys from PFS, Portability Keys, VTRM Keys and Save Keys are retrieved before the crypto flaw was fixed between 7.55 and 9.00 firmware! 🎄🔥:ninja:

To recap briefly, this comes following the PS4 PFS Protection Bypass Guide, PS4 Sealedkey / pfsSKKey for SaveGame & Trophy Data Decryption, PSFSKKey PS4 SaveGame Decryption Tool, Installing PS4 Saves From Other PS4's Without Save Wizard, How to Resign PS4 Saves Without Save Wizard, the PS4 9.00 Webkit Exploit, the AMD Server Vulnerabilities revealed last month, the 9.00 PS4 Payloads and PS4 9.00 Kernel Exploit allowing all PlayStation 4 consoles on PS4 OFW 9.00 or below to be jailbroken. :lovewins:

And from ccp_crypto_bug.c:
Code:
int dump_raw_keys(unsigned int* key_ids, size_t key_count, unsigned int max_key_size, uint8_t** key_data, size_t* key_data_size) {
    uint8_t* kd = NULL;
    size_t kds;
    void* buf = NULL, *m_buf = NULL;
    struct sbl_map_list_entry* d_buf = NULL;
    size_t buf_size = PAGE_SIZE;
    struct ccp_req req;
    struct ccp_msg msg;
    size_t data_size = 0x10;
    uint8_t current_key[0x40];
    uint8_t real_hash[0x20], our_hash[0x20];
    unsigned int key_index, key_size;
    uint8_t* ckd;
    unsigned int i, j;
    size_t c;
    int found;
    int ret;

    //dprintf("Allocating memory for key data buffer...\n");
    kds = (max_key_size + sizeof(int)) * key_count;
    kd = (uint8_t*)alloc(kds);
    if (!kd) {
        //dprintf("Failed.\n");
        ret = ENOMEM;
        goto error;
    }
    memset(kd, 0, kds);

    memset(&req, 0, sizeof(req));
    memset(&msg, 0, sizeof(msg));

    TAILQ_INIT(&req.msgs);
    TAILQ_INSERT_TAIL(&req.msgs, &msg, next);

    //dprintf("Allocating memory for data buffer...\n");
    buf = alloc(buf_size);
    if (!buf) {
        //dprintf("Failed.\n");
        ret = ENOMEM;
        goto error;
    }
    //dprintf("Data buffer CPU address: %p\n", buf);
    memset(buf, 0, buf_size);

    //dprintf("Filling data buffer with random data...\n");
    for (i = 0; i < data_size; ++i)
        *((uint8_t*)buf + i) = (i + 1) & 0xFF;

    //dprintf("Mapping data buffer to GPU...\n");
    ret = sceSblDriverMapPages(&m_buf, buf, BYTES_TO_PAGES(buf_size), 0x61, NULL, &d_buf);
    if (ret != 0) {
        //dprintf("Failed.\n");
        goto error;
    }
    //dprintf("Data buffer GPU address: %p (d: %p)\n", m_buf, d_buf);

    for (c = 0; c < key_count; ++c) {
        key_index = key_ids[c];
        ckd = kd + (max_key_size + sizeof(int)) * c;

        //dprintf("Bruteforcing key index: 0x%04X\n", key_index);

        memset(current_key, 0, sizeof(current_key));
        memset(real_hash, 0, sizeof(real_hash));
        memset(our_hash, 0, sizeof(our_hash));

        for (key_size = 0; key_size < max_key_size; ++key_size) {
            memset(&msg.op, 0, sizeof(msg.op));
            msg.op.hmac.cmd = 0x09034000 | CCP_USE_KEY_FROM_SLOT;
            msg.op.hmac.data_size = data_size;
            msg.op.hmac.data = buf;
            msg.op.hmac.data_size_bits = data_size * 8;
            msg.op.hmac.key_index = key_index;
            msg.op.hmac.key_size = key_size + 1;

            //dprintf("Preparing crypto request...\n");
            ret = sceSblServiceCrypt(&req);
            if (ret != 0) {
                *(int*)(ckd + max_key_size) = ret;
                //dprintf("sceSblServiceCrypt(index) failed (code: 0x%"PRIX32").\n", ret);
                //dprintf("\t0x%04X: N/A\n", key_index);
                break;
            }
            memcpy(real_hash, msg.op.hmac.hash, sizeof(real_hash));

            found = 0;
            for (i = 0; i < 256; ++i) {
                current_key[key_size] = (uint8_t)i;

                memset(&msg.op, 0, sizeof(msg.op));
                msg.op.hmac.cmd = 0x09034000;
                msg.op.hmac.data_size = data_size;
                msg.op.hmac.data = buf;
                msg.op.hmac.data_size_bits = data_size * 8;
                for (j = 0; j < (key_size + 1); ++j)
                    msg.op.hmac.key[(key_size + 1) - j - 1] = current_key[j]; /* reversed order */
                msg.op.hmac.key_size = key_size + 1;

                //dprintf("Preparing crypto request...\n");
                ret = sceSblServiceCrypt(&req);
                if (ret != 0)
                    break;
                memcpy(our_hash, msg.op.hmac.hash, sizeof(our_hash));

                if (memcmp(real_hash, our_hash, sizeof(real_hash)) == 0) {
                    current_key[key_size] = (uint8_t)i;
                    found = 1;
                    break;
                }
            }
            if (ret != 0) {
                *(int*)(ckd + max_key_size) = ret;
                //dprintf("sceSblServiceCrypt(key) failed (code: 0x%"PRIX32").\n", ret);
                break;
            }
            if (found) {
                if (key_size == max_key_size - 1) {
                    *(int*)(ckd + max_key_size) = 0;
                    for (i = 0; i < max_key_size; ++i)
                        ckd[i] = current_key[max_key_size - i - 1];
                }
            } else {
                *(int*)(ckd + max_key_size) = ESRCH;
                //dprintf("\tNOT FOUND\n");
            }
        }
    }

    ret = 0;

    if (key_data) {
        *key_data = kd;
        kd = NULL;
    }
    if (key_data_size)
        *key_data_size = kds;

error:
    if (d_buf) {
        //dprintf("Unmapping data buffer from GPU...\n");
        sceSblDriverUnmapPages(d_buf);
    }

    if (buf) {
        //dprintf("Freeing memory of data buffer...\n");
        dealloc(buf);
    }

    if (kd) {
        //dprintf("Freeing memory of key data buffer...\n");
        dealloc(kd);
    }

    return ret;
}

int dump_gen_keys(unsigned int cmd, int use_hmac, unsigned int max_key_size, unsigned int* key_ids, size_t key_count, uint8_t** key_data, size_t* key_data_size) {
    uint8_t* kd = NULL;
    size_t kds;
    void* buf = NULL, *m_buf = NULL;
    struct sbl_map_list_entry* d_buf = NULL;
    size_t buf_size = PAGE_SIZE;
    struct ccp_req req;
    struct ccp_msg msg;
    size_t data_size = 0x80;
    uint8_t current_key[0x40];
    uint8_t real_hash[0x20], our_hash[0x20];
    unsigned int key_index, key_size, key_index_mod;
    unsigned int key_handle = 0;
    union sbl_key_desc key_desc;
    uint8_t* ckd;
    unsigned int i, j;
    size_t c;
    int found;
    int ret;

    //dprintf("Allocating memory for key data buffer...\n");
    kds = (max_key_size + sizeof(int)) * key_count;
    kd = (uint8_t*)alloc(kds);
    if (!kd) {
        //dprintf("Failed.\n");
        ret = ENOMEM;
        goto error;
    }
    memset(kd, 0, kds);

    memset(&req, 0, sizeof(req));
    memset(&msg, 0, sizeof(msg));

    TAILQ_INIT(&req.msgs);
    TAILQ_INSERT_TAIL(&req.msgs, &msg, next);

    //dprintf("Allocating memory for data buffer...\n");
    buf = alloc(buf_size);
    if (!buf) {
        //dprintf("Failed.\n");
        ret = ENOMEM;
        goto error;
    }
    //dprintf("Data buffer CPU address: %p\n", buf);
    memset(buf, 0, buf_size);

    //dprintf("Filling data buffer with random data...\n");
    for (i = 0; i < data_size; ++i)
        *((uint8_t*)buf + i) = (i + 1) & 0xFF;

    //dprintf("Mapping data buffer to GPU...\n");
    ret = sceSblDriverMapPages(&m_buf, buf, BYTES_TO_PAGES(buf_size), 0x61, NULL, &d_buf);
    if (ret != 0) {
        //dprintf("Failed.\n");
        goto error;
    }
    //dprintf("Data buffer GPU address: %p (d: %p)\n", m_buf, d_buf);

    key_index_mod = use_hmac ? 0x8000 : 0;

    for (c = 0; c < key_count; ++c) {
        key_index = key_ids[c];
        ckd = kd + (max_key_size + sizeof(int)) * c;

        //dprintf("Bruteforcing key index: 0x%04X\n", key_index | key_index_mod);

        memset(&key_desc, 0, sizeof(key_desc));
        key_desc.portability.cmd = cmd;
        key_desc.portability.key_id = key_index | key_index_mod;

        key_handle = 0;
        ret = sceSblKeymgrSetKey(&key_desc, &key_handle);
        if (ret != 0) {
            *(int*)(ckd + max_key_size) = ret;
            //dprintf("sceSblKeymgrSetKey() failed (code: 0x%"PRIX32").\n", ret);
            //dprintf("\t0x%04X: N/A\n", key_index | key_index_mod);
            break;
        }

        memset(current_key, 0, sizeof(current_key));
        memset(real_hash, 0, sizeof(real_hash));
        memset(our_hash, 0, sizeof(our_hash));

        for (key_size = 0; key_size < max_key_size; ++key_size) {
            memset(&msg.op, 0, sizeof(msg.op));
            msg.op.hmac.cmd = 0x09034000 | CCP_USE_KEY_HANDLE;
            msg.op.hmac.data_size = data_size;
            msg.op.hmac.data = buf;
            msg.op.hmac.data_size_bits = data_size * 8;
            msg.op.hmac.key_index = key_handle;
            msg.op.hmac.key_size = key_size + 1;

            //dprintf("Preparing crypto request...\n");
            ret = sceSblServiceCrypt(&req);
            if (ret != 0) {
                *(int*)(ckd + max_key_size) = ret;
                //dprintf("sceSblServiceCrypt(index) failed (code: 0x%"PRIX32").\n", ret);
                //dprintf("\t0x%04X: N/A\n", key_index | key_index_mod);
                break;
            }
            memcpy(real_hash, msg.op.hmac.hash, sizeof(real_hash));

            found = 0;
            for (i = 0; i < 256; ++i) {
                current_key[key_size] = (uint8_t)i;

                memset(&msg.op, 0, sizeof(msg.op));
                msg.op.hmac.cmd = 0x09034000;
                msg.op.hmac.data_size = data_size;
                msg.op.hmac.data = buf;
                msg.op.hmac.data_size_bits = data_size * 8;
                for (j = 0; j < (key_size + 1); ++j)
                    msg.op.hmac.key[(key_size + 1) - j - 1] = current_key[j]; /* reversed order */
                msg.op.hmac.key_size = key_size + 1;

                //dprintf("Preparing crypto request...\n");
                ret = sceSblServiceCrypt(&req);
                if (ret != 0)
                    break;
                memcpy(our_hash, msg.op.hmac.hash, sizeof(our_hash));

                if (memcmp(real_hash, our_hash, sizeof(real_hash)) == 0) {
                    current_key[key_size] = (uint8_t)i;
                    found = 1;
                    break;
                }
            }
            if (ret != 0) {
                *(int*)(ckd + max_key_size) = ret;
                //dprintf("sceSblServiceCrypt(key) failed (code: 0x%"PRIX32").\n", ret);
                //dprintf("\t0x%04X: N/A\n", key_index);
                break;
            }
            if (found) {
                if (key_size == max_key_size - 1) {
                    *(int*)(ckd + max_key_size) = 0;
                    for (i = 0; i < max_key_size; ++i)
                        ckd[i] = current_key[max_key_size - i - 1];
                }
            } else {
                *(int*)(ckd + max_key_size) = ESRCH;
                //dprintf("\tNOT FOUND\n");
            }
        }

        if (key_handle) {
            ret = sceSblKeymgrClearKey(key_handle);
            if (ret != 0) {
                *(int*)(ckd + max_key_size) = ret;
                //dprintf("sceSblKeymgrClearKey() failed (code: 0x%"PRIX32").\n", ret);
                //dprintf("\t0x%04X: N/A\n", key_index);
                break;
            }
        }
    }

    ret = 0;

    if (key_data) {
        *key_data = kd;
        kd = NULL;
    }
    if (key_data_size)
        *key_data_size = kds;

error:
    if (d_buf) {
        //dprintf("Unmapping data buffer from GPU...\n");
        sceSblDriverUnmapPages(d_buf);
    }

    if (buf) {
        //dprintf("Freeing memory of data buffer...\n");
        dealloc(buf);
    }

    if (kd) {
        //dprintf("Freeing memory of key data buffer...\n");
        dealloc(kd);
    }

    return ret;
}

Spoiler: Related Tweets

PS4 Crypto CoProcessor (CCP) Bug on SAMU Key Slots for Save Keys & More!.jpg
 

Comments

jose gozalez

Senior Member
Contributor
These are part of the reasons not to be tempted to update the firmware, as in the ps5, it is possible that "things" that sony has patched come out.
 

arifx2

Senior Member
Contributor
is this the thing kept by savewizard team? they know something cannot fixed and keep updating or they really stop with the "Compatible with System Software 8.52" waiting for the update of cheat and save for the 9.00 offline mode with auto usb check
 

:fire: Latest Help Topics

Top