Skip to content
This repository has been archived by the owner on Apr 10, 2024. It is now read-only.

Commit

Permalink
launch payloads in a thread, and do some cleanup before the thread te…
Browse files Browse the repository at this point in the history
…rminates
  • Loading branch information
john-tornblom committed Sep 30, 2023
1 parent aa9e25d commit f18b415
Show file tree
Hide file tree
Showing 4 changed files with 187 additions and 31 deletions.
28 changes: 20 additions & 8 deletions Makefile
Expand Up @@ -2,8 +2,9 @@ PS5_HOST ?= ps5
PS5_PORT ?= 9020
ELFLDR_PORT ?= 9021

CC := clang
LD := ld.lld
CC := clang
LD := ld.lld
XXD := xxd

CFLAGS := -target x86_64-pc-none -fPIE -fno-stack-protector -ffreestanding \
-fno-builtin -nostdlib -nostdinc -Wall -Werror
Expand All @@ -13,29 +14,40 @@ OBJS := crt.o libc.o kern.o dynlib.o pt.o elfldr.o

all: elfldr.elf hello_world.elf

elfldr-socksrv_elf.c: elfldr-socksrv.elf
xxd -i $^ > $@
elfldr.elf: $(OBJS) main.o
$(LD) $(LDFLAGS) -o $@ $^

elfldr-socksrv.elf: $(OBJS) main-socksrv.o
$(LD) $(LDFLAGS) -o $@ $^

elfldr.elf: $(OBJS) main.o
payload_launchpad.elf: payload_launchpad.o
$(LD) $(LDFLAGS) -o $@ $^

hello_world.elf: hello_world.o
$(LD) $(LDFLAGS) -o $@ $^

main-socksrv.o: main.c
$(CC) -c $(CFLAGS) -DELFLDR_PORT=$(ELFLDR_PORT) -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
$(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 $@ $<


%.o: %.c
$(CC) -c $(CFLAGS) -o $@ $<

clean:
rm -f *.o *.elf elfldr-socksrv_elf.c
rm -f *.o *.elf elfldr-socksrv_elf.c payload_launchpad_elf.c

test: elfldr.elf hello_world.elf
nc -q0 $(PS5_HOST) $(PS5_PORT) < elfldr.elf
Expand Down
73 changes: 50 additions & 23 deletions elfldr.c
Expand Up @@ -38,6 +38,9 @@ along with this program; see the file COPYING. If not, see
(((x) & PF_X) ? PROT_EXEC : 0))


#include "payload_launchpad_elf.c"


/**
* Load an ELF into the address space of a process with the given pid.
**/
Expand Down Expand Up @@ -212,7 +215,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
elfldr_args(pid_t pid) {
elfldr_payload_args(pid_t pid) {
int victim_sock;
int master_sock;
intptr_t buf;
Expand Down Expand Up @@ -440,24 +443,16 @@ elfldr_stdout(pid_t pid, const char *sockpath, int fd) {
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;
}

if(pt_dup2(pid, fd, 1) < 0) {
pt_perror(pid, "[elfldr.elf] pt_dup2");
return -1;
}

if(pt_dup2(pid, fd, 2) < 0) {
pt_perror(pid, "[elfldr.elf] pt_dup2");
return -1;
}

return 0;
return fd;
}


Expand All @@ -466,9 +461,11 @@ 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 addr;
intptr_t args;
struct reg r;
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) {
Expand All @@ -493,16 +490,17 @@ elfldr_exec(const char* procname, int stdout, uint8_t *elf, size_t size) {
return -1;
}

if(pt_getregs(pid, &r)) {
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(elfldr_stdout(pid, ELFLDR_UNIX_SOCKET, stdout)) {
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);
Expand All @@ -511,31 +509,60 @@ elfldr_exec(const char* procname, int stdout, uint8_t *elf, size_t size) {
unlink(ELFLDR_UNIX_SOCKET);
}

if(!(addr=elfldr_load(pid, elf, size))) {
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(!(args=elfldr_args(pid))) {
if(!(payload_args=elfldr_payload_args(pid))) {
puts("[elfldr.elf] elfldr_args() failed");
kern_set_ucred_caps(pid, caps);
pt_detach(pid);
return -1;
}

r.r_rip = addr;
r.r_rdi = args;
if(pt_setregs(pid, &r)) {
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;
}

puts("[elfldr.elf] running ELF...");
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");
Expand Down
2 changes: 2 additions & 0 deletions payload.h
Expand Up @@ -26,3 +26,5 @@ typedef struct payload_args {
int *payloadout;
} payload_args_t;

typedef void (payload_entry_t)(const payload_args_t *args);

115 changes: 115 additions & 0 deletions payload_launchpad.c
@@ -0,0 +1,115 @@
/* 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
<http://www.gnu.org/licenses/>. */

#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();
}

0 comments on commit f18b415

Please sign in to comment.