Skip to content
This repository was archived by the owner on Sep 3, 2020. It is now read-only.
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 60 additions & 56 deletions main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,30 +18,39 @@
*/
#define _CRT_SECURE_NO_WARNINGS


unsigned char WiiUCommenDevKey[16] =
{
0x2F, 0x5C, 0x1B, 0x29, 0x44, 0xE7, 0xFD, 0x6F, 0xC3, 0x97, 0x96, 0x4B, 0x05, 0x76, 0x91, 0xFA,
};
unsigned char WiiUCommenKey[16] =
{
0xD7, 0xB0, 0x04, 0x02, 0x65, 0x9B, 0xA2, 0xAB, 0xD2, 0xCB, 0x0D, 0xB2, 0x7F, 0xA2, 0xB6, 0x56,
};

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <openssl/aes.h>
#include <openssl/sha.h>
#include <openssl\aes.h>
#include <openssl\sha.h>
#include <time.h>
#include <vector>
#include <direct.h>
#include <ctype.h>
#include <cstdint>
#include <sys/stat.h>

#pragma comment(lib,"libeay32.lib")

typedef uint64_t u64;
typedef int64_t s64;
typedef unsigned __int64 u64;
typedef signed __int64 s64;

typedef uint32_t u32;
typedef int32_t s32;
typedef unsigned int u32;
typedef signed int s32;

typedef uint16_t u16;
typedef int16_t s16;
typedef unsigned short u16;
typedef signed short s16;

typedef uint8_t u8;
typedef int8_t s8;
typedef unsigned char u8;
typedef signed char s8;

AES_KEY key;
u8 enc_title_key[16];
Expand Down Expand Up @@ -155,7 +164,7 @@ struct FEntry
unsigned short ContentID;
};

#define bs16(s) (unsigned short)( ((s)>>8) | ((s)<<8) )
#define bs16(s) (u16)( ((s)>>8) | ((s)<<8) )
#define bs32(s) (u32)( (((s)&0xFF0000)>>8) | (((s)&0xFF00)<<8) | ((s)>>24) | ((s)<<24) )

u32 bs24( u32 i )
Expand Down Expand Up @@ -269,7 +278,7 @@ void ExtractFileHash( FILE *in, u64 PartDataOffset, u64 FileOffset, u64 Size, ch
if( soffset+Size > WriteSize )
WriteSize = WriteSize - soffset;

fseeko( in, PartDataOffset+roffset, SEEK_SET );
_fseeki64( in, PartDataOffset+roffset, SEEK_SET );
while(Size > 0)
{
if( WriteSize > Size )
Expand Down Expand Up @@ -351,7 +360,7 @@ void ExtractFile( FILE *in, u64 PartDataOffset, u64 FileOffset, u64 Size, char *
if( soffset+Size > WriteSize )
WriteSize = WriteSize - soffset;

fseeko( in, PartDataOffset+roffset, SEEK_SET );
_fseeki64( in, PartDataOffset+roffset, SEEK_SET );

while(Size > 0)
{
Expand Down Expand Up @@ -379,13 +388,13 @@ s32 main( s32 argc, char*argv[])
{
char str[1024];

printf("CDecrypt v 1.0b by crediar\n");
printf("CDecrypt v 2.0b by crediar\n");
printf("Built: %s %s\n", __TIME__, __DATE__ );

if( argc != 4 )
if( argc != 3 )
{
printf("Usage:\n");
printf(" CDecrypt.exe tmd cetk ckey\n\n");
printf(" CDecrypt.exe tmd cetk\n\n");
return EXIT_SUCCESS;
}

Expand All @@ -404,20 +413,6 @@ s32 main( s32 argc, char*argv[])
perror("Failed to open cetk\n");
return EXIT_FAILURE;
}

u32 CKeyLen;
char *CKey = ReadFile( argv[3], &CKeyLen );
if( CKey == nullptr )
{
perror("Failed to open ckey\n");
return EXIT_FAILURE;
}

if( CKeyLen != 16 )
{
printf("ckey is wrong length\n");
return EXIT_FAILURE;
}

TitleMetaData *tmd = (TitleMetaData*)TMD;

Expand All @@ -430,30 +425,26 @@ s32 main( s32 argc, char*argv[])
printf("Title version:%u\n", bs16(tmd->TitleVersion) );
printf("Content Count:%u\n", bs16(tmd->ContentCount) );

AES_set_decrypt_key( (const u8*)CKey, CKeyLen*8, &key );
if( strcmp( TMD+0x140, "Root-CA00000003-CP0000000b" ) == 0 )
{
AES_set_decrypt_key( (const u8*)WiiUCommenKey, sizeof(WiiUCommenKey)*8, &key );
}
else if( strcmp( TMD+0x140, "Root-CA00000004-CP00000010" ) == 0 )
{
AES_set_decrypt_key( (const u8*)WiiUCommenDevKey, sizeof(WiiUCommenDevKey)*8, &key );
}
else
{
printf("Unknown Root type:\"%s\"\n", TMD+0x140 );
return EXIT_FAILURE;
}

memset( title_id, 0, sizeof(title_id) );

memcpy( title_id, TMD + 0x18C, 8 );
memcpy( enc_title_key, TIK + 0x1BF, 16 );

printf("Encrypted Title KEY:\n\t");
for(s32 i=0; i< sizeof(enc_title_key); ++i)
printf("%02X", enc_title_key[i]);
printf("\n");

printf("Title ID:\n\t");
for(s32 i=0; i< sizeof(title_id); ++i)
printf("%02X", title_id[i]);
printf("\n");

AES_cbc_encrypt(enc_title_key, dec_title_key, sizeof(dec_title_key), &key, title_id, AES_DECRYPT);

printf("Decrypted Title KEY:\n\t");
for(s32 i=0; i< sizeof(dec_title_key); ++i)
printf("%02X", dec_title_key[i]);
printf("\n");

AES_set_decrypt_key( dec_title_key, sizeof(dec_title_key)*8, &key);

char iv[16];
Expand Down Expand Up @@ -482,6 +473,13 @@ s32 main( s32 argc, char*argv[])

AES_cbc_encrypt( (const u8 *)(CNT), (u8 *)(CNT), CNTLen, &key, (u8*)(iv), AES_DECRYPT );

if( bs32(*(u32*)CNT) != 0x46535400 )
{
sprintf( str, "%08X.dec", bs32(tmd->Contents[0].ID) );
FileDump( str, CNT, CNTLen );
return EXIT_FAILURE;
}

FST *_fst = (FST*)(CNT);

printf("FSTInfo Entries:%u\n", bs32(_fst->EntryCount) );
Expand Down Expand Up @@ -524,23 +522,29 @@ s32 main( s32 argc, char*argv[])
printf("level error:%u\n", level );
break;
}
} else {

}
else
{
memset( Path, 0, 1024 );

for( s32 j=0; j<level; ++j )
{
if(j)
Path[strlen(Path)] = '/';
Path[strlen(Path)] = '\\';
memcpy( Path+strlen(Path), CNT + NameOff + bs24( fe[Entry[j]].NameOffset), strlen(CNT + NameOff + bs24( fe[Entry[j]].NameOffset) ) );
mkdir(Path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
_mkdir(Path);
}
if(level)
Path[strlen(Path)] = '/';
Path[strlen(Path)] = '\\';
memcpy( Path+strlen(Path), CNT + NameOff + bs24( fe[i].NameOffset ), strlen(CNT + NameOff + bs24( fe[i].NameOffset )) );

u32 CNTSize = bs32(fe[i].FileLength);
u64 CNTOff = ((u64)bs32(fe[i].FileOffset))<<5;
u64 CNTOff = ((u64)bs32(fe[i].FileOffset));

if( (bs16(fe[i].Flags) & 4) == 0 )
{
CNTOff <<= 5;
}

printf("Size:%07X Offset:0x%010llX CID:%02X U:%02X %s\n", CNTSize, CNTOff, bs16(fe[i].ContentID), bs16(fe[i].Flags), Path );

Expand All @@ -553,7 +557,7 @@ s32 main( s32 argc, char*argv[])
FILE *cnt = fopen( str, "rb" );
if( cnt == NULL )
{
sprintf( str, "%08x", ContFileID );
sprintf( str, "%08X", ContFileID );
cnt = fopen( str, "rb" );
if( cnt == NULL )
{
Expand Down