예제 #1
0
파일: image.c 프로젝트: d0k3/GodMode9
u32 IdentifyImage(const char* path) {
    u8 header[0x200];
    FIL file;
    if (f_open(&file, path, FA_READ | FA_OPEN_EXISTING) != FR_OK)
        return 0;
    f_lseek(&file, 0);
    f_sync(&file);
    UINT fsize = f_size(&file);
    UINT bytes_read;
    if ((f_read(&file, header, 0x200, &bytes_read) != FR_OK) || (bytes_read != 0x200)) {
        f_close(&file);
        return 0;
    }
    f_close(&file);
    if ((getbe32(header + 0x100) == 0x4E435344) && (getbe64(header + 0x110) == (u64) 0x0104030301000000) &&
        (getbe64(header + 0x108) == (u64) 0) && (fsize >= 0x8FC8000)) {
        return IMG_NAND;
    } else if (getbe16(header + 0x1FE) == 0x55AA) { // migt be FAT or MBR
        if ((strncmp((char*) header + 0x36, "FAT12   ", 8) == 0) || (strncmp((char*) header + 0x36, "FAT16   ", 8) == 0) ||
            (strncmp((char*) header + 0x36, "FAT     ", 8) == 0) || (strncmp((char*) header + 0x52, "FAT32   ", 8) == 0)) {
            return IMG_FAT; // this is an actual FAT header
        } else if (((getle32(header + 0x1BE + 0x8) + getle32(header + 0x1BE + 0xC)) < (fsize / 0x200)) && // check file size
            (getle32(header + 0x1BE + 0x8) > 0) && (getle32(header + 0x1BE + 0xC) >= 0x800) && // check first partition sanity
            ((header[0x1BE + 0x4] == 0x1) || (header[0x1BE + 0x4] == 0x4) || (header[0x1BE + 0x4] == 0x6) || // filesystem type
             (header[0x1BE + 0x4] == 0xB) || (header[0x1BE + 0x4] == 0xC) || (header[0x1BE + 0x4] == 0xE))) {
            return IMG_FAT; // this might be an MBR -> give it the benefit of doubt
        }
    }
    return 0;
}
예제 #2
0
파일: cia.c 프로젝트: 44670/Project_CTR
void cia_verify_contents(cia_context *ctx, u32 actions)
{
	u16 contentflags;
	ctr_tmd_body *body;
	ctr_tmd_contentchunk *chunk;
	u8 *verify_buf;
	u32 content_size=0;
	int i;

	// verify TMD content hashes, requires decryption ..
	body  = tmd_get_body(&ctx->tmd);
	chunk = (ctr_tmd_contentchunk*)(body->contentinfo + (sizeof(ctr_tmd_contentinfo) * TMD_MAX_CONTENTS));

	fseek(ctx->file, ctx->offset + ctx->offsetcontent, SEEK_SET);
	for(i = 0; i < getbe16(body->contentcount); i++) 
	{
		content_size = getbe64(chunk->size) & 0xffffffff;

		contentflags = getbe16(chunk->type);

		verify_buf = malloc(content_size);
		fread(verify_buf, content_size, 1, ctx->file);

		if(contentflags & 1 && !(actions & PlainFlag)) // Decrypt if needed
		{
			ctx->iv[0] = (getbe16(chunk->index) >> 8) & 0xff;
			ctx->iv[1] = getbe16(chunk->index) & 0xff;

			ctr_init_cbc_decrypt(&ctx->aes, ctx->titlekey, ctx->iv);
		
			ctr_decrypt_cbc(&ctx->aes, verify_buf, verify_buf, content_size);
		}

		if (ctr_sha_256_verify(verify_buf, content_size, chunk->hash) == Good)
			ctx->tmd.content_hash_stat[i] = 1;
		else
			ctx->tmd.content_hash_stat[i] = 2;

		free(verify_buf);

		chunk++;
	}
예제 #3
0
int main(int argc, char* argv[])
{
	int result = 0;

	fprintf(stdout, "stripiosplugin - based on IOS ELF stripper - by neimod\n");
	if (argc < 3 )
	{
		fprintf(stderr,"Usage: %s <in.elf> <out.bin> [strip addr]\n", argv[0]);

		return -1;
	}

	FILE* fin = fopen(argv[1], "rb");
	FILE* fout = fopen(argv[2], "wb");

	if (fin == 0 || fout == 0)
	{
		if (fin == 0)
			fprintf(stderr,"ERROR opening file %s\n", argv[1]);
		if (fout == 0)
			fprintf(stderr,"ERROR opening file %s\n", argv[2]);
		return 1;
	}

	elfheader header;

	if (fread(&header, sizeof(elfheader), 1, fin) != 1)
	{
		fprintf(stderr,"ERROR reading ELF header\n");
		return 1;
	}

	unsigned long elfmagicword = getbe32(&header.ident0);

	if (elfmagicword != 0x7F454C46)
	{
		fprintf(stderr,"ERROR not a valid ELF\n");
		return 1;
	}

	unsigned long shoff = getbe32(&header.shoff);
	unsigned short shentsize = getbe16(&header.shentsize);
	unsigned short shnum = getbe16(&header.shnum);
	unsigned long memsz = 0, filesz = 0;
	unsigned long vaddr = 0, paddr = 0;

	//printf("shoff %lx\n", shoff);
	//printf("size %x\n", shentsize);
	//printf("entries %x\n", shnum);

	elfshentry* entry = new elfshentry[shnum];

	fseek(fin, shoff, SEEK_SET);
	if (fread(entry, sizeof(elfshentry), shnum, fin) != shnum)
	{
		fprintf(stderr,"ERROR reading sections header\n");
		return 1;
	}

	unsigned short i = 0;
	while (i < shnum)
	{
  		unsigned long addr = getbe32(&entry[i].shaddr);
  		unsigned long offset = getbe32(&entry[i].shoffset);
		unsigned long size = getbe32(&entry[i].shsize);
		if ((addr & ~0xfff) == 0x1377E000) {
  			printf("addr:%lx - ",addr);
			printf("offset:%lx - ",offset);  
			printf("size: %lx\n", size);
		fseek(fin, offset, SEEK_SET);
		char *buf = new char[size];
		if (!buf) {
			fprintf(stderr, "Error allocating memory\n");
			return 2;
		}
		fread(buf, sizeof(char), size, fin);
		if (fwrite(buf, sizeof(char), size, fout) != size) {
			fprintf(stderr, "Error writing output file\n");
			return 2;
		}
		delete [] buf;
		}
		i++;
	}

	if (entry)
		delete[] entry;
	if (fout)
		fclose(fout);

	if (fin)
		fclose(fin);

	return result;
}
예제 #4
0
파일: tmd.c 프로젝트: Poryhack/Project_CTR
void tmd_print(tmd_context* ctx)
{
	unsigned int type = getbe32(ctx->buffer);
	ctr_tmd_header_4096* header4096 = 0;
	ctr_tmd_header_2048* header2048 = 0;
	ctr_tmd_body* body = 0;
	unsigned int contentcount = 0;
	unsigned int savesize = 0;
	unsigned int titlever = 0;
	unsigned int i;

	if (type == TMD_RSA_2048_SHA256 || type == TMD_RSA_2048_SHA1)
	{
		header2048 = (ctr_tmd_header_2048*)ctx->buffer;
	}
	else if (type == TMD_RSA_4096_SHA256 || type == TMD_RSA_4096_SHA1)
	{
		header4096 = (ctr_tmd_header_4096*)ctx->buffer;
	}
	else
	{
		return;
	}

	body = tmd_get_body(ctx);

	contentcount = getbe16(body->contentcount);
	savesize = getle32(body->savedatasize);
	titlever = getbe16(body->titleversion);
	
	fprintf(stdout, "\nTMD header:\n");
	fprintf(stdout, "Signature type:         %s\n", tmd_get_type_string(type));
	fprintf(stdout, "Issuer:                 %s\n", body->issuer);
	fprintf(stdout, "Version:                %d\n", body->version);
	fprintf(stdout, "CA CRL version:         %d\n", body->ca_crl_version);
	fprintf(stdout, "Signer CRL version:     %d\n", body->signer_crl_version);
	memdump(stdout, "System version:         ", body->systemversion, 8);
	memdump(stdout, "Title id:               ", body->titleid, 8);
	fprintf(stdout, "Title type:             %08x\n", getbe32(body->titletype));
	fprintf(stdout, "Group id:               %04x\n", getbe16(body->groupid));
	if(savesize < sizeKB)
		fprintf(stdout, "Save Size:              %08x\n", savesize);
	else if(savesize < sizeMB)
		fprintf(stdout, "Save Size:              %dKB (%08x)\n", savesize/sizeKB, savesize);
	else
		fprintf(stdout, "Save Size:              %dMB (%08x)\n", savesize/sizeMB, savesize);
	fprintf(stdout, "Access rights:          %08x\n", getbe32(body->accessrights));
	fprintf(stdout, "Title version:          %d.%d.%d (v%d)\n", (titlever >> 10) & 0x3F, (titlever >> 4) & 0x3F, titlever & 0xF, titlever);
	fprintf(stdout, "Content count:          %04x\n", getbe16(body->contentcount));
	fprintf(stdout, "Boot content:           %04x\n", getbe16(body->bootcontent));
	memdump(stdout, "Hash:                   ", body->hash, 32);

	fprintf(stdout, "\nTMD content info:\n");
	for(i = 0; i < TMD_MAX_CONTENTS; i++)
	{
		ctr_tmd_contentinfo* info = (ctr_tmd_contentinfo*)(body->contentinfo + sizeof(ctr_tmd_contentinfo)*i);

		if (getbe16(info->commandcount) == 0)
			continue;

		fprintf(stdout, "Content index:          %04x\n", getbe16(info->index));
		fprintf(stdout, "Command count:          %04x\n", getbe16(info->commandcount));
		memdump(stdout, "Unknown:                ", info->unk, 32);
	}
	fprintf(stdout, "\nTMD contents:\n");
	for(i = 0; i < contentcount; i++)
	{
		ctr_tmd_contentchunk* chunk = (ctr_tmd_contentchunk*)(body->contentinfo + 36*64 + i*48);
		unsigned short type = getbe16(chunk->type);

		fprintf(stdout, "Content id:             %08x\n", getbe32(chunk->id));
		fprintf(stdout, "Content index:          %04x\n", getbe16(chunk->index));
		fprintf(stdout, "Content type:           %04x", getbe16(chunk->type));
		if (type)
		{
			fprintf(stdout, " ");
			if (type & 1)
				fprintf(stdout, "[encrypted]");
			if (type & 2)
				fprintf(stdout, "[disc]");
			if (type & 4)
				fprintf(stdout, "[cfm]");
			if (type & 0x4000)
				fprintf(stdout, "[optional]");
			if (type & 0x8000)
				fprintf(stdout, "[shared]");
		}
		fprintf(stdout, "\n");
		fprintf(stdout, "Content size:           %016"PRIx64"\n", getbe64(chunk->size));

		switch(ctx->content_hash_stat[i]) {
			case 1:  memdump(stdout, "Content hash [OK]:      ", chunk->hash, 32); break;
			case 2:  memdump(stdout, "Content hash [FAIL]:    ", chunk->hash, 32); break;
			default: memdump(stdout, "Content hash:           ", chunk->hash, 32); break; 
		}

		fprintf(stdout, "\n");
	}
}
예제 #5
0
파일: cia.c 프로젝트: 44670/Project_CTR
void cia_save(cia_context* ctx, u32 type, u32 flags)
{
	u32 offset;
	u32 size;
	u16 contentflags;
	u8 docrypto;
	filepath* path = 0;
	ctr_tmd_body *body;
	ctr_tmd_contentchunk *chunk;
	int i;
	char tmpname[255];

	switch(type)
	{
		case CIATYPE_CERTS:
			offset = ctx->offsetcerts;
			size = ctx->sizecert;
			path = settings_get_certs_path(ctx->usersettings);
		break;

		case CIATYPE_TIK:
			offset = ctx->offsettik;
			size = ctx->sizetik;
			path = settings_get_tik_path(ctx->usersettings);
		break;

		case CIATYPE_TMD:
			offset = ctx->offsettmd;
			size = ctx->sizetmd;
			path = settings_get_tmd_path(ctx->usersettings);
		break;
		
		case CIATYPE_CONTENT:
			offset = ctx->offsetcontent;
			size = ctx->sizecontent;
			path = settings_get_content_path(ctx->usersettings);
			
		break;

		case CIATYPE_META:
			offset = ctx->offsetmeta;
			size = ctx->sizemeta;
			path = settings_get_meta_path(ctx->usersettings);;
		break;

		default:
			fprintf(stderr, "Error, unknown CIA type specified\n");
			return;	
		break;
	}

	if (path == 0 || path->valid == 0)
		return;

	switch(type)
	{
		case CIATYPE_CERTS: fprintf(stdout, "Saving certs to %s\n", path->pathname); break;
		case CIATYPE_TIK: fprintf(stdout, "Saving tik to %s\n", path->pathname); break;
		case CIATYPE_TMD: fprintf(stdout, "Saving tmd to %s\n", path->pathname); break;
		case CIATYPE_CONTENT:

			body  = tmd_get_body(&ctx->tmd);
			chunk = (ctr_tmd_contentchunk*)(body->contentinfo + (sizeof(ctr_tmd_contentinfo) * TMD_MAX_CONTENTS));

			for(i = 0; i < getbe16(body->contentcount); i++) {
				sprintf(tmpname, "%s.%04x.%08x", path->pathname, getbe16(chunk->index), getbe32(chunk->id));
				fprintf(stdout, "Saving content #%04x to %s\n", getbe16(chunk->index), tmpname);
				
				contentflags = getbe16(chunk->type);
				docrypto = contentflags & 1 && !(flags & PlainFlag);

				if(docrypto) // Decrypt if needed
				{
					ctx->iv[0] = (getbe16(chunk->index) >> 8) & 0xff;
					ctx->iv[1] = getbe16(chunk->index) & 0xff;

					ctr_init_cbc_decrypt(&ctx->aes, ctx->titlekey, ctx->iv);
				}

				cia_save_blob(ctx, tmpname, offset, getbe64(chunk->size) & 0xffffffff, docrypto);

				offset += getbe64(chunk->size) & 0xffffffff;
				chunk++;
			}

			memset(ctx->iv, 0, 16);

			return;
		break;

		case CIATYPE_META: fprintf(stdout, "Saving meta to %s\n", path->pathname); break;
	}

	cia_save_blob(ctx, path->pathname, offset, size, 0);
}
예제 #6
0
u32 InjectHealthAndSafety(u32 param)
{
    u8* buffer = BUFFER_ADDRESS;
    PartitionInfo* ctrnand_info = GetPartitionInfo(P_CTRNAND);
    TitleListInfo* health = titleList + ((GetUnitPlatform() == PLATFORM_3DS) ? 3 : 4);
    TitleListInfo* health_alt = (GetUnitPlatform() == PLATFORM_N3DS) ? titleList + 3 : NULL;
    NcchHeader* ncch = (NcchHeader*) 0x20316000;
    char filename[64];
    u32 offset_app[4];
    u32 size_app[4];
    u32 offset_tmd;
    u32 size_tmd;
    u32 size_hs;
    
    
    if (!(param & N_NANDWRITE)) // developer screwup protection
        return 1;
    
    if ((DebugSeekTitleInNand(&offset_tmd, &size_tmd, offset_app, size_app, health, 4) != 0) && (!health_alt || 
        (DebugSeekTitleInNand(&offset_tmd, &size_tmd, offset_app, size_app, health_alt, 4) != 0)))
        return 1;
    if (size_app[0] > 0x400000) {
        Debug("H&S system app is too big!");
        return 1;
    }
    if (DecryptNandToMem((void*) ncch, offset_app[0], 0x200, ctrnand_info) != 0)
        return 1;
    if (InputFileNameSelector(filename, NULL, "app", ncch->signature, 0x100, 0, false) != 0)
        return 1;
    
    if (!DebugFileOpen(filename))
        return 1;
    size_hs = FileGetSize();
    memset(buffer, 0, size_app[0]);
    if (size_hs > size_app[0]) {
        Debug("H&S inject app is too big!");
        return 1;
    }
    if (!DebugFileRead(buffer, size_hs, 0)) {
        FileClose();
        return 1;
    }
    FileClose();
    if (!DebugFileCreate("hs.enc", true))
        return 1;
    if (!DebugFileWrite(buffer, size_app[0], 0)) {
        FileClose();
        return 1;
    }
    FileClose();
    if (CryptNcch("hs.enc", 0, 0, 0, ncch->flags) != 0)
        return 1;
    
    Debug("Injecting H&S app...");
    if (EncryptFileToNand("hs.enc", offset_app[0], size_app[0], ctrnand_info) != 0)
        return 1;
    
    Debug("Fixing TMD...");
    u8* tmd_data = (u8*) 0x20316000;
    if (DecryptNandToMem(tmd_data, offset_tmd, size_tmd, ctrnand_info) != 0)
        return 1; 
    tmd_data += (tmd_data[3] == 3) ? 0x240 : (tmd_data[3] == 4) ? 0x140 : 0x80;
    u8* content_list = tmd_data + 0xC4 + (64 * 0x24);
    u32 cnt_count = getbe16(tmd_data + 0x9E);
    if (GetHashFromFile("hs.enc", 0, size_app[0], content_list + 0x10) != 0) {
        Debug("Failed!");
        return 1;
    }
    for (u32 i = 0, kc = 0; i < 64 && kc < cnt_count; i++) {
        u32 k = getbe16(tmd_data + 0xC4 + (i * 0x24) + 0x02);
        u8* chunk_hash = tmd_data + 0xC4 + (i * 0x24) + 0x04;
        sha_quick(chunk_hash, content_list + kc * 0x30, k * 0x30, SHA256_MODE);
        kc += k;
    }
    u8* tmd_hash = tmd_data + 0xA4;
    sha_quick(tmd_hash, tmd_data + 0xC4, 64 * 0x24, SHA256_MODE);
    tmd_data = (u8*) 0x20316000;
    if (EncryptMemToNand(tmd_data, offset_tmd, size_tmd, ctrnand_info) != 0)
        return 1; 
    
    
    return 0;
}
예제 #7
0
u32 DebugSeekTitleInNand(u32* offset_tmd, u32* size_tmd, u32* offset_app, u32* size_app, TitleListInfo* title_info, u32 max_cnt)
{
    PartitionInfo* ctrnand_info = GetPartitionInfo(P_CTRNAND);
    u8* buffer = (u8*) 0x20316000;
    u32 cnt_count = 0;
    u32 tid_low = 0;
    u32 tmd_id = 0;
    
    Debug("Searching title \"%s\"...", title_info->name);
    Debug("Method 1: Search in title.db...");
    if (SeekTitleInNandDb(&tid_low, &tmd_id, title_info) == 0) {
        char path[64];
        sprintf(path, "TITLE      %08X   %08X   CONTENT    %08XTMD", (unsigned int) title_info->tid_high, (unsigned int) tid_low, (unsigned int) tmd_id);
        if (SeekFileInNand(offset_tmd, size_tmd, path, ctrnand_info) != 0)
            tid_low = 0;
    }
    if (!tid_low) {
        Debug("Method 2: Search in file system...");
        for (u32 i = 0; i < 6; i++) {
            char path[64];
            if (title_info->tid_low[i] == 0)
                continue;
            sprintf(path, "TITLE      %08X   %08X   CONTENT    ????????TMD", (unsigned int) title_info->tid_high, (unsigned int) title_info->tid_low[i]);
            if (SeekFileInNand(offset_tmd, size_tmd, path, ctrnand_info) == 0) {
                tid_low = title_info->tid_low[i];
                break;
            }
        }
    }
    if (!tid_low) {
        Debug("Failed!");
        return 1;
    }
    Debug("Found title %08X%08X", title_info->tid_high, tid_low);
    
    Debug("TMD0 found at %08X, size %ub", *offset_tmd, *size_tmd);
    if ((*size_tmd < 0xC4 + (0x40 * 0x24)) || (*size_tmd > 0x4000)) {
        Debug("TMD has bad size!");
        return 1;
    }
    if (DecryptNandToMem(buffer, *offset_tmd, *size_tmd, ctrnand_info) != 0)
        return 1;
    u32 size_sig = (buffer[3] == 3) ? 0x240 : (buffer[3] == 4) ? 0x140 : (buffer[3] == 5) ? 0x80 : 0;         
    if ((size_sig == 0) || (memcmp(buffer, "\x00\x01\x00", 3) != 0)) {
        Debug("Unknown signature type: %08X", getbe32(buffer));
        return 1;
    }
    cnt_count = getbe16(buffer + size_sig + 0x9E);
    u32 size_tmd_expected = size_sig + 0xC4 + (0x40 * 0x24) + (cnt_count * 0x30);
    if (*size_tmd < size_tmd_expected) {
        Debug("TMD bad size (expected %ub)!", size_tmd_expected );
        return 1;
    }
    buffer += size_sig + 0xC4 + (0x40 * 0x24);
    
    for (u32 i = 0; i < cnt_count && i < max_cnt; i++) {
        char path[64];
        u32 cnt_id = getbe32(buffer + (0x30 * i));
        if (i >= max_cnt) {
            Debug("APP%i was skipped", i);
            continue;
        }
        sprintf(path, "TITLE      %08X   %08X   CONTENT    %08XAPP", (unsigned int) title_info->tid_high, (unsigned int) tid_low, (unsigned int) cnt_id);
        if (SeekFileInNand(offset_app + i, size_app + i, path, ctrnand_info) != 0) {
            Debug("APP%i not found or fragmented!", i);
            return 1;
        }
        Debug("APP%i found at %08X, size %ukB", i, offset_app[i], size_app[i] / 1024);
    }
    
    return 0;
}