181 lines
4.8 KiB
C
181 lines
4.8 KiB
C
#include <stdlib.h>
|
|
#include <dirent.h>
|
|
#include <unistd.h>
|
|
|
|
#include "nopsmdrm.h"
|
|
#include "hooks/inlineHook.h"
|
|
|
|
#define FAKE_AID 0x0123456789ABCDEFLL
|
|
#define FAKE_LICENSE_OUTPUT "/sdcard/psm"
|
|
static void* LIB_DEFAULT_HANDLE = NULL;
|
|
|
|
int (*scePsmDrmGetKeySet_orig)(ScePsmDrmLicense*, char*, int*, uint64_t*, uint64_t*) = NULL;
|
|
void* (*scePsmDrmGetRif_orig)(char*, char*, ScePsmDrmLicense *) = NULL;
|
|
uintptr_t verify_rif_top_part_orig = NULL;
|
|
|
|
|
|
void* get_func_addr(char* function_name) {
|
|
if(LIB_DEFAULT_HANDLE != NULL){
|
|
uintptr_t function_addr = (uintptr_t)dlsym(LIB_DEFAULT_HANDLE, function_name);
|
|
|
|
LOG("load function_addr %p", function_addr);
|
|
return function_addr;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void MakeFakeLicense(ScePsmDrmLicense* license_buf, uint8_t* klicensee) {
|
|
ScePsmDrmLicense license;
|
|
memset(&license, 0, sizeof(ScePsmDrmLicense));
|
|
license.aid = FAKE_AID;
|
|
license.unk1 = __builtin_bswap32(1);
|
|
|
|
memcpy(license.content_id, license_buf->content_id, 0x30);
|
|
memcpy(license.key, klicensee, 0x200);
|
|
|
|
|
|
char fakeRifPath[0x100];
|
|
snprintf(fakeRifPath, sizeof(fakeRifPath) - 1, "%s/%s.rif", FAKE_LICENSE_OUTPUT, license_buf->content_id);
|
|
LOG("fakeRifPath: %s", fakeRifPath);
|
|
|
|
mkdir(FAKE_LICENSE_OUTPUT);
|
|
|
|
LOG("Writing fake license ...");
|
|
|
|
FILE* fd = fopen(fakeRifPath, "wb");
|
|
if(fd != NULL) {
|
|
fwrite(&license, sizeof(ScePsmDrmLicense), 1, fd);
|
|
fclose(fd);
|
|
}
|
|
|
|
}
|
|
|
|
void GetAllLicenses(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) {
|
|
snprintf(contentId, sizeof(contentId) - 1, "UM0105-%s_00-0000000000000000", ent->d_name);
|
|
LOG("obtaining rif for: %s", contentId);
|
|
|
|
int res = scePsmDrmGetRif_orig(contentId, psm_folder, &license);
|
|
LOG("scePsmDrmGetRif was %x", res);
|
|
|
|
if(res >= 0) {
|
|
res = scePsmDrmGetKeySet_orig(&license, klicensee, NULL, NULL, NULL);
|
|
LOG("scePsmDrmGetKeySet was %x", res);
|
|
if(res >= 0) {
|
|
MakeFakeLicense(&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) {
|
|
LOG("Creating fake license file");
|
|
MakeFakeLicense(license_buf, klicensee);
|
|
}
|
|
else if(license_buf->aid == 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) {
|
|
// get title id :
|
|
char titleid[10];
|
|
memcpy(titleid, contentid + 7, sizeof(titleid));
|
|
titleid[9] = '\0';
|
|
|
|
// 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;
|
|
}
|
|
|
|
if(access("/sdcard/psm/dump_all", F_OK) == 0){
|
|
GetAllLicenses(psm_folder);
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
int verify_rif_top_part_patch() {
|
|
return 0;
|
|
}
|
|
|
|
int patch_libdefault(void* handle) {
|
|
|
|
LIB_DEFAULT_HANDLE = handle;
|
|
|
|
uintptr_t* scePsmDrmGetRif = get_func_addr("scePsmDrmGetRif");
|
|
LOG("Hooking scePsmDrmGetRif %p", scePsmDrmGetRif);
|
|
|
|
int res = registerInlineHook((uintptr_t)scePsmDrmGetRif, (uintptr_t)scePsmDrmGetRif_patch, (uintptr_t**)&scePsmDrmGetRif_orig);
|
|
if(res == 0)
|
|
inlineHook((uintptr_t)scePsmDrmGetRif);
|
|
|
|
uintptr_t* scePsmDrmGetKeySet = get_func_addr("scePsmDrmGetKeySet");
|
|
LOG("Hooking scePsmDrmGetKeySet %p", scePsmDrmGetKeySet);
|
|
|
|
res = registerInlineHook((uintptr_t)scePsmDrmGetKeySet, (uintptr_t)scePsmDrmGetKeySet_patch, (uintptr_t**)&scePsmDrmGetKeySet_orig);
|
|
if(res == 0)
|
|
inlineHook((uintptr_t)scePsmDrmGetKeySet);
|
|
|
|
uintptr_t verify_rif_top_part = get_func_addr("scePsmInitialize") + 0x302EE0;
|
|
LOG("Hooking verify_rif_top_part %p", verify_rif_top_part);
|
|
|
|
res = registerInlineHook((uintptr_t)verify_rif_top_part, (uintptr_t)verify_rif_top_part_patch, (uintptr_t**)&verify_rif_top_part_orig);
|
|
if(res == 0)
|
|
inlineHook((uintptr_t)verify_rif_top_part);
|
|
|
|
return 0;
|
|
}
|
|
|