Beispiel #1
0
int GetNcchInfo(ncch_info *info, ncch_hdr *hdr)
{
	clrmem(info, sizeof(ncch_info));

	info->titleId = u8_to_u64(hdr->titleId,LE);
	info->programId = u8_to_u64(hdr->programId,LE);

	u32 block_size = GetNcchBlockSize(hdr);
	
	info->formatVersion = u8_to_u16(hdr->formatVersion,LE);
	if(!IsCfa(hdr)){
		info->exhdrOffset = sizeof(ncch_hdr);
		info->exhdrSize = u8_to_u32(hdr->exhdrSize,LE);
		info->acexOffset = (info->exhdrOffset + info->exhdrSize);
		info->acexSize = sizeof(access_descriptor);
		info->plainRegionOffset = (u64)(u8_to_u32(hdr->plainRegionOffset,LE)*block_size);
		info->plainRegionSize = (u64)(u8_to_u32(hdr->plainRegionSize,LE)*block_size);
	}

	info->logoOffset = (u64)(u8_to_u32(hdr->logoOffset,LE)*block_size);
	info->logoSize = (u64)(u8_to_u32(hdr->logoSize,LE)*block_size);
	info->exefsOffset = (u64)(u8_to_u32(hdr->exefsOffset,LE)*block_size);
	info->exefsSize = (u64)(u8_to_u32(hdr->exefsSize,LE)*block_size);
	info->exefsHashDataSize = (u64)(u8_to_u32(hdr->exefsHashSize,LE)*block_size);
	info->romfsOffset = (u64) (u8_to_u32(hdr->romfsOffset,LE)*block_size);
	info->romfsSize = (u64) (u8_to_u32(hdr->romfsSize,LE)*block_size);
	info->romfsHashDataSize = (u64)(u8_to_u32(hdr->romfsHashSize,LE)*block_size);
	return 0;
}
Beispiel #2
0
void PrintNCSDHeaderData(NCSD_STRUCT *ctx, NCSD_HEADER *header, CARD_INFO_HEADER *card_info, DEV_CARD_INFO_HEADER *dev_card_info)
{
	printf("[+] CCI Image Details\n");
	u8 CardDevice = header->partition_flags[MEDIA_CARD_DEVICE_OLD] + header->partition_flags[MEDIA_CARD_DEVICE];
	switch (header->partition_flags[MEDIA_TYPE_INDEX]){
		case INNER_DEVICE: printf(" Media Type:            INTERNAL_DEVICE\n"); break;
		case CARD1: printf(" Media Type:            CARD1\n"); break;
		case CARD2: printf(" Media Type:            CARD2\n  > Writable Region:\n   - Offset:            0x%llx\n   - Size:              0x%llx (%lld MB)\n",ctx->WRITABLE_ADDRESS,ctx->CARD2_MAX_SAVEDATA_SIZE,(ctx->CARD2_MAX_SAVEDATA_SIZE/MB)); break;
		case EXTENDED_DEVICE: printf(" Media Type:            EXTENDED_DEVICE\n"); break;
	}
	GetCHIPFullSize(ctx->MEDIA_SIZE,ctx->type);
	GetCCIDataSize(ctx->CCI_IMAGE_SIZE,ctx->type);
	GetCCIFileStatus(ctx->CCI_FILE_SIZE,ctx->CCI_FILE_STATUS,ctx->type);
	switch (CardDevice){
		case CARD_DEVICE_NOR_FLASH: printf(" Additional Device:     EEPROM\n"); break;
		case CARD_DEVICE_NONE: printf(" Additional Device:     None\n"); break;
		case CARD_DEVICE_BT: printf(" Additional Device:     BT\n"); break;
	}
	printf(" Partition Count:       %d\n",ctx->partition_count);
	if(u8_to_u64(card_info->cver_title_id,LE) && u8_to_u16(card_info->cver_title_version,LE)){
		//printf("CVer Title ID:          %016llx\n",u8_to_u64(card_info->cver_title_id,LE));
		//printf("CVer Title Ver:         v%d\n",u8_to_u16(card_info->cver_title_version,LE));
		GetCUPVersion(card_info);
	}
	if(!header->partition_flags[MEDIA_6X_SAVE_CRYPTO] && !header->partition_flags[MEDIA_CARD_DEVICE] && !header->partition_flags[MEDIA_CARD_DEVICE_OLD]){
		printf(" Save Crypto:           Repeating CTR Fail\n");
	}
	else if(!header->partition_flags[MEDIA_6X_SAVE_CRYPTO] && (header->partition_flags[MEDIA_CARD_DEVICE] || header->partition_flags[MEDIA_CARD_DEVICE_OLD])){
		printf(" Save Crypto:           2.2.0 KeyY Method\n");
	}
	else if(header->partition_flags[MEDIA_6X_SAVE_CRYPTO] == 1 && !header->partition_flags[MEDIA_CARD_DEVICE_OLD]){
		if(!header->partition_flags[MEDIA_CARD_DEVICE]){
			printf(" Save Crypto:           2.2.0 KeyY Method\n");
		}
		else if(header->partition_flags[MEDIA_CARD_DEVICE]){
			printf(" Save Crypto:           6.0.0 KeyY Method\n");
		}
	}
	
	printf("[+] CXI Partition\n");
	printf(" Product Code:          %.16s\n",card_info->partition_0_header.product_code);
	printf(" Company Code:          %.2s\n",card_info->partition_0_header.maker_code);
	u32 UniqueID = u8_to_u32(&card_info->partition_0_header.program_id[1],LE)&0xffffff;
	printf(" Unique ID:             %05x\n",UniqueID);
	printf(" Build Type:            %s\n",ctx->BUILD_TYPE? "Debug or Development" : "Release");
	printf(" SDK Version:           %d.%d.%d %s\n",ctx->SDK_VER[0],ctx->SDK_VER[1],ctx->SDK_VER[2],ctx->SDK_PATCH);
	if(ctx->FW_VER[0] || ctx->FW_VER[1]) printf(" Req. Kernel Version:   %d.%d-%d\n",ctx->FW_VER[0],ctx->FW_VER[1],ctx->FW_VER[2]);
	printf("[+] CFA Partitions\n");
	for(int i = 1; i < 8; i++){
		if(i == 1) printf(" E-Manual:              %s\n",ctx->partition_data[i].active? "Yes" : "No"); 
		else if(i == 2) printf(" DLP Child:             %s\n",ctx->partition_data[i].active? "Yes" : "No"); 
		else if(i == 7) printf(" Update Data:           %s\n",ctx->partition_data[i].active? "Yes" : "No"); 
		else{
			if(ctx->partition_data[i].active) printf(" CFA %d:                %s\n",i,ctx->partition_data[i].active? "Yes" : "No"); 
		}
	}
	
	
	
}
Beispiel #3
0
u64 GetDecTitleID(u8 *enc_used, u8 *enc_blank)
{
    u8 xorpad[8];
    u8 decTID[8];
    xor_file(xorpad,FF_bytes,enc_blank,8);
    xor_file(decTID,enc_used,xorpad,8);
    return u8_to_u64(decTID,LE);
}
Beispiel #4
0
void GetNewNcchIdForCci(u8 *newTid, u8 *srcTid, u8 index, tmd_hdr *tmdHdr)
{
	u64 titleId = u8_to_u64(srcTid,LE) & 0xffffffffffff;
	if(tmdHdr && index == 7)
		titleId |= (u64)(GetTmdVersion(tmdHdr)) << 48;
	else
		titleId |= (u64)(index+4) << 48;
		
	u64_to_u8(newTid,titleId,LE);
}
Beispiel #5
0
int ProcessNcchForCci(cci_settings *set)
{
	u8 *ncch;
	ncch_hdr *hdr;
	
	u8 titleId[8];
	u8 srcId[8];
	
	if(set->options.cverDataPath && set->content.active[7]){
		if(ProcessCverDataForCci(set))
			return FAILED_TO_IMPORT_FILE;
	}
	
	for(int i = 0; i < CCI_MAX_CONTENT; i++){
		if(set->content.active[i]){
			ncch = set->content.data + set->content.dOffset[i];
			if(!IsNcch(NULL,ncch)){
				fprintf(stderr,"[CCI ERROR] NCCH %d is corrupt\n",i);
				return NCSD_INVALID_NCCH;
			}
			hdr = (ncch_hdr*)ncch;
			if(i > 0 && !set->options.noModTid){
				if(set->options.verbose){
					printf("[CCI] Modifying NCCH %d IDs\n",i);
					printf("[Old Ids]\n");
					memdump(stdout," > TitleId:   0x",hdr->titleId,8);
					memdump(stdout," > ProgramId: 0x",hdr->programId,8);
				}
				GetNewNcchIdForCci(titleId,srcId,i,set->options.tmdHdr);
				if(ModifyNcchIds(ncch, titleId, srcId, set->keys))
					return -1;
				if(set->options.verbose){
					printf("[New Ids]\n");
					memdump(stdout," > TitleId:   0x",hdr->titleId,8);
					memdump(stdout," > ProgramId: 0x",hdr->programId,8);
				}
			}
			set->content.titleId[i] = u8_to_u64(hdr->titleId,LE);
			if(i == 0)
				memcpy(srcId,hdr->titleId,8);
		}
	}
	
	return 0;
}
Beispiel #6
0
void InstallTicket(std::string FullPath, std::string TitleId)
{
    Handle hTik;
    u32 writtenbyte;
    std::string curr = get_file_contents(FullPath.c_str());

    // Remove the ticket incase there was a bad one previously installed
    char* nTitleId = parse_string(TitleId);
    u64 titleId = u8_to_u64((u8*)nTitleId, BIG_ENDIAN);
    free (nTitleId);
    AM_DeleteTicket(titleId);

    // Install new ticket
    AM_InstallTicketBegin(&hTik);
    FSFILE_Write(hTik, &writtenbyte, 0, curr.c_str(), 0x100000, 0);
    AM_InstallTicketFinish(hTik);
    printf("Ticket Installed.");
    //delete temp ticket, ticket folder still exists... ugly. later stream directly to the handle
    remove(FullPath.c_str());
}
Beispiel #7
0
u64 GetPartitionSize(u8 *ncsd, u8 index)
{
	cci_hdr *hdr = (cci_hdr*)ncsd;
	return (u64)u8_to_u64(hdr->offset_sizeTable[index].size,LE) * (u64)GetCtrBlockSize(hdr->flags[cciflag_MEDIA_BLOCK_SIZE]);
}
Beispiel #8
0
void SetAesCtrOffset(u8 *ctr, u64 offset)
{
	u64_to_u8(ctr+8,u8_to_u64(ctr+8,BE)|align(offset,16)/16,BE);
}
Beispiel #9
0
int GetNCSDData(CCI_CONTEXT *ctx)
{
	// Opening CCI
	FILE *cci = fopen(ctx->cci_file.argument,"rb");
	if(ctx->ncsd_struct == NULL)
		return Fail;
	memset(ctx->ncsd_struct,0x0,sizeof(NCSD_STRUCT));
	
	// Getting File Size of CCI File
	ctx->ncsd_struct->CCI_FILE_SIZE = GetFileSize_u64(ctx->cci_file.argument);

	NCSD_HEADER header;
	CARD_INFO_HEADER card_info;
	DEV_CARD_INFO_HEADER dev_card_info;
	
	// Reading CCI Header Sections
	fseek(cci,0x0,SEEK_SET);
	fread(&ctx->ncsd_struct->signature,0x100,1,cci);
	fseek(cci,0x100,SEEK_SET);
	fread(&header,sizeof(NCSD_HEADER),1,cci);
	fseek(cci,0x200,SEEK_SET);
	fread(&card_info,sizeof(CARD_INFO_HEADER),1,cci);
	fseek(cci,0x1200,SEEK_SET);
	fread(&dev_card_info,sizeof(DEV_CARD_INFO_HEADER),1,cci);
	
	// Checking CCI Magic
	if(u8_to_u32(header.magic,BE) != NCSD_MAGIC){
		printf("[!] NCSD File is corrupt\n");
		goto fail;
	}
	
	// Checking Media Type to see if suitable for CCI
	if(header.partition_flags[MEDIA_TYPE_INDEX] != CARD1 && header.partition_flags[MEDIA_TYPE_INDEX] != CARD2){
		printf("[!] NCSD File is not CCI\n");
		goto fail;
	}	
	
	// Determining Media Unit Size
	ctx->ncsd_struct->MEDIA_UNIT_SIZE = 0x200*pow(2,header.partition_flags[MEDIA_UNIT_SIZE]);
	
	// Media Size
	ctx->ncsd_struct->MEDIA_SIZE = u8_to_u32(header.media_size,LE)*(ctx->ncsd_struct->MEDIA_UNIT_SIZE);
	
	// Get Writable Address
	ctx->ncsd_struct->WRITABLE_ADDRESS = u8_to_u32(card_info.writable_address,LE)*(ctx->ncsd_struct->MEDIA_UNIT_SIZE);
	ctx->ncsd_struct->CARD2_MAX_SAVEDATA_SIZE = ctx->ncsd_struct->MEDIA_SIZE - ctx->ncsd_struct->WRITABLE_ADDRESS;
	// Getting CCI Image Size by summing total size of NCSD Partitions
	u32 tmp = u8_to_u32(header.offsetsize_table[0].offset,LE);
	for(int i = 0; i < 8; i++){
		tmp += u8_to_u32(header.offsetsize_table[i].size,LE);
		if (i == 6) ctx->ncsd_struct->CCI_S_TRIM_SIZE = tmp*ctx->ncsd_struct->MEDIA_UNIT_SIZE; // The Update Partition is always in Partition 7, so this size doesn't include Partition 7
	}
	ctx->ncsd_struct->CCI_IMAGE_SIZE = tmp*ctx->ncsd_struct->MEDIA_UNIT_SIZE;
	
	// Comparing CCI File Size, with calculated size
	ctx->ncsd_struct->CCI_FILE_STATUS = 0;
	if(ctx->ncsd_struct->CCI_FILE_SIZE == ctx->ncsd_struct->MEDIA_SIZE) ctx->ncsd_struct->CCI_FILE_STATUS = IS_FULL;
	else if(ctx->ncsd_struct->CCI_FILE_SIZE == ctx->ncsd_struct->CCI_IMAGE_SIZE) ctx->ncsd_struct->CCI_FILE_STATUS = IS_TRIM;
	else if(ctx->ncsd_struct->CCI_FILE_SIZE == ctx->ncsd_struct->CCI_S_TRIM_SIZE) ctx->ncsd_struct->CCI_FILE_STATUS = IS_S_TRIM;
	else {
		/*
		printf("CCI_FILE_SIZE = 0x%llx\n",ctx->ncsd_struct->CCI_FILE_SIZE);
		printf("MEDIA_SIZE = 0x%llx\n",ctx->ncsd_struct->MEDIA_SIZE);
		printf("CCI_IMAGE_SIZE = 0x%llx\n",ctx->ncsd_struct->CCI_IMAGE_SIZE);
		printf("CCI_S_TRIM_SIZE = 0x%llx\n",ctx->ncsd_struct->CCI_S_TRIM_SIZE);
		*/
		ctx->ncsd_struct->CCI_FILE_STATUS = IS_MALFORMED;
		goto fail;
	}
	
	// Storing Partition Offsets
	ctx->ncsd_struct->partition_count = 0;
	for(int i = 0; i < 8; i++){
		ctx->ncsd_struct->partition_data[i].offset = u8_to_u32(header.offsetsize_table[i].offset,LE)*ctx->ncsd_struct->MEDIA_UNIT_SIZE;
		ctx->ncsd_struct->partition_data[i].size = u8_to_u32(header.offsetsize_table[i].size,LE)*ctx->ncsd_struct->MEDIA_UNIT_SIZE;
		if(ctx->ncsd_struct->partition_data[i].offset != 0 && ctx->ncsd_struct->partition_data[i].size != 0)
			ctx->ncsd_struct->partition_data[i].active = True;
		ctx->ncsd_struct->partition_data[i].title_id = u8_to_u64(header.partition_id_table[i],LE);
		ctx->ncsd_struct->partition_data[i].fs_type = header.partitions_fs_type[i];
		ctx->ncsd_struct->partition_data[i].crypto_type = header.partitions_crypto_type[i];
		
		// Checking to see if partition actually exists
		if(ctx->ncsd_struct->partition_data[i].offset >= ctx->ncsd_struct->CCI_FILE_SIZE){
			ctx->ncsd_struct->partition_data[i].active = False;
			break;
		}
		if(ctx->ncsd_struct->partition_data[i].active) ctx->ncsd_struct->partition_count++;
	}
	
	// Exit if no CXI found
	if(!ctx->ncsd_struct->partition_data[0].active){
		printf("[!] CXI Not Found\n");
		goto fail;
	}
	
	// Getting Data from CXI
	NCCH_HEADER cxi_header;
	fseek_64(cci,(ctx->ncsd_struct->partition_data[0].offset + 0x100),SEEK_SET);
	fread(&cxi_header,sizeof(NCCH_HEADER),1,cci);
	if(u8_to_u32(cxi_header.magic,BE) != NCCH_MAGIC){
		printf("[!] CXI is Corrupt\n");
		goto fail;
	}
	// Must have ExeFS region to be CXI
	if((cxi_header.flags[MEDIA_TYPE_INDEX] & ExeFS) != ExeFS){
		printf("[!] CXI Not Found\n");
		goto fail;
	}
	ctx->ncsd_struct->partition_data[0].content_type = CXI;
	
	// Getting Product Code
	fseek_64(cci,(ctx->ncsd_struct->partition_data[0].offset + 0x150),SEEK_SET);
	fread(ctx->ncsd_struct->partition_data[0].product_code,16,1,cci);
	
	// Checking 'other flag' for crypto settings
	if((cxi_header.flags[OtherFlag] & 1) == 1){
		if((cxi_header.flags[OtherFlag] & 4) == 4) ctx->ncsd_struct->partition_data[0].ncch_crypto_key = no_crypto;	
		else if ((cxi_header.program_id[4] && 0x10) == 0x10) ctx->ncsd_struct->partition_data[0].ncch_crypto_key = fixed_system;
		else ctx->ncsd_struct->partition_data[0].ncch_crypto_key = fixed_zeros;
	}
	else if(!cxi_header.flags[OtherFlag]){
		ctx->ncsd_struct->partition_data[0].ncch_crypto_key = secure_key;
		if(cxi_header.flags[SecureCryptoType2Flag]) ctx->ncsd_struct->partition_data[0].ncch_crypto_key = secure_key2;
	}
	
	// Getting SDK Version
	u32 CXI_Media_Unit_Size = 0x200*pow(2,cxi_header.flags[MEDIA_UNIT_SIZE]);
	u64 plain_region_offset = ctx->ncsd_struct->partition_data[0].offset + u8_to_u32(cxi_header.plain_region_offset,LE)*CXI_Media_Unit_Size;
	u64 plain_region_size = u8_to_u32(cxi_header.plain_region_size,LE)*CXI_Media_Unit_Size;
	int result = GetSDKVersion(cci,plain_region_offset,plain_region_size,ctx->ncsd_struct);
	// If that failed, attempt to guess SDK version
	if(result){
		strcpy(ctx->ncsd_struct->SDK_PATCH,"Release");
		memset(&ctx->ncsd_struct->SDK_VER,0,3);
		ctx->ncsd_struct->SDK_VER[0] = 1;
		if(header.partition_flags[MEDIA_CARD_DEVICE_OLD]) ctx->ncsd_struct->SDK_VER[0] = 2;
		if(header.partition_flags[MEDIA_CARD_DEVICE]) ctx->ncsd_struct->SDK_VER[0] = 3;
		if(u8_to_u32(cxi_header.logo_region_offset,LE) || u8_to_u32(cxi_header.logo_region_size,LE)) ctx->ncsd_struct->SDK_VER[0] = 5;
		if(cxi_header.flags[SecureCryptoType2Flag])  ctx->ncsd_struct->SDK_VER[0] = 6;
	}
	
	
	// Getting Data from remaining CFA partitions	
	for(int i = 1; i < 8; i++){
		u8 magic[4];
		fseek_64(cci,(ctx->ncsd_struct->partition_data[i].offset + 0x100),SEEK_SET);
		fread(&magic,4,1,cci);
		if(u8_to_u32(magic,BE) == NCCH_MAGIC){
			u8 flags[8];
			u8 ProgramID[8];
			fseek_64(cci,(ctx->ncsd_struct->partition_data[i].offset + 0x188),SEEK_SET);
			fread(&flags,8,1,cci);
			fseek_64(cci,(ctx->ncsd_struct->partition_data[i].offset + 0x118),SEEK_SET);
			fread(&ProgramID,8,1,cci);
			if( (flags[NCCH_Type] & ExeFS) != ExeFS && (flags[NCCH_Type] & RomFS) == RomFS ){
				if((flags[NCCH_Type] & Manual) == Manual && (flags[NCCH_Type] & SystemUpdate) != SystemUpdate)
					ctx->ncsd_struct->partition_data[i].content_type = CFA_Manual;
				else if((flags[NCCH_Type] & Child) == Child)
					ctx->ncsd_struct->partition_data[i].content_type = CFA_DLPChild;
				else if((flags[NCCH_Type] & SystemUpdate) == SystemUpdate && (flags[NCCH_Type] & Manual) != Manual)
					ctx->ncsd_struct->partition_data[i].content_type = CFA_Update;
				else
					ctx->ncsd_struct->partition_data[i].content_type = CFA_Simple;
			}
			else if((flags[NCCH_Type] & ExeFS) == ExeFS)
				ctx->ncsd_struct->partition_data[i].content_type = CXI;
			else
				ctx->ncsd_struct->partition_data[i].content_type = _unknown;


			// Checking 'other flag' for crypto settings
			if((flags[OtherFlag] & 1) == 1){
				if((flags[OtherFlag] & 4) == 4) ctx->ncsd_struct->partition_data[i].ncch_crypto_key = no_crypto;	
				else if ((ProgramID[4] && 0x10) == 0x10) ctx->ncsd_struct->partition_data[i].ncch_crypto_key = fixed_system;
				else ctx->ncsd_struct->partition_data[i].ncch_crypto_key = fixed_zeros;
			}
			else if(!flags[OtherFlag]){
				ctx->ncsd_struct->partition_data[i].ncch_crypto_key = secure_key;
				if(flags[SecureCryptoType2Flag]) ctx->ncsd_struct->partition_data[i].ncch_crypto_key = secure_key2;
			}

			fseek_64(cci,(ctx->ncsd_struct->partition_data[i].offset + 0x150),SEEK_SET);
			fread(ctx->ncsd_struct->partition_data[i].product_code,16,1,cci);
		}
		else
			ctx->ncsd_struct->partition_data[i].content_type = _unknown;
	} 
		
	if(ctx->flags[info])
		PrintNCSDHeaderData(ctx->ncsd_struct,&header,&card_info,&dev_card_info);
	if(ctx->flags[part_info])
		PrintCCIPartitionData(ctx->ncsd_struct,&header,&card_info,&dev_card_info);
	fclose(cci);
	return 0;
fail:
	fclose(cci);
	return Fail;

}
Beispiel #10
0
Result DownloadTitle(std::string titleId, std::string encTitleKey, std::string titleName, std::string region)
{
    // Convert the titleid to a u64 for later use
    char* nTitleId = parse_string(titleId);
    u64 uTitleId = u8_to_u64((u8*)nTitleId, BIG_ENDIAN);
    free (nTitleId);

    // Wait for wifi to be available
    u32 wifi = 0;
    Result ret = 0;
    Result res = 0;
    while(R_SUCCEEDED(ret = ACU_GetWifiStatus(&wifi)) && wifi == 0)
    {
        hidScanInput();
        if (hidKeysDown() & KEY_B)
        {
            ret = -1;
            break;
        }
    }

    if (R_FAILED(ret))
    {
        printf("Unable to access internet.\n");
        return ret;
    }

    std::string outputDir = "/CIAngel";

    if (titleName.length() == 0)
    {
        titleName = titleId;
    }

    // Include region in filename
    if (region.length() > 0)
    {
        titleName = titleName + " (" + region + ")";
    }

    std::string mode_text;
    if(config.GetMode() == CConfig::Mode::DOWNLOAD_CIA)
    {
        mode_text = "create";
    }
    else if(config.GetMode() == CConfig::Mode::INSTALL_CIA)
    {
        mode_text = "install";
    }


    printf("Starting - %s\n", titleName.c_str());

    // If in install mode, download/install the SEED entry
    if (config.GetMode() == CConfig::Mode::INSTALL_CIA)
    {
        // Download and install the SEEDDB entry if install mode
        // Code based on code from FBI: https://github.com/Steveice10/FBI/blob/master/source/core/util.c#L254
        // Copyright (C) 2015 Steveice10
        u8 seed[16];
        static const char* regionStrings[] = {"JP", "US", "GB", "GB", "HK", "KR", "TW"};
        u8 region = CFG_REGION_USA;
        CFGU_GetSystemLanguage(&region);

        if(region <= CFG_REGION_TWN) {
            char url[128];
            snprintf(url, 128, SEED_URL "0x%016llX/ext_key?country=%s", uTitleId, regionStrings[region]);

            httpcContext context;
            if(R_SUCCEEDED(res = httpcOpenContext(&context, HTTPC_METHOD_GET, url, 1))) {
                httpcSetSSLOpt(&context, SSLCOPT_DisableVerify);

                u32 responseCode = 0;
                if(R_SUCCEEDED(res = httpcBeginRequest(&context)) && R_SUCCEEDED(res = httpcGetResponseStatusCode(&context, &responseCode, 0))) {
                    if(responseCode == 200) {
                        u32 pos = 0;
                        u32 bytesRead = 0;
                        while(pos < sizeof(seed) && (R_SUCCEEDED(res = httpcDownloadData(&context, &seed[pos], sizeof(seed) - pos, &bytesRead)) || (u32)res == HTTPC_RESULTCODE_DOWNLOADPENDING)) {
                            pos += bytesRead;
                        }
                    } else {
                        res = -1;
                    }
                }

                httpcCloseContext(&context);
            }

            if (R_SUCCEEDED(res))
            {
                res = InstallSeed(uTitleId, seed);
                if (R_FAILED(res))
                {
                    printf("Error installing SEEDDB entry: 0x%lx\n", res);
                }
            }
        }
    }

    // Make sure the CIA doesn't already exist
    std::string cp = outputDir + "/" + titleName + ".cia";
    if (config.GetMode() == CConfig::Mode::DOWNLOAD_CIA && FileExists(cp.c_str()))
    {
        printf("%s already exists.\n", cp.c_str());
        return 0;
    }

    std::ofstream ofs;

    FILE *oh = fopen((outputDir + "/tmp/tmd").c_str(), "wb");
    if (!oh) 
    {
        printf("Error opening %s/tmp/tmd\n", outputDir.c_str());
        return -1;
    }
    res = DownloadFile((NUS_URL + titleId + "/tmd").c_str(), oh, false);
    fclose(oh);
    if (res != 0)
    {
        printf("Could not download TMD. Internet/Title ID is OK?\n");
        return res;
    }

    // Read version
    std::ifstream tmdfs;
    tmdfs.open(outputDir + "/tmp/tmd", std::ofstream::out | std::ofstream::in | std::ofstream::binary);
    char titleVersion[2];
    tmdfs.seekg(top+0x9C, std::ios::beg);
    tmdfs.read(titleVersion, 0x2);
    tmdfs.close();

    CreateTicket(titleId, encTitleKey, titleVersion, outputDir + "/tmp/ticket");

    printf("Now %s the CIA...\n", mode_text.c_str());

    res = ProcessCIA(outputDir + "/tmp", titleName);
    if (res != 0)
    {
        printf("Could not %s the CIA.\n", mode_text.c_str());
        return res;
    }

    if (config.GetMode() == CConfig::Mode::DOWNLOAD_CIA)
    {
        rename((outputDir + "/tmp/" + titleName + ".cia").c_str(), (outputDir + "/" + titleName + ".cia").c_str());
    }

    printf(" DONE!\n");

    return res;
}
Beispiel #11
0
static inline u64 dispatch_t210(t210 a211, u8 a212)
{
    return u8_to_u64(a212);
}
Beispiel #12
0
int GetNCSDData(USER_CONTEXT *ctx, NCSD_STRUCT *ncsd_struct, FILE *ncsd)
{
	if(ncsd_struct == NULL)
		return Fail;
	memset(ncsd_struct,0x0,sizeof(NCSD_STRUCT));
	
	NCSD_HEADER header;
	CARD_INFO_HEADER card_info;
	DEV_CARD_INFO_HEADER dev_card_info;
	
	fseek(ncsd,0x0,SEEK_SET);
	fread(&ncsd_struct->signature,0x100,1,ncsd);
	fseek(ncsd,0x100,SEEK_SET);
	fread(&header,sizeof(NCSD_HEADER),1,ncsd);
	fseek(ncsd,0x200,SEEK_SET);
	fread(&card_info,sizeof(CARD_INFO_HEADER),1,ncsd);
	fseek(ncsd,0x1200,SEEK_SET);
	fread(&dev_card_info,sizeof(DEV_CARD_INFO_HEADER),1,ncsd);
	
	ctr_sha(&header,sizeof(NCSD_HEADER),ncsd_struct->ncsd_header_hash,CTR_SHA_256);
	
	if(u8_to_u32(header.magic,BE) != NCSD_MAGIC){
		printf("[!] ROM is Corrupt\n");
		return Fail;
	}
	
	ncsd_struct->sig_valid = ctr_rsa(ncsd_struct->ncsd_header_hash,ncsd_struct->signature,ctx->keys.NcsdCfa.n,NULL,RSA_2048_SHA256,CTR_RSA_VERIFY);
	
	u32 media_size = ((header.partition_flags[6] + 1)*0x200);
	
	ncsd_struct->rom_size = u8_to_u32(header.rom_size,LE)*media_size;
	ncsd_struct->used_rom_size = 0;
	if(ncsd_struct->used_rom_size == 0){
		u32 tmp = u8_to_u32(header.offsetsize_table[0].offset,LE);
		for(int i = 0; i < 8; i++){
			tmp += u8_to_u32(header.offsetsize_table[i].size,LE);
		}
		ncsd_struct->used_rom_size = tmp*media_size;
	}
		
	
	for(int i = 0; i < 8; i++){
		ncsd_struct->partition_data[i].offset = u8_to_u32(header.offsetsize_table[i].offset,LE)*media_size;
		ncsd_struct->partition_data[i].size = u8_to_u32(header.offsetsize_table[i].size,LE)*media_size;
		if(ncsd_struct->partition_data[i].offset != 0 && ncsd_struct->partition_data[i].size != 0)
			ncsd_struct->partition_data[i].active = True;
		ncsd_struct->partition_data[i].title_id = u8_to_u64(header.partition_id_table[i],LE);
		ncsd_struct->partition_data[i].fs_type = header.partitions_fs_type[i];
		ncsd_struct->partition_data[i].crypto_type = header.partitions_crypto_type[i];
		
		u8 magic[4];
		fseek_64(ncsd,(ncsd_struct->partition_data[i].offset + 0x100),SEEK_SET);
		fread(&magic,4,1,ncsd);
		if(u8_to_u32(magic,BE) == NCCH_MAGIC){
			u8 flags[8];
			u8 flag_bool[8];
			fseek_64(ncsd,(ncsd_struct->partition_data[i].offset + 0x188),SEEK_SET);
			fread(&flags,8,1,ncsd);
			resolve_flag(flags[5],flag_bool);
			if(flag_bool[1] == False && flag_bool[0] == True){
				if(flag_bool[2] == False && flag_bool[3] == True)
					ncsd_struct->partition_data[i].content_type = CFA_Manual;
				else if(flag_bool[2] == True && flag_bool[3] == True)
					ncsd_struct->partition_data[i].content_type = CFA_DLPChild;
				else if(flag_bool[2] == True && flag_bool[3] == False)
					ncsd_struct->partition_data[i].content_type = CFA_Update;
				else
					ncsd_struct->partition_data[i].content_type = _unknown;
			}
			else if(flag_bool[1] == True)
				ncsd_struct->partition_data[i].content_type = CXI;
			else
				ncsd_struct->partition_data[i].content_type = _unknown;
		}
		else
			ncsd_struct->partition_data[i].content_type = _unknown;
	}
	
	if(u8_to_u64(card_info.cver_title_id,LE) == 0){
		u8 stock_title_key[0x10] = {0x6E, 0xC7, 0x5F, 0xB2, 0xE2, 0xB4, 0x87, 0x46, 0x1E, 0xDD, 0xCB, 0xB8, 0x97, 0x11, 0x92, 0xBA};
		if(memcmp(dev_card_info.TitleKey,stock_title_key,0x10) == 0)
			ncsd_struct->type = dev_external_SDK;
		else
			ncsd_struct->type = dev_internal_SDK;
	}
	else
		ncsd_struct->type = retail;
	
	/**
	if(ncsd_struct->type != retail){
		u8 iv[16];
		u8 key[16];
		memset(&iv,0x0,16);
		memset(&key,0x0,16);
		//iv[0] = header.partition_flags[7];
		//memcpy(iv+11,header.partition_flags,5);
		u8 tmp[16] = {0xB2, 0x57, 0xA7, 0xC0, 0x24, 0xC8, 0xC1, 0xB0, 0x75, 0x91, 0xC4, 0xC5, 0x1D, 0x96, 0x67, 0x4F};
		
		memcpy(iv,tmp,16);
		memcpy(key,common_dpki_aesKey,16);
		
		ctr_aes_context aes;
		memset(&aes,0x0,sizeof(ctr_aes_context));
		
		memdump(stdout,"ENC Title Key:   ",dev_card_info.TitleKey,0x10);
		
		ctr_init_aes_cbc(&aes,key,iv,DEC);
		ctr_aes_cbc(&aes,dev_card_info.TitleKey,dev_card_info.TitleKey,0x10,DEC);
		
		memdump(stdout,"DEC Title Key:   ",dev_card_info.TitleKey,0x10);
	}
	**/
	/**
	for(int i = 0; i < 8; i++){
		if(ncsd_struct->partition_data[i].active == True){
			ncsd_struct->partition_data[i].sig_valid = VerifyNCCHSection(ctx,dev_card_info.TitleKey,ncsd_struct->partition_data[i].offset,ncsd);
		}
	}
	**/
	ncsd_struct->valid = True;
	if(ctx->flags[info])
		PrintNCSDData(ncsd_struct,&header,&card_info,&dev_card_info);
	return 0;
}
Beispiel #13
0
void PrintNCSDData(NCSD_STRUCT *ctx, NCSD_HEADER *header, CARD_INFO_HEADER *card_info, DEV_CARD_INFO_HEADER *dev_card_info)
{
	if(ctx->valid != True){
		printf("[!] NCSD Corrupt\n");
		return;
	}
	printf("[+] NCSD\n");
	switch(ctx->sig_valid){
		case Good : memdump(stdout,"Signature(Good):        ",ctx->signature,0x100); break;
		case Fail : memdump(stdout,"Signature(Fail):        ",ctx->signature,0x100); break;
		case NotChecked: memdump(stdout,"Signature:              ",ctx->signature,0x100); break;
	}
	switch(ctx->type){
		case retail : 
			printf("Target:                 Retail/Production\n"); 
			printf("CVer Title ID:          %016llx\n",u8_to_u64(card_info->cver_title_id,LE));
			printf("CVer Title Ver:         v%d\n",u8_to_u16(card_info->cver_title_version,LE));
			char *FW_STRING = malloc(10);
			memset(FW_STRING,0,10);
			GetMin3DSFW(FW_STRING,card_info);
			printf("Min 3DS Firm:           %s\n",FW_STRING);
			_free(FW_STRING);
			break;
		case dev_internal_SDK :
			printf("Target:                 Debug/Development\n");
			printf("SDK Type:               Nintendo Internal SDK\n");
			memdump(stdout,"Title Key:              ",dev_card_info->TitleKey,0x10);
			break;
		case dev_external_SDK :
			printf("Target:                 Debug/Development\n");
			printf("SDK Type:               Nintendo 3RD Party SDK\n");
			memdump(stdout,"Title Key:              ",dev_card_info->TitleKey,0x10);
			break;
	}
	if(ctx->rom_size >= GB){
		printf("ROM Cart Size:          %lld GB",ctx->rom_size/GB); printf(" (%lld Gbit)\n",(ctx->rom_size/GB)*8);
	}
	else{
		printf("ROM Cart Size:          %lld MB",ctx->rom_size/MB); 
		u32 tmp = (ctx->rom_size/MB)*8;
		if(tmp >= 1024)
			printf(" (%d Gbit)\n",tmp/1024);
		else
			printf(" (%d Mbit)\n",tmp);
	}
	if(ctx->used_rom_size >= MB){
		printf("ROM Used Size:          %lld MB",ctx->used_rom_size/MB); printf(" (0x%llx bytes)\n",ctx->used_rom_size);
	}
	else if(ctx->used_rom_size >= KB){
		printf("ROM Used Size:          %lld KB",ctx->used_rom_size/KB); printf(" (0x%llx bytes)\n",ctx->used_rom_size);
	}
	printf("NCSD Title ID:          %016llx\n",u8_to_u64(header->title_id,LE));
	memdump(stdout,"ExHeader Hash:          ",header->exheader_hash,0x20);
	printf("AddHeader Size:         0x%x\n",u8_to_u32(header->additional_header_size,LE));
	printf("Sector 0 Offset:        0x%x\n",u8_to_u32(header->sector_zero_offset,LE));
	memdump(stdout,"Flags:                  ",header->partition_flags,8);
	printf("\n");
	for(int i = 0; i < 8; i++){
		if(ctx->partition_data[i].active == True){
			printf("Partition %d\n",i);
			printf(" Title ID:              %016llx\n",ctx->partition_data[i].title_id);
			printf(" Content Type:          ");
			switch(ctx->partition_data[i].content_type){
				case _unknown : printf("Unknown\n"); break;
				case CXI : printf("Application\n"); break;
				case CFA_Manual : printf("Electronic Manual\n"); break;
				case CFA_DLPChild : printf("Download Play Child\n"); break;
				case CFA_Update : printf("Software Update Partition\n"); break;
			}
			
			printf(" FS Type:               %x\n",ctx->partition_data[i].fs_type);
			printf(" Crypto Type:           %x\n",ctx->partition_data[i].crypto_type);
			printf(" Offset:                0x%x\n",ctx->partition_data[i].offset);
			printf(" Size:                  0x%x\n",ctx->partition_data[i].size);
			printf("\n");
		}
	}
}