Big corporations often bring us cool electronic devices like:
When you want to analyze one of these cool electronic devices, you need to do a research, to get all public information available about it like:
Sometimes devices use propietary operating systems and libraries, but lately, almost all are based on different linux or bsd flavours and many open source libraries. Is that bad? Of course not, a lot of money saving with it, but security is an important issue and must be an important point at design time. Don't you?
All big corporations should have a security department, with different security technical profiles, tracking all security issues about a device from the begining of the project. It is very important for a good service level for final customers and also to avoid marketing disasters related to security issues.
One of the gold rule/best practice is called Security by Design. Involving security guys from early stages of the project, and analyzing in each stage all issues related to security from different points of view to avoid future problems and mitigate risks is a must have. Of course other best practice can be the teams who check security issues should be different from development teams who are making the code.
I speak about mitigation, because eliminate all risks is impossible. You should need leave device inside a faraday jail, of course without internet connection and without final user using it, and never power on the device to eliminate only some risks xD.
I am engineer, and sometimes some engineers when they design a device, they believe that people will use their devices only how they were designed, without considering that factor, the Final User's factor. People will use the device and some of them can do things that will change the normal expected execution conditions. Without considering that behaviour, you will have a bad design from the point of view of security. Remember mitigate.
A good risk management and of course costs will decide which measures must be considered in each stage of the project, for a right risks mitigation.
It's an art for me. The art of know how things are done without full information about who or about how was made/coded/manufactured it.
Which is my experience/background in this field?
I am 45 years old and since 80's i have done things with different platforms/devices in personal life:
First of all we will try answer the initial questions:
We need access to decrypted kernels from different firmware versions but you can dump yourself with proper tools.
I have different PlayStation 4 consoles with different firmwares from 1.05,1.76,4.x,5.05,and one always in last firmware to play with games.
Next is time to use ida/ghidra to get a lot of fun. Kernel from 1.05 has almost all symbols intact so is pure gold, let to translate/look for functions to compare with other firmware versions without symbols easily and you can track the changes from one version to other.
Sony has basically 3 different console flavours:
Well the best is go to the source: libfuse project
But better go to freebsd flavour:
Advice: download a 10.3 freebsd vanilla to avoid problems with deprecated port version for newbies. The first cd iso is enough to get a fresh vm to play with fuse stuff and jails.
So a good challenge, let's the game begin!!!
Freebsd kernel modules can be loaded/unloaded in vanilla freebsd with kldload/kldunload utils in command line. We will check the kernel module included already on freebsd kernel and different modification of it to add some features for jails and from greater versions and to mimic the PlayStation 4 behaviour, it will help to trace problems and understand how stuff is done.
root@bigfree10:~ # kld
kldconfig kldload kldstat kldunload kldxref
root@bigfree10:~ # kldstat
Id Refs Address Size Name
1 1 0xffffffff80200000 17bcd08 kernel
root@bigfree10:~ # kldload fuse
root@bigfree10:~ # kldstat
Id Refs Address Size Name
1 3 0xffffffff80200000 17bcd08 kernel
2 1 0xffffffff81a11000 df9a fuse.ko
root@bigfree10:~ # lsvfs
Filesystem Num Refs Flags
-------------------------------- ---------- ----- ---------------
devfs 0x00000071 1 synthetic, jail
ufs 0x00000035 1
msdosfs 0x00000032 0
nfs 0x0000003a 0 network
cd9660 0x000000bd 0 read-only
procfs 0x00000002 0 synthetic, jail
fusefs 0x000000ed 0 synthetic
root@bigfree10:/usr/src/sys/fs/fuse # kldunload fuse
root@bigfree10:/usr/src/sys/fs/fuse # lsvfs
Filesystem Num Refs Flags
-------------------------------- ---------- ----- ---------------
devfs 0x00000071 1 synthetic, jail
ufs 0x00000035 1
msdosfs 0x00000032 0
nfs 0x0000003a 0 network
cd9660 0x000000bd 0 read-only
procfs 0x00000002 0 synthetic, jail
root@bigfree10:~ # cd /usr/src/sys/fs/fuse
root@bigfree10:/usr/src/sys/fs/fuse # ls
@ fuse_internal.c fuse_node.h
Makefile fuse_internal.h fuse_node.o
export_syms fuse_internal.o fuse_param.h
fuse.h fuse_io.c fuse_vfsops.c
fuse.ko fuse_io.h fuse_vfsops.o
fuse.ko.debug fuse_io.o fuse_vnops.c
fuse.ko.symbols fuse_ipc.c fuse_vnops.o
fuse_debug.h fuse_ipc.h machine
fuse_device.c fuse_ipc.o salida.txt
fuse_device.o fuse_kernel.h vnode_if.h
fuse_file.c fuse_main.c vnode_if_newproto.h
fuse_file.h fuse_main.o vnode_if_typedef.h
fuse_file.o fuse_node.c x86
root@bigfree10:/usr/src/sys/fs/fuse # kldload ./fuse.ko
root@bigfree10:/usr/src/sys/fs/fuse # kldstat
Id Refs Address Size Name
1 3 0xffffffff80200000 17bcd08 kernel
2 1 0xffffffff81a11000 d38d fuse.ko
root@bigfree10:/usr/src/sys/fs/fuse # lsvfs
Filesystem Num Refs Flags
-------------------------------- ---------- ----- ---------------
devfs 0x00000071 1 synthetic, jail
ufs 0x00000035 1
msdosfs 0x00000032 0
nfs 0x0000003a 0 network
cd9660 0x000000bd 0 read-only
procfs 0x00000002 0 synthetic, jail
fusefs 0x000000ed 0 synthetic, jail
We are in PlayStation 4 retail so no command line available obviously. No problem, there is api in kernel land to make the same. But... hey 5.05 kernel on retail has many kld functions in not implemented mode so return always 0x4e aka ENOSYS fuck!!!, devkit kernel has it implemented. It could be a problem if fuse kernel module was not implemented in kernel land on retail. But lucky you it is implemented in kernel and fuse_loader function is waiting for us at offset 0x49DDB0 in 5.05. So we only need some patches to some functions to call fuse_loader and if all is fine it must be return 0.
I got some problems when i was tryng to open/create fuse device although module was loaded fine, after some research i found the function needed to patch to avoid the fucking EPERM retur code xD. Example fuse_device_open available at offset 0x4A2850:
static int fuse_device_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
{
struct fuse_data *fdata;
if(sceSblACMgrIsDebuggerProcess(td->td_ucred))
{
result=ENXIO; //6
if(dev->si_usecount>=2)
{
result=EBUSY;//16
if(dev->si_usecount==2)
{
result=0;
mtx_lock_flags(&fuse_mtx,0,__FUNCTION__,__LINE__);
if(fuse_get_devdata(dev)) //dev->si_drv1
{
fdata->dataflags|=0x8000; //fdata+33=|0x80
mtx_unlock_sleep(&fuse_mtx,0,__FUNCTION__,__LINE__);
}
else
{
mtx_unlock_sleep(&fuse_mtx,0,__FUNCTION__,__LINE__);
result=ENXIO;//6
}
}
}
}
else if(sceSblACMgrIsSyscoreProcess(td->td_ucred))
{
result=EBUSY;
if(dev->si_usecount<=1)
{
fdata = fdata_alloc(dev, td->td_ucred);
mtx_lock_flags(&fuse_mtx,0,__FUNCTION__,__LINE__);
if(fuse_get_devdata(dev)) //dev->si_drv1
{
fdata_trydestroy(fdata);
mtx_unlock_sleep(&fuse_mtx,0,__FUNCTION__,__LINE__);
}
else
{
fdata->dataflags |= FSESS_OPENED;//2
dev->si_drv1 = fdata;
mtx_unlock_sleep(&fuse_mtx,0,__FUNCTION__,__LINE__);
result=0;
}
}
}
else
{
result=EPERM; //1 FUCKING EPERM Operation not permitted on vanilla ps4 retail
}
return result;
}
So patches needed on 5.05 are:
int *ksuser_enabled=(int *)(kernel_base+0x2300B88);
struct vfsconf *p=(struct vfsconf *)(kernel_base + 0x19FC380 );
//suser_enabled in priv_check_cred
*ksuser_enabled=1;
//add jail friendly for fuse file system
p->vfc_flags=0x00400000 | 0x00080000;
//avoid enforce_dev_perms checks
//*kfuse_enforce_dev_perms=0;
//default prison_priv_check to 0
kernel_ptr[0x3B219E]=0;
//skip devkit/testkit/dipsw check in fuse_loader
kernel_ptr[0x49DDDE] = 0xEB;
kernel_ptr[0x49DDDF] = 0x1B;
//skip sceSblACMgrIsSyscoreProcess check in fuse_open_device
kernel_ptr[0x4A28EE] = 0xEB;
kernel_ptr[0x4A28EF] = 0x0;
//skip sceSblACMgrIsDebuggerProcess/sceSblACMgrIsSyscoreProcess check in fuse_close_device
kernel_ptr[0x4A29E2] = 0xEB;
//skip sceSblACMgrIsDebuggerProcess/sceSblACMgrIsSyscoreProcess check in fuse_poll_device
kernel_ptr[0x4A2F34] = 0xEB;
// skip sceSblACMgrIsSyscoreProcess check in fuse_vfsop_mount
kernel_ptr[0x4A30F7] = 0xEB;
kernel_ptr[0x4A30F8] = 0x04;
// skip sceSblACMgrIsMinisyscore/unknown check in fuse_vfsop_unmount
kernel_ptr[0x4A384C] = 0xEB;
kernel_ptr[0x4A384D] = 0x00;
// skip sceSblACMgrIsSystemUcred check in fuse_vfsop_statfs
kernel_ptr[0x4A3BED] = 0xEB;
kernel_ptr[0x4A3BEE] = 0x04;
And for call fuse_loader:
printfkernel("load kernel module FUSEFS\n");
// load FUSEFS module
int (*fuse_loader)(void* m, int op, void* arg)=(void *)(kernel_base + 0x49DDB0);
printfkernel("calling fuse_loader\n");
kernel_ptr[0x4A27FC]=0xB6; <-----let create fuse device with rw-rw-rw
ret=fuse_loader(NULL, 0, NULL);
printfkernel(" fuse_loader return %d\n",ret);
Choose the best stable way to apply patches. You will have inestability/panic issues without a proper conditional hook system, avoid permanent patches in common functions or you can get a lot of panics.
For libfuse try to use 2.8.6 release. For liborbis minimal changes are needed mainly avoid forking stuff and calling external mount_fusefs tool not available on retail in mount_bsd.c. We will do it in kernel land with special function.
We will use fuse-nfs but threre are plenty of options availables. This in particular needs libnfs.
For libnfs try all first in vanilla freebsd. Build will generate rpc functions on fly, so it is better to generate all first and then get the .c and .h files for liborbis. Problem found was that there are some functions not availables in c implementation on PlayStation 4. You cand avoid it in rpc_connect_sockaddr_async in socket.c instead of use getservbyport you can control the ports negotiation and retry until is fine, check on freebsd vanilla first. It is important here get access to backport traces on panics to fix things and network logs from debugnet on liborbis.
No PlayStation 4 were harmed in the making of the stuff described in this article, many reboots only :P
December 2019