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