mirror of
https://github.com/AlexAltea/orbital.git
synced 2025-04-02 10:32:05 -04:00
273 lines
6.2 KiB
C
273 lines
6.2 KiB
C
/**
|
|
* (c) 2017-2018 Alexandro Sanchez Bach.
|
|
* Released under MIT license. Read LICENSE for more details.
|
|
*
|
|
* Based/inspired by previous tools and research by:
|
|
* flatz, m0rph3us1987, wildcard.
|
|
*/
|
|
|
|
#include "ps4.h"
|
|
|
|
#include "blob.h"
|
|
#include "debug.h"
|
|
#include "ksdk.h"
|
|
|
|
#include "gpu_dumper.h"
|
|
#include "pup_decrypter.h"
|
|
#include "self_decrypter.h"
|
|
#include "self_mapper.h"
|
|
|
|
/* kernel payloads */
|
|
int kpatch_getroot(struct thread *td)
|
|
{
|
|
/* Resolve credentials */
|
|
struct ucred *cred;
|
|
struct filedesc *fd;
|
|
|
|
fd = td->td_proc->p_fd;
|
|
cred = td->td_proc->p_ucred;
|
|
|
|
/* Escalate process to uid0 */
|
|
cred->cr_uid = 0;
|
|
cred->cr_ruid = 0;
|
|
cred->cr_rgid = 0;
|
|
cred->cr_groups[0] = 0;
|
|
|
|
/* Break out of FreeBSD jail */
|
|
cred->cr_prison = prison0[0];
|
|
|
|
/* Escalate ucred privs */
|
|
void *td_ucred = *(void **)(((char *)td) + 304);
|
|
// sceSblACMgrIsSystemUcred
|
|
uint64_t *sonyCred = (uint64_t *)(((char *)td_ucred) + 96);
|
|
*sonyCred = 0xffffffffffffffff;
|
|
// sceSblACMgrGetDeviceAccessType
|
|
uint64_t *sceProcType = (uint64_t *)(((char *)td_ucred) + 88);
|
|
*sceProcType = 0x3801000000000013;
|
|
// sceSblACMgrHasSceProcessCapability
|
|
uint64_t *sceProcCap = (uint64_t *)(((char *)td_ucred) + 104);
|
|
*sceProcCap = 0xffffffffffffffff;
|
|
|
|
/* Set vnode to real root "/" to defeat sandbox */
|
|
fd->fd_rdir = rootvnode[0];
|
|
fd->fd_jdir = rootvnode[0];
|
|
|
|
/* Return back to usermode */
|
|
return 0;
|
|
}
|
|
|
|
void kpatch_enablemapself(struct thread *td)
|
|
{
|
|
uint8_t *kmem;
|
|
cpu_disable_wp();
|
|
|
|
/* update offsets (5.00) */
|
|
uint8_t* kernel_base = &((uint8_t*)read_msr(0xC0000082))[-0x1C0];
|
|
uint8_t* map_self_patch1 = &kernel_base[0x117B0];
|
|
uint8_t* map_self_patch2 = &kernel_base[0x117C0];
|
|
#ifdef VERSION_500
|
|
uint8_t* map_self_patch3 = &kernel_base[0x13EF2F];
|
|
#elif VERSION_505
|
|
uint8_t* map_self_patch3 = &kernel_base[0x13F03F];
|
|
#else
|
|
#error "Target firmware not yet supported."
|
|
#endif
|
|
|
|
// sceSblACMgrIsAllowedToMmapSelf result
|
|
kmem = (uint8_t*)map_self_patch1;
|
|
kmem[0] = 0xB8;
|
|
kmem[1] = 0x01;
|
|
kmem[2] = 0x00;
|
|
kmem[3] = 0x00;
|
|
kmem[4] = 0x00;
|
|
kmem[5] = 0xC3;
|
|
|
|
// sceSblACMgrHasMmapSelfCapability result
|
|
kmem = (uint8_t*)map_self_patch2;
|
|
kmem[0] = 0xB8;
|
|
kmem[1] = 0x01;
|
|
kmem[2] = 0x00;
|
|
kmem[3] = 0x00;
|
|
kmem[4] = 0x00;
|
|
kmem[5] = 0xC3;
|
|
|
|
// sceSblAuthMgrIsLoadable bypass
|
|
kmem = (uint8_t*)map_self_patch3;
|
|
kmem[0] = 0x31;
|
|
kmem[1] = 0xC0;
|
|
kmem[2] = 0x90;
|
|
kmem[3] = 0x90;
|
|
kmem[4] = 0x90;
|
|
|
|
cpu_enable_wp();
|
|
}
|
|
|
|
static int traverse_dir(const char *dir, int recursive, void(*handler)(const char*))
|
|
{
|
|
void *dp;
|
|
struct dirent *entry;
|
|
char name[1024];
|
|
|
|
dp = opendir(dir);
|
|
if (!dp) {
|
|
dprintf("Invalid directory.\n");
|
|
return 1;
|
|
}
|
|
|
|
while ((entry = readdir(dp)) != NULL) {
|
|
if (entry->d_type == DT_DIR && recursive) {
|
|
if (!strcmp(entry->d_name, ".") ||
|
|
!strcmp(entry->d_name, "..") ||
|
|
!strcmp(entry->d_name, "$RECYCLE.BIN") ||
|
|
!strcmp(entry->d_name, "sandbox")) {
|
|
continue;
|
|
}
|
|
snprintf(name, sizeof(name), "%s/%s", dir, entry->d_name);
|
|
traverse_dir(name, recursive, handler);
|
|
}
|
|
if (entry->d_type == DT_REG) {
|
|
snprintf(name, sizeof(name), "%s/%s", dir, entry->d_name);
|
|
handler(name);
|
|
}
|
|
}
|
|
closedir(dp);
|
|
return 0;
|
|
}
|
|
|
|
static void decrypt_self_to_blobs(const char *file)
|
|
{
|
|
int err;
|
|
self_t *self;
|
|
const char *dot;
|
|
|
|
// Check filename and open file
|
|
dot = strrchr(file, '.');
|
|
if (!dot) return;
|
|
if (strcmp(dot, ".self") &&
|
|
strcmp(dot, ".sprx") &&
|
|
strcmp(dot, ".elf") &&
|
|
strcmp(dot, ".bin")) {
|
|
return;
|
|
}
|
|
dprintf("Decrypting %s to blobs.\n", file);
|
|
self = self_open(file);
|
|
if (!self) {
|
|
return;
|
|
}
|
|
|
|
// Decrypt SELF
|
|
err = self_verify_header(self);
|
|
if (err)
|
|
goto fail;
|
|
err = self_load_segments(self);
|
|
if (err)
|
|
goto fail;
|
|
blob_transfer_all(self->blobs, BLOB_TRANSFER_NET);
|
|
|
|
fail:
|
|
self_close(self);
|
|
return;
|
|
}
|
|
|
|
static void decrypt_self_to_elf(const char *file)
|
|
{
|
|
const char *dot;
|
|
char path[256];
|
|
uint8_t *elf_data;
|
|
size_t elf_size;
|
|
blob_t blob;
|
|
|
|
// Check filename and open file
|
|
dot = strrchr(file, '.');
|
|
if (!dot) return;
|
|
if (strcmp(dot, ".self") &&
|
|
strcmp(dot, ".sprx") &&
|
|
strcmp(dot, ".elf") &&
|
|
strcmp(dot, ".bin")) {
|
|
return;
|
|
}
|
|
dprintf("Decrypting %s to ELF.\n", file);
|
|
elf_data = self_decrypt_file(file, &elf_size);
|
|
if (!elf_data)
|
|
return;
|
|
|
|
blob.next = NULL;
|
|
blob.data = elf_data;
|
|
blob.size = elf_size;
|
|
snprintf(path, sizeof(path), "elfs/%s", file);
|
|
blob_set_path(&blob, path);
|
|
blob_transfer(&blob, BLOB_TRANSFER_NET);
|
|
free(elf_data);
|
|
}
|
|
|
|
static void decrypt_pup_to_blobs(const char *file)
|
|
{
|
|
int err;
|
|
pup_t *pup;
|
|
const char *dot;
|
|
|
|
// Check filename and open file
|
|
dot = strrchr(file, '.');
|
|
if (!dot) return;
|
|
if (strcmp(dot, ".PUP") &&
|
|
strcmp(dot, ".pup")) {
|
|
return;
|
|
}
|
|
dprintf("Decrypting %s to blobs.\n", file);
|
|
pup = pup_open(file);
|
|
if (!pup) {
|
|
return;
|
|
}
|
|
|
|
// Decrypt PUP
|
|
err = pup_verify_header(pup);
|
|
if (err)
|
|
goto fail;
|
|
err = pup_decrypt_segments(pup);
|
|
if (err)
|
|
goto fail;
|
|
blob_transfer_all(pup->blobs, BLOB_TRANSFER_NET);
|
|
|
|
fail:
|
|
pup_close(pup);
|
|
return;
|
|
}
|
|
|
|
static void decrypt_selfs(void)
|
|
{
|
|
traverse_dir("/", true, decrypt_self_to_blobs);
|
|
traverse_dir("/", true, decrypt_self_to_elf);
|
|
}
|
|
|
|
static void decrypt_pups(void)
|
|
{
|
|
traverse_dir("/mnt/usb0", true, decrypt_pup_to_blobs);
|
|
}
|
|
|
|
int _main(struct thread *td)
|
|
{
|
|
/* Prepare userland environment */
|
|
initKernel();
|
|
initLibc();
|
|
initNetwork();
|
|
|
|
debug_init();
|
|
blob_transfer_init();
|
|
dprintf("Starting dump...\n");
|
|
|
|
/* Prepare kernel environment*/
|
|
syscall(11, init_ksdk);
|
|
syscall(11, kpatch_getroot);
|
|
syscall(11, kpatch_enablemapself);
|
|
|
|
/* Dump/decrypt data */
|
|
decrypt_selfs();
|
|
decrypt_pups();
|
|
//gpu_dump_ih();
|
|
|
|
/* Return back to browser */
|
|
dprintf("Dump finished!\n");
|
|
blob_transfer_close();
|
|
debug_close();
|
|
return 0;
|
|
}
|