Module
Known NIDs
Version |
Name |
World |
Privilege |
NID
|
1.69 |
SceNpDrm |
Non-secure |
Kernel |
0xACCB4845
|
3.60 |
SceNpDrm |
? |
Kernel |
0xE7E2CE05
|
Libraries
Known NIDs
Data segment layout
Address |
Size |
Description
|
0x0000 |
0x4 |
SceNpDrm mutex SceUID
|
0x0004 |
0x4 |
ScePsmDrm mutex SceUID
|
0x0008 |
0x8 |
unknown
|
0x0010 |
0xC0 |
constant data decrypted with sceSblAuthMgrGetEKc key 0.
First 0x10 bytes are reencrypted with aes key from get_aes_key.
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 |
0x34 |
unknown
|
0x0E00 |
0x1040 |
tm0:/npdrm/act.dat data
|
0x1E40 |
0x400 |
tm0:/psmdrm/act.dat data
|
0x2240 |
0x10 |
some key that should be equal to 0x10 of rif from offset 0xC0
This key is compared against OpenPsId from act.dat
|
0x2250 |
0x10 |
unknown
|
0x2260 |
0x4 |
Loose Account Bind flag
|
0x2264 |
0x84 |
unknown
|
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 |
0xB8C5DA7C
|
3.60 |
0xB8C5DA7C
|
int _sceNpDrmGetRifName(char *name, int ignored, int unk2, int unk3);
_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 _sceNpDrmGetRifInfo_opt //size is 0x28
{
char* unk_0; // buffer of size 0x30
char* unk_4; // buffer of size 0x8
char* unk_8; // buffer of size 0x4
char* unk_C; // buffer of size 0x4
char* unk_10; // buffer of size 0x4
char* unk_14; // buffer of size 0x4
char* unk_18; // buffer of size 0x8
char* unk_1C; // buffer of size 0x8
char* unk_20; // buffer of size 0x8
}_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
//out0 buffer is of size 0x30
//out1 buffer is of size 0x8
//out2 buffer is of size 0x4
//out3 buffer is of size 0x4
//out4 buffer is of size 0x4
//out5 buffer is of size 0x4
//out6 buffer is of size 0x8
//out7 buffer is of size 0x8
//out8 buffer is of size 0x8
int sceNpDrmGetRifInfoForDriver(void* rif_data, int rif_size, int num, void* out0, void* out1, void* out2, void* out3, void* out4, void* out5, void* out6, void* out7, void* out8);
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 unknown but at least 0xF8
int sceNpDrmGetRifNameForInstallForDriver(char *name, void *rif_data, int num);
sceNpDrmPresetRifProvisionalFlagForDriver
Version |
NID
|
3.60 |
0xC070FE89
|
//rif data size is unknown but 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
|
int sceNpDrmEbootSigVerifyForDriver(int unk0, int unk1);
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
|
int sceNpDrmGetRifVitaKeyForDriver(void *rif_data, void *dec_rif_key, int unk2, int unk3, int arg_0, int arg_4, int arg_8);
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 - rca
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
//data is of size 0x1040 - this is most likely act.dat data because of size
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 *buffer, SceSize size, int zero, 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 {
/** The offset in the encrypted data */
SceOff offset;
/**
* The identifier specified for _sceNpDrmPackageCheck but NOT ORed
* with (1 << 8)
*/
unsigned int identifier;
} _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
|
ScePsmDrm
get_rif_name
Version |
NID
|
3.60 |
0x0D6470DA
|
//some data is of size 0x400
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);
_get_info_2
Version |
NID
|
3.60 |
0x207A2C53
|
typedef struct get_info2_opt //size is 0x10
{
void* out2;
void* out3;
uint32_t unk_8;
uint32_t unk_C;
}get_info2_opt
int _get_info(void *some_data, void *out0, void *out1, get_info2_opt *opt);
ScePsmDrmForDriver
get_info_for_driver
Version |
NID
|
3.60 |
0x984F9017
|
this function is named after sceNpDrmGetRifInfoForDriver since arguments are very similar
//some_data is of size 0x400 and should contain rca signature at offset 0x300
//out0 is of size 0x30
//out1 is of size 0x8
//out2 is of size 0x8
//out3 is of size 0x8
int get_info_for_driver(void *some_data, void *out0, void *out1, void *out2, void *out3);
unk_CB73E9D3
Version |
NID
|
3.60 |
0xCB73E9D3
|
//data is of size 0x400
int unk_CB73E9D3(void *data, const char *aes_dec_key);
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);
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 SceSblAIMgrForDriver_D78B04A2; 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 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 [...].
PS Vita supports two different RIF file format. The first format (License Type 0) seems to be used by licenses with 0x97 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
|
Version |
0x0 |
0x4
|
License Type |
0x4 |
0x4
|
PSN Account ID |
0x8 |
0x8
|
Content ID |
0x10 |
0x30
|
Primary Key Table index |
0x40 |
0x10
|
RIF Key |
0x50 |
0x10
|
License start time |
0x60 |
0x8
|
License expiration time |
0x68 |
0x8
|
ECDSA Signature |
0x70 |
0x28
|
Unknown |
0x98 |
0x28
|
Unknown |
0xC0 |
0x10
|
Unknown |
0xD0 |
0x10
|
CMD56 handshake part |
0xE0 |
0x14
|
Unknown |
0xF4 |
0x0C
|
RSA Signature |
0x100 |
0x100
|