Skip to content

Commit

Permalink
fix #2 and a few other things
Browse files Browse the repository at this point in the history
  • Loading branch information
jogolden committed Jul 23, 2018
1 parent 63c5040 commit aec9759
Show file tree
Hide file tree
Showing 10 changed files with 137 additions and 72 deletions.
6 changes: 5 additions & 1 deletion debugger/include/net.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@

#define NET_MAX_LENGTH 8192

#define SO_NOSIGPIPE 0x0800
#define SO_USELOOPBACK 0x0040 /* bypass hardware when possible */
#define SO_LINGER 0x0080 /* linger on close if data present */
#define SO_NOSIGPIPE 0x0800 /* no SIGPIPE from EPIPE */
#define SO_SNDBUF 0x1001 /* send buffer size */
#define SO_RCVBUF 0x1002 /* receive buffer size */

// I would like to move away from the stupid sony wrapper functions
// They do not always return what I expect and I want to use straight syscalls
Expand Down
1 change: 1 addition & 0 deletions debugger/include/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#define SERVER_PORT 744

// this will block
void configure_socket(int fd, int buffersize);
void start_server();

#endif
79 changes: 43 additions & 36 deletions debugger/source/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,6 @@

struct debug_context dbgctx;

int connect_debugger() {
struct sockaddr_in server;

server.sin_len = sizeof(server);
server.sin_family = AF_INET;
server.sin_addr.s_addr = dbgctx.client.sin_addr.s_addr;
server.sin_port = sceNetHtons(DBG_PORT);
memset(server.sin_zero, NULL, sizeof(server.sin_zero));

dbgctx.clientfd = sceNetSocket("interrupt", AF_INET, SOCK_STREAM, 0);
if(dbgctx.clientfd <= 0) {
return 1;
}

errno = NULL;
int r = sceNetConnect(dbgctx.clientfd, (struct sockaddr *)&server, sizeof(server));
if(r) {
return 1;
}

return 0;
}

int debug_attach_handle(int fd, struct cmd_packet *packet) {
struct cmd_debug_attach_packet *ap;
int r;
Expand Down Expand Up @@ -85,7 +62,6 @@ int debug_detach_handle(int fd, struct cmd_packet *packet) {
int debug_breakpt_handle(int fd, struct cmd_packet *packet) {
struct cmd_debug_breakpt_packet *bp;
uint8_t int3;
uint8_t original;

bp = (struct cmd_debug_breakpt_packet *)packet->data;

Expand All @@ -110,15 +86,15 @@ int debug_breakpt_handle(int fd, struct cmd_packet *packet) {
breakpoint->enabled = 1;
breakpoint->address = bp->address;

sys_proc_rw(dbgctx.pid, breakpoint->address, &original, 1, 0);
breakpoint->original = original;
sys_proc_rw(dbgctx.pid, breakpoint->address, &breakpoint->original, 1, 0);

int3 = 0xCC;
sys_proc_rw(dbgctx.pid, breakpoint->address, &int3, 1, 1);
} else {
sys_proc_rw(dbgctx.pid, breakpoint->address, &breakpoint->original, 1, 1);

breakpoint->enabled = 0;
breakpoint->address = NULL;
sys_proc_rw(dbgctx.pid, breakpoint->address, &breakpoint->original, 1, 0);
}

net_send_status(fd, CMD_SUCCESS);
Expand Down Expand Up @@ -482,30 +458,61 @@ int debug_stopgo_handle(int fd, struct cmd_packet *packet) {
return 0;
}

int connect_debugger() {
struct sockaddr_in server;

server.sin_len = sizeof(server);
server.sin_family = AF_INET;
server.sin_addr.s_addr = dbgctx.client.sin_addr.s_addr;
server.sin_port = sceNetHtons(DBG_PORT);
memset(server.sin_zero, NULL, sizeof(server.sin_zero));

dbgctx.clientfd = sceNetSocket("interrupt", AF_INET, SOCK_STREAM, 0);
if(dbgctx.clientfd <= 0) {
return 1;
}

errno = NULL;
int r = sceNetConnect(dbgctx.clientfd, (struct sockaddr *)&server, sizeof(server));
if(r) {
return 1;
}

return 0;
}

void debug_cleanup() {
struct __dbreg64 dbreg64;
uint32_t *lwpids;
int nlwps;
int r;

if(dbgctx.pid != -1) {
// disable all breakpoints
for(int i = 0; i < MAX_BREAKPOINTS; i++) {
sys_proc_rw(dbgctx.pid, dbgctx.breakpoints[i].address, &dbgctx.breakpoints[i].original, 1, 1);
}

// reset all debug registers
nlwps = ptrace(PT_GETNUMLWPS, dbgctx.pid, NULL, 0);
lwpids = (uint32_t *)malloc(nlwps * sizeof(uint32_t));

memset(&dbreg64, NULL, sizeof(struct __dbreg64));

r = ptrace(PT_GETLWPLIST, dbgctx.pid, (void *)lwpids, nlwps);
if(!r) {
for(int i = 0; i < nlwps; i++) {
ptrace(PT_SETDBREGS, lwpids[i], &dbreg64, NULL);
if(lwpids) {
memset(&dbreg64, NULL, sizeof(struct __dbreg64));

r = ptrace(PT_GETLWPLIST, dbgctx.pid, (void *)lwpids, nlwps);

if(!r) {
for(int i = 0; i < nlwps; i++) {
ptrace(PT_SETDBREGS, lwpids[i], &dbreg64, NULL);
}
}
}

free(lwpids);
free(lwpids);
}

ptrace(PT_CONTINUE, dbgctx.pid, (void *)1, NULL);
ptrace(PT_DETACH, dbgctx.pid, NULL, NULL);

sceNetSocketClose(dbgctx.clientfd);
dbgctx.pid = dbgctx.clientfd = -1;
}
Expand Down
2 changes: 2 additions & 0 deletions debugger/source/kern.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

#include "kern.h"

// todo: same as proc.c with the read/write functions, send as chunks

int kern_base_handle(int fd, struct cmd_packet *packet) {
uint64_t kernbase;

Expand Down
6 changes: 4 additions & 2 deletions debugger/source/net.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@ int net_send_data(int fd, void *data, int length) {
sent = write(fd, data + offset, left);
}

if (sent <= 0 && errno && errno != EWOULDBLOCK) {
return sent;
if (sent <= 0) {
if(errno && errno != EWOULDBLOCK) {
return sent;
}
} else {
offset += sent;
left -= sent;
Expand Down
1 change: 0 additions & 1 deletion debugger/source/proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,6 @@ int proc_info_handle(int fd, struct cmd_packet *packet) {

size = args.num * sizeof(struct proc_vm_map_entry);

// todo: find a better way than allocating so much space
args.maps = (struct proc_vm_map_entry *)malloc(size);
if(!args.maps) {
net_send_status(fd, CMD_DATA_NULL);
Expand Down
2 changes: 1 addition & 1 deletion debugger/source/ptrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ int ptrace(int req, int pid, void *addr, int data) {

r = syscall(26, req, pid, addr, data);

uprintf("ptrace(req %i, pid %i, addr 0x%llX, data 0x%X) = %i (errno %i)", req, pid, addr, data, r, errno);
//uprintf("ptrace(req %i, pid %i, addr 0x%llX, data 0x%X) = %i (errno %i)", req, pid, addr, data, r, errno);

return r;
}
Expand Down
97 changes: 72 additions & 25 deletions debugger/source/server.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ int cmd_handler(int fd, struct cmd_packet *packet) {
int check_debug_interrupt() {
char lwpinfo[0x98];
struct debug_interrupt_packet *resp;
struct debug_breakpoint *breakpoint;
uint8_t int3;
int status;
int signal;
int r;
Expand All @@ -51,7 +53,7 @@ int check_debug_interrupt() {
uprintf("[ps4debug] sent final SIGKILL");
return 0;
}

resp = (struct debug_interrupt_packet *)malloc(DEBUG_INTERRUPT_PACKET_SIZE);
if(!resp) {
uprintf("[ps4debug] could not allocate interrupt response");
Expand All @@ -73,14 +75,49 @@ int check_debug_interrupt() {
//ptrace(PT_GETFPREGS, resp->lwpid, &resp->fpreg64, NULL);
//ptrace(PT_GETDBREGS, resp->lwpid, &resp->dbreg64, NULL);

// if it is a software breakpoint we need to handle it accordingly
breakpoint = NULL;
for(int i = 0; i < MAX_BREAKPOINTS; i++) {
if(dbgctx.breakpoints[i].address == resp->reg64.r_rip - 1) {
breakpoint = &dbgctx.breakpoints[i];
break;
}
}

if(breakpoint) {
uprintf("[ps4debug] dealing with software breakpoint");
uprintf("[ps4debug] breakpoint: %llX %X", breakpoint->address, breakpoint->original);

// write old instruction
sys_proc_rw(dbgctx.pid, breakpoint->address, &breakpoint->original, 1, 1);

// todo: clean this up

resp->reg64.r_rip -= 1;
ptrace(PT_SETREGS, resp->lwpid, &resp->reg64, NULL);

ptrace(PT_STEP, resp->lwpid, (void *)1, NULL);

while(!wait4(dbgctx.pid, &status, WNOHANG, NULL)) {
sceKernelUsleep(40000);
}

//uprintf("waited for signal %i", WSTOPSIG(status));

int3 = 0xCC;
sys_proc_rw(dbgctx.pid, breakpoint->address, &int3, 1, 1);
} else {
uprintf("[ps4debug] dealing with hardware breakpoint");
}

r = net_send_data(dbgctx.clientfd, resp, DEBUG_INTERRUPT_PACKET_SIZE);
if(r != DEBUG_INTERRUPT_PACKET_SIZE) {
uprintf("[ps4debug] net_send_data failed %i %i", r, errno);
}

uprintf("[ps4debug] check_debug_interrupt interrupt data sent");

free(resp);

uprintf("[ps4debug] check_debug_interrupt interrupt data sent");
}

return 0;
Expand Down Expand Up @@ -206,10 +243,37 @@ int handle_client(int fd, struct sockaddr_in *client) {
return 0;
}

void configure_socket(int fd, int buffersize) {
int flag;

flag = 1;
sceNetSetsockopt(fd, SOL_SOCKET, SO_NBIO, (char *)&flag, sizeof(flag));

flag = 1;
sceNetSetsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(flag));

flag = 1;
sceNetSetsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, (char *)&flag, sizeof(flag));

flag = 0;
sceNetSetsockopt(fd, SOL_SOCKET, SO_LINGER, (char *)&flag, sizeof(flag));

//flag = 0;
//sceNetSetsockopt(fd, SOL_SOCKET, SO_USELOOPBACK, (char *)&flag, sizeof(flag));

if(buffersize) {
flag = NET_MAX_LENGTH;
sceNetSetsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *)&flag, sizeof(flag));

flag = NET_MAX_LENGTH;
sceNetSetsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *)&flag, sizeof(flag));
}
}

void start_server() {
struct sockaddr_in server;
struct sockaddr_in client;
int serv, fd, flag;
int serv, fd;
unsigned int len = sizeof(client);

uprintf("[ps4debug] server started");
Expand All @@ -222,19 +286,10 @@ void start_server() {
memset(server.sin_zero, 0, sizeof(server.sin_zero));

// start up server
// todo: error checking
serv = sceNetSocket("debugserver", AF_INET, SOCK_STREAM, 0);

flag = 1;
sceNetSetsockopt(serv, SOL_SOCKET, SO_NBIO, (char *)&flag, sizeof(int));

flag = 1;
sceNetSetsockopt(serv, SOL_SOCKET, SO_NOSIGPIPE, (char *)&flag, sizeof(int));

flag = 1;
sceNetSetsockopt(serv, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int));

configure_socket(serv, 0);
sceNetBind(serv, (struct sockaddr *)&server, sizeof(server));

sceNetListen(serv, 4);

while(1) {
Expand All @@ -243,17 +298,9 @@ void start_server() {
errno = NULL;
fd = sceNetAccept(serv, (struct sockaddr *)&client, &len);
if(fd > -1 && !errno) {
uprintf("[ps4debug] accepted a client");
uprintf("[ps4debug] accepted a new client");

flag = 1;
sceNetSetsockopt(fd, SOL_SOCKET, SO_NBIO, (char *)&flag, sizeof(int));

flag = 1;
sceNetSetsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, (char *)&flag, sizeof(int));

flag = 1;
sceNetSetsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int));

configure_socket(fd, 1);
handle_client(fd, &client);
}

Expand Down
11 changes: 7 additions & 4 deletions installer/source/installer.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,13 @@ void *allocate_rwx_memory(uint64_t size) {

void *memory = (void *)kmem_alloc(*kernel_map, alignedSize);

cpu_disable_wp();
*(uint8_t *)(kernbase + __kmem_alloc_p1) = VM_PROT_DEFAULT;
*(uint8_t *)(kernbase + __kmem_alloc_p2) = VM_PROT_DEFAULT;
cpu_enable_wp();
// interesting comment here
// ChendoChap fucked up when updating my old jkpatch framework
// so for backwards compat. we need to keep this patched
//cpu_disable_wp();
//*(uint8_t *)(kernbase + __kmem_alloc_p1) = VM_PROT_DEFAULT;
//*(uint8_t *)(kernbase + __kmem_alloc_p2) = VM_PROT_DEFAULT;
//cpu_enable_wp();

return memory;
}
Expand Down
4 changes: 2 additions & 2 deletions kdebugger/source/installer.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ int load_payload(struct proc *p) {
struct vm_map *map = &vm->vm_map;

vm_map_lock(map);
r = vm_map_insert(map, NULL, NULL, 0x926200000, 0x926200000 + 0x300000, VM_PROT_ALL, VM_PROT_ALL, 0);
r = vm_map_insert(map, NULL, NULL, 0x926200000, 0x926200000 + 0x400000, VM_PROT_ALL, VM_PROT_ALL, 0);
vm_map_unlock(map);

if(r) {
return r;
}

return proc_write_mem(p, (void *)0x926200000, cbdbg, bdbg, 0);
return proc_write_mem(p, (void *)0x926200000, cbdbg, bdbg, NULL);
}

int exec_payload(struct proc *p) {
Expand Down

0 comments on commit aec9759

Please sign in to comment.