GcToolKit/kern/cmd56.c

151 lines
4.7 KiB
C

#include <stdint.h>
#include <stdio.h>
#include <taihen.h>
#include <vitasdkkern.h>
#include "cmd56.h"
#include "log.h"
// static variables
static uint8_t LAST_CAPTURED_CMD20_INPUT[0x116];
static uint32_t LAST_CAPTURED_CMD20_KEYID = 0;
static uint8_t HAS_CAPTURED_CMD20 = 0;
// prototype keyid check patch
static int proto_keyid_check_inject = -1;
// hooks for capturing GC comms
static int ksceSblSmCommCallFuncHook = -1;
static tai_hook_ref_t ksceSblSmCommCallFuncHookRef;
int (* gc_insert_interupt)(uint32_t param_1, int param_2, int param_3, char* param_4);
int ksceSblSmCommCallFunc_patch(SceSblSmCommId id, SceUInt32 service_id, SceUInt32 *service_result, SceSblSmCommGcData *data, SceSize size) {
if(data->command == 0x20) {
PRINT_STR("copy auth input, data->data %x\n", data->data);
memcpy(LAST_CAPTURED_CMD20_INPUT, data->data, sizeof(LAST_CAPTURED_CMD20_INPUT));
PRINT_STR("keyid %x\n", data->key_id);
LAST_CAPTURED_CMD20_KEYID = data->key_id;
HAS_CAPTURED_CMD20 = 1;
}
return TAI_CONTINUE(int, ksceSblSmCommCallFuncHookRef, id, service_id, service_result, data, size);
}
void cmd56_patch() {
memset(LAST_CAPTURED_CMD20_INPUT, 0x00, sizeof(LAST_CAPTURED_CMD20_INPUT));
tai_module_info_t gc_authmgr_info;
gc_authmgr_info.size = sizeof(tai_module_info_t);
int authmgr_get_info = taiGetModuleInfoForKernel(KERNEL_PID, "SceSblGcAuthMgr", &gc_authmgr_info);
PRINT_STR("get module SceSblGcAuthMgr 0x%04X\n", authmgr_get_info);
if(authmgr_get_info >= 0) {
// prototype game carts use key ids != 1,
// 3.60 firmware checks if ((key_id & 0xffff7fff) == 1)
// it would be nice if we could dump prototype gamecarts tho ..
uint16_t nop_instruction = 0xBF00;
proto_keyid_check_inject = taiInjectDataForKernel(KERNEL_PID, gc_authmgr_info.modid, 0, 0x9376, &nop_instruction, sizeof(uint16_t));
PRINT_STR("proto_keyid_check_inject 0x%04X\n", proto_keyid_check_inject);
// capture sm communications
ksceSblSmCommCallFuncHook = taiHookFunctionImportForKernel(KERNEL_PID,
&ksceSblSmCommCallFuncHookRef,
"SceSblGcAuthMgr",
0xCD3C89B6, // SceSblSmCommForKernel
0xDB9FC204, // ksceSblSmCommCallFunc
ksceSblSmCommCallFunc_patch);
PRINT_STR("ksceSblSmCommCallFuncHook 0x%04X\n", ksceSblSmCommCallFuncHook);
PRINT_STR("ksceSblSmCommCallFuncHookRef 0x%04X\n", ksceSblSmCommCallFuncHookRef);
}
tai_module_info_t sdstor_info;
sdstor_info.size = sizeof(tai_module_info_t);
int sdstor_get_info = taiGetModuleInfoForKernel(KERNEL_PID, "SceSdstor", &sdstor_info);
PRINT_STR("get module SceSdstor 0x%04X\n", authmgr_get_info);
if(sdstor_get_info >= 0){
int res = module_get_offset(KERNEL_PID, sdstor_info.modid, 0, 0x3BE0 | 1, (uintptr_t*)&gc_insert_interupt);
PRINT_STR("module_get_offset 0x%04X\n", res);
}
}
void cmd56_unpatch() {
if (ksceSblSmCommCallFuncHook >= 0) taiHookReleaseForKernel(ksceSblSmCommCallFuncHook, ksceSblSmCommCallFuncHookRef);
if (proto_keyid_check_inject >= 0) taiInjectReleaseForKernel(proto_keyid_check_inject);
}
// user syscalls
int ResetCmd20Input() {
// remove the flag saying we have captured one so another GC can have data captured.
memset(LAST_CAPTURED_CMD20_INPUT, 0x00, sizeof(LAST_CAPTURED_CMD20_INPUT));
HAS_CAPTURED_CMD20 = 0;
return 0;
}
int GetLastCmd20Input(char* cmd20_input) {
ksceKernelMemcpyKernelToUser(cmd20_input, (const void*)LAST_CAPTURED_CMD20_INPUT, sizeof(LAST_CAPTURED_CMD20_INPUT));
return 0;
}
int GetLastCmd20KeyId() {
return LAST_CAPTURED_CMD20_KEYID;
}
int HasCmd20Captured() {
return HAS_CAPTURED_CMD20;
}
int ResetGc() {
// spent ages trying to find a way to run gc authentication again when already inserted
// then i had a thought ???
// have you tried turning it off and on again ????
char param_4[0x10];
memset(param_4, 0x00, sizeof(param_4));
PRINT_STR("Resetting GC ...\n");
// trigger gc remove interupt
int res = gc_insert_interupt(0, 0x200, 0, param_4);
PRINT_STR("gc_insert_interupt(0, 0x200, 0, param_4) 0x%04X\n", res);
if(res < 0) return res;
// power down gc slot
res = ksceSysconCtrlSdPower(0);
PRINT_STR("ksceSysconCtrlSdPower(0) 0x%04X\n", res);
if(res < 0) return res;
// power up gc slot
res = ksceSysconCtrlSdPower(1);
PRINT_STR("ksceSysconCtrlSdPower(1) 0x%04X\n", res);
if(res < 0) return res;
// trigger gc insert interupt
res = gc_insert_interupt(1, 0x100000, 0, param_4);
PRINT_STR("gc_insert_interupt(1, 0x100000, 0, param_4) 0x%04X\n", res);
if(res < 0) return res;
PRINT_STR("param_4[5] = 0x%04X\n", param_4[5]);
return 0;
}
int ClearFinalKeys() {
return ksceSblGcAuthMgrDrmBBClearCartSecret();
}
int GetFinalKeys(char* keys) {
char k_keys[0x20];
memset(k_keys, 0x00, sizeof(k_keys));
int res = ksceSblGcAuthMgrDrmBBGetCartSecret(k_keys);
ksceKernelMemcpyKernelToUser(keys, (const void*)k_keys, sizeof(k_keys));
return res;
}