PS4 RetailKit Part 2: Mdbg Investigation
Introduction
In this post, I take a deeper look into the PS4's hidden debugging infrastructure, focusing on how the libmdbg_syscore
interface communicates with the kernel and reveals functionality typically reserved for development hardware. Despite Sony’s software based restrictions, I show how much of the mdbg_basic
system remains intact on Retail consoles, and how with the right conditions many debug operations can still be executed successfully.
FUSE: Still Present on Retail
One of the first signs that the Retail PS4 kernel retains dormant debugging infrastructure is the FUSE initialization code. When comparing the Devkit and Retail kernel binaries, I found that the FUSE initialization logic is identical across both. Sony didn’t remove or stub out this part of the system for Retail builds they simply gated its activation behind runtime checks.
Retail:
Devkit:
Here, IsAssistMode
and IsDevelopmentMode
are flags determined from DIP switches via sceKernelCheckDipsw
. On Retail consoles, these switches are not accessible or set, so the condition always fails. Likewise, sceSblAIMgrIsDevKit()
and sceSblAIMgrIsTestKit()
check the IDPS product code to identify the hardware type. These values are hard-coded at the factory and cannot be changed under normal operating conditions so they too always return false on Retail.
This shows that Sony had a clear opportunity to remove FUSE related code entirely from Retail builds, but chose not to. Instead, they relied on environment checks to suppress activation, further reinforcing the idea that Retail and Devkit kernels share far more in common than is often assumed.
libmdbg_syscore
With kernel side debug features like FUSE still intact, the next question was: Where can I find some more of this hidden debug code? That’s where libmdbg_syscore.sprx
comes in. While digging through some documented symbols in this github repository, I came across a set of debug functions with the sceDebug
prefix. These turned out to belong to libmdbg_syscore.sprx
a library likely used to interface with the kernel portion of the debugger.
Curious how this worked under the hood, I started analyzing the binary. I found that it invokes syscall 573, known internally as mdbg_call
, to communicate with the kernel:
I didn’t reverse the structure fully, but it was clear the first buffer (buf_ctrl
) contained a command ID at offset +0x8, and later, also a group ID at +0x0. When examining syscall 573 in the kernel, I found that these groups map to specific dispatch tables with group 1 being mdbg_basic
, the one we care about most.
The structure of mdbg_basic
on Retail matched the Devkit closely but just like FUSE Sony would choose to guard the use of the commands with environment checks and checks to the calling process.
I noticed that every sceDebug
call began by invoking command 30, and looking at the implementation in Retail kernel, there were these access checks:
This means one of the following must be true for the call to succeed:
The calling process is the coredump handler.
The calling process is the debugger and Assist Mode is enabled.
The calling process is syscore.
This matches the behavior on Testkits exactly. Devkits are slightly looser, but the difference is negligible for our purpose.
The good news? This check is trivial to bypass. Changing your process AuthID to that of the debugger (0x3800000000010003
) and enabling Assist Mode allows it through. Looking at other commands like 0x12
(ReadProcessMemory), the same check is repeated so the same bypass works.
Other checks like sceSblACMgrIsDebuggableProcess
, sceSblACMgrIsAllowedSystemLevelDebugging
, or sceSblRcMgrIsAllowULDebugger
that are also present are also easy to patch to always return true
.
Validating and Experimenting
Confident the Retail kernel’s side was intact, I started reversing the userland methods in libmdbg_syscore.sprx
. Without getting too deep into that RE process, here’s a simple test I ran:
Much to my surprise with these new found patches everything would just work.
Some more details on the methods I reversed can be found here.
Conclusion
These findings confirm that Sony’s Retail kernel retains nearly the full debug backend, with mdbg_basic
, FUSE, and associated syscalls all still present and functional just hidden behind environment checks. By mimicking the correct environment and patching a few guard rails, we can unlock a surprising amount of Devkit like functionality on Retail hardware.
In Part 3, we’ll take this a step further by exploring the DECI daemon and what it would take to bring Sony’s official debugger back to life.