ctrtool: Updated exheader validation and ncch spec/flag recognition

This commit is contained in:
jakcron
2015-09-14 21:52:04 +08:00
parent 038aca268a
commit f8993e198a
5 changed files with 171 additions and 113 deletions
+3 -3
View File
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -18,13 +18,13 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v110</PlatformToolset>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v110</PlatformToolset>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+114 -97
View File
@@ -126,6 +126,58 @@ int exheader_programid_valid(exheader_context* ctx)
return 1;
}
void exheader_deserialise_arm11localcaps_permissions(exheader_arm11systemlocalcaps_deserialised *caps, const exheader_arm11systemlocalcaps *arm11)
{
int i;
memset(caps, 0, sizeof(exheader_arm11systemlocalcaps_deserialised));
memcpy(caps->program_id, arm11->programid, 8);
caps->core_version = getle32(arm11->coreversion);
caps->enable_l2_cache = (arm11->flag[0] >> 0) & 1;
caps->use_additional_cores = (arm11->flag[0] >> 1) & 1;
caps->new3ds_systemmode = (arm11->flag[1] >> 0) & 15;
caps->ideal_processor = (arm11->flag[2] >> 0) & 3;
caps->affinity_mask = (arm11->flag[2] >> 2) & 3;
caps->old3ds_systemmode = (arm11->flag[2] >> 4) & 15;
caps->priority = (s8)arm11->flag[3];
// storage info
if (arm11->storageinfo.otherattributes & 2) {
caps->extdata_id = 0;
for (i = 0; i < 3; i++)
caps->other_user_saveid[i] = 0;
caps->use_other_variation_savedata = 0;
for (i = 0; i < 3; i++)
caps->accessible_saveid[i] = 0xfffff & (getle64(arm11->storageinfo.accessibleuniqueids) >> 20 * (2 - i));
for (i = 0; i < 3; i++)
caps->accessible_saveid[i+3] = 0xfffff & (getle64(arm11->storageinfo.extsavedataid) >> 20 * (2 - i));
}
else {
caps->extdata_id = getle64(arm11->storageinfo.extsavedataid);
for (i = 0; i < 3; i++)
caps->other_user_saveid[i] = 0xfffff & (getle64(arm11->storageinfo.accessibleuniqueids) >> 20 * (2 - i));
caps->use_other_variation_savedata = (getle64(arm11->storageinfo.accessibleuniqueids) >> 60) & 1;
for (i = 0; i < 6; i++)
caps->accessible_saveid[i] = 0;
}
caps->system_saveid[0] = getle32(arm11->storageinfo.systemsavedataid);
caps->system_saveid[1] = getle32(arm11->storageinfo.systemsavedataid + 4);
caps->accessinfo = getle64(arm11->storageinfo.accessinfo) & ~((u64)0xff00000000000000);
// Service Access Control
for (i = 0; i < 34; i++)
strncpy(caps->service_access_control[i], (char*)arm11->serviceaccesscontrol[i], 8);
caps->resource_limit_category = arm11->resourcelimitcategory;
}
int exheader_process(exheader_context* ctx, u32 actions)
{
exheader_determine_key(ctx, actions);
@@ -135,13 +187,13 @@ int exheader_process(exheader_context* ctx, u32 actions)
if (ctx->header.codesetinfo.flags.flag & 1)
ctx->compressedflag = 1;
exheader_deserialise_arm11localcaps_permissions(&ctx->system_local_caps, &ctx->header.arm11systemlocalcaps);
if (actions & VerifyFlag)
exheader_verify(ctx);
if (actions & InfoFlag)
{
exheader_print(ctx);
}
exheader_print(ctx);
return 1;
}
@@ -397,11 +449,10 @@ void exheader_print_arm11accessinfo(exheader_context* ctx)
{
char str[100];
u64 i, bit;
u64 accessinfo = 0xffffffffffffff & getle64(ctx->header.arm11systemlocalcaps.storageinfo.accessinfo);
for(i = 0; i < 56; i++)
{
bit = ((u64)1 << i);
if((accessinfo & bit) == bit)
if((ctx->system_local_caps.accessinfo & bit) == bit)
fprintf(stdout, " > %s\n",exheader_print_accessinfobit((u32)i,str));
}
}
@@ -410,72 +461,21 @@ void exheader_print_arm11storageinfo(exheader_context* ctx)
{
u32 i;
// Storage Info
u32 systemsaveID[2];
u64 extdataID;
u32 otherusersaveID[3];
u32 accessiblesaveID[6];
u8 otherattibutes = ctx->header.arm11systemlocalcaps.storageinfo.otherattributes;
u8 accessOtherVariationSavedata = (getle64(ctx->header.arm11systemlocalcaps.storageinfo.accessibleuniqueids) & 0x1000000000000000) == 0x1000000000000000;
systemsaveID[0] = getle32(ctx->header.arm11systemlocalcaps.storageinfo.systemsavedataid);
systemsaveID[1] = getle32(ctx->header.arm11systemlocalcaps.storageinfo.systemsavedataid+4);
extdataID = getle64(ctx->header.arm11systemlocalcaps.storageinfo.extsavedataid);
for(i = 0; i < 3; i++)
{
accessiblesaveID[i] = 0xfffff & (getle64(ctx->header.arm11systemlocalcaps.storageinfo.accessibleuniqueids) >> 20*(2-i));
otherusersaveID[i] = 0xfffff & (getle64(ctx->header.arm11systemlocalcaps.storageinfo.accessibleuniqueids) >> 20*(2-i));
}
for(i = 0; i < 3; i++)
{
accessiblesaveID[i+3] = 0xfffff & (getle64(ctx->header.arm11systemlocalcaps.storageinfo.extsavedataid) >> 20*(2-i));
}
if(otherattibutes & 2)
{
extdataID = 0;
for(i = 0; i < 3; i++)
otherusersaveID[i] = 0;
}
else
{
for(i = 0; i < 6; i++)
accessiblesaveID[i] = 0;
}
fprintf(stdout, "Ext savedata id: 0x%08"PRIx64"\n",extdataID);
fprintf(stdout, "Ext savedata id: 0x%"PRIx64"\n",ctx->system_local_caps.extdata_id);
for(i = 0; i < 2; i++)
fprintf(stdout, "System savedata id %d: 0x%08x %s\n",i+1,systemsaveID[i],exheader_getvalidstring(ctx->validsystemsaveID[i]));
fprintf(stdout, "System savedata id %d: 0x%x %s\n",i+1, ctx->system_local_caps.system_saveid[i],exheader_getvalidstring(ctx->validsystemsaveID[i]));
for(i = 0; i < 3; i++)
fprintf(stdout, "OtherUserSaveDataId%d: 0x%05x\n",i+1,otherusersaveID[i]);
fprintf(stdout, "OtherUserSaveDataId%d: 0x%x\n",i+1, ctx->system_local_caps.other_user_saveid[i]);
fprintf(stdout, "Accessible Savedata Ids:\n");
for(i = 0; i < 6; i++)
{
if(accessiblesaveID[i] != 0x00000)
fprintf(stdout, " > 0x%05x\n",accessiblesaveID[i]);
if(ctx->system_local_caps.accessible_saveid[i] != 0x00000)
fprintf(stdout, " > 0x%05x\n", ctx->system_local_caps.accessible_saveid[i]);
}
fprintf(stdout, "Other Variation Saves: %s\n", accessOtherVariationSavedata ? "Accessible" : "Inaccessible");
if(ctx->validaccessinfo == Unchecked)
memdump(stdout, "Access info: ", ctx->header.arm11systemlocalcaps.storageinfo.accessinfo, 7);
else if(ctx->validaccessinfo == Good)
memdump(stdout, "Access info (GOOD): ", ctx->header.arm11systemlocalcaps.storageinfo.accessinfo, 7);
else
memdump(stdout, "Access info (FAIL): ", ctx->header.arm11systemlocalcaps.storageinfo.accessinfo, 7);
exheader_print_arm11accessinfo(ctx);
fprintf(stdout, "Other attributes: %02X", ctx->header.arm11systemlocalcaps.storageinfo.otherattributes);
/*
if(otherattibutes & 1)
fprintf(stdout," [no use romfs]");
if(otherattibutes & 2)
fprintf(stdout," [use extended savedata access control]");
*/
printf("\n");
fprintf(stdout, "Other Variation Saves: %s\n", ctx->system_local_caps.use_other_variation_savedata ? "Accessible" : "Inaccessible");
fprintf(stdout, "Access info: 0x%"PRIx64" %s\n", ctx->system_local_caps.accessinfo,exheader_getvalidstring(ctx->validaccessinfo));
exheader_print_arm11accessinfo(ctx);
}
int exheader_signature_verify(exheader_context* ctx, rsakey2048* key)
@@ -486,61 +486,78 @@ int exheader_signature_verify(exheader_context* ctx, rsakey2048* key)
return ctr_rsa_verify_hash(ctx->header.accessdesc.signature, hash, key);
}
void exheader_verify(exheader_context* ctx)
{
unsigned int i;
u8 exheaderflag6[3];
u8 descflag6[3];
unsigned int i, j;
exheader_arm11systemlocalcaps_deserialised accessdesc;
exheader_deserialise_arm11localcaps_permissions(&accessdesc, &ctx->header.accessdesc.arm11systemlocalcaps);
ctx->validsystemsaveID[0] = Good;
ctx->validsystemsaveID[1] = Good;
ctx->validaccessinfo = Good;
ctx->validcoreversion = Good;
ctx->validprogramid = Good;
ctx->validpriority = Good;
ctx->validaffinitymask = Good;
ctx->valididealprocessor = Good;
ctx->validold3dssystemmode = Good;
ctx->validnew3dssystemmode = Good;
ctx->validenablel2cache = Good;
ctx->validuseadditionalcores = Good;
ctx->validservicecontrol = Good;
for(i=0; i<8; i++)
{
if (0 == (ctx->header.arm11systemlocalcaps.programid[i] & ~ctx->header.accessdesc.arm11systemlocalcaps.programid[i]))
if (ctx->system_local_caps.program_id[i] == accessdesc.program_id[i] || accessdesc.program_id[i] == 0xFF)
continue;
ctx->validprogramid = Fail;
break;
}
// Ideal Proccessor
exheaderflag6[0] = (ctx->header.arm11systemlocalcaps.flag>>0)&0x3;
descflag6[0] = (ctx->header.accessdesc.arm11systemlocalcaps.flag>>0)&0x3;
// Affinity Mask
exheaderflag6[1] = (ctx->header.arm11systemlocalcaps.flag>>2)&0x3;
descflag6[1] = (ctx->header.accessdesc.arm11systemlocalcaps.flag>>2)&0x3;
// System Mode
//exheaderflag6[2] = (ctx->header.arm11systemlocalcaps.flag>>4)&0xf;
//descflag6[2] = (ctx->header.accessdesc.arm11systemlocalcaps.flag>>4)&0xf;
if (ctx->system_local_caps.core_version != accessdesc.core_version)
ctx->validcoreversion = Fail;
if (ctx->header.accessdesc.arm11systemlocalcaps.priority > ctx->header.arm11systemlocalcaps.priority || ctx->header.arm11systemlocalcaps.priority > 127)
if (ctx->system_local_caps.priority < accessdesc.priority)
ctx->validpriority = Fail;
if((1<<exheaderflag6[0] & descflag6[0]) == 0)
if((1<<ctx->system_local_caps.ideal_processor & accessdesc.ideal_processor) == 0)
ctx->valididealprocessor = Fail;
if (exheaderflag6[1] & ~descflag6[1])
if (ctx->system_local_caps.affinity_mask & ~accessdesc.affinity_mask)
ctx->validaffinitymask = Fail;
if (ctx->system_local_caps.old3ds_systemmode > accessdesc.old3ds_systemmode)
ctx->validold3dssystemmode = Fail;
if (ctx->system_local_caps.new3ds_systemmode > accessdesc.new3ds_systemmode)
ctx->validnew3dssystemmode = Fail;
// Storage Info Verify
if(0 != (getle32(ctx->header.arm11systemlocalcaps.storageinfo.systemsavedataid) & ~getle32(ctx->header.accessdesc.arm11systemlocalcaps.storageinfo.systemsavedataid)))
if(ctx->system_local_caps.system_saveid[0] & ~accessdesc.system_saveid[0])
ctx->validsystemsaveID[0] = Fail;
if(0 != (getle32(ctx->header.arm11systemlocalcaps.storageinfo.systemsavedataid+4) & ~getle32(ctx->header.accessdesc.arm11systemlocalcaps.storageinfo.systemsavedataid+4)))
if(ctx->system_local_caps.system_saveid[1] & ~accessdesc.system_saveid[1])
ctx->validsystemsaveID[1] = Fail;
for(i=0; i<7; i++)
{
if(0 == (ctx->header.arm11systemlocalcaps.storageinfo.accessinfo[i] & ~ctx->header.accessdesc.arm11systemlocalcaps.storageinfo.accessinfo[i]))
continue;
if (ctx->system_local_caps.accessinfo & ~accessdesc.accessinfo)
ctx->validaccessinfo = Fail;
break;
// Service Access Control
for (i = 0; i < 34; i++) {
if (strlen(ctx->system_local_caps.service_access_control[i]) == 0)
continue;
for (j = 0; j < 34; j++) {
if (strcmp(ctx->system_local_caps.service_access_control[i], accessdesc.service_access_control[j]) == 0)
break;
}
if (strcmp(ctx->system_local_caps.service_access_control[i], accessdesc.service_access_control[j]) == 0)
continue;
ctx->validservicecontrol = Fail;
}
if (ctx->usersettings)
@@ -609,21 +626,21 @@ void exheader_print(exheader_context* ctx)
fprintf(stdout, "Program id: %016"PRIx64" %s\n", getle64(ctx->header.arm11systemlocalcaps.programid), exheader_getvalidstring(ctx->validprogramid));
fprintf(stdout, "Core version: 0x%X\n", getle32(ctx->header.arm11systemlocalcaps.coreversion));
fprintf(stdout, "System mode: 0x%X\n", (ctx->header.arm11systemlocalcaps.flag>>4)&0xF);
fprintf(stdout, "Ideal processor: %d %s\n", (ctx->header.arm11systemlocalcaps.flag>>0)&0x3, exheader_getvalidstring(ctx->valididealprocessor));
fprintf(stdout, "Affinity mask: %d %s\n", (ctx->header.arm11systemlocalcaps.flag>>2)&0x3, exheader_getvalidstring(ctx->validaffinitymask));
fprintf(stdout, "Main thread priority: %d %s\n", ctx->header.arm11systemlocalcaps.priority, exheader_getvalidstring(ctx->validpriority));
fprintf(stdout, "System mode: %d %s\n", ctx->system_local_caps.old3ds_systemmode, exheader_getvalidstring(ctx->validold3dssystemmode));
fprintf(stdout, "System mode (New3DS): %d %s\n", ctx->system_local_caps.new3ds_systemmode, exheader_getvalidstring(ctx->validnew3dssystemmode));
fprintf(stdout, "Ideal processor: %d %s\n", ctx->system_local_caps.ideal_processor, exheader_getvalidstring(ctx->valididealprocessor));
fprintf(stdout, "Affinity mask: %d %s\n", ctx->system_local_caps.affinity_mask, exheader_getvalidstring(ctx->validaffinitymask));
fprintf(stdout, "Main thread priority: %d %s\n", ctx->system_local_caps.priority, exheader_getvalidstring(ctx->validpriority));
// print resource limit descriptor too? currently mostly zeroes...
exheader_print_arm11storageinfo(ctx);
exheader_print_arm11kernelcapabilities(ctx);
exheader_print_arm9accesscontrol(ctx);
for(i=0; i<0x20; i++)
fprintf(stdout, "Service access: %s\n", exheader_getvalidstring(ctx->validservicecontrol));
for(i=0; i<34; i++)
{
if (getle64(ctx->header.arm11systemlocalcaps.serviceaccesscontrol[i]) != 0x0000000000000000UL)
fprintf(stdout, "Service access: %.8s\n", ctx->header.arm11systemlocalcaps.serviceaccesscontrol[i]);
if (strlen(ctx->system_local_caps.service_access_control[i]) > 0)
fprintf(stdout, " > %s\n", ctx->system_local_caps.service_access_control[i]);
}
fprintf(stdout, "Reslimit category: %02X\n", ctx->header.arm11systemlocalcaps.resourcelimitcategory);
}
+39 -5
View File
@@ -57,16 +57,41 @@ typedef struct
{
u8 programid[8];
u8 coreversion[4];
u8 reserved0[2];
u8 flag;
u8 priority;
u8 flag[4];
u8 resourcelimitdescriptor[0x10][2];
exheader_storageinfo storageinfo;
u8 serviceaccesscontrol[0x20][8];
u8 reserved[0x1f];
u8 serviceaccesscontrol[34][8];
u8 reserved[0xf];
u8 resourcelimitcategory;
} exheader_arm11systemlocalcaps;
typedef struct
{
u8 program_id[8];
u32 core_version;
// flag
u8 enable_l2_cache;
u8 use_additional_cores;
u8 new3ds_systemmode;
u8 ideal_processor;
u8 affinity_mask;
u8 old3ds_systemmode;
s8 priority;
// storageinfo
u64 extdata_id;
u32 other_user_saveid[3];
u8 use_other_variation_savedata;
u32 accessible_saveid[3];
u32 system_saveid[2];
u64 accessinfo;
char service_access_control[34][10];
u8 resource_limit_category;
} exheader_arm11systemlocalcaps_deserialised;
typedef struct
{
u8 descriptors[28][4];
@@ -115,6 +140,9 @@ typedef struct
u32 offset;
u32 size;
exheader_header header;
exheader_arm11systemlocalcaps_deserialised system_local_caps;
ctr_aes_context aes;
ctr_rsa_context rsa;
int compressedflag;
@@ -123,8 +151,14 @@ typedef struct
int validpriority;
int validaffinitymask;
int valididealprocessor;
int validold3dssystemmode;
int validnew3dssystemmode;
int validenablel2cache;
int validuseadditionalcores;
int validcoreversion;
int validsystemsaveID[2];
int validaccessinfo;
int validservicecontrol;
int validsignature;
} exheader_context;
+14 -7
View File
@@ -540,6 +540,17 @@ static const char* contenttypetostring(unsigned char flags)
case 2: return "Manual";
case 3: return "Child";
case 4: return "Trial";
case 5: return "Extended System Update";
default: return "Unknown";
}
}
static const char* contentplatformtostring(unsigned char platform)
{
switch (platform)
{
case 1: return "CTR";
case 2: return "SNAKE";
default: return "Unknown";
}
}
@@ -566,6 +577,7 @@ void ncch_print(ncch_context* ctx)
fprintf(stdout, "Partition id: %016"PRIx64"\n", getle64(header->partitionid));
fprintf(stdout, "Maker code: %04x\n", getle16(header->makercode));
fprintf(stdout, "Version: %04x\n", getle16(header->version));
fprintf(stdout, "Title seed check: %08x\n", getle32(header->seedcheck));
fprintf(stdout, "Program id: %016"PRIx64"\n", getle64(header->programid));
if(ctx->logohashcheck == Unchecked)
memdump(stdout, "Logo hash: ", header->logohash, 0x20);
@@ -587,16 +599,11 @@ void ncch_print(ncch_context* ctx)
fprintf(stdout, " > Crypto key: None\n");
else if (header->flags[7] & 1)
fprintf(stdout, " > Crypto key: %s\n", programid_is_system(header->programid)? "Fixed":"Zeros");
else if (header->flags[3] & 1)
fprintf(stdout, " > Crypto key: Secure2\n");
else if (header->flags[3] & 10)
fprintf(stdout, " > Crypto key: secure3 (New 3DS)\n");
else
fprintf(stdout, " > Crypto key: Secure\n");
fprintf(stdout, " > Crypto key: Secure (%d)%s\n", header->flags[3], header->flags[7] & 32? " (KeyY seeded)" : "");
fprintf(stdout, " > Form type: %s\n", formtypetostring(header->flags[5]));
fprintf(stdout, " > Content type: %s\n", contenttypetostring(header->flags[5]));
if (header->flags[4] & 1)
fprintf(stdout, " > Content platform: CTR\n");
fprintf(stdout, " > Content platform: %s\n", contentplatformtostring(header->flags[4]));
if (header->flags[7] & 2)
fprintf(stdout, " > No RomFS mount\n");
+1 -1
View File
@@ -26,7 +26,7 @@ typedef struct
u8 partitionid[8];
u8 makercode[2];
u8 version[2];
u8 reserved0[4];
u8 seedcheck[4];
u8 programid[8];
u8 reserved1[0x10];
u8 logohash[0x20];