Join Us and become a Member for a Verified Badge to access private areas with the latest PS4 PKGs.
Status
Not open for further replies.
Following Fail0verflow's PS4 Aux Hax Parts 1-3 and PS4 Aux Hax Part 4 from 2018, some PS4 EMC Firmware findings and Volodymyr Pikhur (aka VPikhur)'s numerous contributions in the PlayStation 4 Scene developer @zecoxao shared via Twitter a PS4 EMC CFW Steps: Phat CUH-1000 and CUH-1100 Guide alongside some PS4 Aeolia EMC CFW Buzzer (Infernal Beep) footage from his (C)ontrol e(X)ecute YouTube Channel since the previous Toggle_QA.PKG / PS4-Flag_Enabler.bin Payload WIPs and QA Flags / Utoken Flags demonstration videos. :geek:

To recap briefly, for those unfamiliar with Volodymyr Pikhur (aka VPikhur)'s past contributions in the PlayStation 4 Scene some highlights include being credited for PS4 Southbridge Processor work with EAP / EMC (PS5 EMC UART Pinouts) via side-channel analysis, glitching and ROM recovery in his PS4 IPL AES + HMAC Key Recovery project, a PS4 Presentation at Recon Brussels 2018 (PS4 Rest Mode REcon Slideshow PDF) discussing the custom PS4 Southbridge silicon's security failures and sharing PS4 APU Floor Plan High-Resolution Die Shots (following PS4 Syscon High-Res Images and prior to the PS5 SoC / APU / SSD-Controller Die-Shots) at Toorcon 2019.

:alert: Before getting overly excited about PS4 External Micro Controller CFW and diving in to control the Southbridge and Syscon for fan temperature limits, buzzer experimenting and LEDs, it's important to note Rebug developer @Abkarino stated on PS4 EMC Custom Firmware via Twitter, to quote:

"Forget it, it is just a CFW for EMC (PS4 Southbridge) that work during sleep mode it is not a CFW like you think."

:arrow: While kd_tech_ reminds everyone on Twitter in addition to the Patches Required, to quote:

"Yep this was done in 2018 and the keys have been posted on psdevwiki yet people are stupid 🤷‍♂️"

Buzzers 1 to 6

Short video describing the buzzers 1 2 3 4 5 and 6 from ps4 aeolia emc cfw. buzzer number 7 is special and requires a hard unplug of the power wire. i'll detail it more soon...


Buzzer 7 (Infernal Beep)

The last buzzer, buzzer 7, is probably the worst. It's an infinite beep, it never stops unless you unplug the power cord. There is also buzzer 0 but i suspect it's the same as no beep or buzzer 1.


⚠️ For those still interested in proceeding, from zecoxao comes the PS4 EMC CFW Steps: Phat CUH-1000 and CUH-1100 Guide to quote: USE AT YOUR RISK

EMC CFW Steps: Phat CUH-1000 and CUH-1100

Tools required:

  • Hardware flasher;
  • Testpoints for Mediacon Interaction (see Jaicrab's page)
  • JaiBrute v2 (see Jaicrab's page)
  • Scripts from the wiki (decrypt and encrypt EMC from MediaCon)
  • Hexeditor (I use HxD for this)
  • Wires (preferably some with black tip, so you can plug them nicely)
  • Soldering Iron (advised TS100)
  • Solder paste and solder
  • UART device (CP2102 advised or an equivalent)
  • 2BLS unpacker (either a python script something else to unpack bls entries)
Tutorial:

Step 1:

  • Using the hardware flasher, dump the sflash to a file (for example sflash0.bin), or if you're on a hacked system, simply dump sflash0 from /dev/sflash0
  • Keep this backup somewhere safe! Make sure you do multiple backups and verify they're the exact same!
Step 2:
  • At offset 0x4000 you can find the first bls entry for emc fw (size 0x60000)
  • At offset 0x64000 you can find the second bls entry for emc fw (size 0x60000)
  • Using HxD, select those entries and place them on the files sflash0s0x32 and sflash0s0x32b
Step 3:
  • Unpack those files using a bls unpacker for 2bls files. You'll obtain C0000001 and C0008001
  • Discard C0008001. we'll only work with C0000001.
Step 4:
Code:
import struct
from binascii import unhexlify as uhx
from binascii import hexlify as hx
from Crypto.Cipher import AES
from Crypto.Hash import SHA, HMAC

import os
import sys

CIPHERKEYSEMC = ['5F74FE7790127FECF82CC6E6D91FA2D1'] # FULL
CIPHERKEYSEAP = ['581A75D7E9C01F3C1BD7473DBD443B98']
HASHERKEYEMC  = ['73FE06F3906B05ECB506DFB8691F9F54']
HASHERKEYEAP  = ['824D9BB4DBA3209294C93976221249E4']
ZEROS128 =      ['00000000000000000000000000000000']

def aes_decrypt_cbc(key, iv, input):
    return AES.new(key, AES.MODE_CBC, iv).decrypt(input)
 
def aes_encrypt_cbc(key, iv, input):
    return AES.new(key, AES.MODE_CBC, iv).encrypt(input)

def emc_decrypt_header(hdr):
    return hdr[:0x30] + aes_decrypt_cbc(uhx(CIPHERKEYSEMC[0]), uhx(ZEROS128[0]), hdr[0x30:0x80])
 
def emc_encrypt_header(hdr):
    return hdr[:0x30] + aes_encrypt_cbc(uhx(CIPHERKEYSEMC[0]), uhx(ZEROS128[0]), hdr[0x30:0x80])
 
def eap_decrypt_header(hdr):
    return hdr[:0x30] + aes_decrypt_cbc(uhx(CIPHERKEYSEAP[0]), uhx(ZEROS128[0]), hdr[0x30:0x80])
 
def eap_encrypt_header(hdr):
    return hdr[:0x30] + aes_encrypt_cbc(uhx(CIPHERKEYSEAP[0]), uhx(ZEROS128[0]), hdr[0x30:0x80])

def main(argc, argv):
        with open(sys.argv[1], 'rb') as f:
            data = f.read(0x80)
            type = data[7:8]
            if type == uhx('48'):
                print 'EMC'
                hdr = emc_decrypt_header(data)
                body_aes_key  = hdr[0x30:0x40]
                body_hmac_key = hdr[0x40:0x50]
                body_hmac = hdr[0x50:0x64]
                zeroes = hdr[0x64:0x6C]
                print(hx(zeroes))
                header_hmac = hdr[0x6C:0x80]
                body_len = struct.unpack('<L', hdr[0xc:0x10])[0]
                print body_len
                ehdr = hdr[:0x6C]
                ebody = f.read(body_len)
                bhmac = HMAC.new(body_hmac_key, ebody, SHA)
                hhmac = HMAC.new(uhx(HASHERKEYEMC[0]), ehdr, SHA)
                body = aes_decrypt_cbc(body_aes_key, uhx(ZEROS128[0]), ebody)
                print bhmac.hexdigest()
                print hhmac.hexdigest()
                print hx(body_hmac)
                print hx(header_hmac)
                with open(sys.argv[1] + '.bin', 'wb') as g:
                    g.write(hdr+body)
            if type == uhx('68'):
                print 'EAP'
                hdr = eap_decrypt_header(data)
                body_aes_key  = hdr[0x30:0x40]
                body_hmac_key = hdr[0x40:0x50]
                body_hmac = hdr[0x50:0x64]
                zeroes = hdr[0x64:0x6C]
                print(hx(zeroes))
                header_hmac = hdr[0x6C:0x80]
                body_len = struct.unpack('<L', hdr[0xc:0x10])[0]
                print body_len
                ehdr = hdr[:0x6C]
                ebody = f.read(body_len)
                bhmac = HMAC.new(body_hmac_key, ebody, SHA)
                hhmac = HMAC.new(uhx(HASHERKEYEAP[0]), ehdr, SHA)
                body = aes_decrypt_cbc(body_aes_key, uhx(ZEROS128[0]), ebody)
                print bhmac.hexdigest()
                print hhmac.hexdigest()
                print hx(body_hmac)
                print hx(header_hmac)
                with open(sys.argv[1] + '.bin', 'wb') as g:
                    g.write(hdr+body)
 
 

if __name__ == '__main__':
    main(len(sys.argv), sys.argv)
Step 5:
  • Open the new file and change
  • ALL instances of 03 00 FD 00 with 0F 00 FD 00 (for 5.05 emc there are 3 or 4 instances) and
  • ALL instances of 07 00 FD 00 with 0F 00 FD 00 (for 5.05 emc there are 96 instances)
Step 6:
Code:
import struct
from binascii import unhexlify as uhx
from binascii import hexlify as hx
from Crypto.Cipher import AES
from Crypto.Hash import SHA, HMAC

import os
import sys

CIPHERKEYSEMC = ['5F74FE7790127FECF82CC6E6D91FA2D1'] # FULL
CIPHERKEYSEAP = ['581A75D7E9C01F3C1BD7473DBD443B98']
HASHERKEYEMC  = ['73FE06F3906B05ECB506DFB8691F9F54']
HASHERKEYEAP  = ['824D9BB4DBA3209294C93976221249E4']
ZEROS128 =      ['00000000000000000000000000000000']

def aes_decrypt_cbc(key, iv, input):
    return AES.new(key, AES.MODE_CBC, iv).decrypt(input)
 
def aes_encrypt_cbc(key, iv, input):
    return AES.new(key, AES.MODE_CBC, iv).encrypt(input)

def emc_decrypt_header(hdr):
    return hdr[:0x30] + aes_decrypt_cbc(uhx(CIPHERKEYSEMC[0]), uhx(ZEROS128[0]), hdr[0x30:0x80])
 
def emc_encrypt_header(hdr):
    return hdr[:0x30] + aes_encrypt_cbc(uhx(CIPHERKEYSEMC[0]), uhx(ZEROS128[0]), hdr[0x30:])
 
def eap_decrypt_header(hdr):
    return hdr[:0x30] + aes_decrypt_cbc(uhx(CIPHERKEYSEAP[0]), uhx(ZEROS128[0]), hdr[0x30:0x80])
 
def eap_encrypt_header(hdr):
    return hdr[:0x30] + aes_encrypt_cbc(uhx(CIPHERKEYSEAP[0]), uhx(ZEROS128[0]), hdr[0x30:0x80])

def main(argc, argv):
        with open(sys.argv[1], 'rb') as f:
            data = f.read()
            type = data[7:8]
            if type == uhx('48'):
                print 'EMC'
 
                body_len = struct.unpack('<L', data[0xc:0x10])[0]
                body = data[0x80:0x80+body_len]
                body_aes_key  = data[0x30:0x40]
                ebody = aes_encrypt_cbc(body_aes_key, uhx(ZEROS128[0]), body)
                body_hmac_key = data[0x40:0x50]
                bhmac = HMAC.new(body_hmac_key, ebody, SHA)
                hdr = (data[0:0x50] + uhx(bhmac.hexdigest()) + data[0x64:0x6C])
                hhmac = HMAC.new(uhx(HASHERKEYEMC[0]), hdr, SHA)
                hdr = (hdr + uhx(hhmac.hexdigest()))
                hdr = emc_encrypt_header(hdr)
                print bhmac.hexdigest()
                print hhmac.hexdigest()
                with open(sys.argv[1] + '.bin', 'wb') as g:
                    g.write(hdr+ebody)
            if type == uhx('68'):
                print 'EAP'
                body_len = struct.unpack('<L', data[0xc:0x10])[0]
                body = data[0x80:0x80+body_len]
                body_aes_key  = data[0x30:0x40]
                ebody = aes_encrypt_cbc(body_aes_key, uhx(ZEROS128[0]), body)
                body_hmac_key = data[0x40:0x50]
                bhmac = HMAC.new(body_hmac_key, ebody, SHA)
                hdr = (data[0:0x50] + uhx(bhmac.hexdigest()) + data[0x64:0x6C])
                hhmac = HMAC.new(uhx(HASHERKEYEAP[0]), hdr, SHA)
                hdr = (hdr + uhx(hhmac.hexdigest()))
                hdr = eap_encrypt_header(hdr)
                print bhmac.hexdigest()
                print hhmac.hexdigest()
                with open(sys.argv[1] + '.bin', 'wb') as g:
                    g.write(hdr+ebody)
 
 

if __name__ == '__main__':
    main(len(sys.argv), sys.argv)
Step 7:
  • Go to the original file you unpacked (either sflash0s0x32 or sflash0s0x32b) and at offset 0x200, replace the content with the content of C0000001.bin.bin using HxD
Step 8:
  • Replace the contents of sflash0 with the contents of modified sflash0s0x32 and sflash0s0x32b files, respectively at 0x4000, size 0x60000 and at 0x64000 size 0x60000.
Step 9:
  • With all in place, you only need to flash sflash0 back to the console.
Step 10:
  • After you've flashed it, if you haven't done it yet, don't forget to solder to the MediaCon testpads TX RX and also GND (use colored wires for easier differentiating, label if you must)
Step 11:
  • TX goes to TX on the CP2102, RX goes to RX on the CP2102, and GND goes to GND on the CP2102. plug accordingly.
Step 12:
  • Test the patch by issuing the command socuid with JaiBrute v2.
The usage is:
Code:
.\JaiBrute.exe \\.\com3 cmd
where \\.\com3 is your CP2102 com number (don't forget to install the Universal CP210x drivers)

Step 13:
  • There are no more steps. You have now absolute power over the lowest level of the console. Be careful with the commands you try as some may cause irreversible damage!
Pictures:

Testpads:


PS4 EMC CFW Steps Phat CUH-1000 and CUH-1100 Guide by Zecoxao 2.jpg


CP2102:

PS4 EMC CFW Steps Phat CUH-1000 and CUH-1100 Guide by Zecoxao.png


It is permanent until you update the firmware.

List of commands (5.05)
Code:
 help:A9
# ANY    "R16":A8
# ANY    "R32":A6
# ANY    "R8":79
# ANY    "W16":AD
# ANY    "W32":AB
# ANY    "W8":7E
# ANY    "_hdmi":F0
# ANY    "boot":A3
# ANY    "bootadr": DA
# ANY    "bootenable":0A
# ANY    "bootmode":48
# ANY    "buzzer":91
# ANY    "cb":B4
# ANY    "cclog":F7
# ANY    "ccul":96
# ANY    "cec":1A
# ANY    "cktemprid":B2
# ANY    "combuf":6B
# ANY    "comlog":70
# ANY    "csarea":5E
# ANY    "ddr":29
# ANY    "ddrc":8C
# ANY    "ddrr":9B
# ANY    "ddrw":A0
# ANY    "devpm":0B
# ANY    "dled":88
# ANY    "dsarea":5F
# ANY    "ejectsw":E4
# ANY    "errlog":7A
# ANY    "etempr":7C
# ANY    "fdownmode":B2
# ANY    "fduty":1B
# ANY    "flimit":74
# ANY    "fmode":FA
# ANY    "fservo":84
# ANY    "fsstate":E9
# ANY    "fstartup":68
# ANY    "getmacadr":97
# ANY    "halt":98
# ANY    "haltmode":3D
# ANY    "hdmir":03
# ANY    "hdmis":04
# ANY    "hdmistate":B2
# ANY    "hdmiw":08
# ANY    "help":98
# ANY    "mbu":33
# ANY    "mduty":22
# ANY    "nvscsum":FE
# ANY    "nvsinit":FA
# ANY    "nvsl2sw":CE
# ANY    "osarea":6A
# ANY    "osbootparam":96
# ANY    "osdebuginfo":84
# ANY    "osstate":F2
# ANY    "pcie":90
# ANY    "pdarea":5C
# ANY    "powcount":6E
# ANY    "powersw":06
# ANY    "powupcause":3B
# ANY    "qafinfo": D3
# ANY    "r16":C8
# ANY    "r32":C6
# ANY    "r8":99
# ANY    "resetsw":FC
# ANY    "rtc":38
# ANY    "runseq":8D
# ANY    "s3state":B6
# ANY    "sb":C4
# ANY    "sbnvs":1B
# ANY    "scfupdbegin":79
# ANY    "scfupddl":44
# ANY    "scfupdend":AB
# ANY    "scnvsinit": D0
# ANY    "scpdis":75
# ANY    "screset":E8
# ANY    "scversion":CB
# ANY    "sdkversion":37
# ANY    "sdnvs":1D
# ANY    "smlog":11
# ANY    "socdmode":3D
# ANY    "socuid":76
# ANY    "spoff":0D
# ANY    "spon":AF
# ANY    "sqlog":15
# ANY    "ssbdis":77
# ANY    "startwd":F8
# ANY    "state":10
# ANY    "stinfo":82
# ANY    "stopwd":90
# ANY    "stwb":AF
# ANY    "subsysid":65
# ANY    "subsysinfo":44
# ANY    "syspowdown":5C
# ANY    "task":A2
# ANY    "tempr":17
# ANY    "temprlog":59
# ANY    "testpcie":50
# ANY    "thrm":AA
# ANY    "uareq1":3E
# ANY    "uareq2":3F
# ANY    "version":F5
# ANY    "vshinfo":EC
# ANY    "w16":CD
# ANY    "w32":CB
# ANY    "w8":9E
# ANY    "wsc":3C
OK 00000000:3A
Brickable commands (don't try these unless you know what you're doing):
Code:
# ANY "scfupdbegin":79 (syscon update begin, destroyer brick)
# ANY "scfupddl":44 (syscon update download, destroyer brick)
# ANY "scfupdend":AB (syscon update end, destroyer brick)
# ANY "scnvsinit": D0 (initializes nvs, ultra hyper mega brick)

# ANY "w16":CD (writes in uint16_t to any place emc controls, brick)
# ANY "w32":CB (writes in uint32_t to any place emc controls, brick)
# ANY "w8":9E (writes in uint8_t to any place emc controls, brick)

# ANY "sb":C4 (switches the bank of the ps4, ultra brick)
This works on all firmwares, due to the fact that no public-private keys are involved in the process of verification of the firmware (it is simply hmac-sha1) so it will always work until X.XX because we have all the necessary master keys, for both encryption and validation.

Software method (5.05 hackable CUH-1000 and CUH-1100 ONLY!):

Some notes before you use this payload:

  • MAKE SURE THAT THE FILE YOU'RE FLASHING IS IN THE RIGHT LOCATION! YOU WILL BRICK OTHERWISE!
  • MAKE SURE THAT THE FILE IS PROPERLY ENCRYPTED! YOU WILL BRICK OTHERWISE!
  • MAKE SURE THAT THE FILE HAS THE CORRECT SIZE (0x60000 bytes or 384KB) YOU WILL BRICK OTHERWISE!
  • MAKE SURE THE MD5SUM OF 0.bin IS CORRECT (58213910f9b24d5b5069ea22046c21b8 0.bin)
Download: 0.zip (3.06 KB - includes 0.bin) / sflash0s0x32.zip (302.61 KB - includes sflash0s0x32, skips steps 3-7 on 5.05 - MD5: 35c094f9e71f7825d9a0060b0ee870fa sflash0s0x32)

With that out of the way, here is the instruction on flashing via software side:

FTP the file /dev/sflash0s0x32 (you need an ftp client, goldhen 2.00b2 has a good one, use it)

Modify the file according to the steps 3-7 (unpack, decrypt, patch, encrypt, replace on sflash0s0x32)

Create a new folder under PS4 hdd /data/ folder with the name payloads (NOT PAYLOADS, NOT payload, NOT PAYLOAD)

Place the file sflash0s0x32 there, so it looks like this:
Code:
/data/payloads/sflash0s0x32
Extract the file 0.zip to obtain the payload 0.bin

Place the payload 0.bin under /data/payloads/ so it looks like this
Code:
/data/payloads/0.bin
AlAzif has made available a payload loader pkg. install it, then refresh the payload list with square, and finally press x on 0.bin

Wait AT LEAST 4 minutes! After 4 minutes pass, use ftp and verify if the file /dev/sflash0s0x32 matches the same file you patched

If it doesn't, tough luck, you're probably bricked at this point and you need to open the console and do the hardware method. if it does, congratulations! you have yourself an emc cfw.

Mounting PS4 HDD on WSL2 (Windows Subsystem for Linux 2)

From @zecoxao's Tweet below: To note that you can recover anything from here, including your licenses, your activation files, your trophies, your savedatas, and your apps in PKG format.

⚠️ BAIKAL IS NOT SUPPORTED! YOU HAVE BEEN WARNED!
  • Need WSL2 (For mounting support)
  • Need HDD (Obviously)
  • Need HDD Script (Python, requires binascii, pathlib, pycryptodome)
  • Need Sflash0 dump (either from console or from ftp server in hacked console)
  • sflash0 must be labeled like this and next to script
  • Need WSL2 Kernel with UFS Read Only Support (for user partition)
  • Need to install cryptmount
  • Need to generate keys.bin with script
  • Need cmtab properly edited and proper permissions (644)
Example of my cmtab:
Code:
# /etc/cryptmount/cmtab - encrypted filesystem information for cryptmount
# try 'man 8 cryptmount' or 'man 5 cmtab' for more details
user {
    dev=/dev/sdc13
    dir=/mnt/c/Users/zecoxao/Desktop/user
    flags=user,nofsck
    fstype=ufs mountoptions=ro,noatime,noexec,ufstype=ufs2
    cipher=aes-xts-plain64
    keyfile=/mnt/c/Users/zecoxao/Desktop/hdd_script/keys.bin
    keyformat=raw
}
sudo cryptmount user will mount the user partition (found either at /dev/sdX27 or at /dev/sdX13)

Link for script: hdd_script.zip (2.11 KB - includes hdd_script.py)

Spoiler

Link for WSL2 UFS RO Kernel: WSL2_UFS_Support_Read_Only.rar (2.83 GB)

Commands:
Code:
Get Disk List (PowerShell Admin)
GET-CimInstance -query "SELECT * from Win32_DiskDrive"
Mount Disk with WSL2 (CommandLine Admin)
wsl --mount \\.\PHYSICALDRIVE1
Copy bzImage to User Profile (WSL)
powershell.exe /C 'Copy-Item .\arch\x86\boot\bzImage $env:USERPROFILE'
Add kernel entry to .wslconfig (WSL)
powershell.exe /C 'Write-Output [wsl2]`nkernel=$env:USERPROFILE\bzImage | % {$_.replace("\","\\")} | Out-File $env:USERPROFILE\.wslconfig -encoding ASCII'

Spoiler: Related Tweets

Decided to create a repo that specializes in decryption of retail ps4 eap hdd partitions:
Credits to @rajeshca911 (Twitter) for supplying the ps4 pro dumps in order to test this.

Note that if your ps4 is a phat 1000 or 1100 model, IVOFFSET will work as 0.
How to mount EAP partitions on Windows:

Mounting PS4 HDD On Windows, Only Specific Partitions
Requirements:
  • .wslconfig (for this you also need wsl2 installed, wsl1 should work as well)
  • bzImage (this is ufs readonly! for ufs rw you need to compile your own bzImage)
Both .wslconfig are place on C:\Users\(your_username)\ (in my case it's zecoxao)

cmtab
eap key partitions (i've chosen eap_vsh, update, user)
folders (according to cmtab)
and of course, your keys

in the case of user partition the number of the partition will be 27 so you do this
subtract 27 with 1
this will give 26
then you left shift 32
this will give 111669149696

Modify .wslconfig and cmtab accordingly! (path to bzImage, directory where to mount eap partitions, keys.bin location, ivoffset, etc)

PS4 EMC CFW Steps Phat CUH-1000 and CUH-1100 Guide by Zecoxao.jpg
 

Comments

I see my Twitter post in there :p

One thing i'm curious about as its not stated, is the Hardware flasher needed in general or purley for non JB consoles? I have everything else, just no Hardware flasher, wouldn't know which to choose either as there are a few out there.
 
@Hansika Motwani Not even close. The jailbreak is still lost with a firmware update. However it's still a good step towards a CFW.

In PS3 days you could install a custom firmware directly in the PS3 interface as PS3 private keys were leaked, which allowed signing of CFW files.
 
Status
Not open for further replies.
Back
Top