SceNpDrm

From Vita Development Wiki
Jump to navigation Jump to search

Module

Known NIDs

Version Name World Privilege NID
1.69 SceNpDrm Non-secure Kernel 0xACCB4845
3.60 SceNpDrm Non-secure Kernel 0xE7E2CE05

Libraries

Known NIDs

Version Name World Visibility NID
1.69-3.60 SceNpDrm Non-secure User 0xF2799B1B
1.69-3.60 SceNpDrmForDriver Non-secure Kernel 0xD84DC44A
1.69-3.60 SceNpDrmPackage Non-secure User 0x88514DB2
3.60 ScePsmDrm Non-secure User 0x3F2B0888
3.60 ScePsmDrmForDriver Non-secure Kernel 0x9F4924F2

Data segment layout

Address Size Description
0x0000 0x4 SceNpDrm mutex SceUID
0x0004 0x4 ScePsmDrm mutex SceUID
0x0008 0x8 unknown
0x0010 0xC0 static keys decrypted with sceSblAuthMgrGetEKcForDriver key 0.

First 0x10 bytes are reencrypted with ConsoleId.

First 0x10 bytes are aes_key used to decrypt 0x800 bytes of Primary Key Table from act.dat.

Second 0x10 bytes are aes_key used to decrypt Primary Key Table index from rif.

0x00D0 0xCF8 unknown
0x0DC8 0x4 Game Exist flag
0x0DCC 0x4 Is DEX flag or Is Tool flag
0x0DD0 0x30 unknown
0x0E00 0x1040 tm0:/npdrm/act.dat data
0x1E40 0x400 tm0:/psmdrm/act.dat data
0x2240 0x10 OpenPsId

This data is compared against OpenPsId from act.dat.

This key is compared against OpenPsId in from .rif file at offset 0xC0.

0x2250 0x4 act data Is Valid flag
0x2254 0x4 unknown
0x2258 0x8 /CONFIG/NP/account_id registry key
0x2260 0x4 Loose Account Bind flag
0x2264 0x4 /CONFIG/NP/debug_upgradable registry key
0x2268 0x20 sha 256 digest of get_act_data
0x2288 0x20 hmac sha 256 digest of get_act_data
0x22A8 0x8 unknown
0x22B0 0x8 account_id
0x22B8 0x8 psm activation start date
0x22C0 0x8 psm activation end date
0x22C8 0x20 some key decrypted with 0x2288

Obtaining klicensee

1. Get the list of static keys. (on 3.60, 0xC0 bytes from SceNpDrm code segment at offset 0x111D0)

2. Decrypt 0xC0 bytes of static keys using sceSblAuthMgrGetEKcForDriver key 0.

3. Get 0x10 bytes of ConsoleId using sceSblSsMgrGetConsoleIdForDriver.

4. Encrypt first 0x10 bytes of static keys with ConsoleId using AES (need to figure out which AES exactly).

5. Read 0x800 bytes of Primary Key Table from act.dat

6. Decrypt 0x800 bytes of Primary Key Table with reencrypted static key using AES (need to figure out which AES exactly).

7. Get 0x97 / 0x200 bytes of RIF data and select one of 5 scenarios for decrypting RIF Key based on license flags (need to figure out).

Scenario 1 - maybe DRM Free

Take RIF Key 2.

Take static keys 3, 4.

Take first 0x70 bytes of RIF data.

Use sceSblAuthMgrDecBindDataForDriver to decrypt RIF key 2 and obtain klicensee.

Scenario 2

Take RIF Key 2.

Take primary keys 1, 2.

Take first 0x70 bytes of RIF data.

Use sceSblAuthMgrDecBindDataForDriver to decrypt RIF key 2 and obtain klicensee.

Scenario 3 - Game Cartridge

Take RIF Key 2.

Take cmd56 handshake keys with get_5018_data.

Take first 0x70 bytes of RIF data.

Use sceSblAuthMgrDecBindDataForDriver to decrypt RIF key 2 and obtain klicensee.

Scenario 4 - Game Cartridge

Take RIF Key 1.

Take cmd56 handshake keys with get_5018_data.

Take first 0x70 bytes of RIF data.

Erase RIF Key 1 from RIF data.

Use sceSblAuthMgrDecBindDataForDriver to decrypt RIF key 1 and obtain klicensee.

Scenario 5

Decrypt Primary Table Key index from RIF data with static key 2 using AES (need to figure out which AES exactly).

Take primary key using decrypted index.

Decrypt RIF key 1 with obtained primary key using AES (need to figure out which AES exactly).

Get rif name algorithm

uint8_t rif_name_keys[0x10] = {
	0x19, 0xDD, 0x4F, 0xB9, 0x89, 0x48, 0x2B, 0xD4,
	0xCB, 0x9E, 0xC9, 0xC7, 0x9A, 0x2E, 0xFB, 0xD0
};

int aes_encrypt(const void *buf, int size, uint8_t *keys) {
	AES_ctx ctx;
	AES_set_key(&ctx, rif_name_keys, 0x80);

	int i;
	for (i = 0; i < size; i += 0x10) {
		AES_encrypt(&ctx, buf+i, buf+i);
	}
}

typedef struct {
	uint64_t mode; // 0: bounded, 1: fixed
	uint64_t aid;
} SceNpDrmRifName;

int getRifName(char *name, int length, uint64_t aid, uint64_t mode) {
	SceNpDrmRifName rif_name;
	rif_name.mode = mode;
	rif_name.aid = aid;
	aes_encrypt(&rif_name, sizeof(SceNpDrmRifName), rif_name_keys);
	
	snprintf(name, length, "%016llx%016llx.rif", __builtin_bswap64(((uint64_t *)&rif_name)[0]), __builtin_bswap64(((uint64_t *)&rif_name)[1]));	
}

SceNpDrm

_sceNpDrmCheckDrmReset

Version NID
1.69 0x4458812B
3.60 0x4458812B
//opt is of size 0x18
int _sceNpDrmCheckDrmReset(int unk0, int unk1, void *opt);

_sceNpDrmRemoveActData

Version NID
1.69 0x507D06A6
3.60 0x507D06A6
//opt is of size 0x8
int _sceNpDrmRemoveActData(int unk0, void* opt);

_sceNpDrmGetRifName

Version NID
1.69-3.60 0xB8C5DA7C
int _sceNpDrmGetRifName(char *name, int ignored, uint64_t aid);

_sceNpDrmGetRifNameForInstall

Version NID
1.69 0xD312424D
3.60 0xD312424D
//name is of size 0x30
//rif_data is of size 0x200
int _sceNpDrmGetRifNameForInstall(char *name, void *rif_data, int num);

_sceNpDrmGetRifInfo

Version NID
1.69 0xE8343660
3.60 0xE8343660
typedef struct rif_info //size is 0x70
{
   char content_id[0x30];
   char version_number[0x04];
   char rif_lic_flags[0x04];
   char lic_type0[0x04]; //lic type related
   char lic_type1[0x04]; //lic type related
   char account_id[0x08];
   char rif_data_98[0x08];
   char lic_start_time[0x08];
   char lic_exp_time[0x08];
   char dec_rif_key[0x10]; //decrypted rif key
}rif_info;

typedef struct _sceNpDrmGetRifInfo_opt //size is 0x28
{
  char* content_id;
  char* account_id;
  char* version_number;
  char* rif_lic_flags;
  char* lic_type0; //lic type related
  char* lic_type1; //lic type related
  char* lic_start_time;
  char* lic_exp_time;
  char* rif_data_98;
}_sceNpDrmGetRifInfo_opt;

//rif data is of size 0x200

int _sceNpDrmGetRifInfo(void* rif_data, int rif_size, int num, _sceNpDrmGetRifInfo_opt* opt);

_sceNpDrmGetFixedRifName

Version NID
1.69 0xE935B0FC
3.60 0xE935B0FC
int _sceNpDrmGetFixedRifName(char *name, int ignored, int unk2, int unk3);

_sceNpDrmCheckActData

Version NID
1.69 0xFEEBCD62
3.60 0xFEEBCD62
//opt is of size 0x10
int _sceNpDrmCheckActData(int unk0, int unk1, int unk2, void* opt);

_sceNpDrmPresetRifProvisionalFlag

Version NID
3.60 0x2523F57F
//rif data is of size 0x200
int _sceNpDrmPresetRifProvisionalFlag(void* rif_data);

SceNpDrmForDriver

sceNpDrmGetRifInfoForDriver

Version NID
3.60 0xDB406EAE
 
//rif data is of size 0x200
int sceNpDrmGetRifInfoForDriver(void* rif_data, int rif_size, int num, char* content_id, char* account_id, char* version_number, char* rif_lic_flags, char* lic_type0, char* lic_type1, char* lic_start_time, char* lic_exp_time, char* rif_data_98);

sceNpDrmPackageSetGameExistForDriver

Version NID
3.60 0x3BFD2850
int sceNpDrmPackageSetGameExistForDriver(int value);

sceNpDrmGetFixedRifNameForDriver

Version NID
3.60 0x5D73448C
//name is of size 0x30
int sceNpDrmGetFixedRifNameForDriver(char *name, int ignored, int unk2, int unk3);

sceNpDrmGetRifNameForDriver

Version NID
3.60 0xDF62F3B8
//name is of size 0x30
int sceNpDrmGetRifNameForDriver(char *name, int ignored, int unk2, int unk3);

sceNpDrmGetRifNameForInstallForDriver

Version NID
3.60 0x17573133
//name is of size 0x30
//rif_data size is at least 0xF8
int sceNpDrmGetRifNameForInstallForDriver(char *name, void *rif_data, int num);

sceNpDrmPresetRifProvisionalFlagForDriver

Version NID
3.60 0xC070FE89
// rif data size is at least 0xF8
int sceNpDrmPresetRifProvisionalFlagForDriver(void* rif_data, int unk1);

sceNpDrmCheckActDataForDriver

Version NID
3.60 0x9265B350

checks tm0:/npdrm/act.dat

//size of act data is 0x1040

int sceNpDrmCheckActDataForDriver(int unk0, int unk1, int unk2, int unk3, int arg_0);

sceNpDrmRemoveActDataForDriver

Version NID
3.60 0x8B85A509

checks tm0:/npdrm/act.dat

int sceNpDrmRemoveActDataForDriver(int unk);

sceNpDrmUpdateAccountIdForDriver

Version NID
3.60 0x116FC0D6
int sceNpDrmUpdateAccountIdForDriver(int unk0, int unk1);

sceNpDrmEbootSigGenMultiDiscForDriver

Version NID
3.60 0x39A7A666
int sceNpDrmEbootSigGenMultiDiscForDriver(int unk0, int unk1, int unk2, int unk3);

sceNpDrmEbootSigGenPs1ForDriver

Version NID
3.60 0x6D9223E1
int sceNpDrmEbootSigGenPs1ForDriver(int unk0, int unk1, int unk2, int unk3);

sceNpDrmGetLegacyDocKeyForDriver

Version NID
3.60 0x4E321BDE
//rif data is of size 0x200
//data1 is of size 0x90 - most likely decrypted with rif key from rif data using SceSblGcAuthMgr enc_dec 0x4c5de1aa
int sceNpDrmGetLegacyDocKeyForDriver(void *rif_data, void *data1, int unk, void *dest);

sceNpDrmEbootSigVerifyForDriver

Version NID
3.60 0x7A319692

drm_data - __sce_ebootpbp or license data, size is 0x200.

int sceNpDrmEbootSigVerifyForDriver(const char *path, void *drm_data);

sceNpDrmEbootSigGenPspForDriver

Version NID
3.60 0x90B1A6D3
int sceNpDrmEbootSigGenPspForDriver(int unk0, int unk1, int unk2, int unk3);

sceNpDrmEbootSigConvertForDriver

Version NID
3.60 0xA29B75F9
int sceNpDrmEbootSigConvertForDriver(int unk0, int unk1, int unk2);

sceNpDrmPspEbootVerifyForDriver

Version NID
3.60 0xB6CA3A2C
int sceNpDrmPspEbootVerifyForDriver(int unk0, int unk1);

sceNpDrmPspEbootSigGenForDriver

Version NID
3.60 0xEF387FC4
int sceNpDrmPspEbootSigGenForDriver(int unk0, int unk1, int unk2);

sceNpDrmIsLooseAccountBindForDriver

Version NID
3.60 0xFC84CA1A
int sceNpDrmIsLooseAccountBindForDriver();

sceNpDrmUpdateDebugSettingsForDriver

Version NID
3.60 0xA91C7443

checks /CONFIG/NP debug_upgradable and /CONFIG/NP2 debug_drm_loose_bind registry values

int sceNpDrmUpdateDebugSettingsForDriver();

sceNpDrmGetRifPspKeyForDriver

Version NID
3.60 0xDACB71F4
//rif_data is of size 0x200
//dec_rif_key is of size 0x10
int sceNpDrmGetRifPspKeyForDriver(void *rif_data, void *dec_rif_key, int unk2, int unk3, int arg_0);

sceNpDrmGetRifVitaKeyForDriver

Version NID
3.60 0x723322B5

use sceNpDrmGetRifInfoForDriver to get required fields

int sceNpDrmGetRifVitaKeyForDriver(void *rif_data, void *dec_rif_key, char* lic_type0, char* lic_type1, char* lic_start_time, char* lic_exp_time, char* rif_lic_flags);

set_act_data

Version NID
3.60 0x742EBAF4

Related to sceSblGcAuthMgrPcactActivation.

decrypts act_data with aes_dec_key and stores it to data segment

verifies sha1 - ecdsa or sha256 - RSA

checks Loose Account Bind flag

verifies OpenPsId

creates tm0:/npdrm folder

writes tm0:/npdrm/act.dat file

repeats all verification steps

decrypts Primary Key Table

// act_data is of size 0x1040
int set_act_data(void *act_data, const char *aes_dec_key);

get_act_data

Version NID
3.60 0xD91C3BCE

Related to sceSblGcAuthMgrPcactGetChallenge

reads 0x1038 bytes of tm0:/npdrm/act.dat data

//act_data is of size 0x1038
int get_act_data(void* act_data);

verify_rif

Version NID
3.60 0xFE7B17B6

verify ECDSA - SHA1 pair or RSA - SHA256 pair

//rif_data max size is 0x200
int verify_rif(void* rif_data, int rif_size);

verify_rif_full

Version NID
3.60 0xFF63672D

check OpenPsId

check cmd56 handshake part

perform steps to get decrypted rif key

//rif data size is unknown but at least 0xF8
int verify_rif_full(void* rif_data);

reset_act_dat

Version NID
3.60 0x77926F5

reads tm0:/npdrm/act.dat

verifies sha1 - ecdsa or sha256 - rca

checks Loose Account Bind flag

verifies OpenPsId

clears Secondary Table, RSA Signature, Unknown Sig, ECDSA Signature

decrypts Primary Key Table

int reset_act_dat();

SceNpDrmPackage

_sceNpDrmPackageTransform

Version NID
1.69 0x567DCA1
3.60 0x567DCA1
//opt is of size 0x28
int _sceNpDrmPackageTransform(int unk0, int unk1, void* opt, int unk3);

_sceNpDrmPackageInstallFinished

Version NID
1.69 0x6896EAF2
3.60 0x6896EAF2
//opt is of size 0x8
int _sceNpDrmPackageInstallFinished(int unk0, int unk1, int unk2, void* opt);

_sceNpDrmPackageCheck

Version NID
1.69 0xA1D885FA
3.60 0xA1D885FA
int _sceNpDrmPackageCheck(const void *buffer1, SceSize size, void *buffer2, unsigned int identifier);

sceNpDrmPackageIsGameExist

Version NID
1.69 0xB9337914
3.60 0xB9337914
int sceNpDrmPackageIsGameExist();

_sceNpDrmPackageInstallStarted

Version NID
1.69 0xCEC18DA4
3.60 0xCEC18DA4
//opt is of size 0x10
int _sceNpDrmPackageInstallStarted(int unk0, int unk1, int unk2, void* opt);

_sceNpDrmPackageDecrypt

Version NID
1.69 0xD6F05ACC
3.60 0xD6F05ACC
typedef struct _sceNpDrmPackageDecrypt //size is 0x10
{
  SceOff offset; //The offset in the encrypted data
  unsigned int identifier;
  uint32_t unk_C;
} _sceNpDrmPackageDecrypt_opt;

int _sceNpDrmPackageDecrypt(void * buffer, SceSize size, _sceNpDrmPackageDecrypt_opt * opt);

sceNpDrmPackageInstallOngoing

Version NID
1.69 0xED0471FE
3.60 0xED0471FE
int sceNpDrmPackageInstallOngoing(int unk0, int unk1);

_sceNpDrmPackageUninstallFinished

Version NID
3.60 0x23A28861
//opt is of size 0x8
int _sceNpDrmPackageUninstallFinished(int unk0, int unk1, int unk2, void* opt);

_sceNpDrmPackageUninstallStarted

Version NID
3.60 0x4901C3E6
//opt is of size 0x10
int _sceNpDrmPackageUninstallStarted(int unk0, int unk1, int unk2, void* opt);

sceNpDrmPackageUninstallOngoing

Version NID
3.60 0xF1FF6193
int sceNpDrmPackageUninstallOngoing(int unk0, int unk1);

unk_200D2DE4

Version NID
3.60 0x200D2DE4
int unk_200D2DE4(int unk0, int unk1);

unk_4665E75A

Version NID
3.60 0x4665E75A
//opt is of size 0x10
int unk_4665E75A(int unk0, int unk1, int unk2, void *opt);

unk_640C1724

Version NID
3.60 0x640C1724
//opt is of size 0x8
int unk_640C1724(int unk0, int unk1, int unk2, void *opt);

unk_97BB85BD

Version NID
3.60 0x97BB85BD
//opt is of size 0x10
int unk_97BB85BD(int unk0, int unk1, int unk2, void *opt)

unk_A5E0F38C

Version NID
3.60 0xA5E0F38C
int unk_A5E0F38C(int unk0, int unk1);

unk_C75A775B

Version NID
3.60 0xC75A775B
//opt is of size 0x8
int unk_C75A775B(int unk0, int unk1, int unk2, void *opt);

ScePsmDrm

get_rif_name

Version NID
3.60 0x0D6470DA
//some data is of size 0x400 and contains rif data
int get_rif_name(char *rif_name, void *some_data);

_get_info

Version NID
3.60 0xE31A6220
typedef struct get_info_opt //size is 0x10
{
 void* out2;
 void* out3;
 uint32_t unk_8;
 uint32_t unk_C;
}get_info_opt

int _get_info(void *some_data, void *out0, void *out1, get_info_opt *opt);

scePsmDrmGetRifKey

Version NID
3.60 0x207A2C53

/**
* rif_data size 0x400
* klicensee size 0x200
**/
int scePsmDrmGetRifKey(SceNpDrmLicense * rif_data , uint8_t *klicensee, uint32_t *flags, uint64_t *start_time, uint64_t *expiration_time);

unk_E193CBB

Version NID
3.60 0xE193CBB
int unk_E193CBB(int unk0);

unk_3E881391

Version NID
3.60 0x3E881391
int unk_3E881391(int unk0);

unk_A89653B3

Version NID
3.60 0xA89653B3
//opt is of size 0x10
int unk_A89653B3(int unk0, int unk1, int unk2, void *opt);

ScePsmDrmForDriver

scePsmDrmGetRifInfoForDriver

Version NID
3.60 0x984F9017

This function is named after sceNpDrmGetRifInfoForDriver since arguments are very similar.

//license_buf is of size 0x400
//content_id is of size 0x30
//account_id is of size 0x8
//start_time is of size 0x8
//expiration_time is of size 0x8
int scePsmDrmGetRifInfoForDriver(ScePsmDrmLicense *license_buf, char *content_id, uint64_t *account_id, uint64_t *start_time, uint64_t *expiration_time);

get_info_2_for_driver

Version NID
3.60 0x8C8CFD01

this function is named after sceNpDrmGetRifInfoForDriver since arguments are very similar

//data is of size 0x400
//out0 is of size 0x200
//out1 is of size 0x4
//out2 is of size 0x8
//out3 is of size 0x8
int get_info_2_for_driver(void *data, void *out0, void *out1, void *out2, int out3);

set_psm_act_data

Version NID
3.60 0xCB73E9D3

decrypts psm_act_data with aes_dec_key

creates tm0:/psmdrm if nesessary

writes tm0:/psmdrm/act.dat

verifies sha256 - rca

//data is of size 0x400
int set_psm_act_data(void *psm_act_data, const char *aes_dec_key);

unk_4CD5375C

Version NID
3.60 0x4CD5375C

Deletes psmact.dat.

int unk_4CD5375C(int unk);

unk_791198CE

Version NID
3.60 0x791198CE
int unk_791198CE();

unk_B09003A7

Version NID
3.60 0xB09003A7
int unk_B09003A7(int unk0, int unk1, int unk2, int unk3, int arg_0);

Package integrity checks

Disable hash/signature verification

To find the function responsible for package verification search for immediate 0x7F504B47 ('.PKG'). Inside it does a lot of stuff including determining the function that will do signature checks. Find the condition that looks like if ( (v62 & 7) == 3 ); below you will see the assignment check_func = &off_81009CFC;. To bypass signature checks you need to patch two functions located at this offset and offset+4, making them behave as "return 1" is enough. For reference, on 1.60 the functions are sub_81000310 and sub_81000AA4. sub_81000310 is the only function in this module that calls SceSblGcAuthMgrPkgForDriver_E459A9A8_imp.

Note that on 1.60 this module sometimes is loaded at different addresses between reboots.

Allow debug packages to be installed

Find the function that calls sceSblAIMgrIsCEXForDriver. Patch it to always return 1. On 1.60 it's at 0x81002d64.

Search for immediate 0x80870003, there should be two matches. Replace both with "MOV Reg, #0". On 1.60 the locations are 0x810035fe and 0x81004856.

RIF

The rif file holds the klicensee for NPDRM contents.

The RIF files are used as the eboot.bin DRM. For each installed PKG and Game Card you will have an unique RIF file with proper information that will be used when you open the game to verify if you own the game(to PKG) and decrypt the eboot.bin. The RIF files may hold important information as PSN Account ID, the key used to decrypt one of the SELF encrypt layers [...].

PSVita supports two different RIF file format. The first format (License Type 0) seems to be used by licenses with 0x98 bytes size and the second (License Type 1) seems to be used by RIF files with 0x200 bytes size. The difference between them is just the signature verification. License Type 0 only uses ECDSA Signature, the License Type 1 uses the ECDSA Signature verification and an extra RSA signature verification.

Name Offset Size Remarks
Version 0x0 0x2
Version Flag 0x2 0x2 0 or 1
License Type 0x4 0x2
License Flags 0x6 0x2
PSN Account ID 0x8 0x8
Content ID 0x10 0x30 CONTENT_ID
Primary Key Table index 0x40 0x10 Used for selecting act.dat key.
RIF Key 1 0x50 0x10 Used to decrypt NPDRM SELF/SPRX/EDAT/PFS files.
License start time 0x60 0x8 For human readable, convert to decimal and use an Epoch-Unix converter time format online.
License expiration time 0x68 0x8 If zeroed, there is no time limit. Used for PS+ time-limited content for example.
ECDSA Signature 0x70 0x28 Patched in most PS3 CFWs to allow unsigned. See Rif_Junk on Rap2Rif by Flatz, params are same as for act.dat.
Some Flag 0x98 0x8
RIF Key 2 0xA0 0x10
Unknown_B0 0xB0 0x10
OpenPsId 0xC0 0x10 Present only if bit 8 is set in License Flags.
Unknown_D0 0xD0 0x10
CMD56 handshake part 0xE0 0x14 Present only if bit 0xA is set in License Flags.
Unknown_F4 0xF4 0x4 Some Flag related to debug_upgradable.
Unknown_F8 0xF8 0x4
SKU flag 0xFC 0x4
RSA Signature 0x100 0x100

PSM-ACT

PSM Activation file

Name Offset Size Example Remark
Magic 0x0 0x8 "PSM-ACT"
Unknown1 0x8 0x8 00 00 00 00 00 00 00 00
Account Id 0x10 0x8 91 78 34 02 01 EF CD AB PSN account ID (little endian)
Unknown2 0x18 0x4 00 00 00 00 Must be 0
Unknown3 0x1C 0x4 00 00 00 00 Must be 0
Activation start time 0x20 0x8 00 00 01 4C 16 4D 83 A8
Activation expiration time 0x28 0x8 00 00 04 2A D4 3D 3E 68
SHA256 from act.dat 0x30 0x20 SHA256 digest of get_act_data (0x39222A58)
Unknown4 0x50 0xB0 Zeros
Unknown5 0x100 0x200 KEY saved at 0x22C8 - Decrypted with 0x2288
RSA signature 0x300 0x100

PSM-RIF

PSM RIF file

Name Offset Size Example Remark
Magic Number 0x0 0x8 "PSM-RIF"
Unknown1 0x8 0x4 00 00 00 01 Maybe Version and Version Flag?
Unknown2 0xC 0x4 00 00 00 00 Maybe License Type and License Flags?
Account ID 0x10 0x8 91 78 34 02 01 EF CD AB PSN account ID (little endian)
Unknown3 0x18 0x4 00 00 00 00 Must be 0
Unknown4 0x1C 0x4 00 00 00 00 Must be 0
Activation start time 0x20 0x8 00 00 01 4C 16 4D 83 A8
Activation expiration time 0x28 0x8 7F FF FF FF FF FF FF FF Max Value
SHA256 from act.dat 0x30 0x20 SHA256 digest of get_act_data (0x39222A58)
Content ID 0x50 0x30 EM0041-NPOA00013_00-0000000000000000
Unknown5 0x80 0x80 Zeros
Unknown6 0x100 0x200 Key saved at 0x1F40. First 0x200 bytes are decrypted with 0x22C8 and then only the first 0x20 bytes are again decrypted with 0x2288
RSA signature 0x300 0x100