mirror of
https://github.com/SciresM/hactool
synced 2024-11-26 05:50:24 +00:00
Add JSON output for KIP1/INI, fix encrypted package2 input
This commit is contained in:
parent
cdbcdf0d4a
commit
d2d9146f68
7 changed files with 89 additions and 9 deletions
60
kip.c
60
kip.c
|
@ -2,6 +2,7 @@
|
|||
#include <stdio.h>
|
||||
#include "kip.h"
|
||||
#include "npdm.h"
|
||||
#include "cJSON.h"
|
||||
|
||||
void ini1_process(ini1_ctx_t *ctx) {
|
||||
/* Read *just* safe amount. */
|
||||
|
@ -79,10 +80,55 @@ void ini1_save(ini1_ctx_t *ctx) {
|
|||
strcat(padded_name, ".kip1");
|
||||
printf("Saving %s to %s/%s...\n", padded_name, dirpath->char_path, padded_name);
|
||||
save_buffer_to_directory_file(ctx->kips[i].header, kip1_get_size(&ctx->kips[i]), dirpath, padded_name);
|
||||
if (ctx->tool_ctx->action & ACTION_SAVEINIJSON) {
|
||||
printf("SAVING INI JSON!\n");
|
||||
memset(&padded_name, 0, sizeof(padded_name));
|
||||
memcpy(&padded_name, ctx->kips[i].header->name, sizeof(ctx->kips[i].header->name));
|
||||
strcat(padded_name, ".json");
|
||||
filepath_t json_path;
|
||||
filepath_init(&json_path);
|
||||
filepath_copy(&json_path, dirpath);
|
||||
filepath_append(&json_path, padded_name);
|
||||
FILE *f_json = os_fopen(json_path.os_path, OS_MODE_WRITE);
|
||||
if (f_json == NULL) {
|
||||
fprintf(stderr, "Failed to open %s!\n", json_path.char_path);
|
||||
return;
|
||||
}
|
||||
const char *json = kip1_get_json(&ctx->kips[i]);
|
||||
if (fwrite(json, 1, strlen(json), f_json) != strlen(json)) {
|
||||
fprintf(stderr, "Failed to write JSON file!\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
fclose(f_json);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char *kip1_get_json(kip1_ctx_t *ctx) {
|
||||
cJSON *kip_json = cJSON_CreateObject();
|
||||
const char *output_str = NULL;
|
||||
char work_buffer[0x300] = {0};
|
||||
|
||||
/* Add KIP1 header fields. */
|
||||
strcpy(work_buffer, ctx->header->name);
|
||||
cJSON_AddStringToObject(kip_json, "name", work_buffer);
|
||||
cJSON_AddU64ToObject(kip_json, "title_id", ctx->header->title_id);
|
||||
cJSON_AddU32ToObject(kip_json, "main_thread_stack_size", ctx->header->section_headers[1].attribute);
|
||||
cJSON_AddNumberToObject(kip_json, "main_thread_priority", ctx->header->main_thread_priority);
|
||||
cJSON_AddNumberToObject(kip_json, "default_cpu_id", ctx->header->default_core);
|
||||
cJSON_AddNumberToObject(kip_json, "process_category", ctx->header->process_category);
|
||||
|
||||
/* Add KAC. */
|
||||
cJSON *kac_json = kac_get_json(ctx->header->capabilities, sizeof(ctx->header->capabilities) / sizeof(uint32_t));
|
||||
cJSON_AddItemToObject(kip_json, "kernel_capabilities", kac_json);
|
||||
|
||||
output_str = cJSON_Print(kip_json);
|
||||
|
||||
cJSON_Delete(kip_json);
|
||||
return output_str;
|
||||
}
|
||||
|
||||
void kip1_process(kip1_ctx_t *ctx) {
|
||||
/* Read *just* safe amount. */
|
||||
kip1_header_t raw_header;
|
||||
|
@ -143,4 +189,18 @@ void kip1_print(kip1_ctx_t *ctx, int suppress) {
|
|||
|
||||
void kip1_save(kip1_ctx_t *ctx) {
|
||||
/* Do nothing. */
|
||||
filepath_t *json_path = &ctx->tool_ctx->settings.npdm_json_path;
|
||||
if (ctx->tool_ctx->file_type == FILETYPE_KIP1 && json_path->valid == VALIDITY_VALID) {
|
||||
FILE *f_json = os_fopen(json_path->os_path, OS_MODE_WRITE);
|
||||
if (f_json == NULL) {
|
||||
fprintf(stderr, "Failed to open %s!\n", json_path->char_path);
|
||||
return;
|
||||
}
|
||||
const char *json = kip1_get_json(ctx);
|
||||
if (fwrite(json, 1, strlen(json), f_json) != strlen(json)) {
|
||||
fprintf(stderr, "Failed to write JSON file!\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
fclose(f_json);
|
||||
}
|
||||
}
|
1
kip.h
1
kip.h
|
@ -54,6 +54,7 @@ void ini1_process(ini1_ctx_t *ctx);
|
|||
void ini1_print(ini1_ctx_t *ctx);
|
||||
void ini1_save(ini1_ctx_t *ctx);
|
||||
|
||||
const char *kip1_get_json(kip1_ctx_t *ctx);
|
||||
void kip1_process(kip1_ctx_t *ctx);
|
||||
void kip1_print(kip1_ctx_t *ctx, int suppress);
|
||||
void kip1_save(kip1_ctx_t *ctx);
|
||||
|
|
9
main.c
9
main.c
|
@ -54,8 +54,8 @@ static void usage(void) {
|
|||
" --basenca Set Base NCA to use with update partitions.\n"
|
||||
" --basefake Use a fake Base RomFS with update partitions (all reads will return 0xCC).\n"
|
||||
" --onlyupdated Ignore non-updated files in update partitions.\n"
|
||||
"NPDM options:\n"
|
||||
" --json=file Specify file path for saving JSON representation of NPDM to.\n"
|
||||
"NPDM/KIP1 options:\n"
|
||||
" --json=file Specify file path for saving JSON representation of program permissions to.\n"
|
||||
"PFS0 options:\n"
|
||||
" --pfs0dir=dir Specify PFS0 directory path.\n"
|
||||
" --outdir=dir Specify PFS0 directory path. Overrides previous path, if present.\n"
|
||||
|
@ -85,6 +85,7 @@ static void usage(void) {
|
|||
"INI1 options:\n"
|
||||
" --ini1dir=dir Specify INI1 directory path.\n"
|
||||
" --outdir=dir Specify INI1 directory path. Overrides previous path, if present.\n"
|
||||
" --saveini1json Enable generation of JSON descriptors for all INI1 members.\n"
|
||||
"NAX0 options:\n"
|
||||
" --sdseed=seed Set console unique seed for SD card NAX0 encryption.\n"
|
||||
" --sdpath=path Set relative path for NAX0 key derivation (ex: /registered/000000FF/cafebabecafebabecafebabecafebabe.nca).\n"
|
||||
|
@ -166,6 +167,7 @@ int main(int argc, char **argv) {
|
|||
{"sbk", 1, NULL, 34},
|
||||
{"tseckey", 1, NULL, 35},
|
||||
{"json", 1, NULL, 36},
|
||||
{"saveini1json", 0, NULL, 37},
|
||||
{NULL, 0, NULL, 0},
|
||||
};
|
||||
|
||||
|
@ -359,6 +361,9 @@ int main(int argc, char **argv) {
|
|||
case 36:
|
||||
filepath_set(&tool_ctx.settings.npdm_json_path, optarg);
|
||||
break;
|
||||
case 37:
|
||||
tool_ctx.action |= ACTION_SAVEINIJSON;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
|
|
16
npdm.c
16
npdm.c
|
@ -677,21 +677,27 @@ void npdm_save(npdm_t *npdm, hactool_ctx_t *tool_ctx) {
|
|||
}
|
||||
}
|
||||
|
||||
void cJSON_AddU8ToObject(cJSON *obj, char *name, unsigned int val) {
|
||||
void cJSON_AddU8ToObject(cJSON *obj, char *name, uint8_t val) {
|
||||
char buf[0x20] = {0};
|
||||
snprintf(buf, sizeof(buf), "0x%02x", val);
|
||||
snprintf(buf, sizeof(buf), "0x%02"PRIx8, val);
|
||||
cJSON_AddStringToObject(obj, name, buf);
|
||||
}
|
||||
|
||||
void cJSON_AddU16ToObject(cJSON *obj, char *name, uint16_t val) {
|
||||
char buf[0x20] = {0};
|
||||
snprintf(buf, sizeof(buf), "0x%04x", val & 0xFFFF);
|
||||
snprintf(buf, sizeof(buf), "0x%04"PRIx16, val & 0xFFFF);
|
||||
cJSON_AddStringToObject(obj, name, buf);
|
||||
}
|
||||
|
||||
void cJSON_AddU32ToObject(cJSON *obj, char *name, uint32_t val) {
|
||||
char buf[0x20] = {0};
|
||||
snprintf(buf, sizeof(buf), "0x%08"PRIx16, val);
|
||||
cJSON_AddStringToObject(obj, name, buf);
|
||||
}
|
||||
|
||||
void cJSON_AddU64ToObject(cJSON *obj, char *name, uint64_t val) {
|
||||
char buf[0x20] = {0};
|
||||
snprintf(buf, sizeof(buf), "0x%016llx", val);
|
||||
snprintf(buf, sizeof(buf), "0x%016"PRIx64, val);
|
||||
cJSON_AddStringToObject(obj, name, buf);
|
||||
}
|
||||
|
||||
|
@ -835,7 +841,7 @@ const char *npdm_get_json(npdm_t *npdm) {
|
|||
cJSON_AddU64ToObject(npdm_json, "title_id", aci0->title_id);
|
||||
cJSON_AddU64ToObject(npdm_json, "title_id_range_min", acid->title_id_range_min);
|
||||
cJSON_AddU64ToObject(npdm_json, "title_id_range_max", acid->title_id_range_max);
|
||||
cJSON_AddU64ToObject(npdm_json, "main_thread_stack_size", npdm->main_stack_size);
|
||||
cJSON_AddU32ToObject(npdm_json, "main_thread_stack_size", npdm->main_stack_size);
|
||||
cJSON_AddNumberToObject(npdm_json, "main_thread_priority", npdm->main_thread_prio);
|
||||
cJSON_AddNumberToObject(npdm_json, "default_cpu_id", npdm->default_cpuid);
|
||||
cJSON_AddNumberToObject(npdm_json, "process_category", npdm->process_category);
|
||||
|
|
8
npdm.h
8
npdm.h
|
@ -4,6 +4,7 @@
|
|||
#include "types.h"
|
||||
#include "utils.h"
|
||||
#include "settings.h"
|
||||
#include "cJSON.h"
|
||||
|
||||
#define MAGIC_META 0x4154454D
|
||||
#define MAGIC_ACID 0x44494341
|
||||
|
@ -140,4 +141,11 @@ char *npdm_get_proc_category(int process_category);
|
|||
void kac_print(uint32_t *descriptors, uint32_t num_descriptors);
|
||||
const char *npdm_get_json(npdm_t *npdm);
|
||||
|
||||
void cJSON_AddU8ToObject(cJSON *obj, char *name, uint8_t val);
|
||||
void cJSON_AddU16ToObject(cJSON *obj, char *name, uint16_t val);
|
||||
void cJSON_AddU32ToObject(cJSON *obj, char *name, uint32_t val);
|
||||
void cJSON_AddU64ToObject(cJSON *obj, char *name, uint64_t val);
|
||||
cJSON *kac_get_json(uint32_t *descriptors, uint32_t num_descriptors);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -132,7 +132,7 @@ void pk21_process(pk21_ctx_t *ctx) {
|
|||
is_encrypted = true;
|
||||
}
|
||||
}
|
||||
is_encrypted &= ctx->header.magic == MAGIC_PK21;
|
||||
is_encrypted &= ctx->header.magic != MAGIC_PK21;
|
||||
|
||||
if (is_encrypted) {
|
||||
if (rsa2048_pss_verify(&ctx->header.ctr, 0x100, ctx->header.signature, ctx->tool_ctx->settings.keyset.package2_fixed_key_modulus)) {
|
||||
|
@ -178,7 +178,6 @@ void pk21_process(pk21_ctx_t *ctx) {
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (ctx->package_size != 0x200 + ctx->header.section_sizes[0] + ctx->header.section_sizes[1] + ctx->header.section_sizes[2]) {
|
||||
fprintf(stderr, "Error: Package2 Header is corrupt!\n");
|
||||
|
|
|
@ -111,6 +111,7 @@ enum hactool_file_type
|
|||
#define ACTION_DEV (1<<5)
|
||||
#define ACTION_EXTRACTINI1 (1<<6)
|
||||
#define ACTION_ONLYUPDATEDROMFS (1<<7)
|
||||
#define ACTION_SAVEINIJSON (1<<0)
|
||||
|
||||
struct nca_ctx; /* This will get re-defined by nca.h. */
|
||||
|
||||
|
|
Loading…
Reference in a new issue