diff --git a/jni/Android.mk b/jni/Android.mk index d5a196f..cd276ed 100644 --- a/jni/Android.mk +++ b/jni/Android.mk @@ -10,6 +10,7 @@ LOCAL_C_INCLUDES += $(MAIN_LOCAL_PATH) LOCAL_SRC_FILES := default.c \ nopsmdrm.c \ + sysinfo.c \ hooks/inlineHook.c \ hooks/relocate.c diff --git a/jni/default.c b/jni/default.c index 927a21f..47c2471 100644 --- a/jni/default.c +++ b/jni/default.c @@ -3,14 +3,17 @@ #include #include +#include "sysinfo.h" #include "nopsmdrm.h" +#define PSM_LIB_PATHS "/data/data/com.playstation.psstore/lib/" + jint (*JNI_OnLoad_real)(JavaVM* vm, void* reserved) = NULL; JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { LOGFUNCTION(); - void* handle = dlopen("/data/data/com.playstation.psstore/lib/libdefault_real.so", RTLD_LAZY); + void* handle = dlopen(PSM_LIB_PATHS "libdefault_real.so", RTLD_LAZY); LOG("dlopen libdefault_real.so @ %p errno = %x", handle, errno); if(handle == NULL) { @@ -28,7 +31,9 @@ JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { LOG("RUN JNI_OnLoad_real @ %p", JNI_OnLoad_real); jint res = JNI_OnLoad_real(vm, reserved); LOG("Install Pathces"); - patch_libdefault(handle); + + set_lib_default_handle(handle); + patch_nopsmdrm(); return res; } \ No newline at end of file diff --git a/jni/log.h b/jni/log.h new file mode 100644 index 0000000..90a0cc8 --- /dev/null +++ b/jni/log.h @@ -0,0 +1,15 @@ +#ifndef LIB_DEFAULT_LOG_H +#define LIB_DEFAULT_LOG_H + +#include +#define LOG(...) __android_log_print(ANDROID_LOG_DEBUG, "LIBDEFAULTPROXY", __VA_ARGS__) +#define LOGFUNCTION() __android_log_print(ANDROID_LOG_DEBUG, "LIBDEFAULTPROXY", "%s", __FUNCTION__) +#define LOGBUF(buffer, buffer_sz) char buf[buffer_sz * 3 + 2]; \ + char *out_p = buf;\ + const unsigned char *const in_p = (void*)buffer;\ + for (int i = 0; i < buffer_sz; i++) { \ + sprintf(out_p, " %02x", in_p[i]); \ + out_p += 3; \ + } \ + LOG("%s", buf); +#endif // LIB_DEFAULT_LOG_H \ No newline at end of file diff --git a/jni/nopsmdrm.c b/jni/nopsmdrm.c index 6973107..f3576df 100644 --- a/jni/nopsmdrm.c +++ b/jni/nopsmdrm.c @@ -1,48 +1,41 @@ +#include +#include #include #include #include #include "nopsmdrm.h" -#include "hooks/inlineHook.h" +#include "sysinfo.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; +int (*scePsmDrmGetRif_orig)(char*, char*, ScePsmDrmLicense *) = NULL; +void* rif_hmac_verify_edata_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) { +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); - mkdir(FAKE_LICENSE_OUTPUT); + // 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); @@ -51,8 +44,7 @@ void MakeFakeLicense(ScePsmDrmLicense* license_buf, uint8_t* klicensee) { } -void GetAllLicenses(char* psm_folder) { - +void get_all_licenses(char* psm_folder) { char contentId[0x100]; char klicensee[0x200]; ScePsmDrmLicense license; @@ -62,18 +54,20 @@ void GetAllLicenses(char* psm_folder) { return; struct dirent* ent = NULL; - while((ent = readdir(dfd)) != 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(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) { - MakeFakeLicense(&license, klicensee); + if(res >= 0) { // if got keys successfully, create a FAKE.rif for the game! + make_fake_license(&license, klicensee); } } } @@ -83,13 +77,14 @@ int scePsmDrmGetKeySet_patch(ScePsmDrmLicense *license_buf, char *klicensee, int 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"); - MakeFakeLicense(license_buf, klicensee); + make_fake_license(license_buf, klicensee); } - else if(license_buf->aid == FAKE_AID) { + 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; @@ -112,11 +107,13 @@ int scePsmDrmGetRif_patch(char *contentid, char *psm_folder, ScePsmDrmLicense *r int res = scePsmDrmGetRif_orig(contentid, psm_folder, rif_file); LOG("res = %x", res); - if(res < 0) { + 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[10]; - memcpy(titleid, contentid + 7, sizeof(titleid)); - titleid[9] = '\0'; + char titleid[0x100]; + memset(titleid, 0x00, sizeof(titleid)); + strncpy(titleid, (contentid + 7), 9); // locate FAKE.RIF char fakeRifPath[0x100]; @@ -126,7 +123,7 @@ int scePsmDrmGetRif_patch(char *contentid, char *psm_folder, ScePsmDrmLicense *r // Read FAKE.RIF into the buffer ... FILE* fd = fopen(fakeRifPath, "rb"); if(fd != NULL) { - LOG("reading in FAKE.rif ..."); + LOG("Reading in FAKE.rif ..."); fread(rif_file, sizeof(ScePsmDrmLicense), 1, fd); fclose(fd); } @@ -135,45 +132,31 @@ int scePsmDrmGetRif_patch(char *contentid, char *psm_folder, ScePsmDrmLicense *r return res; } - LOG("faking success.."); + LOG("Faking success.."); return 0; } - if(access("/sdcard/psm/dump_all", F_OK) == 0){ - GetAllLicenses(psm_folder); + // 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 verify_rif_top_part_patch() { - return 0; +int rif_hmac_verify_edata_patch() { + return 0; // SCE_OK } -int patch_libdefault(void* handle) { - - LIB_DEFAULT_HANDLE = handle; +int patch_nopsmdrm() { - uintptr_t* scePsmDrmGetRif = get_func_addr("scePsmDrmGetRif"); - LOG("Hooking scePsmDrmGetRif %p", scePsmDrmGetRif); + // patch psmdrm (nopsmdrm patches ...) + hook_func_export("scePsmDrmGetRif", scePsmDrmGetRif_patch, &scePsmDrmGetRif_orig); + hook_func_export("scePsmDrmGetKeySet", scePsmDrmGetKeySet_patch, &scePsmDrmGetKeySet_orig); - 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); + // 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; } diff --git a/jni/nopsmdrm.h b/jni/nopsmdrm.h index 3607e4d..59e847c 100644 --- a/jni/nopsmdrm.h +++ b/jni/nopsmdrm.h @@ -1,18 +1,10 @@ -#ifndef PSM_KDC_NOPSMDRM_H -#define PSM_KDC_NOPSMDRM_H - -#include -#define LOG(...) __android_log_print(ANDROID_LOG_DEBUG, "LIBDEFAULTPROXY", __VA_ARGS__) -#define LOGFUNCTION() __android_log_print(ANDROID_LOG_DEBUG, "LIBDEFAULTPROXY", "%s", __FUNCTION__) -#define LOGBUF(buffer, buffer_sz) char buf[buffer_sz * 3 + 2]; \ - char *out_p = buf;\ - const unsigned char *const in_p = (void*)buffer;\ - for (int i = 0; i < buffer_sz; i++) { \ - sprintf(out_p, " %02x", in_p[i]); \ - out_p += 3; \ - } \ - LOG("%s", buf); +#ifndef LIB_DEFAULT_NOPSMDRM_H +#define LIB_DEFAULT_NOPSMDRM_H +#include "log.h" +#define FAKE_AID 0x0123456789ABCDEFLL +#define FAKE_LICENSE_OUTPUT "/sdcard/psm" +#define DUMP_ALL_FLAG_FILE (FAKE_LICENSE_OUTPUT "/dump_all") typedef struct { @@ -32,6 +24,6 @@ typedef struct } ScePsmDrmLicense; -int patch_libdefault(void* handle); +int patch_nopsmdrm(); -#endif //PSM_KDC_NOPSMDRM_H +#endif //LIB_DEFAULT_NOPSMDRM_H diff --git a/jni/sysinfo.c b/jni/sysinfo.c new file mode 100644 index 0000000..da13919 --- /dev/null +++ b/jni/sysinfo.c @@ -0,0 +1,39 @@ +#include +#include "sysinfo.h" +#include "hooks/inlineHook.h" + +static void* LIB_DEFAULT_HANDLE = 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 hook_func(void* func_ptr, void* patch_func, void* orig_func) { + LOG("registerInlineHook: %p", func_ptr); + int res = registerInlineHook((uintptr_t)func_ptr, (uintptr_t)patch_func, (uintptr_t**)orig_func); + + if(res == 0){ + LOG("success; res = 0x%x", res); + inlineHook(func_ptr); + } + else { + LOG("failed, res = 0x%x", res); + } +} + +void hook_func_export(char* function_name, void* patch_func, void* orig_func) { + void* func_ptr = get_func_addr(function_name); + LOG("Hooking %s %p", function_name, func_ptr); + + hook_func(func_ptr, patch_func, orig_func); +} + +void set_lib_default_handle(void* handle) { + LIB_DEFAULT_HANDLE = handle; +} \ No newline at end of file diff --git a/jni/sysinfo.h b/jni/sysinfo.h new file mode 100644 index 0000000..cf61a5c --- /dev/null +++ b/jni/sysinfo.h @@ -0,0 +1,10 @@ +#ifndef LIB_DEFAULT_SYSINFO_H +#define LIB_DEFAULT_SYSINFO_H +#include "log.h" + +void set_lib_default_handle(void* handle); +void hook_func_export(char* function_name, void* patch_func, void* orig_func); +void hook_func(void* func_ptr, void* patch_func, void* orig_func); +void* get_func_addr(char* function_name); + +#endif //LIB_DEFAULT_NOPSMDRM_H \ No newline at end of file