Skip to content

Commit

Permalink
Merge pull request #153 from m0rph3us1987/develop
Browse files Browse the repository at this point in the history
Let's debug some ps4 kernel
  • Loading branch information
kiwidoggie authored Jan 5, 2022
2 parents 42775db + b118d93 commit d8cc579
Show file tree
Hide file tree
Showing 13 changed files with 1,712 additions and 3 deletions.
12 changes: 12 additions & 0 deletions kernel/src/Plugins/PS4GDB/syscalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,18 @@ int ps4gdb_sys_bind(int s, int port){
return kbind_t(s, (sockaddr*)&sockadr, sizeof(sockadr), curthread);
}

int ps4gdb_sys_bindt(int s, int port, struct thread *td){
PS4GDB_kbzero();

struct sockaddr_in sockadr;
kbzero(&sockadr, sizeof(sockadr));
sockadr.sin_family = AF_INET;
sockadr.sin_port = htons(port);
sockadr.sin_addr.s_addr = INADDR_ANY;

return kbind_t(s, (sockaddr*)&sockadr, sizeof(sockadr), td);
}

int ps4gdb_sys_listen(int s, int backlog){
return klisten_t(s, backlog, curthread);
}
Expand Down
17 changes: 17 additions & 0 deletions kernel/src/Plugins/PluginManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <Plugins/TTYRedirector/TTYRedirector.hpp>
#include <Plugins/ModuleLoader/ModuleLoader.hpp>
#include <Plugins/PS4GDB/PS4GDB.hpp>
#include <Plugins/RING0GDB/RING0GDB.hpp>

// Utility functions
#include <Utils/Logger.hpp>
Expand Down Expand Up @@ -48,6 +49,7 @@ PluginManager::PluginManager() :
m_FileManager = nullptr;
m_PS4GDB = nullptr;
m_ModuleLoader = nullptr;
m_RING0GDB = nullptr;
}

PluginManager::~PluginManager()
Expand Down Expand Up @@ -180,6 +182,15 @@ bool PluginManager::OnLoad()
s_Success = false;
break;
}

// Initialize RING0GDB
m_RING0GDB = new Mira::Plugins::RING0GDB();
if (m_RING0GDB == nullptr)
{
WriteLog(LL_Error, "could not allocate RING0GDB.");
s_Success = false;
break;
}
} while (false);

if (m_Debugger)
Expand Down Expand Up @@ -254,6 +265,12 @@ bool PluginManager::OnLoad()
WriteLog(LL_Error, "could not load ModuleLoader.");
}

if(m_RING0GDB)
{
if (!m_RING0GDB->OnLoad())
WriteLog(LL_Error, "could not load RING0GDB.");
}

return s_Success;
}

Expand Down
1 change: 1 addition & 0 deletions kernel/src/Plugins/PluginManager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ namespace Mira
Mira::Utils::IModule* m_TTYRedirector;
Mira::Utils::IModule* m_PS4GDB;
Mira::Utils::IModule* m_ModuleLoader;
Mira::Utils::IModule* m_RING0GDB;

public:
Mira::Utils::IModule* GetDebugger() { return m_Debugger; }
Expand Down
190 changes: 190 additions & 0 deletions kernel/src/Plugins/RING0GDB/RING0GDB.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
#include "RING0GDB.hpp"
#include "kdl.h"
#include "log.h"
#include "syscalls.hpp"
#include <Utils/Kdlsym.hpp>
#include <Utils/Kernel.hpp>
#include <Utils/Hook.hpp>

#include <Utils/SysWrappers.hpp>

#include <sys/param.h>
#include <sys/types.h>
#include <sys/filedesc.h>
#include <sys/proc.h>
#include <sys/stdint.h>
#include <sys/fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/mman.h>
#include <sys/unistd.h>
#include <vm/vm.h>
#include <sys/malloc.h>
#include <sys/errno.h>
#include <sys/sx.h>
#include <sys/stat.h>
#include <dirent.h>
#include <sys/sysent.h>

#include <Mira.hpp>
#include <Utils/Kdlsym.hpp>

void gdbstub_set_debug_traps (void);

using namespace Mira::Plugins;

RING0GDB::RING0GDB()
{

}

RING0GDB::~RING0GDB()
{

}

bool RING0GDB::OnLoad()
{
return this->SpawnKproc();
}

bool RING0GDB::OnUnload()
{
return true;
}

bool RING0GDB::OnSuspend()
{
return OnUnload();
}

bool RING0GDB::OnResume()
{
return this->SpawnKproc();
}

void RING0GDB::GetRoot()
{
struct prison **prison0 = NULL;
struct vnode **rootvnode = NULL;
struct thread *td = curthread;

/* Resolve credentials */
struct ucred *cred;
struct filedesc *fd;

fd = td->td_proc->p_fd;
cred = td->td_proc->p_ucred;

/* Escalate process to uid0 */
cred->cr_uid = 0;
cred->cr_ruid = 0;
cred->cr_rgid = 0;
cred->cr_groups[0] = 0;

/* Break out of FreeBSD jail */
prison0 = (struct prison **)kdlsym(prison0);
cred->cr_prison = prison0[0];

/* Set sony auth ID flag */
cred->cr_sceAuthID = 0x3800000000000007ULL;

/* Obtain system credentials for Sony stuff */
cred->cr_sceCaps[0] = 0xffffffffffffffff;
cred->cr_sceCaps[1] = 0xffffffffffffffff;

/* Set vnode to real root "/" to defeat sandbox */
rootvnode = (struct vnode **)kdlsym(rootvnode);
fd->fd_rdir = rootvnode[0];
fd->fd_jdir = rootvnode[0];
}

bool RING0GDB::SpawnKproc()
{
auto kproc_create = (int(*)(void (*func)(void *), void *arg, struct proc **newpp, int flags, int pages, const char *fmt, ...)) kdlsym(kproc_create);
auto kmalloc = (void*(*)(size_t size, struct malloc_type *type, int Flags))kdlsym(malloc);
auto kM_TEMP = (struct malloc_type *)kdlsym(M_TEMP);

struct proc *p = (struct proc*)kmalloc(sizeof(struct proc), kM_TEMP, 0x102);
WriteLog(LL_Info, "RING0GDBMain allocated at: 0x%llx", (uint64_t)p);
WriteLog(LL_Info, "Spawing KprocMain...");
kproc_create(RING0GDB::RING0GDBMain, NULL, &p, 0, 0, "RING0GDB");
return true;
}

struct thread *RING0GDBMainThread;

void RING0GDB::RING0GDBMain(void *)
{
WriteLog(LL_Info, "RING0GDB::RING0GDBMain Getting root...");
RING0GDB::GetRoot();

// create new vmspace
WriteLog(LL_Info, "RING0GDB::RING0GDBMain Creating new vmspace...");
vm_offset_t sv_minuser;
struct vmspace *vmspace;
struct proc *p = curproc;
struct sysentvec *sv = (struct sysentvec *)kdlsym(self_orbis_sysvec);

// allocate user mode virtual space
auto kvmspace_alloc = (struct vmspace*(*)(vm_offset_t min, vm_offset_t max)) kdlsym(vmspace_alloc);
auto kpmap_activate = (void(*)(struct thread *td)) kdlsym(pmap_activate);


sv_minuser = MAX(sv->sv_minuser, PAGE_SIZE);
vmspace = kvmspace_alloc(sv_minuser, sv->sv_maxuser);
if (!vmspace)
{
WriteLog(LL_Error, "RING0GDB::RING0GDBMain Could not allocate new vm space\n");
return;
}

// setup vmspace
WriteLog(LL_Info, "RING0GDB::RING0GDBMain Activate vmspace...");
p->p_vmspace = vmspace;
if (p == curthread->td_proc)
kpmap_activate(curthread);

WriteLog(LL_Info, "RING0GDB::RING0GDBMain Creating stdin/out/err...\n");
kopen_t("/dev/console", O_RDONLY,0, curthread);
kopen_t("/dev/console", O_RDONLY,0, curthread);
kopen_t("/dev/console", O_RDONLY,0, curthread);

WriteLog(LL_Info, "RING0GDB::RING0GDBMain Starting server: PROTOCOL PORT 9946\n");
//Print thread info
struct thread *td = curthread;
/* Resolve credentials */
struct ucred *cred;
cred = td->td_proc->p_ucred;
LOG_DBG("sceAuthID: 0x%llx\n",cred->cr_sceAuthID);
LOG_DBG("cr_sceCaps[0]: 0x%llx\n",cred->cr_sceCaps[0]);
LOG_DBG("cr_sceCaps[1]: 0x%llx\n",cred->cr_sceCaps[1]);
// Start server
LOG_DBG("PID: %d\n", ps4gdb_sys_getpid());

uint8_t idtr[10];
cpu_sidt((struct idt*)&idtr);

uint64_t *base = (uint64_t*)&idtr[2];
uint16_t *limit = (uint16_t*)&idtr[0];

LOG_DBG("kernelbase: 0x%llx\n", (uint8_t*)kernelRdmsr(0xC0000082) - kdlsym_addr_Xfast_syscall);
LOG_DBG("idtr->base: 0x%llx\n", *base);
LOG_DBG("idtr->limit: 0x%llx\n", *limit);

// Setup debug traps
RING0GDBMainThread = curthread;
gdbstub_set_debug_traps();

//Endlessloop here to keep the process alive
PS4GDB_kavcontrol_sleep();
LOG_DBG("Entering main process sleep\n");
int kill_this_process = 0;
while(1){
kavcontrol_sleep(100000);
if(kill_this_process == 1)
break;
}

return;
}
72 changes: 72 additions & 0 deletions kernel/src/Plugins/RING0GDB/RING0GDB.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#pragma once
#include <Utils/IModule.hpp>
#include <Utils/Hook.hpp>
#include <Utils/Kernel.hpp>
#include <Utils/Logger.hpp>
#include <Utils/Kdlsym.hpp>
#include <Utils/SysWrappers.hpp>

#include <Messaging/Rpc/Connection.hpp>
#include <Messaging/Rpc/Connection.hpp>
#include <Messaging/MessageManager.hpp>
#include <Plugins/PluginManager.hpp>

#include <OrbisOS/Utilities.hpp>

#include <Mira.hpp>

extern "C"
{
#include <Messaging/Rpc/rpc.pb-c.h>

#include <sys/uio.h>
#include <sys/proc.h>
#include <sys/ioccom.h>
#include <sys/ptrace.h>
#include <sys/mman.h>
#include <sys/sx.h>
#include <sys/errno.h>
#include <sys/wait.h>
#include <sys/socket.h>

#include <vm/vm.h>
#include <vm/pmap.h>

#include <machine/reg.h>
#include <machine/param.h>
#include <machine/frame.h>
#include <machine/psl.h>
#include <machine/pmap.h>
#include <machine/segments.h>

#include <sys/eventhandler.h>
};

namespace Mira
{
namespace Plugins
{
class RING0GDB : public Utils::IModule
{
public:
RING0GDB();
virtual ~RING0GDB();

virtual const char* GetName() override { return "RING0GDB"; }
virtual const char* GetDescription() override { return "PS4 kernel gdbstub"; }

// Module callbacks
virtual bool OnLoad() override;
virtual bool OnUnload() override;
virtual bool OnSuspend() override;
virtual bool OnResume() override;

protected:
private:
// Necessary methods
static void RING0GDBMain(void *);
bool SpawnKproc();
static void GetRoot();
};
}
}
9 changes: 9 additions & 0 deletions kernel/src/Plugins/RING0GDB/cpu.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.intel_syntax noprefix
.text

.global cpu_sidtRing01

cpu_sidtRing01:
sidt [rdi]
xor rax,rax
ret
Loading

0 comments on commit d8cc579

Please sign in to comment.