VTRM
The PS4s VTRM functionality seems to be similar with the one from the PS3. We can either Dump them via HW or via Software methode. Tools to unpack and dump the VTRM can be found here Tool on the Top, under sources.
On the PS4 a Dev unit only hase one Region where a Retail unit will have two Regions. One of thoes regions will be used for deactivation and the other one for activation.
Region0
SCEVTRM Magic on 0x380048.
The 0xFC in this example here mark the very first entry for a VTRM. Otherwise it would be 4 bytes either all 0x00 which means not in use or 0x03 0x00 0x00 0x00 which means in use. 0xFC is always tighten to 0x00 placed on offset 0x380050 and 0x380058 or in the second VTRM on 0x3A0050 and 0x3A0058 and it is the counter for activation and deactivation of the console. Following the counting: This means for every
uneven number == Activated
and for every
even number == Deactivated
or
If VTRM0 is marked as in use then the console is deactivated and if VTRM1 is marked in use then PS4 is activated.
Following some examples. Remember mark 0xFC and count 0x00 == factory state.
Deactivated
Console A | Console B | Console C |
---|---|---|
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00380000 FC FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF üÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 00380010 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 00380020 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 00380030 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 00380040 01 00 00 00 FF FF FF FF 53 43 45 56 54 52 4D 00 ....ÿÿÿÿSCEVTRM. 00380050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00380060 00 10 00 00 00 00 00 00 1D 00 00 00 00 00 00 00 ................ 00380070 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ |
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00380000 00 00 00 00 FF FF FF FF FF FF FF FF FF FF FF FF üÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 00380010 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 00380020 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 00380030 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 00380040 01 00 00 00 FF FF FF FF 53 43 45 56 54 52 4D 00 ....ÿÿÿÿSCEVTRM. 00380050 16 00 00 00 00 00 00 00 16 00 00 00 00 00 00 00 ................ 00380060 00 10 00 00 00 00 00 00 1D 00 00 00 00 00 00 00 ................ 00380070 FF FF FF FF FF FF FF FF FC FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ |
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00380000 00 00 00 00 FF FF FF FF FF FF FF FF FF FF FF FF üÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 00380010 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 00380020 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 00380030 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 00380040 01 00 00 00 FF FF FF FF 53 43 45 56 54 52 4D 00 ....ÿÿÿÿSCEVTRM. 00380050 0E 00 00 00 00 00 00 00 0E 00 00 00 00 00 00 00 ................ 00380060 00 10 00 00 00 00 00 00 1D 00 00 00 00 00 00 00 ................ 00380070 FF FF FF FF FF FF FF FF FC FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ |
So we have more ways to identify if a Dump is from a Retail or a Dev/Test console. Either we can check if there are any incremental counters used on the VTRM or we can check if the VTRM hase any mark like 0xFC or 0x00000000 or 0x03000000 then it is reatail else Dev/test. Or we also can check the first 4 bytes of both VTRMs against 4x 0xFF bytes, if True == Dev/Test else Retail.
NOTE: Dev / Test Consoles only do use one VTRM. The array for the second VTRM is completely empty on this SKU models beside that they don't have any mark and also no counter. (yea sure why if they only use one ^^)
NOTE²: There is another byte that will change douring this process. On offset 0x3A0078 for factory the byte is 0xFF. As soon the console would be the first time activated (so count 0x01) then this byte change to 0xFE. After this (so count 0x02 and upwards) the byte will always be 0xFC.
Region0 Digest?
This region of 0x60 ~= 96 bytes is the exact same on the same console of diffrent FW and BIOS versions. We can use thoes 96 bytes to identify dumps as diffrent or as from one and the same device. It's kind of a unique Console identifyer. I will add a new entry to the SystemFlash Extractor and hash this array with SHA1 which we then can use to store it in the DataBase. That gives us the ability to even identify a Dump and his informations from the DataBase out as one and the same device or as a diffrent one, while to same time to protect the privacy of the user in case we use a checksum to store and not the console specific unique vlaue.
Region1
SCEVTRM Magic on 0x3A0048
Activated
Console A | Console B | Console C |
---|---|---|
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00380000 03 00 00 00 FF FF FF FF FF FF FF FF FF FF FF FF üÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 00380010 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 00380020 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 00380030 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 00380040 01 00 00 00 FF FF FF FF 53 43 45 56 54 52 4D 00 ....ÿÿÿÿSCEVTRM. 00380050 01 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 ................ 00380060 00 10 00 00 00 00 00 00 1D 00 00 00 00 00 00 00 ................ 00380070 FF FF FF FF FF FF FF FF FE FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ |
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00380000 03 00 00 00 FF FF FF FF FF FF FF FF FF FF FF FF üÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 00380010 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 00380020 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 00380030 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 00380040 01 00 00 00 FF FF FF FF 53 43 45 56 54 52 4D 00 ....ÿÿÿÿSCEVTRM. 00380050 17 00 00 00 00 00 00 00 17 00 00 00 00 00 00 00 ................ 00380060 00 10 00 00 00 00 00 00 1D 00 00 00 00 00 00 00 ................ 00380070 FF FF FF FF FF FF FF FF FC FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ |
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00380000 03 00 00 00 FF FF FF FF FF FF FF FF FF FF FF FF üÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 00380010 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 00380020 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 00380030 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 00380040 01 00 00 00 FF FF FF FF 53 43 45 56 54 52 4D 00 ....ÿÿÿÿSCEVTRM. 00380050 0F 00 00 00 00 00 00 00 0F 00 00 00 00 00 00 00 ................ 00380060 00 10 00 00 00 00 00 00 1D 00 00 00 00 00 00 00 ................ 00380070 FF FF FF FF FF FF FF FF FC FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ |
Console A, B | Console C |
---|---|
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 003801D0 FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿ 003801E0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ [...] filled FF region 003A0160 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 003A0170 FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿ |
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 0039FFF0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 003A0000 03 00 00 00 FF FF FF FF FF FF FF FF FF FF FF FF ....ÿÿÿÿÿÿÿÿÿÿÿÿ 003A0010 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ [...] filled FF region 003A0040 01 00 00 00 FF FF FF FF 53 43 45 56 54 52 4D 00 ....ÿÿÿÿSCEVTRM. 003A0040 01 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 ................ 003A0040 00 10 00 00 00 00 00 00 1D 00 00 00 00 00 00 00 ................ 003A0040 FF FF FF FF FF FF FF FF FE FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿ 003A0050 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ [...] filled FF region 003A0160 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 003A0170 FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿ |
Region1 Digest?
The same like for Region0 applys here but with the diffrence that thoes both digest? from Region0 and Region1 do differ on the same console and also on diffrent versions. But Region0 do match Region0 of diffrent FW and BIOS versions and the same apply for Region1. Thoes 96 bytes from Region1 are always the same on diffrent FW and BIOS versions of the same console.
Structure
Header
- size always 96 bytes
From | To | Description |
---|---|---|
00 | 03 | Flag Marks the VTRM status |
04 | 3F | Padding0 Nothing only 0xFF bytes |
40 | 43 | Constant always 0x01000000 |
44 | 47 | Padding1 Nothing always 0xFF bytes |
48 | 4F | Magic The VTRM Magic |
50 | 53 | Count0 The activation count |
54 | 57 | Padding2 Nothing always 0x00 bytes |
58 | 5B | Count1 The control byte for the activation count |
5C | 5F | Padding3 Nothing always 0x00 bytes |
60 | 6F | Ukn Unknowen always the same 16 bytes |
70 | 76 | Padding4 Nothing always 0xFF bytes |
77 | 77 | Ctrlflag Tigthen with the Flag variable |
78 | 7F | Padding5 Nothing always 0xFF bytes |
C
typedef struct vtrmHeader {
unsigned char FLAG;
unsigned const char PADDING0;
unsigned const char CONSTANT;
unsigned const char PADDING1;
unsigned const char MAGIC;
unsigned char COUNT0;
unsigned const char PADDING2;
unsigned char COUNT1;
unsigned const char PADDING3;
unsigned const char UKN;
unsigned const char PADDING4;
unsigned char CTRLFLAG;
unsigned const char PADDING5;
} vtrmHeader;
CSharp
protected internal struct vtrmHeader {
internal static byte[] FLAG = new byte[4];
internal static byte[] PADDING0 = new byte[60];
internal static byte[] CONSTANT = new byte[4];
internal static byte[] PADDING1 = new byte[4];
internal static byte[] MAGIC = new byte[8];
internal static byte[] COUNT0 = new byte[4];
internal static byte[] PADDING2 = new byte[4];
internal static byte[] COUNT1 = new byte[4];
internal static byte[] PADDING3 = new byte[4];
internal static byte[] UKN = new byte[16];
internal static byte[] PADDING4 = new byte[8];
internal static byte[] CTRLFLAG = new byte[1];
internal static byte[] PADDING5 = new byte[7];
}
Body
Function Calls
From 1.76. pastebin
VtrmCipherCalcHeaderDigest LOAD FFFFFFFF827CF0E0 00000141 00000138 00000000 R . . . B . . VtrmCipherCalcAssignTableDigest LOAD FFFFFFFF827CF230 00000078 00000020 00000000 R . . . B . . VtrmCipherCalcSectorDigestTableDigest LOAD FFFFFFFF827CF2B0 00000078 00000020 00000000 R . . . B . . VtrmCipherCalcUserRegionDigest LOAD FFFFFFFF827CF330 00000078 00000020 00000000 R . . . B . . VtrmCipherEncryptUserRegion LOAD FFFFFFFF827CF3B0 000000A6 00000048 00000000 R . . . B . . VtrmCipherDecryptUserRegion LOAD FFFFFFFF827CF460 000000A6 00000048 00000000 R . . . B . . vtrm_erase_sector LOAD FFFFFFFF827CF510 0000001B R . . . . . . vtrm_pread LOAD FFFFFFFF827CF530 00000029 R . . . . . . vtrm_pwrite LOAD FFFFFFFF827CF560 00000029 R . . . . . . VtrmUtilLockInitialize LOAD FFFFFFFF827CF590 0000001D 00000008 00000000 R . . . B . . VtrmUtilLockFinialize LOAD FFFFFFFF827CF5B0 00000014 00000008 00000000 R . . . B . . VtrmUtilLock LOAD FFFFFFFF827CF5D0 0000003A 00000008 00000000 R . . . B . . VtrmUtilUnlock LOAD FFFFFFFF827CF610 0000003A 00000008 00000000 R . . . B . . VTRM_MALLOC LOAD FFFFFFFF827CF650 00000011 R . . . . . . VTRM_FREE LOAD FFFFFFFF827CF670 0000000C R . . . . . . VTRM_CONTIGMALLOC LOAD FFFFFFFF827CF680 00000039 00000018 00000000 R . . . B . . VTRM_CONTIGFREE LOAD FFFFFFFF827CF6C0 0000000C R . . . . . . VtrmUtilBswap16 LOAD FFFFFFFF827CF6D0 00000008 R . . . . . . VtrmUtilBswap32 LOAD FFFFFFFF827CF6E0 00000005 R . . . . . . VtrmUtilBswap64 LOAD FFFFFFFF827CF6F0 00000007 R . . . . . . VtrmUtilDumpVtrmHeader LOAD FFFFFFFF827CF700 00000001 R . . . . . . VtrmUtilFillVtrmHeaderDefault LOAD FFFFFFFF827CF710 00000055 R . . . . . . VtrmUtilCheckVtrmHeader LOAD FFFFFFFF827CF770 00000038 R . . . . . . VtrmUtilIsErasedSector LOAD FFFFFFFF827CF7B0 00000026 R . . . . . . VtrmUtilCompareDataVersion LOAD FFFFFFFF827CF7E0 00000041 R . . . . . . VtrmUtilDumpDigest LOAD FFFFFFFF827CF830 00000001 R . . . . . . VtrmUtilCountAllocatedEntry LOAD FFFFFFFF827CF840 0000003F R . . . . . .