libdefault_proxy/jni/nopsmdrm.c

164 lines
4.9 KiB
C

#include <sys/stat.h>
#include <sys/types.h>
#include <stdlib.h>
#include <dirent.h>
#include <unistd.h>
#include "nopsmdrm.h"
#include "sysinfo.h"
int (*scePsmDrmGetKeySet_orig)(ScePsmDrmLicense*, char*, int*, uint64_t*, uint64_t*) = NULL;
int (*scePsmDrmGetRif_orig)(char*, char*, ScePsmDrmLicense *) = NULL;
void* rif_hmac_verify_edata_orig = NULL;
void make_fake_license(ScePsmDrmLicense* license_buf, void* klicensee) {
// allocate a FAKE license structure on the stack,
ScePsmDrmLicense license;
memset(&license, 0, sizeof(ScePsmDrmLicense));
// set account id to FAKE_AID, unk1 to 1 ...
license.aid = FAKE_AID;
license.unk1 = __builtin_bswap32(1);
// copy the content id and klicensee buf into the FAKE.rif
memcpy(license.content_id, license_buf->content_id, 0x30);
memcpy(license.key, klicensee, 0x200);
// get the path to the FAKE.rif (/sdcard/psm/CONTENT_ID.rif)
char fakeRifPath[0x100];
snprintf(fakeRifPath, sizeof(fakeRifPath) - 1, "%s/%s.rif", FAKE_LICENSE_OUTPUT, license_buf->content_id);
LOG("fakeRifPath: %s", fakeRifPath);
// create the (/sdcard/psm/) if not exist already ...
mkdir(FAKE_LICENSE_OUTPUT, 0777);
// write the FAKE.rif file ..
LOG("Writing fake license ...");
FILE* fd = fopen(fakeRifPath, "wb");
if(fd != NULL) {
fwrite(&license, sizeof(ScePsmDrmLicense), 1, fd);
fclose(fd);
}
}
void get_all_licenses(char* psm_folder) {
char contentId[0x100];
char klicensee[0x200];
ScePsmDrmLicense license;
DIR* dfd = opendir(psm_folder);
if(dfd == NULL)
return;
struct dirent* ent = NULL;
while((ent = readdir(dfd)) != NULL) { // iterate over every folder in the psm folder ..
// create a bogus 'content id' string (the GetRif function only reads the titleid part anyways!)
snprintf(contentId, sizeof(contentId) - 1, "UM0105-%s_00-0000000000000000", ent->d_name);
LOG("obtaining rif for: %s", contentId);
// read the rif for this content id
int res = scePsmDrmGetRif_orig(contentId, psm_folder, &license);
LOG("scePsmDrmGetRif was %x", res);
if(res >= 0) { // if thats successful, get the keys for that rif we just read
res = scePsmDrmGetKeySet_orig(&license, klicensee, NULL, NULL, NULL);
LOG("scePsmDrmGetKeySet was %x", res);
if(res >= 0) { // if got keys successfully, create a FAKE.rif for the game!
make_fake_license(&license, klicensee);
}
}
}
}
int scePsmDrmGetKeySet_patch(ScePsmDrmLicense *license_buf, char *klicensee, int* flags, uint64_t* start_time, uint64_t* expiration_time) {
LOG("license_buf %p, klicensee %p, flags %p, start_time %p, expiration_time %p", license_buf, klicensee, flags, start_time, expiration_time);
int res = scePsmDrmGetKeySet_orig(license_buf, klicensee, flags, start_time, expiration_time);
if(res >= 0) {
// if it was no error, (i.e an offical license was loaded) then save it as a fake license.
LOG("Creating fake license file");
make_fake_license(license_buf, klicensee);
}
else if(license_buf->aid == FAKE_AID) {
// the function did return an error, check if the account ID == FAKE_AID.
LOG("Using FAKE.RIF!");
memcpy(klicensee, license_buf->key, 0x200);
return 0;
}
// bypass expiration time
if(start_time != NULL) {
*start_time = 0x0;
}
if(expiration_time != NULL) {
*expiration_time = 0x7FFFFFFFFFFFFFFFLL;
}
return res;
}
int scePsmDrmGetRif_patch(char *contentid, char *psm_folder, ScePsmDrmLicense *rif_file) {
LOG("contentid: %s psm_folder: %s", contentid, psm_folder);
int res = scePsmDrmGetRif_orig(contentid, psm_folder, rif_file);
LOG("res = %x", res);
if(res < 0) { // if original function returned an error ( < 0)
// then we want to read in the FAKE.RIF for the game ...
// get title id :
char titleid[0x100];
memset(titleid, 0x00, sizeof(titleid));
strncpy(titleid, (contentid + 7), 9);
// locate FAKE.RIF
char fakeRifPath[0x100];
snprintf(fakeRifPath, sizeof(fakeRifPath) - 1, "%s%s/License/FAKE.rif", psm_folder, titleid);
LOG("fakeRifPath: %s", fakeRifPath);
// Read FAKE.RIF into the buffer ...
FILE* fd = fopen(fakeRifPath, "rb");
if(fd != NULL) {
LOG("Reading in FAKE.rif ...");
fread(rif_file, sizeof(ScePsmDrmLicense), 1, fd);
fclose(fd);
}
else {
LOG("Failed to open FAKE.rif!!!");
return res;
}
LOG("Faking success..");
return 0;
}
// check if /sdcard/psm/dump_all exists, if it does, dump all licenses you have.
if(access(DUMP_ALL_FLAG_FILE, F_OK) == 0){
get_all_licenses(psm_folder);
remove(DUMP_ALL_FLAG_FILE);
}
return res;
}
int rif_hmac_verify_edata_patch() {
return 0; // SCE_OK
}
int patch_nopsmdrm() {
// patch psmdrm (nopsmdrm patches ...)
hook_func_export("scePsmDrmGetRif", scePsmDrmGetRif_patch, &scePsmDrmGetRif_orig);
hook_func_export("scePsmDrmGetKeySet", scePsmDrmGetKeySet_patch, &scePsmDrmGetKeySet_orig);
// patch rif hmac key verify (make it work with vita rifs)
hook_func((get_func_addr("scePsmInitialize") + 0x302EE0), rif_hmac_verify_edata_patch, &rif_hmac_verify_edata_orig);
return 0;
}