diff --git a/.gitmodules b/.gitmodules index e54497a..f43c8dd 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ -[submodule "payload/freebsd-headers"] - path = payload/freebsd-headers - url = https://github.com/OpenOrbis/freebsd-headers +[submodule "payload/sdk"] + path = payload/sdk + url = https://github.com/PS5Dev/PS5SDK diff --git a/payload/Makefile b/payload/Makefile index 7da7361..030ee9b 100644 --- a/payload/Makefile +++ b/payload/Makefile @@ -1,9 +1,9 @@ TARGET = payload -OBJS = start.o payload.o +OBJS = start.o stubs.o payload.o resolve.o kernel.o CC = gcc OBJCOPY = objcopy -CFLAGS = -DSMP -isystem freebsd-headers/include -Wl,--build-id=none -Os -fno-stack-protector -fcf-protection=none -fpic -fpie +CFLAGS = -isystem sdk/include -Wl,--build-id=none -Os -Wno-builtin-declaration-mismatch -fno-stack-protector -fcf-protection=none -fpic -fpie LDFLAGS = -T linker.ld -nostartfiles -nostdlib all: $(TARGET).bin diff --git a/payload/freebsd-headers b/payload/freebsd-headers deleted file mode 160000 index ad8cef9..0000000 --- a/payload/freebsd-headers +++ /dev/null @@ -1 +0,0 @@ -Subproject commit ad8cef9530ec4d7d603be0d5736c732455865345 diff --git a/payload/kernel.c b/payload/kernel.c new file mode 100644 index 0000000..85e437d --- /dev/null +++ b/payload/kernel.c @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2021-2024 Andy Nguyen + * + * This software may be modified and distributed under the terms + * of the MIT license. See the LICENSE file for details. + */ + +#include +#include +#include + +#include "payload.h" + +#define PAGE_SIZE 0x4000 + +struct pipebuf { + uint32_t cnt; + uint32_t in; + uint32_t out; + uint32_t size; + uintptr_t buffer; +}; + +static int corrupt_pipebuf(uint32_t cnt, uint32_t in, uint32_t out, + uint32_t size, uintptr_t buffer) { + struct pipebuf buf = {}; + buf.cnt = cnt; + buf.in = in; + buf.out = out; + buf.size = size; + buf.buffer = buffer; + write(payload_args->master_pipe_fd[1], &buf, sizeof(buf)); + return read(payload_args->master_pipe_fd[0], &buf, sizeof(buf)); +} + +int kread(void *dest, uintptr_t src, size_t n) { + corrupt_pipebuf(n, 0, 0, PAGE_SIZE, src); + return read(payload_args->victim_pipe_fd[0], dest, n); +} + +int kwrite(uintptr_t dest, const void *src, size_t n) { + corrupt_pipebuf(0, 0, 0, PAGE_SIZE, dest); + return write(payload_args->victim_pipe_fd[1], src, n); +} + +uint8_t kread8(uintptr_t addr) { + uint8_t val = 0; + kread(&val, addr, sizeof(val)); + return val; +} + +uint16_t kread16(uintptr_t addr) { + uint16_t val = 0; + kread(&val, addr, sizeof(val)); + return val; +} + +uint32_t kread32(uintptr_t addr) { + uint32_t val = 0; + kread(&val, addr, sizeof(val)); + return val; +} + +uint64_t kread64(uintptr_t addr) { + uint64_t val = 0; + kread(&val, addr, sizeof(val)); + return val; +} + +void kwrite8(uintptr_t addr, uint8_t val) { kwrite(addr, &val, sizeof(val)); } + +void kwrite16(uintptr_t addr, uint16_t val) { kwrite(addr, &val, sizeof(val)); } + +void kwrite32(uintptr_t addr, uint32_t val) { kwrite(addr, &val, sizeof(val)); } + +void kwrite64(uintptr_t addr, uint64_t val) { kwrite(addr, &val, sizeof(val)); } diff --git a/payload/kernel.h b/payload/kernel.h new file mode 100644 index 0000000..f7d8819 --- /dev/null +++ b/payload/kernel.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2021-2024 Andy Nguyen + * + * This software may be modified and distributed under the terms + * of the MIT license. See the LICENSE file for details. + */ + +#ifndef __KERNEL_H__ +#define __KERNEL_H__ + +int kread(void *dest, uintptr_t src, size_t n); +uint8_t kread8(uintptr_t addr); +uint16_t kread16(uintptr_t addr); +uint32_t kread32(uintptr_t addr); +uint64_t kread64(uintptr_t addr); + +int kwrite(uintptr_t dest, const void *src, size_t n); +void kwrite8(uintptr_t addr, uint8_t val); +void kwrite16(uintptr_t addr, uint16_t val); +void kwrite32(uintptr_t addr, uint32_t val); +void kwrite64(uintptr_t addr, uint64_t val); + +#endif diff --git a/payload/payload.c b/payload/payload.c index dc95ef2..3c5adab 100644 --- a/payload/payload.c +++ b/payload/payload.c @@ -1,3 +1,10 @@ +/* + * Copyright (C) 2021-2024 Andy Nguyen + * + * This software may be modified and distributed under the terms + * of the MIT license. See the LICENSE file for details. + */ + #include #include #include @@ -6,328 +13,64 @@ #include #include #include +#include + +#include "kernel.h" +#include "payload.h" +#include "resolve.h" #define LOG_IP "192.168.1.53" #define LOG_PORT 1337 -#define LIBC_MODULE_HANDLE 0x2 -#define LIBKERNEL_MODULE_HANDLE 0x2001 +int inet_pton(int, const char *__restrict, void *__restrict); -#define PAGE_SIZE 0x4000 +PayloadArgs *payload_args; -typedef int32_t SceKernelModule; +static int old_stdout = -1; +static int log_sock = -1; -void *(*dlsym)(SceKernelModule handle, const char *symbol); - -// libkernel functions - -int *(*___error)(void); -int (*_accept)(int s, struct sockaddr *restrict addr, - socklen_t *restrict addrlen); -int (*_bind)(int s, const struct sockaddr *addr, socklen_t addrlen); -int (*_close)(int fd); -int (*_connect)(int s, const struct sockaddr *name, socklen_t namelen); -int (*_inet_pton)(int af, const char *restrict src, void *restrict dst); -int (*_listen)(int s, int backlog); -void *(*_mmap)(void *addr, size_t len, int prot, int flags, int fd, - off_t offset); -ssize_t (*_read)(int fd, void *buf, size_t nbytes); -int (*_socket)(int domain, int type, int protocol); -ssize_t (*_write)(int fd, const void *buf, size_t nbytes); - -int *__error(void) { return ___error(); } - -int accept(int s, struct sockaddr *restrict addr, socklen_t *restrict addrlen) { - return _accept(s, addr, addrlen); -} - -int bind(int s, const struct sockaddr *addr, socklen_t addrlen) { - return _bind(s, addr, addrlen); -} - -int close(int fd) { return _close(fd); } - -int connect(int s, const struct sockaddr *name, socklen_t namelen) { - return _connect(s, name, namelen); -} - -int inet_pton(int af, const char *restrict src, void *restrict dst) { - return _inet_pton(af, src, dst); -} - -int listen(int s, int backlog) { return _listen(s, backlog); } - -void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset) { - return _mmap(addr, len, prot, flags, fd, offset); -} - -ssize_t read(int fd, void *buf, size_t nbytes) { - return _read(fd, buf, nbytes); -} - -int socket(int domain, int type, int protocol) { - return _socket(domain, type, protocol); -} - -ssize_t write(int fd, const void *buf, size_t nbytes) { - return _write(fd, buf, nbytes); -} - -// libc functions - -void *(*_calloc)(size_t number, size_t size); -int (*_fclose)(FILE *stream); -FILE *(*_fopen)(const char *restrict path, const char *restrict mode); -size_t (*_fread)(void *restrict ptr, size_t size, size_t nmemb, - FILE *restrict stream); -// void (*_free)(void *ptr); -int (*_fseek)(FILE *stream, long offset, int whence); -long (*_ftell)(FILE *stream); -// void *(*_malloc)(size_t size); -void *(*_memcpy)(void *dst, const void *src, size_t len); -void *(*_memset)(void *s, int c, size_t n); -void *(*_realloc)(void *ptr, size_t size); -char *(*_strcat)(char *restrict s, const char *restrict append); -char *(*_strchr)(const char *s, int c); -char *(*_strrchr)(const char *s, int c); -int (*_strcmp)(const char *s1, const char *s2); -char *(*_strcpy)(char *restrict dst, const char *restrict src); -size_t (*_strlen)(const char *s); -int (*_strncmp)(const char *s1, const char *s2, size_t len); -int (*_vsnprintf)(char *restrict str, size_t size, const char *restrict format, - va_list ap); - -void *calloc(size_t number, size_t size) { return _calloc(number, size); } - -int fclose(FILE *stream) { return _fclose(stream); } - -FILE *fopen(const char *restrict path, const char *restrict mode) { - return _fopen(path, mode); -} - -size_t fread(void *restrict ptr, size_t size, size_t nmemb, - FILE *restrict stream) { - return _fread(ptr, size, nmemb, stream); -} - -// void free(void *ptr) { _free(ptr); } - -int fseek(FILE *stream, long offset, int whence) { - return _fseek(stream, offset, whence); -} - -long ftell(FILE *stream) { return _ftell(stream); } - -// void *malloc(size_t size) { return _malloc(size); } - -void *memcpy(void *dst, const void *src, size_t len) { - return _memcpy(dst, src, len); -} - -void *memset(void *s, int c, size_t n) { return _memset(s, c, n); } - -void *realloc(void *ptr, size_t size) { return _realloc(ptr, size); } - -int snprintf(char *restrict str, size_t size, const char *restrict format, - ...) { - int r; - va_list args; - va_start(args, format); - r = vsnprintf(str, size, format, args); - va_end(args); - return r; -} - -char *strcat(char *restrict s, const char *restrict append) { - return _strcat(s, append); -} - -int strcmp(const char *s1, const char *s2) { return _strcmp(s1, s2); } - -char *strchr(const char *s, int c) { return _strchr(s, c); } - -char *strrchr(const char *s, int c) { return _strrchr(s, c); } - -char *strcpy(char *restrict dst, const char *restrict src) { - return _strcpy(dst, src); -} - -size_t strlen(const char *s) { return _strlen(s); } - -int strncmp(const char *s1, const char *s2, size_t len) { - return _strncmp(s1, s2, len); -} - -int vsnprintf(char *restrict str, size_t size, const char *restrict format, - va_list ap) { - return _vsnprintf(str, size, format, ap); -} - -void resolve_imports(void) { -#define LIBKERNEL_RESOLVE(name) _##name = dlsym(LIBKERNEL_MODULE_HANDLE, #name) - LIBKERNEL_RESOLVE(__error); - LIBKERNEL_RESOLVE(accept); - LIBKERNEL_RESOLVE(bind); - LIBKERNEL_RESOLVE(close); - LIBKERNEL_RESOLVE(connect); - LIBKERNEL_RESOLVE(inet_pton); - LIBKERNEL_RESOLVE(listen); - LIBKERNEL_RESOLVE(mmap); - LIBKERNEL_RESOLVE(read); - LIBKERNEL_RESOLVE(socket); - LIBKERNEL_RESOLVE(write); -#undef LIBKERNEL_RESOLVE - -#define LIBC_RESOLVE(name) _##name = dlsym(LIBC_MODULE_HANDLE, #name) - LIBC_RESOLVE(calloc); - LIBC_RESOLVE(fclose); - LIBC_RESOLVE(fopen); - LIBC_RESOLVE(fread); - // LIBC_RESOLVE(free); - free = dlsym(LIBC_MODULE_HANDLE, "free"); - LIBC_RESOLVE(fseek); - LIBC_RESOLVE(ftell); - // LIBC_RESOLVE(malloc); - malloc = dlsym(LIBC_MODULE_HANDLE, "malloc"); - LIBC_RESOLVE(memcpy); - LIBC_RESOLVE(memset); - LIBC_RESOLVE(realloc); - LIBC_RESOLVE(strcat); - LIBC_RESOLVE(strchr); - LIBC_RESOLVE(strrchr); - LIBC_RESOLVE(strcmp); - LIBC_RESOLVE(strcpy); - LIBC_RESOLVE(strlen); - LIBC_RESOLVE(strncmp); - LIBC_RESOLVE(vsnprintf); -#undef LIBC_RESOLVE -} - -int log_sock = -1; - -int printf(const char *__restrict fmt, ...) { - va_list list; - char str[1024]; - - va_start(list, fmt); - vsnprintf(str, sizeof(str), fmt, list); - va_end(list); - - write(log_sock, str, strlen(str)); - - return 0; -} - -int puts(const char *str) { - write(log_sock, str, strlen(str)); - write(log_sock, "\n", 1); - return 0; -} - -int init_log(void) { +static int init_log(void) { int ret; - int s = socket(AF_INET, SOCK_STREAM, 0); - if (s < 0) - return s; + log_sock = socket(AF_INET, SOCK_STREAM, 0); + if (log_sock < 0) + return log_sock; struct sockaddr_in sin; memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = htons(LOG_PORT); ret = inet_pton(AF_INET, LOG_IP, &sin.sin_addr); - if (ret < 0) + if (ret < 0) { + close(log_sock); return ret; + } - ret = connect(s, (struct sockaddr *)&sin, sizeof(sin)); - if (ret < 0) + ret = connect(log_sock, (struct sockaddr *)&sin, sizeof(sin)); + if (ret < 0) { + close(log_sock); return ret; + } - log_sock = s; + // Redirect stdout. + old_stdout = dup(1); + dup2(log_sock, 1); return 0; } -void shutdown_log(void) { close(log_sock); } - -typedef struct { - void *dlsym; - uint64_t kaslr_offset; - int *master_pipe_fd; - int *victim_pipe_fd; -} PayloadArgs; - -PayloadArgs *payload_args; - -struct pipebuf { - uint32_t cnt; - uint32_t in; - uint32_t out; - uint32_t size; - uintptr_t buffer; -}; - -int corrupt_pipebuf(uint32_t cnt, uint32_t in, uint32_t out, uint32_t size, - uintptr_t buffer) { - struct pipebuf buf = {}; - buf.cnt = cnt; - buf.in = in; - buf.out = out; - buf.size = size; - buf.buffer = buffer; - write(payload_args->master_pipe_fd[1], &buf, sizeof(buf)); - return read(payload_args->master_pipe_fd[0], &buf, sizeof(buf)); +static void shutdown_log(void) { + dup2(old_stdout, 1); + close(old_stdout); + close(log_sock); } -int kread(void *dest, uintptr_t src, size_t n) { - corrupt_pipebuf(n, 0, 0, PAGE_SIZE, src); - return read(payload_args->victim_pipe_fd[0], dest, n); -} - -int kwrite(uintptr_t dest, const void *src, size_t n) { - corrupt_pipebuf(0, 0, 0, PAGE_SIZE, dest); - return write(payload_args->victim_pipe_fd[1], src, n); -} - -uint8_t kread8(uintptr_t addr) { - uint8_t val = 0; - kread(&val, addr, sizeof(val)); - return val; -} - -uint16_t kread16(uintptr_t addr) { - uint16_t val = 0; - kread(&val, addr, sizeof(val)); - return val; -} - -uint32_t kread32(uintptr_t addr) { - uint32_t val = 0; - kread(&val, addr, sizeof(val)); - return val; -} - -uint64_t kread64(uintptr_t addr) { - uint64_t val = 0; - kread(&val, addr, sizeof(val)); - return val; -} - -void kwrite8(uintptr_t addr, uint8_t val) { kwrite(addr, &val, sizeof(val)); } - -void kwrite16(uintptr_t addr, uint16_t val) { kwrite(addr, &val, sizeof(val)); } - -void kwrite32(uintptr_t addr, uint32_t val) { kwrite(addr, &val, sizeof(val)); } - -void kwrite64(uintptr_t addr, uint64_t val) { kwrite(addr, &val, sizeof(val)); } - int payload(PayloadArgs *args) { int ret; payload_args = args; - dlsym = args->dlsym; - resolve_imports(); + resolve_imports(args->dlsym); ret = init_log(); if (ret < 0) diff --git a/payload/payload.h b/payload/payload.h new file mode 100644 index 0000000..dac082d --- /dev/null +++ b/payload/payload.h @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2021-2024 Andy Nguyen + * + * This software may be modified and distributed under the terms + * of the MIT license. See the LICENSE file for details. + */ + +#ifndef __PAYLOAD_H__ +#define __PAYLOAD_H__ + +typedef struct { + void *dlsym; + uint64_t kaslr_offset; + int *master_pipe_fd; + int *victim_pipe_fd; +} PayloadArgs; + +extern PayloadArgs *payload_args; + +#endif diff --git a/payload/resolve.c b/payload/resolve.c new file mode 100644 index 0000000..8244dc6 --- /dev/null +++ b/payload/resolve.c @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2021-2024 Andy Nguyen + * + * This software may be modified and distributed under the terms + * of the MIT license. See the LICENSE file for details. + */ + +#include + +#include "resolve.h" + +void resolve_imports(void *(*dlsym)(SceKernelModule handle, + const char *symbol)) { +#define LIBKERNEL_RESOLVE(name) \ + extern void *name; \ + *(uintptr_t *)((uintptr_t)&name + 0x6) = \ + (uintptr_t)dlsym(LIBKERNEL_MODULE_HANDLE, #name) + + LIBKERNEL_RESOLVE(__error); + LIBKERNEL_RESOLVE(close); + LIBKERNEL_RESOLVE(connect); + LIBKERNEL_RESOLVE(dup); + LIBKERNEL_RESOLVE(dup2); + LIBKERNEL_RESOLVE(inet_pton); + LIBKERNEL_RESOLVE(read); + LIBKERNEL_RESOLVE(socket); + LIBKERNEL_RESOLVE(write); +#undef LIBKERNEL_RESOLVE + +#define LIBC_RESOLVE(name) \ + extern void *name; \ + *(uintptr_t *)((uintptr_t)&name + 0x6) = \ + (uintptr_t)dlsym(LIBC_MODULE_HANDLE, #name) + + LIBC_RESOLVE(printf); + LIBC_RESOLVE(putchar); + LIBC_RESOLVE(puts); + LIBC_RESOLVE(vsnprintf); +#undef LIBC_RESOLVE +} diff --git a/payload/resolve.h b/payload/resolve.h new file mode 100644 index 0000000..44a3afc --- /dev/null +++ b/payload/resolve.h @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2021-2024 Andy Nguyen + * + * This software may be modified and distributed under the terms + * of the MIT license. See the LICENSE file for details. + */ + +#ifndef __RESOLVE_H__ +#define __RESOLVE_H__ + +#define LIBC_MODULE_HANDLE 0x2 +#define LIBKERNEL_MODULE_HANDLE 0x2001 + +typedef int32_t SceKernelModule; + +void resolve_imports(void *(*dlsym)(SceKernelModule handle, + const char *symbol)); + +#endif diff --git a/payload/sdk b/payload/sdk new file mode 160000 index 0000000..a2e03a2 --- /dev/null +++ b/payload/sdk @@ -0,0 +1 @@ +Subproject commit a2e03a2a0231a3a3397fa6cd087a01ca6d04f273 diff --git a/payload/start.S b/payload/start.S index 04f9d40..727e517 100644 --- a/payload/start.S +++ b/payload/start.S @@ -1,4 +1,12 @@ -.text +/* + * Copyright (C) 2021-2024 Andy Nguyen + * + * This software may be modified and distributed under the terms + * of the MIT license. See the LICENSE file for details. + */ + +.intel_syntax noprefix +.section .text .global _start _start: diff --git a/payload/stubs.S b/payload/stubs.S new file mode 100644 index 0000000..322114a --- /dev/null +++ b/payload/stubs.S @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2021-2024 Andy Nguyen + * + * This software may be modified and distributed under the terms + * of the MIT license. See the LICENSE file for details. + */ + +.intel_syntax noprefix +.section .text + +.macro stub +jmp qword [rip-8] +.skip 8 +.endm + +// libkernel + +.global __error +__error: stub + +.global close +close: stub + +.global connect +connect: stub + +.global dup +dup: stub + +.global dup2 +dup2: stub + +.global inet_pton +inet_pton: stub + +.global read +read: stub + +.global socket +socket: stub + +.global write +write: stub + +// libc + +.global printf +printf: stub + +.global putchar +putchar: stub + +.global puts +puts: stub + +.global vsnprintf +vsnprintf: stub