mirror of
https://github.com/ps5-payload-dev/elfldr.git
synced 2026-10-19 02:19:52 -05:00
setup stdio for payloads
This commit is contained in:
1 parent
897a79e53c
commit
4add2df892
6 files changed
+179
-17
No files matched your search
+1
-1
@@ -65,7 +65,7 @@ main() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = elfldr_exec(pid, socksrv_elf);
|
||||
ret = elfldr_exec(pid, -1, socksrv_elf);
|
||||
|
||||
// restore privileges
|
||||
if(kernel_set_proc_rootdir(pid, vnode)) {
|
||||
|
||||
@@ -28,6 +28,7 @@ along with this program; see the file COPYING. If not, see
|
||||
#include <sys/socket.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/user.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
@@ -286,6 +287,126 @@ elfldr_load(pid_t pid, uint8_t *elf) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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);
|
||||
mdbg_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;
|
||||
|
||||
mdbg_setlong(pid, hdr + __builtin_offsetof(struct msghdr, msg_name), 0);
|
||||
mdbg_setint(pid, hdr + __builtin_offsetof(struct msghdr, msg_namelen), 0);
|
||||
mdbg_setlong(pid, hdr + __builtin_offsetof(struct msghdr, msg_iov), iov);
|
||||
mdbg_setint(pid, hdr + __builtin_offsetof(struct msghdr, msg_iovlen), 1);
|
||||
mdbg_setlong(pid, hdr + __builtin_offsetof(struct msghdr, msg_control), control);
|
||||
mdbg_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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create payload args in the address space of the process with the given pid.
|
||||
**/
|
||||
@@ -460,7 +581,9 @@ elfldr_set_procname(pid_t pid, const char* name) {
|
||||
* Execute an ELF inside the process with the given pid.
|
||||
**/
|
||||
int
|
||||
elfldr_exec(pid_t pid, uint8_t* elf) {
|
||||
elfldr_exec(pid_t pid, int stdio, uint8_t* elf) {
|
||||
char path[PATH_MAX];
|
||||
|
||||
if(elfldr_raise_privileges(pid)) {
|
||||
puts("[elfldr.elf] Unable to raise privileges");
|
||||
kill(pid, SIGKILL);
|
||||
@@ -468,6 +591,26 @@ elfldr_exec(pid_t pid, uint8_t* elf) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(stdio > 0) {
|
||||
sprintf(path, "/system_tmp/elfldr.%d.sock", pid);
|
||||
stdio = elfldr_stdout(pid, path, stdio);
|
||||
unlink(path);
|
||||
|
||||
if(stdio < 0) {
|
||||
puts("[elfldr.elf] elfldr_stdout() failed");
|
||||
kill(pid, SIGKILL);
|
||||
pt_detach(pid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pt_close(pid, STDERR_FILENO);
|
||||
pt_close(pid, STDOUT_FILENO);
|
||||
|
||||
pt_dup2(pid, stdio, STDOUT_FILENO);
|
||||
pt_dup2(pid, stdio, STDERR_FILENO);
|
||||
pt_close(pid, stdio);
|
||||
}
|
||||
|
||||
if(elfldr_prepare_exec(pid, elf)) {
|
||||
kill(pid, SIGKILL);
|
||||
pt_detach(pid);
|
||||
@@ -488,7 +631,7 @@ elfldr_exec(pid_t pid, uint8_t* elf) {
|
||||
* Execute an ELF inside a new process.
|
||||
**/
|
||||
pid_t
|
||||
elfldr_spawn(uint8_t* elf) {
|
||||
elfldr_spawn(int stdio, uint8_t* elf) {
|
||||
char* argv[] = {"homebrew", 0};
|
||||
uint8_t int3instr = 0xcc;
|
||||
struct kevent evt;
|
||||
@@ -556,6 +699,7 @@ elfldr_spawn(uint8_t* elf) {
|
||||
pt_detach(pid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(mdbg_copyout(pid, brkpoint, &orginstr, sizeof(orginstr))) {
|
||||
perror("[elfldr.elf] mdbg_copyout");
|
||||
kill(pid, SIGKILL);
|
||||
@@ -591,7 +735,7 @@ elfldr_spawn(uint8_t* elf) {
|
||||
|
||||
// Execute the ELF
|
||||
elfldr_set_procname(pid, "homebrew");
|
||||
if(elfldr_exec(pid, elf)) {
|
||||
if(elfldr_exec(pid, stdio, elf)) {
|
||||
perror("[elfldr.elf] pt_detach");
|
||||
kill(pid, SIGKILL);
|
||||
pt_detach(pid);
|
||||
@@ -624,6 +768,7 @@ elfldr_find_pid(const char* name) {
|
||||
|
||||
if(sysctl(mib, 4, buf, &buf_size, 0, 0)) {
|
||||
perror("[elfldr.elf] sysctl");
|
||||
free(buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,6 @@ along with this program; see the file COPYING. If not, see
|
||||
#include <unistd.h>
|
||||
|
||||
pid_t elfldr_find_pid(const char* name);
|
||||
pid_t elfldr_spawn(uint8_t *elf);
|
||||
int elfldr_exec(pid_t pid, uint8_t* elf);
|
||||
pid_t elfldr_spawn(int stdio, uint8_t *elf);
|
||||
int elfldr_exec(pid_t pid, int stdio, uint8_t* elf);
|
||||
|
||||
@@ -294,6 +294,24 @@ pt_close(pid_t pid, int fd) {
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
pt_bind(pid_t pid, int sockfd, intptr_t addr, uint32_t addrlen) {
|
||||
return (int)pt_syscall(pid, SYS_bind, sockfd, addr, addrlen);
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
pt_recvmsg(pid_t pid, int fd, intptr_t msg, int flags) {
|
||||
return (int)pt_syscall(pid, SYS_recvmsg, fd, msg, flags);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
pt_dup2(pid_t pid, int oldfd, int newfd) {
|
||||
return (int)pt_syscall(pid, SYS_dup2, oldfd, newfd);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
pt_pipe(pid_t pid, intptr_t pipefd) {
|
||||
intptr_t faddr = pt_resolve(pid, "-Jp7F+pXxNg");
|
||||
|
||||
@@ -45,8 +45,11 @@ 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,
|
||||
uint32_t optlen);
|
||||
int pt_bind(pid_t pid, int sockfd, intptr_t addr, uint32_t addrlen) ;
|
||||
ssize_t pt_recvmsg(pid_t pid, int fd, intptr_t msg, int flags);
|
||||
|
||||
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);
|
||||
@@ -73,25 +73,20 @@ readsock(int fd) {
|
||||
/**
|
||||
* Process connections in induvidual threads.
|
||||
**/
|
||||
static void*
|
||||
serve_thread(void* args) {
|
||||
int fd = (int)(long)args;
|
||||
static void
|
||||
on_connection(int fd) {
|
||||
uint8_t* elf;
|
||||
|
||||
if(!(elf=readsock(fd))) {
|
||||
close(fd);
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for the ELF magic header
|
||||
if(!memcmp(elf, "\x7f\x45\x4c\x46", 4)) {
|
||||
elfldr_spawn(elf);
|
||||
elfldr_spawn(fd, elf);
|
||||
}
|
||||
|
||||
free(elf);
|
||||
close(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -106,7 +101,6 @@ serve_elfldr(uint16_t port) {
|
||||
struct ifaddrs *ifaddr;
|
||||
int ifaddr_wait = 1;
|
||||
socklen_t socklen;
|
||||
pthread_t trd;
|
||||
int connfd;
|
||||
int srvfd;
|
||||
|
||||
@@ -179,7 +173,9 @@ serve_elfldr(uint16_t port) {
|
||||
perror("[elfldr.elf] accept");
|
||||
break;
|
||||
}
|
||||
pthread_create(&trd, NULL, serve_thread, (void*)(long)connfd);
|
||||
|
||||
on_connection(connfd);
|
||||
close(connfd);
|
||||
}
|
||||
|
||||
return close(srvfd);
|
||||
|
||||
Reference in new issue
Block a user