Skip to content

Commit 992d615

Browse files
committed
Fix crashes in BKTR edge-cases.
1 parent 488dc27 commit 992d615

File tree

1 file changed

+21
-7
lines changed

1 file changed

+21
-7
lines changed

nca.c

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,8 @@ size_t nca_bktr_section_physical_fread(nca_section_ctx_t *ctx, void *buffer, siz
8383
nca_update_bktr_ctr(ctx->ctr, subsec->ctr_val, ctx->bktr_ctx.bktr_seek + ctx->offset);
8484
fseeko64(ctx->file, (ctx->offset + ctx->bktr_ctx.bktr_seek) & ~0xF, SEEK_SET);
8585
uint32_t block_ofs;
86-
bktr_subsection_entry_t *next_subsec = bktr_get_subsection(ctx->bktr_ctx.subsection_block, ctx->bktr_ctx.bktr_seek + count);
87-
if (next_subsec == subsec || (ctx->bktr_ctx.bktr_seek + count == next_subsec->offset && next_subsec == subsec + 1)) {
86+
bktr_subsection_entry_t *next_subsec = subsec + 1;
87+
if (ctx->bktr_ctx.bktr_seek + count <= next_subsec->offset) {
8888
/* Easy path, reading *only* within the subsection. */
8989
if ((block_ofs = ctx->bktr_ctx.bktr_seek & 0xF) != 0) {
9090
if ((read = fread(block_buf, 1, 0x10, ctx->file)) != 0x10) {
@@ -397,7 +397,7 @@ void nca_process(nca_ctx_t *ctx) {
397397
} else {
398398
/* Decrypt title key. */
399399
if (ctx->tool_ctx->settings.has_titlekey) {
400-
aes_ctx_t *aes_ctx = new_aes_ctx(ctx->tool_ctx->settings.keyset.titlekeks[ctx->crypto_type], 16, AES_MODE_CTR);
400+
aes_ctx_t *aes_ctx = new_aes_ctx(ctx->tool_ctx->settings.keyset.titlekeks[ctx->crypto_type], 16, AES_MODE_ECB);
401401
aes_decrypt(aes_ctx, ctx->tool_ctx->settings.dec_titlekey, ctx->tool_ctx->settings.titlekey, 0x10);
402402
free_aes_ctx(aes_ctx);
403403
}
@@ -901,7 +901,7 @@ void nca_process_bktr_section(nca_section_ctx_t *ctx) {
901901
exit(EXIT_FAILURE);
902902
}
903903
/* Allocate space for an extra (fake) subsection entry, to simplify our logic. */
904-
void *subs = calloc(1, sb->subsection_header.size + sizeof(bktr_subsection_entry_t));
904+
void *subs = calloc(1, sb->subsection_header.size + 2 * sizeof(bktr_subsection_entry_t));
905905
if (subs == NULL) {
906906
fprintf(stderr, "Failed to allocate subsection header!\n");
907907
exit(EXIT_FAILURE);
@@ -921,11 +921,22 @@ void nca_process_bktr_section(nca_section_ctx_t *ctx) {
921921
ctx->bktr_ctx.relocation_block = relocs;
922922
ctx->bktr_ctx.subsection_block = subs;
923923

924+
if (ctx->bktr_ctx.subsection_block->bktr_entry_offset != sb->subsection_header.offset) {
925+
free(relocs);
926+
free(subs);
927+
ctx->bktr_ctx.relocation_block = NULL;
928+
ctx->bktr_ctx.subsection_block = NULL;
929+
ctx->superblock_hash_validity = VALIDITY_INVALID;
930+
return;
931+
}
932+
924933
/* This simplifies logic greatly... */
925934
ctx->bktr_ctx.relocation_block->entries[ctx->bktr_ctx.relocation_block->num_entries].virt_offset = ctx->bktr_ctx.relocation_block->patch_romfs_size;
926935
ctx->bktr_ctx.subsection_block->entries[ctx->bktr_ctx.subsection_block->num_entries].offset = sb->relocation_header.offset;
927936
ctx->bktr_ctx.subsection_block->entries[ctx->bktr_ctx.subsection_block->num_entries].ctr_val = ctx->header->section_ctr_low;
928-
937+
ctx->bktr_ctx.subsection_block->entries[ctx->bktr_ctx.subsection_block->num_entries + 1].offset = ctx->size;
938+
ctx->bktr_ctx.subsection_block->entries[ctx->bktr_ctx.subsection_block->num_entries + 1].ctr_val = 0;
939+
929940

930941
/* Now parse out the romfs stuff. */
931942
for (unsigned int i = 0; i < IVFC_MAX_LEVEL; i++) {
@@ -1110,8 +1121,10 @@ void nca_save_section(nca_section_ctx_t *ctx) {
11101121
size = ctx->romfs_ctx.ivfc_levels[IVFC_MAX_LEVEL - 1].data_size;
11111122
break;
11121123
case BKTR:
1113-
offset = ctx->bktr_ctx.ivfc_levels[IVFC_MAX_LEVEL - 1].data_offset;
1114-
size = ctx->bktr_ctx.ivfc_levels[IVFC_MAX_LEVEL - 1].data_size;
1124+
if (ctx->tool_ctx->base_file != NULL) {
1125+
offset = ctx->bktr_ctx.ivfc_levels[IVFC_MAX_LEVEL - 1].data_offset;
1126+
size = ctx->bktr_ctx.ivfc_levels[IVFC_MAX_LEVEL - 1].data_size;
1127+
}
11151128
break;
11161129
case INVALID:
11171130
break;
@@ -1131,6 +1144,7 @@ void nca_save_section(nca_section_ctx_t *ctx) {
11311144
}
11321145
if (secpath != NULL && secpath->valid == VALIDITY_VALID) {
11331146
printf("Saving Section %"PRId32" to %s...\n", ctx->section_num, secpath->char_path);
1147+
printf("Size: %012"PRIx64"\n", size);
11341148
nca_save_section_file(ctx, offset, size, secpath);
11351149
}
11361150

0 commit comments

Comments
 (0)