diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 796cfc8..35ca99d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,19 +20,34 @@ jobs: runs-on: ubuntu-latest steps: - - name: Checkout Source Code + - name: Checkout uses: actions/checkout@v3 - - name: Setup Build Env - run: sudo apt-get install build-essential clang lld + - name: Checkout + uses: actions/checkout@v3 + with: + repository: john-tornblom/ps5-payload-sdk + path: ps5-payload-sdk + + - name: Setup SDK + working-directory: ps5-payload-sdk + run: | + sudo apt update + sudo apt install wget build-essential clang clang-15 lld lld-15 + make + make DESTDIR=${{ runner.tool_cache }}/ps5-payload-sdk install + echo PS5_PAYLOAD_SDK=${{ runner.tool_cache }}/ps5-payload-sdk >> $GITHUB_ENV + echo PS5_HOST=ps5 >> $GITHUB_ENV + echo PS5_PORT=9020 >> $GITHUB_ENV - name: Build Payload - run: make + run: | + make clean all - name: Upload Payload uses: actions/upload-artifact@v3 with: name: Payload - path: ./elfldr.elf + path: ./bootstrap.elf if-no-files-found: error diff --git a/.gitignore b/.gitignore index cb35f1f..eb9e024 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ *~ *.o *.elf -elfldr-socksrv_elf.c +elfldr_elf.c diff --git a/Makefile b/Makefile index 21661ef..81afe4a 100644 --- a/Makefile +++ b/Makefile @@ -1,55 +1,51 @@ -PS5_HOST ?= ps5 -PS5_PORT ?= 9020 -ELFLDR_PORT ?= 9021 +# Copyright (C) 2024 John Törnblom +# +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; see the file COPYING. If not see +# . -CC := clang -LD := ld.lld -XXD := xxd +ifndef PS5_PAYLOAD_SDK + $(error PS5_PAYLOAD_SDK is undefined) +endif -CFLAGS := -target x86_64-pc-none -fPIE -fno-stack-protector -ffreestanding \ - -fno-builtin -nostdlib -nostdinc -Wall -Werror -LDFLAGS := -pie -T elf_x86_64.x +PS5_HOST ?= ps5 +PS5_PORT ?= 9020 -OBJS := crt.o libc.o kern.o dynlib.o pt.o elfldr.o +CC := $(PS5_PAYLOAD_SDK)/host/x86_64-ps5-payload-cc +LD := $(PS5_PAYLOAD_SDK)/host/x86_64-ps5-payload-ld -all: elfldr.elf hello_world.elf +CFLAGS := -O2 -elfldr.elf: $(OBJS) main.o - $(LD) $(LDFLAGS) -o $@ $^ +all: bootstrap.elf -elfldr-socksrv.elf: $(OBJS) main-socksrv.o - $(LD) $(LDFLAGS) -o $@ $^ +elfldr.elf: main.o pt.o elfldr.o + $(LD) $^ -lSceLibcInternal -lkernel_sys -o $@ -payload_launchpad.elf: payload_launchpad.o - $(LD) $(LDFLAGS) -o $@ $^ +bootstrap.elf: bootstrap.o pt.o elfldr.o + $(LD) $^ -lSceLibcInternal -lkernel_web -o $@ -hello_world.elf: hello_world.o - $(LD) $(LDFLAGS) -o $@ $^ - - -main.o: main.c elfldr-socksrv_elf.c - $(CC) -c $(CFLAGS) -DELFLDR_BOOTSTRAP -o $@ $< - -elfldr-socksrv_elf.c: elfldr-socksrv.elf - $(XXD) -i $^ > $@ - -elfldr.o: elfldr.c payload_launchpad_elf.c +bootstrap.o: bootstrap.c elfldr_elf.c $(CC) -c $(CFLAGS) -o $@ $< -payload_launchpad_elf.c: payload_launchpad.elf - $(XXD) -i $^ > $@ - -main-socksrv.o: main.c - $(CC) -c $(CFLAGS) -DELFLDR_PORT=$(ELFLDR_PORT) -o $@ $< - +elfldr_elf.c: elfldr.elf + xxd -i $^ > $@ %.o: %.c - $(CC) -c $(CFLAGS) -o $@ $< + $(CC) -c $(CFLAGS) -o $@ $^ clean: - rm -f *.o *.elf elfldr-socksrv_elf.c payload_launchpad_elf.c + rm -f *.o bootstrap.elf elfldr.elf elfldr_elf.c + +test: bootstrap.elf + nc -q0 $(PS5_HOST) $(PS5_PORT) < $^ -test: elfldr.elf hello_world.elf - nc -q0 $(PS5_HOST) $(PS5_PORT) < elfldr.elf - @sleep 1 - nc -q0 $(PS5_HOST) $(ELFLDR_PORT) < hello_world.elf diff --git a/README.md b/README.md index 3e15410..0bfe254 100644 --- a/README.md +++ b/README.md @@ -5,14 +5,15 @@ Unlike the ELF loaders bundled with those exploits, this one uses the ptrace syscall to load itself into the `ScePartyDaemon` process, hence will continue running in the background even when playing games. Furthermore, this ELF loader will also resume its execution when the PS5 returns from rest mode. Payloads that -are loaded are executed in the `SceRedisServer` process, so if the payload crashes, +are loaded are executed in induvidual processes, so if the payload crashes, the ELF loader will keep on running. ## Building -On Debian-flavored operating systems, one can invoke the following commands to -install dependencies and build the ELF loader. +Assuming you have the [ps5-payload-sdk][sdk] installed on a POSIX machine, +the ELF loader can be compiled using the following two commands: + ```console -john@localhost:ps5-payload-elfldr$ sudo apt-get install build-essential clang lld +john@localhost:ps5-payload-elfldr$ export PS5_PAYLOAD_SDK=/opt/ps5-payload-sdk john@localhost:ps5-payload-elfldr$ make ``` @@ -20,7 +21,7 @@ john@localhost:ps5-payload-elfldr$ make To deploy the ELF loader itself, we first bootstrap via the ELF loader bundled with the exploit of your choice. ```console -john@localhost:ps5-payload-elfldr$ nc -q0 PS5_HOST 9020 < elfldr.elf +john@localhost:ps5-payload-elfldr$ nc -q0 PS5_HOST 9020 < bootstrap.elf ``` **Note**: recent versions of the [BD-J ps5-payload-loader][bdj] include a binary version of this ELF loader which can be launched directly from the menu system. @@ -38,6 +39,7 @@ please file an issue before you start to work on you changes. This will allow us to discuss the solution properly before you commit time and effort. [bdj]: https://github.com/john-tornblom/bdj-sdk/tree/master/samples/ps5-payload-loader +[sdk]: https://github.com/john-tornblom/ps5-payload-sdk [webkit]: https://github.com/Cryptogenic/PS5-IPV6-Kernel-Exploit [issues]: https://github.com/john-tornblom/ps5-payload-elfldr/issues/new diff --git a/bootstrap.c b/bootstrap.c new file mode 100644 index 0000000..8bc8b89 --- /dev/null +++ b/bootstrap.c @@ -0,0 +1,94 @@ +/* Copyright (C) 2024 John Törnblom + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 3, or (at your option) any +later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, see +. */ + +#include +#include +#include + +#include + +#include "elfldr.h" +#include "elfldr_elf.c" +#include "pt.h" + + +/** + * sceKernelSpawn() is not available in libkernel_web, which is what is used by + * the webkit exploit entry point. However, we do not actually use it during + * bootstraping, hence we just define an empty implementation to silence the + * linker. + **/ +int sceKernelSpawn(pid_t* pid, int dbg, const char* binpath, const char* rootpath, + char* const argv[]) { + return -1; +} + + +int main() { + uint8_t privcaps[16] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; + uint8_t qa_flags[16]; + uint8_t caps[16]; + int error; + pid_t pid; + + if(kernel_get_qaflags(qa_flags)) { + puts("[elfldr.elf] kernel_get_qa_flags() failed"); + return -1; + } + qa_flags[1] |= 0x03; + if(kernel_set_qaflags(qa_flags)) { + puts("[elfldr.elf] kernel_set_qa_flags() failed"); + return -1; + } + + if((pid=elfldr_find_pid("ScePartyDaemon")) < 0) { + puts("[elfldr.elf] elfldr_find_pid() failed"); + return -1; + } + + if(pt_attach(pid)) { + perror("[elfldr.elf] pt_attach"); + return -1; + } + + if(kernel_get_ucred_caps(pid, caps)) { + puts("[elfldr.elf] kern_get_ucred_caps() failed"); + pt_detach(pid); + return -1; + } + + if(kernel_set_ucred_caps(pid, privcaps)) { + puts("[elfldr.elf] kern_set_ucred_caps() failed"); + pt_detach(pid); + return -1; + } + + error = elfldr_exec(pid, elfldr_elf); + + if(kernel_set_ucred_caps(pid, caps)) { + puts("[elfldr.elf] kern_set_ucred_caps() failed"); + pt_detach(pid); + return -1; + } + + if(pt_detach(pid)) { + perror("[elfldr.elf] pt_detach"); + return -1; + } + + return error; +} diff --git a/crt.c b/crt.c deleted file mode 100644 index 623e614..0000000 --- a/crt.c +++ /dev/null @@ -1,35 +0,0 @@ -/* Copyright (C) 2023 John Törnblom - -This program is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 3, or (at your option) any -later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; see the file COPYING. If not, see -. */ - -#include "payload.h" - - -extern int libc_init(const payload_args_t *args); -extern int kern_init(const payload_args_t *args); -extern int main(const payload_args_t *args); - - -void -_start(payload_args_t *args) { - if((*args->payloadout=libc_init(args))) { - return; - } - if((*args->payloadout=kern_init(args))) { - return; - } - - *args->payloadout = main(args); -} diff --git a/dynlib.c b/dynlib.c deleted file mode 100644 index 65957b9..0000000 --- a/dynlib.c +++ /dev/null @@ -1,199 +0,0 @@ -/* Copyright (C) 2023 John Törnblom - -This program is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 3, or (at your option) any -later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; see the file COPYING. If not, see -. */ - -#include "dynlib.h" -#include "elf.h" -#include "kern.h" - - -typedef struct dynlib_dynsec { - struct { - intptr_t le_next; - intptr_t le_prev; - } list_entry; - - intptr_t sysvec; - uint32_t refcount; - size_t size; - - intptr_t symtab; - size_t symtabsize; - - intptr_t strtab; - size_t strtabsize; - - intptr_t pltrela; - size_t pltrelasize; - - intptr_t rela; - size_t relasize; - - intptr_t hash; - size_t hashsize; - - intptr_t dynamic; - size_t dynamicsize; - - intptr_t sce_comment; - size_t sce_commentsize; - - intptr_t sce_dynlib; - size_t sce_dynlibsize; - - intptr_t unknown1; // execpath? - size_t unknown1size; - - intptr_t buckets; - size_t bucketssize; - uint32_t nbuckets; - - intptr_t chains; - size_t chainssize; - uint32_t nchains; - - uint64_t unknown2[7]; -} dynlib_dynsec_t; - - -typedef struct dynlib_obj { - intptr_t next; - intptr_t path; - uint64_t unknown0[2]; - uint32_t refcount; - uint64_t handle; - - intptr_t mapbase; - size_t mapsize; - size_t textsize; - - intptr_t database; - size_t datasize; - - intptr_t unknown1; - size_t unknown1size; - - intptr_t vaddrbase; - intptr_t relocbase; - intptr_t entry; - - uint32_t tlsindex; - intptr_t tlsinit; - size_t tlsinitsize; - size_t tlssize; - off_t tlsoffset; - size_t tlsalign; - - intptr_t pltgot; - - uint64_t unknown2[6]; - - intptr_t init; - intptr_t fini; - - intptr_t eh_frame_hdr; - size_t eh_frame_hdr_size; - - intptr_t eh_frame; - size_t eh_frame_size; - - int status; - int flags; - - uint64_t unknown5[5]; - intptr_t dynsec; - uint64_t unknown6[6]; //fingerprint? -} dynlib_obj_t; - - -intptr_t -dynlib_resolve(pid_t pid, uint32_t handle, const char *nid) { - intptr_t kproc = kern_get_proc(pid); - dynlib_dynsec_t dynsec; - Elf64_Sym *symtab; - dynlib_obj_t obj; - intptr_t kaddr; - intptr_t vaddr; - char *strtab; - - if(!(kproc=kern_get_proc(pid))) { - return 0; - } - - if(kern_copyout(kproc + 0x3e8, &kaddr, sizeof(kaddr)) < 0) { - return 0; - } - - do { - if(kern_copyout(kaddr, &kaddr, sizeof(kaddr)) < 0) { - return 0; - } - if(!kaddr) { - return 0; - } - - if(kern_copyout(kaddr + __builtin_offsetof(dynlib_obj_t, handle), - &obj.handle, sizeof(obj.handle)) < 0) { - return 0; - } - } while(obj.handle != handle); - - if(kern_copyout(kaddr, &obj, sizeof(obj)) < 0) { - return 0; - } - - if(kern_copyout(obj.dynsec, &dynsec, sizeof(dynsec)) < 0) { - return 0; - } - - if(!(symtab=malloc(dynsec.symtabsize))) { - return 0; - } - - if(kern_copyout(dynsec.symtab, symtab, dynsec.symtabsize) < 0) { - free(symtab); - return 0; - } - - if(!(strtab=malloc(dynsec.strtabsize))) { - free(symtab); - return 0; - } - - if(kern_copyout(dynsec.strtab, strtab, dynsec.strtabsize) < 0) { - free(symtab); - free(strtab); - return 0; - } - - vaddr = 0; - for(size_t i=0; i. */ - -#pragma once - -#include "libc.h" - - -intptr_t dynlib_resolve(pid_t pid, uint32_t handle, const char *nid); -intptr_t dynlib_resolve_sceKernelDlsym(pid_t pid); - diff --git a/elf.h b/elf.h deleted file mode 100644 index ccc3f0b..0000000 --- a/elf.h +++ /dev/null @@ -1,105 +0,0 @@ -/* Copyright (C) 2023 John Törnblom - -This program is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 3, or (at your option) any -later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; see the file COPYING. If not, see -. */ - -#pragma once - - -#define ET_EXEC 2 -#define ET_DYN 3 -#define PT_LOAD 1 -#define PT_DYNAMIC 2 -#define SHT_RELA 4 -#define R_X86_64_GLOB_DAT 6 -#define R_X86_64_JMP_SLOT 7 -#define R_X86_64_RELATIVE 8 -#define PF_X 1 -#define PF_W 2 -#define PF_R 4 -#define DT_NULL 0 -#define DT_NEEDED 1 -#define DT_STRTAB 5 -#define DT_SYMTAB 6 - - -typedef struct { - long d_tag; - union { - unsigned long d_val; - unsigned long d_ptr; - } d_un; -} Elf64_Dyn; - - -typedef struct { - unsigned int st_name; - unsigned char st_info; - unsigned char st_other; - unsigned short st_shndx; - unsigned long st_value; - unsigned long st_size; -} Elf64_Sym; - - -typedef struct { - unsigned char e_ident[16]; - unsigned short e_type; - unsigned short e_machine; - unsigned int e_version; - unsigned long e_entry; - unsigned long e_phoff; - unsigned long e_shoff; - unsigned int e_flags; - unsigned short e_ehsize; - unsigned short e_phentsize; - unsigned short e_phnum; - unsigned short e_shentsize; - unsigned short e_shnum; - unsigned short e_shstrndx; -} Elf64_Ehdr; - - -typedef struct { - unsigned int p_type; - unsigned int p_flags; - unsigned long p_offset; - unsigned long p_vaddr; - unsigned long p_paddr; - unsigned long p_filesz; - unsigned long p_memsz; - unsigned long p_align; -} Elf64_Phdr; - - -typedef struct { - unsigned int sh_name; - unsigned int sh_type; - unsigned long sh_flags; - unsigned long sh_addr; - unsigned long sh_offset; - unsigned long sh_size; - unsigned int sh_link; - unsigned int sh_info; - unsigned long sh_addralign; - unsigned long sh_entsize; -} Elf64_Shdr; - - -typedef struct { - unsigned long r_offset; - unsigned long r_info; - long r_addend; -} Elf64_Rela; - diff --git a/elf_x86_64.x b/elf_x86_64.x deleted file mode 100644 index 2856a19..0000000 --- a/elf_x86_64.x +++ /dev/null @@ -1,34 +0,0 @@ -/* Copyright (C) 2023 John Törnblom - -This program is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 3, or (at your option) any -later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; see the file COPYING. If not, see -. */ - -OUTPUT_FORMAT("elf64-x86-64") -OUTPUT_ARCH(i386:x86-64) -ENTRY(_start) - -PHDRS { - ph_text PT_LOAD FLAGS (0x1 | 0x4); - ph_rodata PT_LOAD FLAGS (0x4); - ph_data PT_LOAD FLAGS (0x2 | 0x4); -} - -SECTIONS { - .text : { *(.text .text.*) } : ph_text - . = ALIGN(0x4000); - .rodata : { *(.rodata .rodata.*) } : ph_rodata - . = ALIGN(0x4000); - .data : { *(.data .data.*) } : ph_data - .bss : { *(.bss .bss.*) *(COMMON) } -} diff --git a/elfldr.c b/elfldr.c index 2e31508..f8c018f 100644 --- a/elfldr.c +++ b/elfldr.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 John Törnblom +/* Copyright (C) 2024 John Törnblom This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -14,18 +14,31 @@ You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, see . */ -#include "dynlib.h" -#include "elf.h" -#include "kern.h" -#include "libc.h" +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "elfldr.h" #include "pt.h" -#include "syscall.h" -/** - * Parameters for the ELF loader. - **/ -#define ELFLDR_UNIX_SOCKET "/system_tmp/elfldr.sock" +#ifndef IPV6_2292PKTOPTIONS +#define IPV6_2292PKTOPTIONS 25 +#endif /** @@ -50,7 +63,8 @@ typedef struct elfldr_ctx { } elfldr_ctx_t; -#include "payload_launchpad_elf.c" +int sceKernelSpawn(pid_t* pid, int dbg, const char* binpath, const char* rootpath, + char* const argv[]); /** @@ -61,7 +75,7 @@ r_relative(elfldr_ctx_t *ctx, Elf64_Rela* rela) { intptr_t loc = ctx->base_addr + rela->r_offset; intptr_t val = ctx->base_addr + rela->r_addend; - return pt_setlong(ctx->pid, loc, val); + return mdbg_copyin(ctx->pid, &val, loc, sizeof(val)); } @@ -80,8 +94,8 @@ pt_load(elfldr_ctx_t *ctx, Elf64_Phdr *phdr) { return -1; } - if(pt_copyin(ctx->pid, ctx->elf+phdr->p_offset, addr, phdr->p_memsz)) { - pt_perror(ctx->pid, "[elfldr.elf] pt_copyin"); + if(mdbg_copyin(ctx->pid, ctx->elf+phdr->p_offset, addr, phdr->p_memsz)) { + pt_perror(ctx->pid, "[elfldr.elf] mdbg_copyin"); return -1; } @@ -108,8 +122,8 @@ pt_reload(elfldr_ctx_t *ctx, Elf64_Phdr *phdr) { } // Backup data - else if(pt_copyout(ctx->pid, addr, data, memsz)) { - pt_perror(ctx->pid, "[elfldr.elf] pt_copyout"); + else if(mdbg_copyout(ctx->pid, addr, data, memsz)) { + pt_perror(ctx->pid, "[elfldr.elf] mdbg_copyout"); error = -1; } @@ -143,8 +157,8 @@ pt_reload(elfldr_ctx_t *ctx, Elf64_Phdr *phdr) { // Resore data else { - if(pt_copyin(ctx->pid, data, addr, memsz)) { - pt_perror(ctx->pid, "[elfldr.elf] pt_copyin"); + if(mdbg_copyin(ctx->pid, data, addr, memsz)) { + pt_perror(ctx->pid, "[elfldr.elf] mdbg_copyin"); error = -1; } pt_munmap(ctx->pid, addr, memsz); @@ -162,7 +176,7 @@ pt_reload(elfldr_ctx_t *ctx, Elf64_Phdr *phdr) { * Load an ELF into the address space of a process with the given pid. **/ static intptr_t -elfldr_load(pid_t pid, uint8_t *elf, size_t size) { +elfldr_load(pid_t pid, uint8_t *elf) { Elf64_Ehdr *ehdr = (Elf64_Ehdr*)elf; Elf64_Phdr *phdr = (Elf64_Phdr*)(elf + ehdr->e_phoff); Elf64_Shdr *shdr = (Elf64_Shdr*)(elf + ehdr->e_shoff); @@ -273,7 +287,7 @@ elfldr_load(pid_t pid, uint8_t *elf, size_t size) { /** * Create payload args in the address space of the process with the given pid. **/ -intptr_t +static intptr_t elfldr_payload_args(pid_t pid) { int victim_sock; int master_sock; @@ -292,12 +306,12 @@ elfldr_payload_args(pid_t pid) { return 0; } - pt_setint(pid, buf+0x00, 20); - pt_setint(pid, buf+0x04, IPPROTO_IPV6); - pt_setint(pid, buf+0x08, IPV6_TCLASS); - pt_setint(pid, buf+0x0c, 0); - pt_setint(pid, buf+0x10, 0); - pt_setint(pid, buf+0x14, 0); + mdbg_setint(pid, buf+0x00, 20); + mdbg_setint(pid, buf+0x04, IPPROTO_IPV6); + mdbg_setint(pid, buf+0x08, IPV6_TCLASS); + mdbg_setint(pid, buf+0x0c, 0); + mdbg_setint(pid, buf+0x10, 0); + mdbg_setint(pid, buf+0x14, 0); if(pt_setsockopt(pid, master_sock, IPPROTO_IPV6, IPV6_2292PKTOPTIONS, buf, 24)) { pt_perror(pid, "[elfldr.elf] pt_setsockopt"); return 0; @@ -308,18 +322,18 @@ elfldr_payload_args(pid_t pid) { return 0; } - pt_setint(pid, buf+0x00, 0); - pt_setint(pid, buf+0x04, 0); - pt_setint(pid, buf+0x08, 0); - pt_setint(pid, buf+0x0c, 0); - pt_setint(pid, buf+0x10, 0); + mdbg_setint(pid, buf+0x00, 0); + mdbg_setint(pid, buf+0x04, 0); + mdbg_setint(pid, buf+0x08, 0); + mdbg_setint(pid, buf+0x0c, 0); + mdbg_setint(pid, buf+0x10, 0); if(pt_setsockopt(pid, victim_sock, IPPROTO_IPV6, IPV6_PKTINFO, buf, 20)) { pt_perror(pid, "[elfldr.elf] pt_setsockopt"); return 0; } - if(kern_overlap_sockets(pid, master_sock, victim_sock)) { - puts("[elfldr.elf] kern_overlap_sockets() failed"); + if(kernel_overlap_sockets(pid, master_sock, victim_sock)) { + puts("[elfldr.elf] kernel_overlap_sockets() failed"); return 0; } @@ -331,32 +345,150 @@ elfldr_payload_args(pid_t pid) { pipe1 = pt_getint(pid, buf+4); intptr_t args = buf; - intptr_t dlsym = dynlib_resolve_sceKernelDlsym(pid); + intptr_t dlsym = pt_resolve(pid, "LwG8g3niqwA"); intptr_t rwpipe = buf + 0x100; intptr_t rwpair = buf + 0x200; - intptr_t kpipe_addr = kern_get_proc_file(pid, pipe0); + intptr_t kpipe_addr = kernel_get_proc_file(pid, pipe0); intptr_t payloadout = buf + 0x300; - pt_setlong(pid, args + 0x00, dlsym); - pt_setlong(pid, args + 0x08, rwpipe); - pt_setlong(pid, args + 0x10, rwpair); - pt_setlong(pid, args + 0x18, kpipe_addr); - pt_setlong(pid, args + 0x20, kern_get_data_baseaddr()); - pt_setlong(pid, args + 0x28, payloadout); - pt_setint(pid, rwpipe + 0, pipe0); - pt_setint(pid, rwpipe + 4, pipe1); - pt_setint(pid, rwpair + 0, master_sock); - pt_setint(pid, rwpair + 4, victim_sock); - pt_setint(pid, payloadout, 0); + mdbg_setlong(pid, args + 0x00, dlsym); + mdbg_setlong(pid, args + 0x08, rwpipe); + mdbg_setlong(pid, args + 0x10, rwpair); + mdbg_setlong(pid, args + 0x18, kpipe_addr); + mdbg_setlong(pid, args + 0x20, KERNEL_ADDRESS_DATA_BASE); + mdbg_setlong(pid, args + 0x28, payloadout); + mdbg_setint(pid, rwpipe + 0, pipe0); + mdbg_setint(pid, rwpipe + 4, pipe1); + mdbg_setint(pid, rwpair + 0, master_sock); + mdbg_setint(pid, rwpair + 4, victim_sock); + mdbg_setint(pid, payloadout, 0); return args; } -/** - * Get the pid of a process with the given name. - **/ -static pid_t +static int +elfldr_raise_privileges(pid_t pid) { + uint8_t caps[16] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; + intptr_t vnode; + + if(!(vnode=kernel_get_root_vnode())) { + puts("[elfldr.elf] kernel_get_root_vnode() failed"); + return -1; + } + if(kernel_set_proc_rootdir(pid, vnode)) { + puts("[elfldr.elf] kernel_set_proc_rootdir() failed"); + return -1; + } + if(kernel_set_ucred_uid(pid, 0)) { + puts("[elfldr.elf] kernel_set_ucred_uid() failed"); + return -1; + } + + if(kernel_set_ucred_caps(pid, caps)) { + puts("[elfldr.elf] kernel_set_ucred_caps() failed"); + return -1; + } + + return 0; +} + + +int +elfldr_exec(pid_t pid, uint8_t *elf) { + intptr_t entry; + intptr_t args; + struct reg r; + + if(pt_getregs(pid, &r)) { + perror("[elfldr.elf] pt_getregs"); + return -1; + } + + if(!(entry=elfldr_load(pid, elf))) { + puts("[elfldr.elf] elfldr_load() failed"); + return -1; + } + + if(!(args=elfldr_payload_args(pid))) { + puts("[elfldr.elf] elfldr_payload_args() failed"); + return -1; + } + + r.r_rip = entry; + r.r_rdi = args; + + if(pt_setregs(pid, &r)) { + perror("[elfldr.elf] pt_setregs"); + return -1; + } + + return 0; +} + + +int +elfldr_spawn(uint8_t *elf) { + uint8_t int3instr = 0xcc; + char* argv[] = {0, 0}; + struct reg r = {0}; + intptr_t brkpoint; + intptr_t rootdir; + pid_t pid = -1; + + // SceSpZeroConf + argv[0] = "/system/vsh/app/NPXS40112/eboot.bin"; + if(sceKernelSpawn(&pid, 1, argv[0], NULL, argv)) { + perror("sceKernelSpawn"); + pt_detach(pid); + return -1; + } + + if(!(brkpoint=kernel_dynlib_entry_addr(pid, 0))) { + puts("[elfldr.elf] kernel_dynlib_entry_addr() failed"); + pt_detach(pid); + return -1; + } + + if(mdbg_copyin(pid, &int3instr, brkpoint, sizeof(int3instr))) { + perror("[elfldr.elf] mdbg_copyin"); + pt_detach(pid); + return -1; + } + + if(pt_continue(pid)) { + perror("[elfldr.elf] pt_continue"); + pt_detach(pid); + return -1; + } + + if(waitpid(pid, 0, 0) == -1) { + perror("[elfldr.elf] waitpid"); + pt_detach(pid); + return -1; + } + + if(elfldr_raise_privileges(pid)) { + puts("[elfldr.elf] Unable to raise privileges"); + pt_detach(pid); + return -1; + } + + if(elfldr_exec(pid, elf)) { + pt_setregs(pid, &r); + } + + if(pt_detach(pid)) { + perror("[elfldr.elf] pt_detach"); + return -1; + } + + return pid; +} + + +pid_t elfldr_find_pid(const char* name) { int mib[4] = {1, 14, 8, 0}; pid_t pid = -1; @@ -394,368 +526,3 @@ elfldr_find_pid(const char* name) { return pid; } - -/** - * Send a file descriptor to a process that listens on a UNIX domain socket - * with the given socket path. - **/ -static int -elfldr_sendfd(const char *sockpath, int fd) { - struct sockaddr_un addr = {0}; - struct msghdr msg = {0}; - struct cmsghdr *cmsg; - uint8_t buf[24]; - int sockfd; - - addr.sun_family = AF_UNIX; - strcpy(addr.sun_path, sockpath); - - memset(&msg, 0, sizeof(msg)); - msg.msg_name = &addr; - msg.msg_namelen = sizeof(struct sockaddr_un); - msg.msg_control = buf; - msg.msg_controllen = sizeof(buf); - - memset(buf, 0, sizeof(buf)); - cmsg = (struct cmsghdr *)buf; - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - cmsg->cmsg_len = 20; - *((int *)&buf[16]) = fd; - - if((sockfd=socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) { - perror("[elfldr.elf] socket"); - return -1; - } - - if(sendmsg(sockfd, &msg, 0) < 0) { - perror("[elfldr.elf] sendmsg"); - close(sockfd); - return -1; - } - - return close(sockfd); -} - - -/** - * Pipe stdout of a process with the given pid to a file descriptor, where - * communication is done via a UNIX domain socket of the given socket path. - **/ -static int -elfldr_stdout(pid_t pid, const char *sockpath, int fd) { - struct sockaddr_un addr = {0}; - intptr_t ptbuf; - int sockfd; - - if((ptbuf=pt_mmap(pid, 0, PAGE_SIZE, PROT_READ | PROT_WRITE, - MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)) == -1) { - pt_perror(pid, "[elfldr.elf] pt_mmap"); - return -1; - } - - if((sockfd=pt_socket(pid, AF_UNIX, SOCK_DGRAM, 0)) < 0) { - pt_perror(pid, "[elfldr.elf] pt_socket"); - pt_munmap(pid, ptbuf, PAGE_SIZE); - return -1; - } - - addr.sun_family = AF_UNIX; - strcpy(addr.sun_path, sockpath); - pt_copyin(pid, &addr, ptbuf, sizeof(addr)); - if(pt_bind(pid, sockfd, ptbuf, sizeof(addr))) { - pt_perror(pid, "[elfldr.elf] pt_bind"); - pt_munmap(pid, ptbuf, PAGE_SIZE); - pt_close(pid, sockfd); - return -1; - } - - if(elfldr_sendfd(sockpath, fd)) { - pt_munmap(pid, ptbuf, PAGE_SIZE); - pt_close(pid, sockfd); - return -1; - } - - intptr_t hdr = ptbuf; - intptr_t iov = ptbuf + 0x100; - intptr_t control = ptbuf + 0x200; - - pt_setlong(pid, hdr + __builtin_offsetof(struct msghdr, msg_name), 0); - pt_setint(pid, hdr + __builtin_offsetof(struct msghdr, msg_namelen), 0); - pt_setlong(pid, hdr + __builtin_offsetof(struct msghdr, msg_iov), iov); - pt_setint(pid, hdr + __builtin_offsetof(struct msghdr, msg_iovlen), 1); - pt_setlong(pid, hdr + __builtin_offsetof(struct msghdr, msg_control), control); - pt_setint(pid, hdr + __builtin_offsetof(struct msghdr, msg_controllen), 24); - if(pt_recvmsg(pid, sockfd, hdr, 0) < 0) { - pt_perror(pid, "[elfldr.elf] pt_recvmsg"); - pt_munmap(pid, ptbuf, PAGE_SIZE); - pt_close(pid, sockfd); - return -1; - } - - if((fd=pt_getint(pid, control+16)) < 0) { - pt_munmap(pid, ptbuf, PAGE_SIZE); - pt_close(pid, sockfd); - return -1; - } - - if(pt_munmap(pid, ptbuf, PAGE_SIZE)) { - pt_perror(pid, "[elfldr.elf] pt_munmap"); - pt_close(pid, sockfd); - pt_close(pid, fd); - } - - if(pt_close(pid, sockfd)) { - pt_perror(pid, "[elfldr.elf] pt_close"); - pt_close(pid, fd); - return -1; - } - - return fd; -} - - -int -elfldr_exec(const char* procname, int stdout, uint8_t *elf, size_t size) { - uint8_t privcaps[16] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; - uint8_t caps[16]; - intptr_t payload_entry; - intptr_t payload_args; - intptr_t launch_entry; - struct reg jmp_reg; - struct reg bak_reg; - pid_t pid; - - if((pid=elfldr_find_pid(procname)) < 0) { - puts("[elfldr.elf] elfldr_find_pid() failed"); - return -1; - } - - if(pt_attach(pid)) { - perror("[elfldr.elf] pt_attach"); - return -1; - } - - if(kern_get_ucred_caps(pid, caps)) { - puts("[elfldr.elf] kern_get_ucred_caps() failed"); - pt_detach(pid); - return -1; - } - - if(kern_set_ucred_caps(pid, privcaps)) { - puts("[elfldr.elf] kern_set_ucred_caps() failed"); - pt_detach(pid); - return -1; - } - - if(pt_getregs(pid, &bak_reg)) { - perror("[elfldr.elf] pt_getregs"); - kern_set_ucred_caps(pid, caps); - pt_detach(pid); - return -1; - } - memcpy(&jmp_reg, &bak_reg, sizeof(jmp_reg)); - - if(stdout > 0) { - unlink(ELFLDR_UNIX_SOCKET); - if((stdout=elfldr_stdout(pid, ELFLDR_UNIX_SOCKET, stdout)) < 0) { - puts("[elfldr.elf] elfldr_stdout() failed"); - kern_set_ucred_caps(pid, caps); - pt_detach(pid); - return -1; - } - unlink(ELFLDR_UNIX_SOCKET); - } - - if(!(payload_entry=elfldr_load(pid, elf, size))) { - puts("[elfldr.elf] elfldr_load() failed"); - kern_set_ucred_caps(pid, caps); - pt_detach(pid); - return -1; - } - - if(!(payload_args=elfldr_payload_args(pid))) { - puts("[elfldr.elf] elfldr_args() failed"); - kern_set_ucred_caps(pid, caps); - pt_detach(pid); - return -1; - } - - if(!(launch_entry=elfldr_load(pid, payload_launchpad_elf, - payload_launchpad_elf_len))) { - puts("[elfldr.elf] elfldr_load() failed"); - kern_set_ucred_caps(pid, caps); - pt_detach(pid); - return -1; - } - - jmp_reg.r_rip = launch_entry; - jmp_reg.r_rsp -= 8; - jmp_reg.r_rdi = payload_entry; - jmp_reg.r_rsi = payload_args; - jmp_reg.r_rdx = stdout; - if(pt_setregs(pid, &jmp_reg)) { - perror("[elfldr.elf] pt_setregs"); - kern_set_ucred_caps(pid, caps); - pt_detach(pid); - return -1; - } - - if(pt_continue(pid)) { - perror("[elfldr.elf] pt_continue"); - kern_set_ucred_caps(pid, caps); - pt_detach(pid); - return -1; - } - if(waitpid(pid, 0, 0) == -1) { - perror("[elfldr.elf] waitpid"); - kern_set_ucred_caps(pid, caps); - pt_detach(pid); - } - - if(pt_setregs(pid, &bak_reg)) { - perror("[elfldr.elf] pt_setregs"); - kern_set_ucred_caps(pid, caps); - pt_detach(pid); - return -1; - } - - puts("[elfldr.elf] running ELF..."); - kern_set_ucred_caps(pid, caps); - if(pt_detach(pid)) { - perror("[elfldr.elf] pt_detach"); - return -1; - } - - return 0; -} - - -/** - * Read an ELF from a given socket connection. - **/ -static ssize_t -elfldr_read(int connfd, uint8_t **data) { - uint8_t buf[0x4000]; - off_t offset = 0; - ssize_t len; - - *data = 0; - while((len=read(connfd, buf, sizeof(buf)))) { - *data = realloc(*data, offset + len); - if(*data == 0) { - perror("[elfldr.elf] realloc"); - return -1; - } - - memcpy(*data + offset, buf, len); - offset += len; - } - - return offset; -} - - -/** - * Accept ELFs from the given port, and execute them inside the process - * with the given name. - **/ -int -elfldr_serve(const char* procname, uint16_t port) { - struct sockaddr_in server_addr; - struct sockaddr_in client_addr; - socklen_t addr_len; - - uint8_t *elf; - size_t size; - - int connfd; - int srvfd; - - if((srvfd=socket(AF_INET, SOCK_STREAM, 0)) < 0) { - perror("[elfldr.elf] socket"); - return -1; - } - - if(setsockopt(srvfd, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int)) < 0) { - perror("[elfldr.elf] setsockopt"); - close(srvfd); - return -1; - } - - memset(&server_addr, 0, sizeof(server_addr)); - server_addr.sin_family = AF_INET; - server_addr.sin_port = htons(port); - - if(bind(srvfd, &server_addr, sizeof(server_addr)) != 0) { - perror("[elfldr.elf] bind"); - close(srvfd); - return -1; - } - - if(listen(srvfd, 5) != 0) { - perror("[elfldr.elf] listen"); - close(srvfd); - return -1; - } - - addr_len = sizeof(client_addr); - while(1) { - if((connfd=accept(srvfd, &client_addr, &addr_len)) < 0) { - perror("[elfldr.elf] accept"); - close(connfd); - close(srvfd); - return -1; - } - - // We got a connection, read ELF and launch it in the given process. - if((size=elfldr_read(connfd, &elf))) { - elfldr_exec(procname, connfd, elf, size); - free(elf); - } - close(connfd); - } - close(srvfd); - - return 0; -} - - -int -elfldr_socksrv(const char* procname, uint16_t port) { - pid_t pid; - - // kill previous instances of elfldr.elf - while((pid=elfldr_find_pid("elfldr.elf")) > 0) { - if(kill(pid, SIGKILL)) { - perror("[elfldr.elf] kill"); - } - sleep(1); - } - - // fork process - if((pid=syscall(SYS_rfork, RFPROC | RFNOWAIT | RFFDG)) < 0) { - perror("[elfldr.elf] rfork"); - return -1; - } - // parent process should just return - if(pid) { - return pid; - } - - // initialize child process - syscall(SYS_setsid); // become session leader - syscall(0x1d0, -1, "elfldr.elf"); // set proc name - dup2(open("/dev/console", 1), 1); // set stdout to /dev/klog - dup2(open("/dev/console", 1), 2); // set stderr to /dev/klog - - while(1) { - puts("[elfldr.elf] Launching socket server..."); - elfldr_serve(procname, port); - sleep(3); - } - - // unreacheable - return syscall(SYS_exit, 0); -} diff --git a/elfldr.h b/elfldr.h index c22a944..086420e 100644 --- a/elfldr.h +++ b/elfldr.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 John Törnblom +/* Copyright (C) 2024 John Törnblom This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -16,18 +16,10 @@ along with this program; see the file COPYING. If not, see #pragma once -#include "libc.h" +#include -/** - * Execute an ELF inside the process with the given name, and pipe outout - * to the given stdout file descriptor. - **/ -int elfldr_exec(const char* procname, int stdout, uint8_t *elf, size_t size); +pid_t elfldr_find_pid(const char* name); +int elfldr_exec(pid_t pid, uint8_t *elf); - -/** - * Launch a socket server that accapts ELF files that are executed in the - * process with given name, where stdout is piped to the connecting socket. - **/ -int elfldr_socksrv(const char* procname, uint16_t port); +pid_t elfldr_spawn(uint8_t *elf); diff --git a/hello_world.c b/hello_world.c deleted file mode 100644 index ffb4d4e..0000000 --- a/hello_world.c +++ /dev/null @@ -1,65 +0,0 @@ -/* Copyright (C) 2023 John Törnblom - -This program is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 3, or (at your option) any -later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; see the file COPYING. If not, see -. */ - -#include "payload.h" - - -static __attribute__ ((used)) long ptr_syscall; - - -asm(".intel_syntax noprefix\n" - ".global syscall\n" - ".type syscall @function\n" - "syscall:\n" - " mov rax, rdi\n" // sysno - " mov rdi, rsi\n" // arg1 - " mov rsi, rdx\n" // arg2 - " mov rdx, rcx\n" // arg3 - " mov r10, r8\n" // arg4 - " mov r8, r9\n" // arg5 - " mov r9, qword ptr [rsp + 8]\n" // arg6 - " jmp qword ptr [rip + ptr_syscall]\n" // syscall - " ret\n" - ); - -long syscall(long sysno, ...); - - -void -klog(const char *s) { - syscall(0x259, 7, "<118>", 0); - syscall(0x259, 7, s, 0); - syscall(0x259, 7, "\n", 0); -} - - -void -_start(const payload_args_t *args) { - void (*puts)(const char*); - - if((args->sceKernelDlsym(0x2, "puts", &puts))) { - return; - } - if(args->sceKernelDlsym(0x2001, "getpid", &ptr_syscall)) { - return; - } - ptr_syscall += 0xa; // jump directly to syscall instruction - - - klog("[hello_world.elf] Hello, world!"); - puts("[hello_world.elf] Hello, world!"); -} - diff --git a/kern.c b/kern.c deleted file mode 100644 index ceae181..0000000 --- a/kern.c +++ /dev/null @@ -1,450 +0,0 @@ -/* Copyright (C) 2023 John Törnblom - -This program is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 3, or (at your option) any -later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; see the file COPYING. If not, see -. */ - -#include "libc.h" -#include "kern.h" -#include "payload.h" - - -static int (*sysctlbyname)(const char*, void*, size_t*, const void*, size_t); - -static intptr_t ADDRESS_DATA_BASE = 0; -static intptr_t ADDRESS_ALLPROC = 0; -static intptr_t ADDRESS_QA_FLAGS = 0; - -static off_t OFFSET_PROC_P_UCRED = 0x40; -static off_t OFFSET_PROC_P_PID = 0xBC; - -static off_t OFFSET_UCRED_CR_SCEAUTHID = 0x58; -static off_t OFFSET_UCRED_CR_SCECAPS = 0x60; - - -static int master_sock = -1; -static int victim_sock = -1; -static int rw_pipe[2] = {-1, -1}; -static intptr_t pipe_addr = 0; - - -static uint32_t -kern_get_fw_version(void) { - uint32_t version = 0; - size_t size = sizeof(version); - - if(sysctlbyname("kern.sdk_version", &version, &size, 0, 0)) { - return 0; - } - - return version; -} - - -/** - * - **/ -int -kern_init(const payload_args_t *args) { - int error = 0; - - if((error=args->sceKernelDlsym(0x2001, "sysctlbyname", &sysctlbyname))) { - return error; - } - - if((master_sock=args->rwpair[0]) < 0) { - return -1; - } - - if((victim_sock=args->rwpair[1]) < 0) { - return -1; - } - - if((rw_pipe[0]=args->rwpipe[0]) < 0) { - return -1; - } - - if((rw_pipe[1]=args->rwpipe[1]) < 0) { - return -1; - } - - if(!(pipe_addr=args->kpipe_addr)) { - return -1; - } - - if(!(ADDRESS_DATA_BASE=args->kdata_base_addr)) { - return -1; - } - - switch(kern_get_fw_version() & 0xffff0000) { - case 0x3000000: - case 0x3100000: - case 0x3200000: - case 0x3210000: - ADDRESS_ALLPROC = ADDRESS_DATA_BASE + 0x276DC58; - ADDRESS_QA_FLAGS = ADDRESS_DATA_BASE + 0x6466498; - break; - - case 0x4020000: - ADDRESS_ALLPROC = ADDRESS_DATA_BASE + 0x27EDCB8; - ADDRESS_QA_FLAGS = ADDRESS_DATA_BASE + 0x6505498; - break; - - case 0x4000000: - case 0x4030000: - case 0x4500000: - case 0x4510000: - ADDRESS_ALLPROC = ADDRESS_DATA_BASE + 0x27EDCB8; - ADDRESS_QA_FLAGS = ADDRESS_DATA_BASE + 0x6506498; - break; - - default: - return -1; - } - - return 0; -} - - -static int -kern_write(intptr_t addr, unsigned long *data) { - intptr_t victim_buf[3]; - - // sanity check for invalid kernel pointers - if(!(addr & 0xffff000000000000)) { - return -1; - } - - victim_buf[0] = addr; - victim_buf[1] = 0; - victim_buf[2] = 0; - - if(setsockopt(master_sock, IPPROTO_IPV6, IPV6_PKTINFO, victim_buf, 0x14)) { - return -1; - } - - if(setsockopt(victim_sock, IPPROTO_IPV6, IPV6_PKTINFO, data, 0x14)) { - return -1; - } - - return 0; -} - - -int -kern_copyin(const void *udaddr, intptr_t kaddr, size_t len) { - intptr_t write_buf[3]; - - // Set pipe flags - write_buf[0] = 0; - write_buf[1] = 0x4000000000000000; - write_buf[2] = 0; - if(kern_write(pipe_addr, (unsigned long *) &write_buf)) { - return -1; - } - - // Set pipe data addr - write_buf[0] = kaddr; - write_buf[1] = 0; - write_buf[2] = 0; - if(kern_write(pipe_addr + 0x10, (unsigned long *) &write_buf)) { - return -1; - } - - // Perform write across pipe - if(write(rw_pipe[1], udaddr, len) < 0) { - return -1; - } - - return 0; -} - - -int -kern_copyout(intptr_t kaddr, void *udaddr, size_t len) { - intptr_t write_buf[3]; - - // Set pipe flags - write_buf[0] = 0x4000000040000000; - write_buf[1] = 0x4000000000000000; - write_buf[2] = 0; - if(kern_write(pipe_addr, (unsigned long *) &write_buf)) { - return -1; - } - - // Set pipe data addr - write_buf[0] = kaddr; - write_buf[1] = 0; - write_buf[2] = 0; - if(kern_write(pipe_addr + 0x10, (unsigned long *) &write_buf)) { - return -1; - } - - // Perform read across pipe - if(read(rw_pipe[0], udaddr, len) < 0) { - return -1; - } - - return 0; -} - - -intptr_t -kern_get_data_baseaddr(void) { - return ADDRESS_DATA_BASE; -} - - -int -kern_get_qa_flags(uint8_t val[16]) { - return kern_copyout(ADDRESS_QA_FLAGS, val, 16); -} - -int -kern_set_qa_flags(const uint8_t val[16]) { - return kern_copyin(val, ADDRESS_QA_FLAGS, 16); -} - - -intptr_t -kern_get_proc(pid_t pid) { - pid_t other_pid = 0; - intptr_t addr = 0; - intptr_t next = 0; - - if(kern_copyout(ADDRESS_ALLPROC, &addr, sizeof(addr))) { - return 0; - } - - while(addr) { - if(kern_copyout(addr + OFFSET_PROC_P_PID, &other_pid, - sizeof(other_pid))) { - return 0; - } - - if(pid == other_pid) { - break; - } - - if(kern_copyout(addr, &next, sizeof(next))) { - return 0; - } - - addr = next; - } - - return addr; -} - - -static intptr_t -kern_get_proc_ucred(pid_t pid) { - intptr_t proc = 0; - intptr_t ucred = 0; - - if(!(proc=kern_get_proc(pid))) { - return 0; - } - - if(kern_copyout(proc + OFFSET_PROC_P_UCRED, &ucred, - sizeof(ucred))) { - return 0; - } - - return ucred; -} - - -int -kern_get_ucred_auth_id(pid_t pid, uint64_t *val) { - intptr_t ucred = 0; - - if(!(ucred=kern_get_proc_ucred(pid))) { - return -1; - } - - if(kern_copyout(ucred + OFFSET_UCRED_CR_SCEAUTHID, val, 8)) { - return -1; - } - - return 0; -} - - -int -kern_set_ucred_auth_id(pid_t pid, uint64_t val) { - intptr_t ucred = 0; - - if(!(ucred=kern_get_proc_ucred(pid))) { - return -1; - } - - if(kern_copyin(&val, ucred + OFFSET_UCRED_CR_SCEAUTHID, 8)) { - return -1; - } - - return 0; -} - - -int -kern_get_ucred_caps(pid_t pid, uint8_t caps[16]) { - intptr_t ucred = 0; - - if(!(ucred=kern_get_proc_ucred(pid))) { - return -1; - } - - if(kern_copyout(ucred + OFFSET_UCRED_CR_SCECAPS, caps, 16)) { - return -1; - } - - return 0; -} - - -int -kern_set_ucred_caps(pid_t pid, const uint8_t caps[16]) { - intptr_t ucred = 0; - - if(!(ucred=kern_get_proc_ucred(pid))) { - return -1; - } - - if(kern_copyin(caps, ucred + OFFSET_UCRED_CR_SCECAPS, 16)) { - return -1; - } - - return 0; -} - - - -intptr_t -kern_get_proc_file(pid_t pid, int fd) { - intptr_t fd_files; - intptr_t fde_file; - intptr_t file; - intptr_t proc; - intptr_t p_fd; - - if(!(proc=kern_get_proc(pid))) { - return 0; - } - - if(kern_copyout(proc + 0x48, &p_fd, sizeof(p_fd))) { - return 0; - } - - if(kern_copyout(p_fd, &fd_files, sizeof(fd_files))) { - return 0; - } - - if(kern_copyout(fd_files + 8 + (0x30 * fd), - &fde_file, sizeof(fde_file))) { - return 0; - } - - if(kern_copyout(fde_file, &file, sizeof(file))) { - return 0; - } - - return file; -} - - -static intptr_t -kern_get_proc_inp6_outputopts(pid_t pid, int fd) { - intptr_t inp6_outputopts; - intptr_t so_pcb; - intptr_t file; - - if(!(file=kern_get_proc_file(pid, fd))) { - return 0; - } - - if(kern_copyout(file + 0x18, &so_pcb, sizeof(so_pcb))) { - return 0; - } - - if(kern_copyout(so_pcb + 0x120, &inp6_outputopts, - sizeof(inp6_outputopts))) { - return 0; - } - - return inp6_outputopts; -} - - - -static int -kern_inc_so_count(pid_t pid, int fd) { - intptr_t file; - int so_count; - - if(!(file=kern_get_proc_file(pid, fd))) { - return -1; - } - - if(kern_copyout(file, &so_count, sizeof(so_count))) { - return -1; - } - - so_count++; - if(kern_copyin(&so_count, file, sizeof(so_count))) { - return -1; - } - return 0; -} - - -int -kern_overlap_sockets(pid_t pid, int master_sock, int victim_sock) { - intptr_t master_inp6_outputopts; - intptr_t victim_inp6_outputopts; - intptr_t pktinfo; - unsigned int tclass; - - if(kern_inc_so_count(pid, master_sock)) { - return -1; - } - - if(!(master_inp6_outputopts=kern_get_proc_inp6_outputopts(pid, - master_sock))) { - return -1; - } - - if(kern_inc_so_count(pid, victim_sock)) { - return -1; - } - - if(!(victim_inp6_outputopts=kern_get_proc_inp6_outputopts(pid, - victim_sock))) { - return -1; - } - - pktinfo = victim_inp6_outputopts + 0x10; - if(kern_copyin(&pktinfo, master_inp6_outputopts + 0x10, - sizeof(pktinfo))) { - - return -1; - } - - tclass = 0x13370000; - if(kern_copyin(&tclass, master_inp6_outputopts + 0xc0, sizeof(tclass))) { - return -1; - } - - return 0; -} - diff --git a/kern.h b/kern.h deleted file mode 100644 index d3aac04..0000000 --- a/kern.h +++ /dev/null @@ -1,37 +0,0 @@ -/* Copyright (C) 2023 John Törnblom - -This program is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 3, or (at your option) any -later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; see the file COPYING. If not, see -. */ - -#pragma once - -#include "libc.h" - -intptr_t kern_get_data_baseaddr(void); -intptr_t kern_get_proc(pid_t pid); -intptr_t kern_get_proc_file(pid_t pid, int fd); - -int kern_copyin(const void *udaddr, intptr_t kaddr, size_t len); -int kern_copyout(intptr_t kaddr, void *udaddr, size_t len); - -int kern_get_qa_flags(uint8_t flags[16]); -int kern_set_qa_flags(const uint8_t flags[16]); - -int kern_get_ucred_auth_id(pid_t pid, uint64_t *auth_id); -int kern_set_ucred_auth_id(pid_t pid, uint64_t auth_id); - -int kern_get_ucred_caps(pid_t pid, uint8_t caps[16]); -int kern_set_ucred_caps(pid_t pid, const uint8_t caps[16]); - -int kern_overlap_sockets(pid_t pid, int master_sock, int victim_sock); diff --git a/libc.c b/libc.c deleted file mode 100644 index 3c26fc9..0000000 --- a/libc.c +++ /dev/null @@ -1,364 +0,0 @@ -/* Copyright (C) 2023 John Törnblom - -This program is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 3, or (at your option) any -later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; see the file COPYING. If not, see -. */ - -#include "kern.h" -#include "libc.h" -#include "payload.h" -#include "syscall.h" - - -static int (*sce_htons)(uint16_t); -static int (*sce_sleep)(int); -static void* (*sce_malloc)(size_t); -static void* (*sce_realloc)(void*, size_t); -static void (*sce_free)(void*); -static void* (*sce_memset)(void*, int, size_t); -static void* (*sce_memcpy)(void*, const void*, size_t); -static char* (*sce_strcpy)(const char*, const char*); -static int (*sce_strcmp)(const char*, const char*); -static int (*sce_strncmp)(const char*, const char*, size_t); -static int (*sce_strcat)(char*, const char*); -static void (*sce_puts)(const char*); -static void (*sce_perror)(const char*); -static char* (*sce_strerror)(int); -static int* (*sce_errno)(void); - -static intptr_t sce_syscall; -asm(".intel_syntax noprefix\n" - ".global syscall\n" - ".type syscall @function\n" - "syscall:\n" - " mov rax, rdi\n" // sysno - " mov rdi, rsi\n" // arg1 - " mov rsi, rdx\n" // arg2 - " mov rdx, rcx\n" // arg3 - " mov r10, r8\n" // arg4 - " mov r8, r9\n" // arg5 - " mov r9, qword ptr [rsp + 8]\n" // arg6 - " jmp qword ptr [rip + sce_syscall]\n" // syscall - " ret\n" - ); - - -int -libc_init(const payload_args_t *args) { - int error; - - if((error=args->sceKernelDlsym(0x2001, "htons", &sce_htons))) { - return error; - } - if((error=args->sceKernelDlsym(0x2001, "sleep", &sce_sleep))) { - return error; - } - if((error=args->sceKernelDlsym(0x2001, "getpid", &sce_syscall))) { - return error; - } - sce_syscall += 0xa; // jump directly to syscall instruction - - if((error=args->sceKernelDlsym(0x2, "malloc", &sce_malloc))) { - return error; - } - if((error=args->sceKernelDlsym(0x2, "realloc", &sce_realloc))) { - return error; - } - if((error=args->sceKernelDlsym(0x2, "free", &sce_free))) { - return error; - } - if((error=args->sceKernelDlsym(0x2, "memset", &sce_memset))) { - return error; - } - if((error=args->sceKernelDlsym(0x2, "memcpy", &sce_memcpy))) { - return error; - } - if((error=args->sceKernelDlsym(0x2, "strcpy", &sce_strcpy))) { - return error; - } - if((error=args->sceKernelDlsym(0x2, "strcmp", &sce_strcmp))) { - return error; - } - if((error=args->sceKernelDlsym(0x2, "strncmp", &sce_strncmp))) { - return error; - } - if((error=args->sceKernelDlsym(0x2, "strcat", &sce_strcat))) { - return error; - } - if((error=args->sceKernelDlsym(0x2, "puts", &sce_puts))) { - return error; - } - if((error=args->sceKernelDlsym(0x2, "perror", &sce_perror))) { - return error; - } - if((error=args->sceKernelDlsym(0x2, "strerror", &sce_strerror))) { - return error; - } - return 0; -} - - -int -open(const char *path, int flags) { - return (int)syscall(SYS_open, path, flags); -} - - -int -unlink(const char *path) { - return (int)syscall(SYS_unlink, path); -} - - -ssize_t -read(int fd, void *buf, size_t cnt) { - return syscall(SYS_read, fd, buf, cnt); -} - - -ssize_t -write(int fd, const void *buf, size_t cnt) { - return syscall(SYS_write, fd, buf, cnt); -} - - -int -dup2(int oldfd, int newfd) { - return (int)syscall(SYS_dup2, oldfd, newfd); -} - - -int -close(int fd) { - return (int)syscall(SYS_close, fd); -} - - -int -socket(int dom, int ty, int proto) { - return (int)syscall(SYS_socket, dom, ty, proto); -} - - -int -setsockopt(int fd, int lvl, int name, const void *val, socklen_t len) { - return (int)syscall(SYS_setsockopt, fd, lvl, name, val, len); -} - - -int -bind(int fd, const struct sockaddr_in *addr, socklen_t addr_len) { - return (int)syscall(SYS_bind, fd, addr, addr_len); -} - - -int -listen(int fd, int backlog) { - return (int)syscall(SYS_listen, fd, backlog); -} - - -int -accept(int fd, struct sockaddr_in *addr, socklen_t *addr_len) { - return (int)syscall(SYS_accept, fd, addr, addr_len); -} - - -ssize_t sendmsg(int fd, const struct msghdr *msg, int flags) { - return (ssize_t)syscall(SYS_sendmsg, fd, msg, flags); -} - - -pid_t -getpid(void) { - return (pid_t)syscall(SYS_getpid); -} - - -int -kill(pid_t pid, int sig) { - return (int)syscall(SYS_kill, pid, sig); -} - - -pid_t -rfork(int flags) { - return (pid_t)syscall(SYS_rfork, flags); -} - - -pid_t -waitpid(pid_t pid, int *status, int opts) { - return (pid_t)syscall(SYS_wait4, pid, status, opts, 0); -} - - -int -ptrace(int request, pid_t pid, intptr_t addr, int data) { - uint8_t privcaps[16] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; - pid_t mypid = getpid(); - uint8_t caps[16]; - uint64_t authid; - int ret; - - if(kern_get_ucred_auth_id(mypid, &authid)) { - return -1; - } - if(kern_get_ucred_caps(mypid, caps)) { - return -1; - } - - if(kern_set_ucred_auth_id(mypid, 0x4800000000010003l)) { - return -1; - } - if(kern_set_ucred_caps(mypid, privcaps)) { - return -1; - } - - ret = (int)syscall(SYS_ptrace, request, pid, addr, data); - - if(kern_set_ucred_auth_id(mypid, authid)) { - return -1; - } - if(kern_set_ucred_caps(mypid, caps)) { - return -1; - } - - return ret; -} - - -int -sysctl(const int *name, size_t namelen, void *oldp, size_t *oldlenp, - const void *newp, size_t newlen) { - return syscall(SYS___sysctl, name, namelen, oldp, oldlenp, newp, newlen); -} - - -int -jitshm_create(const char* name, size_t size, int flags) { - return (int)syscall(0x215, name, size, flags); -} - - -int -jitshm_alias(int fd, int flags) { - return (int)syscall(0x216, fd, flags); -} - - -void* -mmap(void* addr, size_t len, int prot, int flags, int fd, off_t off) { - return (void*)syscall(SYS_mmap, addr, len, prot, flags, fd, off); -} - - -int -munmap(void* addr, size_t len) { - return (int)syscall(SYS_munmap, addr, len); -} - - -int -mprotect(void* addr, size_t len, int prot) { - return (int)syscall(SYS_mprotect, addr, len, prot); -} - - -void* -malloc(size_t len) { - return sce_malloc(len); -} - - -void* -realloc(void *ptr, size_t len) { - return sce_realloc(ptr, len); -} - - -void -free(void *ptr) { - return sce_free(ptr); -} - - -void* -memset(void *dst, int c, size_t len) { - return sce_memset(dst, c, len); -} - - -void* -memcpy(void *dst, const void* src, size_t len) { - return sce_memcpy(dst, src, len); -} - - -char* -strcpy(char *dst, const char *src) { - return sce_strcpy(dst, src); -} - - -int -strcmp(const char* s1, const char* s2) { - return sce_strcmp(s1, s2); -} - - -int -strncmp(const char *s1, const char *s2, size_t len) { - return sce_strncmp(s1, s2, len); -} - - -int -strcat(char* s1, const char* s2) { - return sce_strcat(s1, s2); -} - - -uint16_t -htons(uint16_t val) { - return sce_htons(val); -} - - -uint32_t -sleep(uint32_t seconds) { - return sce_sleep(seconds); -} - - -void puts(const char *s) { - sce_puts(s); -} - - -void -perror(const char* s) { - sce_perror(s); -} - - -char* -strerror(int error) { - return sce_strerror(error); -} - - -int* geterrno(void) { - return sce_errno(); -} diff --git a/libc.h b/libc.h deleted file mode 100644 index a18d703..0000000 --- a/libc.h +++ /dev/null @@ -1,167 +0,0 @@ -/* Copyright (C) 2023 John Törnblom - -This program is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 3, or (at your option) any -later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; see the file COPYING. If not, see -. */ - -#pragma once - -#define AF_UNIX 1 -#define AF_INET 2 -#define AF_INET6 28 - -#define SOCK_STREAM 1 -#define SOCK_DGRAM 2 - -#define IPPROTO_UDP 17 -#define IPPROTO_IPV6 41 - -#define IPV6_2292PKTOPTIONS 25 -#define IPV6_PKTINFO 46 -#define IPV6_TCLASS 61 - -#define SOL_SOCKET 0xffff -#define SO_REUSEADDR 0x0004 -#define SCM_RIGHTS 0x01 - -#define PAGE_SIZE 0x4000 - -#define PROT_NONE 0x0 -#define PROT_READ 0x1 -#define PROT_WRITE 0x2 -#define PROT_EXEC 0x4 - -#define MAP_SHARED 0x1 -#define MAP_PRIVATE 0x2 -#define MAP_FIXED 0x10 -#define MAP_ANONYMOUS 0x1000 - -#define RFFDG (1<<2) -#define RFPROC (1<<4) -#define RFNOWAIT (1<<6) -#define RFCFDG (1<<12) - -#define SIGKILL 9 -#define SIGCONT 19 - -#define EAGAIN 35 - -#define errno (*geterrno()) - -typedef char int8_t; -typedef short int16_t; -typedef int int32_t; -typedef long int64_t; - -typedef unsigned char uint8_t; -typedef unsigned short uint16_t; -typedef unsigned int uint32_t; -typedef unsigned long uint64_t; - -typedef uint64_t intptr_t; -typedef uint64_t off_t; -typedef uint64_t size_t; -typedef int64_t ssize_t; -typedef uint32_t socklen_t; -typedef uint32_t in_addr_t; -typedef int32_t pid_t; -typedef int32_t uid_t; -typedef int32_t gid_t; - -struct in_addr { - in_addr_t s_addr; -}; - -struct sockaddr_in { - uint8_t sin_len; - uint8_t sin_family; - uint16_t sin_port; - struct in_addr sin_addr; - uint8_t sin_zero[8]; -}; - -struct sockaddr_un { - uint8_t sun_len; - uint8_t sun_family; - char sun_path[104]; -}; - -struct msghdr { - void *msg_name; - socklen_t msg_namelen; - struct iovec *msg_iov; - int msg_iovlen; - void *msg_control; - socklen_t msg_controllen; - int msg_flags; -}; - -struct cmsghdr { - socklen_t cmsg_len; - int cmsg_level; - int cmsg_type; -}; - - -long syscall(int, ...); - -int open(const char *path, int flags); -int unlink(const char *pathname); -ssize_t read(int fd, void *buf, size_t cnt); -ssize_t write(int fd, const void* buf, size_t cnt); -int dup2(int oldfd, int newfd); -int close(int fd); - -int socket(int dom, int ty, int proto); -int setsockopt(int fd, int lvl, int name, const void *val, - unsigned int len); -int bind(int fd, const struct sockaddr_in *addr, socklen_t addr_len); -int listen(int fd, int backlog); -int accept(int fd, struct sockaddr_in *addr, socklen_t *addr_len); -ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags); - -pid_t rfork(int flags); -pid_t getpid(void); -pid_t waitpid(pid_t pid, int *status, int opts); -int kill(pid_t pid, int sig); - -int ptrace(int request, pid_t pid, intptr_t addr, int data); -int sysctl(const int *name, size_t namelen, void *oldp, size_t *oldlenp, - const void *newp, size_t newlen); - -int jitshm_create(const char* name, size_t size, int flags); -int jitshm_alias(int fd, int flags); - -void* mmap(void* addr, size_t len, int prot, int flags, int fd, off_t off); -int munmap(void* addr, size_t len); -int mprotect(void* addr, size_t len, int prot); - -uint16_t htons(uint16_t val); -uint32_t sleep(uint32_t seconds); - -void* malloc(size_t len); -void* realloc(void *ptr, size_t len); -void free(void *ptr); -void* memset(void *dst, int c, size_t len); -void* memcpy(void *dst, const void* src, size_t len); - -char* strcpy(char *dst, const char *src); -int strcmp(const char* s1, const char* s2); -int strncmp(const char *s1, const char *s2, size_t n); -int strcat(char* s1, const char* s2); - -void puts(const char *s); -void perror(const char *s); -char *strerror(int error); -int* geterrno(void); - diff --git a/main.c b/main.c index 660face..c430f11 100644 --- a/main.c +++ b/main.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 John Törnblom +/* Copyright (C) 2024 John Törnblom This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -14,37 +14,256 @@ You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, see . */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + #include "elfldr.h" -#include "kern.h" -#include "libc.h" -#ifdef ELFLDR_BOOTSTRAP -#include "elfldr-socksrv_elf.c" -#endif +/** + * Name of the process. + **/ +#define PROCNAME "elfldr.elf" -int -main() { - uint8_t qa_flags[16]; +/** + * Data structure used to send UI notifications on the PS5. + **/ +typedef struct notify_request { + char useless1[45]; + char message[3075]; +} notify_request_t; - if(kern_get_qa_flags(qa_flags)) { - puts("[elfldr.elf] kern_get_qa_flags() failed"); - return -1; - } - qa_flags[1] |= 0x03; - if(kern_set_qa_flags(qa_flags)) { - puts("[elfldr.elf] kern_set_qa_flags() failed"); - return -1; + +/** + * Send a UI notification request. + **/ +int sceKernelSendNotificationRequest(int, notify_request_t*, size_t, int); + + +/** + * Read an ELF from a given file descriptor. + **/ +static uint8_t* +readsock(int fd) { + uint8_t buf[0x4000]; + uint8_t* data = 0; + off_t offset = 0; + ssize_t len; + + while((len=read(fd, buf, sizeof(buf)))) { + data = realloc(data, offset + len + 1); + if(data == 0) { + perror("[elfldr.elf] realloc"); + return 0; + } + + memcpy(data + offset, buf, len); + offset += len; } -#ifdef ELFLDR_BOOTSTRAP - puts("[elfldr.elf] Bootstrapping"); - return elfldr_exec("ScePartyDaemon", -1, elfldr_socksrv_elf, - elfldr_socksrv_elf_len); -#else - puts("[elfldr.elf] Launching socket server"); - return elfldr_socksrv("SceRedisServer", ELFLDR_PORT); -#endif + data[offset] = 0; + + return data; +} + + +/** + * Read an ELF from a given path. + **/ +static uint8_t* +readfile(const char* path) { + uint8_t* buf; + FILE* file; + long len; + + if(!(file=fopen(path, "rb"))) { + perror("fopen"); + return 0; + } + + if(fseek(file, 0, SEEK_END)) { + perror("fseek"); + return 0; + } + + if((len=ftell(file)) < 0) { + perror("ftell"); + return 0; + } + + if(fseek(file, 0, SEEK_SET)) { + perror("fseek"); + return 0; + } + + if(!(buf=malloc(len))) { + return 0; + } + + if(fread(buf, 1, len, file) != len) { + perror("fread"); + free(buf); + return 0; + } + + if(fclose(file)) { + perror("fclose"); + free(buf); + return 0; + } + + return buf; +} + + +/** + * + **/ +static int +serve_elfldr(uint16_t port) { + struct sockaddr_in srvaddr; + struct sockaddr_in cliaddr; + char ip[INET_ADDRSTRLEN]; + struct ifaddrs *ifaddr; + notify_request_t req; + int ifaddr_wait = 1; + socklen_t socklen; + uint8_t* elf; + int connfd; + int srvfd; + + if(getifaddrs(&ifaddr) == -1) { + perror("[elfldr.elf] getifaddrs"); + return -1; + } + + // Enumerate all AF_INET IPs + for(struct ifaddrs *ifa=ifaddr; ifa!=NULL; ifa=ifa->ifa_next) { + if(ifa->ifa_addr == NULL) { + continue; + } + + if(ifa->ifa_addr->sa_family != AF_INET) { + continue; + } + + // skip localhost + if(!strncmp("lo", ifa->ifa_name, 2)) { + continue; + } + + struct sockaddr_in *in = (struct sockaddr_in*)ifa->ifa_addr; + inet_ntop(AF_INET, &(in->sin_addr), ip, sizeof(ip)); + + // skip interfaces without an ip + if(!strncmp("0.", ip, 2)) { + continue; + } + ifaddr_wait = 0; + + bzero(&req, sizeof(req)); + sprintf(req.message, "elfldr.elf running on %s:%d (%s)", ip, port, ifa->ifa_name); + printf("[elfldr.elf] %s\n", req.message); + } + + freeifaddrs(ifaddr); + + if(ifaddr_wait) { + return 0; + } + + if((srvfd=socket(AF_INET, SOCK_STREAM, 0)) < 0) { + perror("[elfldr.elf] socket"); + return -1; + } + + if(setsockopt(srvfd, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int)) < 0) { + perror("[elfldr.elf] setsockopt"); + return -1; + } + + memset(&srvaddr, 0, sizeof(srvaddr)); + srvaddr.sin_family = AF_INET; + srvaddr.sin_addr.s_addr = htonl(INADDR_ANY); + srvaddr.sin_port = htons(port); + + if(bind(srvfd, (struct sockaddr*)&srvaddr, sizeof(srvaddr)) != 0) { + perror("[elfldr.elf] bind"); + return -1; + } + + if(listen(srvfd, 5) != 0) { + perror("[elfldr.elf] listen"); + return -1; + } + + while(1) { + socklen = sizeof(cliaddr); + if((connfd=accept(srvfd, (struct sockaddr*)&cliaddr, &socklen)) < 0) { + perror("[elfldr.elf] accept"); + break; + } + + if(!(elf=readsock(connfd))) { + close(connfd); + continue; + } + + if(!memcmp(elf, "\x7f\x45\x4c\x46", 4)) { + elfldr_spawn(elf); + } else { + write(connfd, "Not an ELF file\n", 16); + } + free(elf); + close(connfd); + } + + return close(srvfd); +} + + +int main() { + const int port = 9021; + pid_t pid; + + signal(SIGCHLD, SIG_IGN); + + if((pid=syscall(SYS_rfork, RFPROC | RFNOWAIT | RFFDG))) { + return pid; + } + + signal(SIGCHLD, SIG_IGN); + while((pid=elfldr_find_pid(PROCNAME)) > 0) { + if(kill(pid, SIGKILL)) { + perror("[elfldr.elf] kill"); + } + sleep(1); + } + + syscall(SYS_setsid); + syscall(SYS_thr_set_name, -1, PROCNAME); + dup2(open("/dev/console", O_WRONLY), STDOUT_FILENO); + dup2(open("/dev/console", O_WRONLY), STDERR_FILENO); + kernel_set_proc_rootdir(getpid(), kernel_get_root_vnode()); + + while(1) { + serve_elfldr(port); + sleep(3); + } + + return 0; } diff --git a/payload.h b/payload.h deleted file mode 100644 index b89584c..0000000 --- a/payload.h +++ /dev/null @@ -1,30 +0,0 @@ -/* Copyright (C) 2023 John Törnblom - -This program is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 3, or (at your option) any -later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; see the file COPYING. If not, see -. */ - -#pragma once - - -typedef struct payload_args { - int (*sceKernelDlsym)(int, const char*, void*); - int *rwpipe; - int *rwpair; - long kpipe_addr; - long kdata_base_addr; - int *payloadout; -} payload_args_t; - -typedef void (payload_entry_t)(const payload_args_t *args); - diff --git a/payload_launchpad.c b/payload_launchpad.c deleted file mode 100644 index 1d5a926..0000000 --- a/payload_launchpad.c +++ /dev/null @@ -1,115 +0,0 @@ -/* Copyright (C) 2023 John Törnblom - -This program is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 3, or (at your option) any -later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; see the file COPYING. If not, see -. */ - -#include "payload.h" - - -typedef void* pthread_t; -typedef void* pthread_attr_t; - - -typedef struct payload_ctx { - payload_entry_t *entry; - payload_args_t *args; - int stdout; -} payload_ctx_t; - - -static void* (*malloc)(unsigned long); -static void (*free)(void*); -static void* (*memcpy)(void*, const void*, unsigned long); -static int (*close)(int); -static int (*dup)(int); -static int (*dup2)(int, int); -static int (*pthread_create)(pthread_t*, pthread_attr_t*, - void*(*f)(void*), void*); - - -static void* -payload_thread(void* args) { - payload_ctx_t *ctx = (payload_ctx_t*)args; - int stdout = dup(1); - int stderr = dup(2); - - dup2(ctx->stdout, 1); - dup2(ctx->stdout, 2); - - ctx->entry(ctx->args); - free(args); - - dup2(stdout, 1); - dup2(stderr, 2); - close(ctx->stdout); - - return 0; -} - - -int main(payload_ctx_t *ctx) { - pthread_t trd; - void* trd_args = malloc(sizeof(payload_ctx_t)); - - memcpy(trd_args, ctx, sizeof(payload_ctx_t)); - pthread_create(&trd, 0, payload_thread, trd_args); - - return 0; -} - - -static int -init(payload_args_t *args) { - int error; - - if((error=args->sceKernelDlsym(0x2001, "pthread_create", &pthread_create))) { - return error; - } - if((error=args->sceKernelDlsym(0x2001, "dup", &dup))) { - return error; - } - if((error=args->sceKernelDlsym(0x2001, "dup2", &dup2))) { - return error; - } - if((error=args->sceKernelDlsym(0x2001, "close", &close))) { - return error; - } - if((error=args->sceKernelDlsym(0x2, "malloc", &malloc))) { - return error; - } - if((error=args->sceKernelDlsym(0x2, "free", &free))) { - return error; - } - if((error=args->sceKernelDlsym(0x2, "memcpy", &memcpy))) { - return error; - } - - return 0; -} - - -void -_start(payload_entry_t *entry, payload_args_t *args, int stdout) { - payload_ctx_t ctx = { - .entry = entry, - .args = args, - .stdout = stdout - }; - - if(!(*args->payloadout=init(args))) { - *args->payloadout = main(&ctx); - } - - __builtin_debugtrap(); -} diff --git a/pt.c b/pt.c index 9b0aee4..88c86ed 100644 --- a/pt.c +++ b/pt.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 John Törnblom +/* Copyright (C) 2024 John Törnblom This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -14,35 +14,74 @@ You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, see . */ -#include "libc.h" +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + #include "pt.h" -#include "syscall.h" - -#define PT_READ_D 2 -#define PT_WRITE_D 5 -#define PT_CONTINUE 7 -#define PT_STEP 9 -#define PT_ATTACH 10 -#define PT_DETACH 11 -#define PT_IO 12 -#define PT_GETREGS 33 -#define PT_SETREGS 34 - -#define PIOD_READ_D 1 -#define PIOD_WRITE_D 2 -struct ptrace_io_desc { - int piod_op; - void *piod_offs; - void *piod_addr; - size_t piod_len; -}; +static int +sys_ptrace(int request, pid_t pid, caddr_t addr, int data) { + uint8_t privcaps[16] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; + pid_t mypid = getpid(); + uint8_t caps[16]; + uint64_t authid; + int ret; + + if(!(authid=kernel_get_ucred_authid(mypid))) { + return -1; + } + if(kernel_get_ucred_caps(mypid, caps)) { + return -1; + } + + if(kernel_set_ucred_authid(mypid, 0x4800000000010003l)) { + return -1; + } + if(kernel_set_ucred_caps(mypid, privcaps)) { + return -1; + } + + ret = (int)syscall(SYS_ptrace, request, pid, addr, data); + + if(kernel_set_ucred_authid(mypid, authid)) { + return -1; + } + if(kernel_set_ucred_caps(mypid, caps)) { + return -1; + } + + return ret; +} + + +intptr_t +pt_resolve(pid_t pid, const char* nid) { + intptr_t addr; + + if((addr=kernel_dynlib_resolve(pid, 0x1, nid))) { + return addr; + } + + return kernel_dynlib_resolve(pid, 0x2001, nid); +} int pt_attach(pid_t pid) { - if(ptrace(PT_ATTACH, pid, 0, 0) == -1) { + if(sys_ptrace(PT_ATTACH, pid, 0, 0) == -1) { return -1; } @@ -56,7 +95,7 @@ pt_attach(pid_t pid) { int pt_detach(pid_t pid) { - if(ptrace(PT_DETACH, pid, 0, 0) == -1) { + if(sys_ptrace(PT_DETACH, pid, 0, 0) == -1) { return -1; } @@ -65,82 +104,8 @@ pt_detach(pid_t pid) { int -pt_continue(pid_t pid) { - if(ptrace(PT_CONTINUE, pid, 1, SIGCONT) == -1) { - return -1; - } - - return 0; -} - - -int -pt_getregs(pid_t pid, struct reg *r) { - return ptrace(PT_GETREGS, pid, (intptr_t)r, 0); -} - - -int -pt_setregs(pid_t pid, const struct reg *r) { - return ptrace(PT_SETREGS, pid, (intptr_t)r, 0); -} - - -int -pt_getint(pid_t pid, intptr_t addr) { - return ptrace(PT_READ_D, pid, addr, 0); -} - - -int -pt_setint(pid_t pid, intptr_t addr, int val) { - return ptrace(PT_WRITE_D, pid, addr, val); -} - - -int -pt_copyin(pid_t pid, void* buf, intptr_t addr, size_t len) { - struct ptrace_io_desc iod = { - .piod_op = PIOD_WRITE_D, - .piod_offs = (void*)addr, - .piod_addr = buf, - .piod_len = len}; - - while(ptrace(PT_IO, pid, (intptr_t)&iod, 0)) { - if(errno != EAGAIN) { - return -1; - } - } - - return 0; -} - -int -pt_copyout(pid_t pid, intptr_t addr, void* buf, size_t len) { - struct ptrace_io_desc iod = { - .piod_op = PIOD_READ_D, - .piod_offs = (void*)addr, - .piod_addr = buf, - .piod_len = len}; - return ptrace(PT_IO, pid, (intptr_t)&iod, 0); -} - - -int -pt_setchar(pid_t pid, intptr_t addr, char val) { - return pt_copyin(pid, &val, addr, sizeof(val)); -} - - -int -pt_setlong(pid_t pid, intptr_t addr, long val) { - return pt_copyin(pid, &val, addr, sizeof(val)); -} - - -static int pt_step(int pid) { - if(ptrace(PT_STEP, pid, (intptr_t)1, 0)) { + if(sys_ptrace(PT_STEP, pid, (caddr_t)1, 0)) { return -1; } @@ -152,12 +117,39 @@ pt_step(int pid) { } -static uint64_t -pt_call(pid_t pid, intptr_t addr, - uint64_t arg1, uint64_t arg2, uint64_t arg3, - uint64_t arg4, uint64_t arg5, uint64_t arg6) { +int +pt_continue(pid_t pid) { + if(sys_ptrace(PT_CONTINUE, pid, (caddr_t)1, SIGCONT) == -1) { + return -1; + } + + return 0; +} + + +int +pt_getint(pid_t pid, intptr_t addr) { + return sys_ptrace(PT_READ_D, pid, (caddr_t)addr, 0); +} + + +int +pt_getregs(pid_t pid, struct reg *r) { + return sys_ptrace(PT_GETREGS, pid, (caddr_t)r, 0); +} + + +int +pt_setregs(pid_t pid, const struct reg *r) { + return sys_ptrace(PT_SETREGS, pid, (caddr_t)r, 0); +} + + +long +pt_call(pid_t pid, intptr_t addr, ...) { struct reg jmp_reg; struct reg bak_reg; + va_list ap; if(pt_getregs(pid, &bak_reg)) { return -1; @@ -165,12 +157,15 @@ pt_call(pid_t pid, intptr_t addr, memcpy(&jmp_reg, &bak_reg, sizeof(jmp_reg)); jmp_reg.r_rip = addr; - jmp_reg.r_rdi = arg1; - jmp_reg.r_rsi = arg2; - jmp_reg.r_rdx = arg3; - jmp_reg.r_rcx = arg4; - jmp_reg.r_r8 = arg5; - jmp_reg.r_r9 = arg5; + + va_start(ap, addr); + jmp_reg.r_rdi = va_arg(ap, uint64_t); + jmp_reg.r_rsi = va_arg(ap, uint64_t); + jmp_reg.r_rdx = va_arg(ap, uint64_t); + jmp_reg.r_rcx = va_arg(ap, uint64_t); + jmp_reg.r_r8 = va_arg(ap, uint64_t); + jmp_reg.r_r9 = va_arg(ap, uint64_t); + va_end(ap); if(pt_setregs(pid, &jmp_reg)) { return -1; @@ -195,20 +190,19 @@ pt_call(pid_t pid, intptr_t addr, } -static uint64_t -pt_syscall(pid_t pid, int sysno, - uint64_t arg1, uint64_t arg2, uint64_t arg3, - uint64_t arg4, uint64_t arg5, uint64_t arg6) { - intptr_t addr = dynlib_resolve(pid, 0x2001, "HoLVWNanBBc"); +long +pt_syscall(pid_t pid, int sysno, ...) { + intptr_t addr = pt_resolve(pid, "HoLVWNanBBc"); struct reg jmp_reg; struct reg bak_reg; + va_list ap; if(!addr) { return -1; } else { addr += 0xa; } - + if(pt_getregs(pid, &bak_reg)) { return -1; } @@ -216,12 +210,15 @@ pt_syscall(pid_t pid, int sysno, memcpy(&jmp_reg, &bak_reg, sizeof(jmp_reg)); jmp_reg.r_rip = addr; jmp_reg.r_rax = sysno; - jmp_reg.r_rdi = arg1; - jmp_reg.r_rsi = arg2; - jmp_reg.r_rdx = arg3; - jmp_reg.r_r10 = arg4; - jmp_reg.r_r8 = arg5; - jmp_reg.r_r9 = arg6; + + va_start(ap, sysno); + jmp_reg.r_rdi = va_arg(ap, uint64_t); + jmp_reg.r_rsi = va_arg(ap, uint64_t); + jmp_reg.r_rdx = va_arg(ap, uint64_t); + jmp_reg.r_r10 = va_arg(ap, uint64_t); + jmp_reg.r_r8 = va_arg(ap, uint64_t); + jmp_reg.r_r9 = va_arg(ap, uint64_t); + va_end(ap); if(pt_setregs(pid, &jmp_reg)) { return -1; @@ -248,13 +245,13 @@ pt_syscall(pid_t pid, int sysno, int pt_jitshm_create(pid_t pid, intptr_t name, size_t size, int flags) { - return (int)pt_syscall(pid, 0x215, name, size, flags, 0, 0, 0); + return (int)pt_syscall(pid, 0x215, name, size, flags); } int pt_jitshm_alias(pid_t pid, int fd, int flags) { - return (int)pt_syscall(pid, 0x216, fd, flags, 0, 0, 0, 0); + return (int)pt_syscall(pid, 0x216, fd, flags); } @@ -267,25 +264,19 @@ pt_mmap(pid_t pid, intptr_t addr, size_t len, int prot, int flags, int pt_munmap(pid_t pid, intptr_t addr, size_t len) { - return pt_syscall(pid, SYS_munmap, addr, len, 0, 0, 0, 0); + return pt_syscall(pid, SYS_munmap, addr, len); } int pt_mprotect(pid_t pid, intptr_t addr, size_t len, int prot) { - return pt_syscall(pid, SYS_mprotect, addr, len, prot, 0, 0, 0); -} - - -int -pt_close(pid_t pid, int fd) { - return (int)pt_syscall(pid, SYS_close, fd, 0, 0, 0, 0, 0); + return pt_syscall(pid, SYS_mprotect, addr, len, prot); } int pt_socket(pid_t pid, int domain, int type, int protocol) { - return (int)pt_syscall(pid, SYS_socket, domain, type, protocol, 0, 0, 0); + return (int)pt_syscall(pid, SYS_socket, domain, type, protocol); } @@ -296,36 +287,23 @@ pt_setsockopt(pid_t pid, int fd, int level, int optname, intptr_t optval, optlen, 0); } - int -pt_bind(pid_t pid, int sockfd, intptr_t addr, socklen_t addrlen) { - return (int)pt_syscall(pid, SYS_bind, sockfd, addr, addrlen, 0, 0, 0); -} - - -ssize_t -pt_recvmsg(pid_t pid, int fd, intptr_t msg, int flags) { - return (int)pt_syscall(pid, SYS_recvmsg, fd, msg, flags, 0, 0, 0); -} - - -int -pt_dup2(pid_t pid, int oldfd, int newfd) { - return (int)pt_syscall(pid, SYS_dup2, oldfd, newfd, 0, 0, 0, 0); +pt_close(pid_t pid, int fd) { + return (int)pt_syscall(pid, SYS_close, fd); } int pt_pipe(pid_t pid, intptr_t pipefd) { - intptr_t faddr = dynlib_resolve(pid, 0x2001, "-Jp7F+pXxNg"); + intptr_t faddr = pt_resolve(pid, "-Jp7F+pXxNg"); return (int)pt_call(pid, faddr, pipefd, 0, 0, 0, 0, 0); } void pt_perror(pid_t pid, const char *s) { - intptr_t faddr = dynlib_resolve(pid, 0x2001, "9BcDykPmo1I"); //__error - intptr_t addr = pt_call(pid, faddr, 0, 0, 0, 0, 0, 0); + intptr_t faddr = pt_resolve(pid, "9BcDykPmo1I"); + intptr_t addr = pt_call(pid, faddr); int err = pt_getint(pid, addr); char buf[255]; diff --git a/pt.h b/pt.h index c8c2ac3..37df5f0 100644 --- a/pt.h +++ b/pt.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 John Törnblom +/* Copyright (C) 2024 John Törnblom This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -16,57 +16,24 @@ along with this program; see the file COPYING. If not, see #pragma once -#include "dynlib.h" -#include "libc.h" - - -struct reg { - uint64_t r_r15; - uint64_t r_r14; - uint64_t r_r13; - uint64_t r_r12; - uint64_t r_r11; - uint64_t r_r10; - uint64_t r_r9; - uint64_t r_r8; - uint64_t r_rdi; - uint64_t r_rsi; - uint64_t r_rbp; - uint64_t r_rbx; - uint64_t r_rdx; - uint64_t r_rcx; - uint64_t r_rax; - uint32_t r_trapno; - uint16_t r_fs; - uint16_t r_gs; - uint32_t r_err; - uint16_t r_es; - uint16_t r_ds; - uint64_t r_rip; - uint64_t r_cs; - uint64_t r_rflags; - uint64_t r_rsp; - uint64_t r_ss; -}; +#include +#include +#include int pt_attach(pid_t pid); int pt_detach(pid_t pid); +int pt_step(pid_t pid); int pt_continue(pid_t pid); int pt_getregs(pid_t pid, struct reg *r); int pt_setregs(pid_t pid, const struct reg *r); - -int pt_setchar(pid_t pid, intptr_t addr, char val); -int pt_setint(pid_t pid, intptr_t addr, int val); -int pt_setlong(pid_t pid, intptr_t addr, long val); - -int pt_copyin(pid_t pid, void* buf, intptr_t addr, size_t len); -int pt_copyout(pid_t pid, intptr_t addr, void* buf, size_t len); - int pt_getint(pid_t pid, intptr_t addr); +long pt_syscall(pid_t pid, int sysno, ...); +intptr_t pt_resolve(pid_t pid, const char* nid); + int pt_jitshm_create(pid_t pid, intptr_t name, size_t size, int flags); int pt_jitshm_alias(pid_t pid, int fd, int flags); @@ -77,13 +44,9 @@ int pt_mprotect(pid_t pid, intptr_t addr, size_t len, int prot); int pt_socket(pid_t pid, int domain, int type, int protocol); int pt_setsockopt(pid_t pid, int fd, int level, int optname, intptr_t optval, - socklen_t optlen); -int pt_bind(pid_t pid, int sockfd, intptr_t addr, socklen_t addrlen) ; -ssize_t pt_recvmsg(pid_t pid, int fd, intptr_t msg, int flags); + uint32_t optlen); int pt_close(pid_t pid, int fd); -int pt_dup2(pid_t pid, int oldfd, int newfd); int pt_pipe(pid_t pid, intptr_t pipefd); - void pt_perror(pid_t pid, const char *s); diff --git a/syscall.h b/syscall.h deleted file mode 100644 index 79b154c..0000000 --- a/syscall.h +++ /dev/null @@ -1,470 +0,0 @@ -/* - * System call numbers. - * - * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: releng/11.0/sys/sys/syscall.h 303858 2016-08-08 21:19:57Z bdrewery $ - * created from FreeBSD: stable/11/sys/kern/syscalls.master 303854 2016-08-08 20:23:11Z bdrewery - */ - -#define SYS_syscall 0 -#define SYS_exit 1 -#define SYS_fork 2 -#define SYS_read 3 -#define SYS_write 4 -#define SYS_open 5 -#define SYS_close 6 -#define SYS_wait4 7 - /* 8 is old creat */ -#define SYS_link 9 -#define SYS_unlink 10 - /* 11 is obsolete execv */ -#define SYS_chdir 12 -#define SYS_fchdir 13 -#define SYS_mknod 14 -#define SYS_chmod 15 -#define SYS_chown 16 -#define SYS_break 17 - /* 18 is freebsd4 getfsstat */ - /* 19 is old lseek */ -#define SYS_getpid 20 -#define SYS_mount 21 -#define SYS_unmount 22 -#define SYS_setuid 23 -#define SYS_getuid 24 -#define SYS_geteuid 25 -#define SYS_ptrace 26 -#define SYS_recvmsg 27 -#define SYS_sendmsg 28 -#define SYS_recvfrom 29 -#define SYS_accept 30 -#define SYS_getpeername 31 -#define SYS_getsockname 32 -#define SYS_access 33 -#define SYS_chflags 34 -#define SYS_fchflags 35 -#define SYS_sync 36 -#define SYS_kill 37 - /* 38 is old stat */ -#define SYS_getppid 39 - /* 40 is old lstat */ -#define SYS_dup 41 -#define SYS_freebsd10_pipe 42 -#define SYS_getegid 43 -#define SYS_profil 44 -#define SYS_ktrace 45 - /* 46 is old sigaction */ -#define SYS_getgid 47 - /* 48 is old sigprocmask */ -#define SYS_getlogin 49 -#define SYS_setlogin 50 -#define SYS_acct 51 - /* 52 is old sigpending */ -#define SYS_sigaltstack 53 -#define SYS_ioctl 54 -#define SYS_reboot 55 -#define SYS_revoke 56 -#define SYS_symlink 57 -#define SYS_readlink 58 -#define SYS_execve 59 -#define SYS_umask 60 -#define SYS_chroot 61 - /* 62 is old fstat */ - /* 63 is old getkerninfo */ - /* 64 is old getpagesize */ -#define SYS_msync 65 -#define SYS_vfork 66 - /* 67 is obsolete vread */ - /* 68 is obsolete vwrite */ -#define SYS_sbrk 69 -#define SYS_sstk 70 - /* 71 is old mmap */ -#define SYS_vadvise 72 -#define SYS_munmap 73 -#define SYS_mprotect 74 -#define SYS_madvise 75 - /* 76 is obsolete vhangup */ - /* 77 is obsolete vlimit */ -#define SYS_mincore 78 -#define SYS_getgroups 79 -#define SYS_setgroups 80 -#define SYS_getpgrp 81 -#define SYS_setpgid 82 -#define SYS_setitimer 83 - /* 84 is old wait */ -#define SYS_swapon 85 -#define SYS_getitimer 86 - /* 87 is old gethostname */ - /* 88 is old sethostname */ -#define SYS_getdtablesize 89 -#define SYS_dup2 90 -#define SYS_fcntl 92 -#define SYS_select 93 -#define SYS_fsync 95 -#define SYS_setpriority 96 -#define SYS_socket 97 -#define SYS_connect 98 - /* 99 is old accept */ -#define SYS_getpriority 100 - /* 101 is old send */ - /* 102 is old recv */ - /* 103 is old sigreturn */ -#define SYS_bind 104 -#define SYS_setsockopt 105 -#define SYS_listen 106 - /* 107 is obsolete vtimes */ - /* 108 is old sigvec */ - /* 109 is old sigblock */ - /* 110 is old sigsetmask */ - /* 111 is old sigsuspend */ - /* 112 is old sigstack */ - /* 113 is old recvmsg */ - /* 114 is old sendmsg */ - /* 115 is obsolete vtrace */ -#define SYS_gettimeofday 116 -#define SYS_getrusage 117 -#define SYS_getsockopt 118 -#define SYS_readv 120 -#define SYS_writev 121 -#define SYS_settimeofday 122 -#define SYS_fchown 123 -#define SYS_fchmod 124 - /* 125 is old recvfrom */ -#define SYS_setreuid 126 -#define SYS_setregid 127 -#define SYS_rename 128 - /* 129 is old truncate */ - /* 130 is old ftruncate */ -#define SYS_flock 131 -#define SYS_mkfifo 132 -#define SYS_sendto 133 -#define SYS_shutdown 134 -#define SYS_socketpair 135 -#define SYS_mkdir 136 -#define SYS_rmdir 137 -#define SYS_utimes 138 - /* 139 is obsolete 4.2 sigreturn */ -#define SYS_adjtime 140 - /* 141 is old getpeername */ - /* 142 is old gethostid */ - /* 143 is old sethostid */ - /* 144 is old getrlimit */ - /* 145 is old setrlimit */ - /* 146 is old killpg */ -#define SYS_setsid 147 -#define SYS_quotactl 148 - /* 149 is old quota */ - /* 150 is old getsockname */ -#define SYS_nlm_syscall 154 -#define SYS_nfssvc 155 - /* 156 is old getdirentries */ - /* 157 is freebsd4 statfs */ - /* 158 is freebsd4 fstatfs */ -#define SYS_lgetfh 160 -#define SYS_getfh 161 - /* 162 is freebsd4 getdomainname */ - /* 163 is freebsd4 setdomainname */ - /* 164 is freebsd4 uname */ -#define SYS_sysarch 165 -#define SYS_rtprio 166 -#define SYS_semsys 169 -#define SYS_msgsys 170 -#define SYS_shmsys 171 - /* 173 is freebsd6 pread */ - /* 174 is freebsd6 pwrite */ -#define SYS_setfib 175 -#define SYS_ntp_adjtime 176 -#define SYS_setgid 181 -#define SYS_setegid 182 -#define SYS_seteuid 183 -#define SYS_stat 188 -#define SYS_fstat 189 -#define SYS_lstat 190 -#define SYS_pathconf 191 -#define SYS_fpathconf 192 -#define SYS_getrlimit 194 -#define SYS_setrlimit 195 -#define SYS_getdirentries 196 - /* 197 is freebsd6 mmap */ -#define SYS___syscall 198 - /* 199 is freebsd6 lseek */ - /* 200 is freebsd6 truncate */ - /* 201 is freebsd6 ftruncate */ -#define SYS___sysctl 202 -#define SYS_mlock 203 -#define SYS_munlock 204 -#define SYS_undelete 205 -#define SYS_futimes 206 -#define SYS_getpgid 207 -#define SYS_poll 209 -#define SYS_freebsd7___semctl 220 -#define SYS_semget 221 -#define SYS_semop 222 -#define SYS_freebsd7_msgctl 224 -#define SYS_msgget 225 -#define SYS_msgsnd 226 -#define SYS_msgrcv 227 -#define SYS_shmat 228 -#define SYS_freebsd7_shmctl 229 -#define SYS_shmdt 230 -#define SYS_shmget 231 -#define SYS_clock_gettime 232 -#define SYS_clock_settime 233 -#define SYS_clock_getres 234 -#define SYS_ktimer_create 235 -#define SYS_ktimer_delete 236 -#define SYS_ktimer_settime 237 -#define SYS_ktimer_gettime 238 -#define SYS_ktimer_getoverrun 239 -#define SYS_nanosleep 240 -#define SYS_ffclock_getcounter 241 -#define SYS_ffclock_setestimate 242 -#define SYS_ffclock_getestimate 243 -#define SYS_clock_getcpuclockid2 247 -#define SYS_ntp_gettime 248 -#define SYS_minherit 250 -#define SYS_rfork 251 -#define SYS_openbsd_poll 252 -#define SYS_issetugid 253 -#define SYS_lchown 254 -#define SYS_aio_read 255 -#define SYS_aio_write 256 -#define SYS_lio_listio 257 -#define SYS_getdents 272 -#define SYS_lchmod 274 -#define SYS_netbsd_lchown 275 -#define SYS_lutimes 276 -#define SYS_netbsd_msync 277 -#define SYS_nstat 278 -#define SYS_nfstat 279 -#define SYS_nlstat 280 -#define SYS_preadv 289 -#define SYS_pwritev 290 - /* 297 is freebsd4 fhstatfs */ -#define SYS_fhopen 298 -#define SYS_fhstat 299 -#define SYS_modnext 300 -#define SYS_modstat 301 -#define SYS_modfnext 302 -#define SYS_modfind 303 -#define SYS_kldload 304 -#define SYS_kldunload 305 -#define SYS_kldfind 306 -#define SYS_kldnext 307 -#define SYS_kldstat 308 -#define SYS_kldfirstmod 309 -#define SYS_getsid 310 -#define SYS_setresuid 311 -#define SYS_setresgid 312 - /* 313 is obsolete signanosleep */ -#define SYS_aio_return 314 -#define SYS_aio_suspend 315 -#define SYS_aio_cancel 316 -#define SYS_aio_error 317 - /* 318 is freebsd6 aio_read */ - /* 319 is freebsd6 aio_write */ - /* 320 is freebsd6 lio_listio */ -#define SYS_yield 321 - /* 322 is obsolete thr_sleep */ - /* 323 is obsolete thr_wakeup */ -#define SYS_mlockall 324 -#define SYS_munlockall 325 -#define SYS___getcwd 326 -#define SYS_sched_setparam 327 -#define SYS_sched_getparam 328 -#define SYS_sched_setscheduler 329 -#define SYS_sched_getscheduler 330 -#define SYS_sched_yield 331 -#define SYS_sched_get_priority_max 332 -#define SYS_sched_get_priority_min 333 -#define SYS_sched_rr_get_interval 334 -#define SYS_utrace 335 - /* 336 is freebsd4 sendfile */ -#define SYS_kldsym 337 -#define SYS_jail 338 -#define SYS_nnpfs_syscall 339 -#define SYS_sigprocmask 340 -#define SYS_sigsuspend 341 - /* 342 is freebsd4 sigaction */ -#define SYS_sigpending 343 - /* 344 is freebsd4 sigreturn */ -#define SYS_sigtimedwait 345 -#define SYS_sigwaitinfo 346 -#define SYS___acl_get_file 347 -#define SYS___acl_set_file 348 -#define SYS___acl_get_fd 349 -#define SYS___acl_set_fd 350 -#define SYS___acl_delete_file 351 -#define SYS___acl_delete_fd 352 -#define SYS___acl_aclcheck_file 353 -#define SYS___acl_aclcheck_fd 354 -#define SYS_extattrctl 355 -#define SYS_extattr_set_file 356 -#define SYS_extattr_get_file 357 -#define SYS_extattr_delete_file 358 -#define SYS_aio_waitcomplete 359 -#define SYS_getresuid 360 -#define SYS_getresgid 361 -#define SYS_kqueue 362 -#define SYS_kevent 363 -#define SYS_extattr_set_fd 371 -#define SYS_extattr_get_fd 372 -#define SYS_extattr_delete_fd 373 -#define SYS___setugid 374 -#define SYS_eaccess 376 -#define SYS_afs3_syscall 377 -#define SYS_nmount 378 -#define SYS___mac_get_proc 384 -#define SYS___mac_set_proc 385 -#define SYS___mac_get_fd 386 -#define SYS___mac_get_file 387 -#define SYS___mac_set_fd 388 -#define SYS___mac_set_file 389 -#define SYS_kenv 390 -#define SYS_lchflags 391 -#define SYS_uuidgen 392 -#define SYS_sendfile 393 -#define SYS_mac_syscall 394 -#define SYS_getfsstat 395 -#define SYS_statfs 396 -#define SYS_fstatfs 397 -#define SYS_fhstatfs 398 -#define SYS_ksem_close 400 -#define SYS_ksem_post 401 -#define SYS_ksem_wait 402 -#define SYS_ksem_trywait 403 -#define SYS_ksem_init 404 -#define SYS_ksem_open 405 -#define SYS_ksem_unlink 406 -#define SYS_ksem_getvalue 407 -#define SYS_ksem_destroy 408 -#define SYS___mac_get_pid 409 -#define SYS___mac_get_link 410 -#define SYS___mac_set_link 411 -#define SYS_extattr_set_link 412 -#define SYS_extattr_get_link 413 -#define SYS_extattr_delete_link 414 -#define SYS___mac_execve 415 -#define SYS_sigaction 416 -#define SYS_sigreturn 417 -#define SYS_getcontext 421 -#define SYS_setcontext 422 -#define SYS_swapcontext 423 -#define SYS_swapoff 424 -#define SYS___acl_get_link 425 -#define SYS___acl_set_link 426 -#define SYS___acl_delete_link 427 -#define SYS___acl_aclcheck_link 428 -#define SYS_sigwait 429 -#define SYS_thr_create 430 -#define SYS_thr_exit 431 -#define SYS_thr_self 432 -#define SYS_thr_kill 433 -#define SYS_jail_attach 436 -#define SYS_extattr_list_fd 437 -#define SYS_extattr_list_file 438 -#define SYS_extattr_list_link 439 -#define SYS_ksem_timedwait 441 -#define SYS_thr_suspend 442 -#define SYS_thr_wake 443 -#define SYS_kldunloadf 444 -#define SYS_audit 445 -#define SYS_auditon 446 -#define SYS_getauid 447 -#define SYS_setauid 448 -#define SYS_getaudit 449 -#define SYS_setaudit 450 -#define SYS_getaudit_addr 451 -#define SYS_setaudit_addr 452 -#define SYS_auditctl 453 -#define SYS__umtx_op 454 -#define SYS_thr_new 455 -#define SYS_sigqueue 456 -#define SYS_kmq_open 457 -#define SYS_kmq_setattr 458 -#define SYS_kmq_timedreceive 459 -#define SYS_kmq_timedsend 460 -#define SYS_kmq_notify 461 -#define SYS_kmq_unlink 462 -#define SYS_abort2 463 -#define SYS_thr_set_name 464 -#define SYS_aio_fsync 465 -#define SYS_rtprio_thread 466 -#define SYS_sctp_peeloff 471 -#define SYS_sctp_generic_sendmsg 472 -#define SYS_sctp_generic_sendmsg_iov 473 -#define SYS_sctp_generic_recvmsg 474 -#define SYS_pread 475 -#define SYS_pwrite 476 -#define SYS_mmap 477 -#define SYS_lseek 478 -#define SYS_truncate 479 -#define SYS_ftruncate 480 -#define SYS_thr_kill2 481 -#define SYS_shm_open 482 -#define SYS_shm_unlink 483 -#define SYS_cpuset 484 -#define SYS_cpuset_setid 485 -#define SYS_cpuset_getid 486 -#define SYS_cpuset_getaffinity 487 -#define SYS_cpuset_setaffinity 488 -#define SYS_faccessat 489 -#define SYS_fchmodat 490 -#define SYS_fchownat 491 -#define SYS_fexecve 492 -#define SYS_fstatat 493 -#define SYS_futimesat 494 -#define SYS_linkat 495 -#define SYS_mkdirat 496 -#define SYS_mkfifoat 497 -#define SYS_mknodat 498 -#define SYS_openat 499 -#define SYS_readlinkat 500 -#define SYS_renameat 501 -#define SYS_symlinkat 502 -#define SYS_unlinkat 503 -#define SYS_posix_openpt 504 -#define SYS_gssd_syscall 505 -#define SYS_jail_get 506 -#define SYS_jail_set 507 -#define SYS_jail_remove 508 -#define SYS_closefrom 509 -#define SYS___semctl 510 -#define SYS_msgctl 511 -#define SYS_shmctl 512 -#define SYS_lpathconf 513 - /* 514 is obsolete cap_new */ -#define SYS___cap_rights_get 515 -#define SYS_cap_enter 516 -#define SYS_cap_getmode 517 -#define SYS_pdfork 518 -#define SYS_pdkill 519 -#define SYS_pdgetpid 520 -#define SYS_pselect 522 -#define SYS_getloginclass 523 -#define SYS_setloginclass 524 -#define SYS_rctl_get_racct 525 -#define SYS_rctl_get_rules 526 -#define SYS_rctl_get_limits 527 -#define SYS_rctl_add_rule 528 -#define SYS_rctl_remove_rule 529 -#define SYS_posix_fallocate 530 -#define SYS_posix_fadvise 531 -#define SYS_wait6 532 -#define SYS_cap_rights_limit 533 -#define SYS_cap_ioctls_limit 534 -#define SYS_cap_ioctls_get 535 -#define SYS_cap_fcntls_limit 536 -#define SYS_cap_fcntls_get 537 -#define SYS_bindat 538 -#define SYS_connectat 539 -#define SYS_chflagsat 540 -#define SYS_accept4 541 -#define SYS_pipe2 542 -#define SYS_aio_mlock 543 -#define SYS_procctl 544 -#define SYS_ppoll 545 -#define SYS_futimens 546 -#define SYS_utimensat 547 -#define SYS_numa_getaffinity 548 -#define SYS_numa_setaffinity 549 -#define SYS_MAXSYSCALL 550