diff --git a/.gitattributes b/.gitattributes index 9e4215a..fdeec27 100644 --- a/.gitattributes +++ b/.gitattributes @@ -14,6 +14,8 @@ WiiQt/nandbin.cpp -text WiiQt/nandbin.h -text WiiQt/nanddump.cpp -text WiiQt/nanddump.h -text +WiiQt/nandspare.cpp -text +WiiQt/nandspare.h -text WiiQt/nusdownloader.cpp -text WiiQt/nusdownloader.h -text WiiQt/savebanner.cpp -text diff --git a/WiiQt/nandbin.cpp b/WiiQt/nandbin.cpp index 14b697b..98260d5 100755 --- a/WiiQt/nandbin.cpp +++ b/WiiQt/nandbin.cpp @@ -254,6 +254,56 @@ bool NandBin::InitNand( QIcon dirs, QIcon files ) blocks << block; } + //debug shitzz + //ecc + /*int blNo = 7; + for( int b = 0; b < 8; b++ ) + { + qDebug() << "cluster" << b << "of block" << hex << blNo; + int clNo = ( blNo * 8 ) + b; + for( int i = 0; i < 8; i++ ) + { + qDebug() << "page" << i << "of cluster" << hex << ( clNo - ( blNo * 8 ) ) << "(" << clNo << ")"; + QByteArray whole = GetPage( ( clNo * 8 ) + i, true ); + if( whole.size() != 0x840 ) + { + qDebug() << "wrong size" << hex << whole.size(); + continue; + } + QByteArray eccR = whole.mid( 0x800, 0x40 ); + QByteArray eccC = NandSpare::CalcEcc( whole.left( 0x800 ) ); + + hexdump( eccR ); + hexdump( eccC ); + } + }*/ + + //this makes correct hmac data for the superblocks + /*int blNo = 0xff0;//first superblock + //int blNo = 0xffe;//last superblock + for( int b = blNo; b < 16 + blNo; b += 2 ) + { + //if( !( b % 2 ) ) + //continue; + QByteArray clData; + for( int c = 0; c < 16; c++ ) + { + for( int p = 0; p < 8; p++ ) + { + QByteArray whole = GetPage( ( ( b * 64 ) + ( c * 8 ) + p ), true ); + clData += whole.left( 0x800 ); + } + } + qDebug() << "hmac:"; + QByteArray hmR = spare.Get_hmac_meta( clData, ( b * 8 ) ); + hexdump( hmR ); + }*/ + //GetFile( 369 ); + + + + + if( !bootBlocks.SetBlocks( blocks ) ) return false; @@ -292,6 +342,7 @@ quint8 NandBin::Boot1Version() bool NandBin::GetKey( int type ) { + QByteArray hmacKey; switch( type ) { case 0: @@ -307,9 +358,12 @@ bool NandBin::GetKey( int type ) keyPath.resize( sl + 1 ); keyPath += "keys.bin"; - key = ReadKeyfile( keyPath ); + key = ReadKeyfile( keyPath, 0 ); if( key.isEmpty() ) return false; + hmacKey = ReadKeyfile( keyPath, 1 ); + if( hmacKey.isEmpty() ) + return false; } break; case 2: @@ -319,6 +373,9 @@ bool NandBin::GetKey( int type ) emit SendError( tr( "Tried to read keys from unopened file" ) ); return false; } + f.seek( 0x21000144 ); + hmacKey = f.read( 20 ); + f.seek( 0x21000158 ); key = f.read( 16 ); } @@ -328,10 +385,12 @@ bool NandBin::GetKey( int type ) return false; break; } + spare.SetHMacKey( hmacKey );//set the hmac key for calculating spare data + //hexdump( hmacKey ); return true; } -QByteArray NandBin::ReadKeyfile( QString path ) +QByteArray NandBin::ReadKeyfile( QString path, quint8 type ) { QByteArray retval; QFile f( path ); @@ -340,14 +399,22 @@ QByteArray NandBin::ReadKeyfile( QString path ) emit SendError( tr( "Can't open %1!" ).arg( path ) ); return retval; } - if( f.size() < 0x16e ) + if( f.size() < 0x400 ) { f.close(); emit SendError( tr( "keys.bin is too small!" ) ); return retval; } - f.seek( 0x158 ); - retval = f.read( 16 ); + if( type == 0 ) + { + f.seek( 0x158 ); + retval = f.read( 16 ); + } + else if( type == 1 ) + { + f.seek( 0x144 ); + retval = f.read( 20 ); + } f.close(); return retval; @@ -388,7 +455,7 @@ qint32 NandBin::FindSuperblock() f.seek( n_len[ type ] - 4 ); } - return -1; + return -1;//hmmmm what happens if the last supercluster is the latest one? seems like a bug to fix at a later date... } fst_t NandBin::GetFST( quint16 entry ) @@ -422,7 +489,7 @@ fst_t NandBin::GetFST( quint16 entry ) f.read( (char*)&fst.attr, 1 ); f.read( (char*)&fst.sub, 2 ); f.read( (char*)&fst.sib, 2 ); - if( type && ( entry + 1 ) % 64 == 0 )//bug in other nand.bin extracterizers. the entry for every 64th fst item is inturrupeted by some ecc shit + if( type && ( entry + 1 ) % 64 == 0 )//bug in other nand.bin extracterizers. the entry for every 64th fst item is inturrupeted by some spare shit { f.read( (char*)&fst.size, 2 ); f.seek( f.pos() + 0x40 ); @@ -440,6 +507,7 @@ fst_t NandBin::GetFST( quint16 entry ) fst.uid = qFromBigEndian( fst.uid ); fst.gid = qFromBigEndian( fst.gid ); fst.x3 = qFromBigEndian( fst.x3 ); + fst.fst_pos = entry; fst.mode &= 1; return fst; @@ -473,6 +541,21 @@ quint16 NandBin::GetFAT( quint16 fat_entry ) return ret; } +QByteArray NandBin::GetPage( quint32 pageNo, bool withEcc ) +{ + //qDebug() << "NandBin::GetPage( " << hex << pageNo << ", " << withEcc << " )"; + quint32 n_pagelen[] = { 0x800, 0x840, 0x840 }; + + if( f.size() < ( pageNo + 1 ) * n_pagelen[ type ] ) + { + emit SendError( tr( "Tried to read page past size of nand.bin" ) ); + return QByteArray(); + } + f.seek( pageNo * n_pagelen[ type ] ); //seek to the beginning of the page to read + QByteArray page = f.read( ( type && withEcc ) ? n_pagelen[ type ] : 0x800 ); + return page; +} + QByteArray NandBin::GetCluster( quint16 cluster_entry, bool decrypt ) { //qDebug() << "NandBin::GetCluster" << hex << cluster_entry; @@ -492,7 +575,9 @@ QByteArray NandBin::GetCluster( quint16 cluster_entry, bool decrypt ) f.seek( ( cluster_entry * n_clusterlen[ type ] ) + ( i * n_pagelen[ type ] ) ); //seek to the beginning of the page to read //QByteArray page = f.read( n_pagelen[ type ] ); //read the page, with ecc QByteArray page = f.read( 0x800 ); //read the page, skip the ecc + //hexdump( page.mid( 0x800, 0x40 ) );//just here for debugging purposes + //cluster += page.left( 0x800 ); cluster += page; } if( cluster.size() != 0x4000 ) @@ -520,25 +605,31 @@ QByteArray NandBin::GetFile( quint16 entry ) return GetFile( fst ); } -QByteArray NandBin::GetFile( fst_t fst ) +QByteArray NandBin::GetFile( fst_t fst_ ) { - if( !fst.size ) + qDebug() << "NandBin::GetFile" << (const char*)fst_.filename; + if( !fst_.size ) return QByteArray(); - quint16 fat = fst.sub; + quint16 fat = fst_.sub; //int cluster_span = (int)( fst.size / 0x4000) + 1; QByteArray data; + //int idx = 0; for (int i = 0; fat < 0xFFF0; i++) { QByteArray cluster = GetCluster( fat ); if( cluster.size() != 0x4000 ) return QByteArray(); + //debug shit... am i creating correct hmac data? + //WriteDecryptedCluster( 0, cluster, fst_, idx++ ); + data += cluster; fat = GetFAT( fat ); } + //this check doesnt really seem to matter, it always appears to be 1 extra cluster added to the end //of the file and that extra bit is dropped in this function before the data is returned. /*if( data.size() != cluster_span * 0x4000 ) @@ -551,18 +642,18 @@ QByteArray NandBin::GetFile( fst_t fst ) emit SendError( tr( "Error reading file [ block size is not a as expected ] %1" ).arg( FstName( fst ) ) ); }*/ - if( (quint32)data.size() < fst.size ) + if( (quint32)data.size() < fst_.size ) { qDebug() << "(quint32)data.size() < fst.size :: " << hex << data.size() - << "expected size:" << hex << fst.size; + << "expected size:" << hex << fst_.size; emit SendError( tr( "Error reading file [ returned data size is less that the size in the fst ]" ) ); return QByteArray(); } - if( (quint32)data.size() > fst.size ) - data.resize( fst.size );//dont need to give back all the data, only up to the expected size + if( (quint32)data.size() > fst_.size ) + data.resize( fst_.size );//dont need to give back all the data, only up to the expected size return data; } @@ -694,6 +785,79 @@ void NandBin::ShowInfo() << "\nreserved:" << hex << reserved; } +bool NandBin::WriteCluster( quint32 pageNo, const QByteArray data, const QByteArray hmac ) +{ + if( data.size() != 0x4000 ) + { + qWarning() << "NandBin::WriteCluster -> size:" << hex << data.size(); + return false; + } + + for( int i = 0; i < 8; i++ ) + { + QByteArray spareData( 0x40, '\0' ); + quint8* sp = (quint8*)spareData.data(); + QByteArray ecc = spare.CalcEcc( data.mid( i * 0x800, 0x800 ) ); + memcpy( sp + 0x30, ecc.data(), 0x14 ); + sp[ 0 ] = 0xff; // good block + if( !hmac.isEmpty() ) + { + if( i == 6 ) + { + memcpy( (char*)sp + 1, hmac.data(), 20 ); + memcpy( (char*)sp + 21, hmac.data(), 12 ); + } + else if( i == 7 ) + { + memcpy( (char*)sp + 1, hmac.data() + 12, 8 ); + } + } + if( !WritePage( pageNo + i, data.mid( i * 0x800, 0x800 ) + spareData ) ) + return false; + } + return true; +} + +bool NandBin::WriteDecryptedCluster( quint32 pageNo, const QByteArray data, fst_t fst, quint16 idx ) +{ + qDebug() << "NandBin::WriteDecryptedCluster"; + QByteArray hmac = spare.Get_hmac_data( data, fst.uid, (const unsigned char *)&fst.filename, fst.fst_pos, fst.x3, idx ); + + hexdump( hmac ); + return true; + /*fs_hmac_data( + buffer, + fp->node->uid, + (const unsigned char *)fp->node->name, + fp->idx, + fp->node->dummy, + fp->cluster_idx, + hmac + );*/ + AesSetKey( key ); + QByteArray encData = AesEncrypt( 0, data ); + return WriteCluster( pageNo, encData, hmac ); +} + +bool NandBin::WritePage( quint32 pageNo, const QByteArray data ) +{ + //qDebug() << "NandBin::WritePage(" << hex << pageNo << ")"; + return true; + quint32 n_pagelen[] = { 0x800, 0x840, 0x840 }; + if( (quint32)data.size() != n_pagelen[ type ] ) + { + qWarning() << "data is wrong size" << hex << data.size(); + return false; + } + + if( f.size() < ( pageNo + 1 ) * n_pagelen[ type ] ) + { + emit SendError( tr( "Tried to write page past size of nand.bin" ) ); + return false; + } + f.seek( pageNo * n_pagelen[ type ] ); //seek to the beginning of the page to write + return f.write( data ); +} /* structure of blocks 0 - 7 diff --git a/WiiQt/nandbin.h b/WiiQt/nandbin.h index 37e95fa..951a2d3 100755 --- a/WiiQt/nandbin.h +++ b/WiiQt/nandbin.h @@ -3,6 +3,7 @@ #include "includes.h" #include "blocks0to7.h" +#include "nandspare.h" struct fst_t { quint8 filename[ 0xc ]; @@ -14,6 +15,7 @@ struct fst_t quint32 uid; quint16 gid; quint32 x3; + quint16 fst_pos;//not really part of the nand structure, but needed when calculating hmac data }; // class to deal with an encrypted wii nand dump // basic usage... create an object, set a path, call InitNand. then you can get the detailed list of entries with GetTree() @@ -89,6 +91,8 @@ public: const QList Boot2Infos(); quint8 Boot1Version(); + QByteArray GetPage( quint32 pageNo, bool withEcc = false ); + private: QByteArray key; @@ -104,6 +108,8 @@ private: QIcon groupIcon; QIcon keyIcon; + NandSpare spare;//used to handle the hmac mumbojumbo + //read all the fst and remember them rather than seeking back and forth in the file all the time // uses ~120KiB RAM bool fstInited; @@ -115,7 +121,7 @@ private: int GetDumpType( quint64 fileSize ); bool GetKey( int type ); - QByteArray ReadKeyfile( QString path ); + QByteArray ReadKeyfile( QString path, quint8 type );//type 0 for nand key, type 1 for hmac qint32 FindSuperblock(); quint16 GetFAT( quint16 fat_entry ); fst_t GetFST( quint16 entry ); @@ -137,6 +143,10 @@ private: //holds info about boot1 & 2 Blocks0to7 bootBlocks; + bool WriteCluster( quint32 pageNo, const QByteArray data, const QByteArray hmac ); + bool WriteDecryptedCluster( quint32 pageNo, const QByteArray data, fst_t fst, quint16 idx ); + bool WritePage( quint32 pageNo, const QByteArray data ); + signals: //connect to these to receive messages from this object void SendError( QString ); diff --git a/WiiQt/nandspare.cpp b/WiiQt/nandspare.cpp new file mode 100644 index 0000000..6652427 --- /dev/null +++ b/WiiQt/nandspare.cpp @@ -0,0 +1,215 @@ +#include "nandspare.h" +#include "tools.h" + +NandSpare::NandSpare() +{ +} +void NandSpare::SetHMacKey( const QByteArray key ) +{ + hmacKey = key; +} + +quint8 NandSpare::Parity( quint8 x ) +{ + quint8 y = 0; + while( x ) + { + y ^= ( x & 1 ); + x >>= 1; + } + return y; +} + +QByteArray NandSpare::CalcEcc( QByteArray in ) +{ + if( in.size() != 0x800 ) + return QByteArray(); + + quint8 a[ 12 ][ 2 ]; + quint32 a0, a1; + quint8 x; + + QByteArray ret( 16, '\0' ); + char* ecc = ret.data(); + char* data = in.data(); + + for( int k = 0; k < 4; k++ ) + { + memset( a, 0, sizeof a ); + for( int i = 0; i < 512; i++ ) + { + x = data[ i ]; + for( int j = 0; j < 9; j++ ) + a[ 3 + j ][ ( i >> j ) & 1 ] ^= x; + } + + x = a[ 3 ][ 0 ] ^ a[ 3 ][ 1 ]; + a[ 0 ][ 0 ] = x & 0x55; + a[ 0 ][ 1 ] = x & 0xaa; + a[ 1 ][ 0 ] = x & 0x33; + a[ 1 ][ 1 ] = x & 0xcc; + a[ 2 ][ 0 ] = x & 0x0f; + a[ 2 ][ 1 ] = x & 0xf0; + + for( int j = 0; j < 12; j++ ) + { + a[ j ][ 0 ] = Parity( a[ j ][ 0 ]); + a[ j ][ 1 ] = Parity( a[ j ][ 1 ]); + } + a0 = a1 = 0; + + for( int j = 0; j < 12; j++ ) + { + a0 |= a[ j ][ 0 ] << j; + a1 |= a[ j ][ 1 ] << j; + } + ecc[ 0 ] = a0; + ecc[ 1 ] = a0 >> 8; + ecc[ 2 ] = a1; + ecc[ 3 ] = a1 >> 8; + + data += 512; + ecc += 4; + } + return ret; +} + +typedef struct{ + unsigned char key[ 0x40 ]; + SHA1Context hash_ctx; +} hmac_ctx; + +void wbe32(void *ptr, quint32 val) { *(quint32*)ptr = qFromBigEndian( (quint32)val ); } +void wbe16(void *ptr, quint16 val) { *(quint16*)ptr = qFromBigEndian( val ); } + +// reversing done by gray +static unsigned char hmac_key[ 20 ]; + +void hmac_init(hmac_ctx *ctx, const char *key, int key_size) +{ + key_size = key_size<0x40 ? key_size: 0x40; + + memset( ctx->key,0,0x40 ); + memcpy( ctx->key,key,key_size ); + + for( int i = 0; i < 0x40; ++i ) + ctx->key[ i ] ^= 0x36; // ipad + + SHA1Reset( &ctx->hash_ctx ); + SHA1Input( &ctx->hash_ctx, ctx->key, 0x40 ); +} + +void hmac_update( hmac_ctx *ctx, const quint8 *data, int size ) +{ + SHA1Input( &ctx->hash_ctx,data,size ); +} + +void hmac_final( hmac_ctx *ctx, unsigned char *hmac ) +{ + //int i; + unsigned char hash[ 0x14 ]; + memset( hash, 0, 0x14 ); + + SHA1Result(&ctx->hash_ctx); + + // this sha1 implementation is buggy, needs to switch endian + for( int i = 0;i < 5;++i ) + { + wbe32( hash + 4 * i, ctx->hash_ctx.Message_Digest[ i ] ); + } + for( int i = 0; i < 0x40; ++i ) + ctx->key[i] ^= 0x36^0x5c; // opad + + SHA1Reset(&ctx->hash_ctx); + SHA1Input(&ctx->hash_ctx,ctx->key,0x40); + SHA1Input(&ctx->hash_ctx,hash,0x14); + SHA1Result(&ctx->hash_ctx); + + //hexdump(ctx->hash_ctx.Message_Digest, 0x14); + for( int i = 0; i < 5; ++i ) + { + wbe32( hash + 4 * i, ctx->hash_ctx.Message_Digest[ i ] ); + } + memcpy( hmac, hash, 0x14 ); +} + +void fs_hmac_set_key(const char *key, int key_size) +{ + memset( hmac_key, 0, 0x14 ); + memcpy( hmac_key, key, key_size < 0x14 ? key_size : 0x14 ); +} + +void fs_hmac_generic( const unsigned char *data, int size, const unsigned char *extra, int extra_size, unsigned char *hmac ) +{ + hmac_ctx ctx; + + hmac_init( &ctx,(const char *)hmac_key,0x14 ); + + hmac_update( &ctx,extra, extra_size ); + hmac_update( &ctx,data, size ); + + hmac_final( &ctx, hmac ); +} + +void fs_hmac_meta( const unsigned char *super_data, short super_blk, unsigned char *hmac ) +{ + unsigned char extra[ 0x40 ]; + + memset( extra,0,0x40 ); + wbe16( extra + 0x12, super_blk ); + + fs_hmac_generic( super_data, 0x40000, extra, 0x40, hmac ); +} + +void fs_hmac_data( const unsigned char *data, quint32 uid, const unsigned char *name, quint32 entry_n, quint32 x3, quint16 blk, unsigned char *hmac ) +{ + //int i,j; + unsigned char extra[ 0x40 ]; + memset( extra, 0, 0x40 ); + + wbe32( extra, uid ); + + memcpy( extra + 4, name, 12 ); + + wbe16( extra + 0x12, blk ); + wbe32( extra + 0x14, entry_n ); + wbe32( extra + 0x18, x3 ); + +// fprintf(stderr,"extra (%s): \nX ",name); +// for(i=0;i<0x20;++i){ +// fprintf(stderr,"%02X ",extra[i]); +// if(!((i+1)&0xf)) fprintf(stderr,"\nX "); +// } + fs_hmac_generic( data, 0x4000, extra, 0x40, hmac ); +} + +QByteArray NandSpare::Get_hmac_data( const QByteArray cluster, quint32 uid, const unsigned char *name, quint32 entry_n, quint32 x3, quint16 blk ) +{ + qDebug() << "NandSpare::Get_hmac_data" << hex << cluster.size() << uid << QString( (const char*)name, 12 ) << entry_n << x3 << blk; + if( hmacKey.size() != 0x14 || cluster.size() != 0x4000 ) + return QByteArray(); + + fs_hmac_set_key( hmacKey.data(), 0x14 ); + + QByteArray ret( 0x14, '\xba' ); + fs_hmac_data( (const unsigned char *)cluster.data(), uid, name, entry_n, x3, blk, (unsigned char *)ret.data() ); + + return ret; +} + +QByteArray NandSpare::Get_hmac_meta( const QByteArray cluster, quint16 super_blk ) +{ + //qDebug() << "NandSpare::Get_hmac_meta" << hex << super_blk; + if( hmacKey.size() != 0x14 || cluster.size() != 0x40000 ) + { + //qDebug() << "NandSpare::Get_hmac_meta" << hex << hmacKey.size() << cluster.size(); + return QByteArray(); + } + + fs_hmac_set_key( hmacKey.data(), 0x14 ); + + QByteArray ret( 0x14, '\0' ); + fs_hmac_meta( (const unsigned char *)cluster.data(), super_blk, (unsigned char *)ret.data() ); + + return ret; +} diff --git a/WiiQt/nandspare.h b/WiiQt/nandspare.h new file mode 100644 index 0000000..d2913a0 --- /dev/null +++ b/WiiQt/nandspare.h @@ -0,0 +1,206 @@ +#ifndef NANDSPARE_H +#define NANDSPARE_H + +//some class to handle the ecc & hmac data in the nandBin + +#include "includes.h" +#include "sha1.h" + + +class NandSpare +{ +public: + NandSpare(); + void SetHMacKey( const QByteArray key ); + QByteArray Get_hmac_data( const QByteArray cluster, quint32 uid, const unsigned char *name, quint32 entry_n, quint32 x3, quint16 blk ); + QByteArray Get_hmac_meta( const QByteArray cluster, quint16 super_blk ); + + static QByteArray CalcEcc( QByteArray in ); + static quint8 Parity( quint8 x ); +private: + QByteArray hmacKey; + +}; + +#endif // NANDSPARE_H + +/* +spare data... + +0x40 bytes +0x30 = hmac +0x10 = ecc + +block 0 ( boot1 ) +all hmac is 0xffs +all ecc is calc'd. after the first 9 pages, it works out to all 0s + +block 1 ( boot2v2 ) +all hmac is 0xff and then 0s + +block 2 +same as above until page 2 +starting at page 2, no ecc or hmac is written. its all 0xff +spare data is only written for pages used, not on a cluster basis + +block 3 ( bootmii ) +same as block 1 + +block 4 +same as above( hmac starts with 0xff then all 0s. after page2 cluster 2 all ecc works at to 0s as well ) +spare data is written for clusters used, not on a page basis + +block 5 ( never been used ) +all spare data is 0xffs, nothing is calculated + +block 6 ( boot2 copy ) +same as block 2 + +block 7 +same as block 1 + + + +super blocks + +hmac data is only on +block ff1 cluster 7 page: 6 ( 3fc7e ) +block ff1 cluster 7 page: 7 ( 3fc7f ) +block ff3 cluster 7 page: 6 ( 3fcfe ) +block ff3 cluster 7 page: 7 ( 3fcff ) +block ff5 cluster 7 page: 6 ( 3fd7e ) +block ff5 cluster 7 page: 7 ( 3fd7f ) +block ff7 cluster 7 page: 6 ( 3fdfe ) +block ff7 cluster 7 page: 7 ( 3fdff ) +block ff9 cluster 7 page: 6 ( 3fe7e ) +block ff9 cluster 7 page: 7 ( 3fe7f ) +block ffb cluster 7 page: 6 ( 3fefe ) +block ffb cluster 7 page: 7 ( 3feff ) +block ffd cluster 7 page: 6 ( 3ff7e ) +block ffd cluster 7 page: 7 ( 3ff7f ) +block fff cluster 7 page: 6 ( 3fffe ) +block fff cluster 7 page: 7 ( 3ffff ) + +*/ +/* +block ff1 cluster 7 page: 6 ( 3fc7e ) +NandBin::GetPage( 3fc7e , true ) + +00000000 ff1646bd cef67127 e662a4dc 5154ec52 ..F...q'.b..QT.R +00000010 c844ebb9 fb1646bd cef67127 e662a4dc .D....F...q'.b.. +00000020 51000000 00000000 00000000 00000000 Q............... +00000030 00000000 00000000 00000000 00000000 ................ +block ff1 cluster 7 page: 7 ( 3fc7f ) +NandBin::GetPage( 3fc7f , true ) + +00000000 ff54ec52 c844ebb9 fb000000 0020049e .T.R.D....... .. +00000010 00000000 40000000 002004f1 a8000000 ....@.... ...... +00000020 00000000 00000000 00000000 00000000 ................ +00000030 00000000 00000000 00000000 00000000 ................ + +block ff3 cluster 7 page: 6 ( 3fcfe ) +NandBin::GetPage( 3fcfe , true ) + +00000000 ff199405 907b607c 4cd691d2 825f2de9 .....{`|L...._-. +00000010 18185217 38199405 907b607c 4cd691d2 ..R.8....{`|L... +00000020 82000000 00000000 00000000 00000000 ................ +00000030 00000000 00000000 00000000 00000000 ................ +block ff3 cluster 7 page: 7 ( 3fcff ) +NandBin::GetPage( 3fcff , true ) + +00000000 ff5f2de9 18185217 38600000 000043dd ._-...R.8`....C. +00000010 05cf0bd7 38c882b2 24b67f57 6087c41f ....8...$..W`... +00000020 4d000000 00000000 00000000 00000000 M............... +00000030 00000000 00000000 00000000 00000000 ................ + +block ff5 cluster 7 page: 6 ( 3fd7e ) +NandBin::GetPage( 3fd7e , true ) + +00000000 ff1c1964 3e97b995 b864f566 b9fa025d ...d>....d.f...] +00000010 4f708e95 cc1c1964 3e97b995 b864f566 Op.....d>....d.f +00000020 b9000000 00000000 00000000 00000000 ................ +00000030 00000000 00000000 00000000 00000000 ................ +block ff5 cluster 7 page: 7 ( 3fd7f ) +NandBin::GetPage( 3fd7f , true ) + +00000000 fffa025d 4f708e95 cc2004f8 80b8f3d4 ...]Op... ...... +00000010 b94820bc f631c4c2 40c8e1da 12a29ba9 .H ..1..@....... +00000020 df000000 00000000 00000000 00000000 ................ +00000030 00000000 00000000 00000000 00000000 ................ +*//* +block ff7 cluster 7 page: 6 ( 3fdfe ) +NandBin::GetPage( 3fdfe , true ) + +00000000 ffff8ca6 8f936ad2 d4fb8424 16cd48ef ......j....$..H. +00000010 1ee1003f edff8ca6 8f936ad2 d4fb8424 ...?......j....$ +00000020 16000000 00000000 00000000 00000000 ................ +00000030 00000000 00000000 00000000 00000000 ................ +block ff7 cluster 7 page: 7 ( 3fdff ) +NandBin::GetPage( 3fdff , true ) + +00000000 ffcd48ef 1ee1003f ed000000 1020000d ..H....?..... .. +00000010 eb000000 01000000 03000000 022004f7 ............. .. +00000020 f4000000 00000000 00000000 00000000 ................ +00000030 00000000 00000000 00000000 00000000 ................ + +block ff9 cluster 7 page: 6 ( 3fe7e ) +NandBin::GetPage( 3fe7e , true ) + +00000000 ffada309 ba23b5e5 fa37a52d 10d13f10 .....#...7.-..?. +00000010 72265162 43ada309 ba23b5e5 fa37a52d r&QbC....#...7.- +00000020 10000000 00000000 00000000 00000000 ................ +00000030 00000000 00000000 00000000 00000000 ................ +block ff9 cluster 7 page: 7 ( 3fe7f ) +NandBin::GetPage( 3fe7f , true ) + +00000000 ffd13f10 72265162 432000ae 00000000 ..?.r&QbC ...... +00000010 002004ae 00000000 102004f1 e02000ad . ....... ... .. +00000020 c4000000 00000000 00000000 00000000 ................ +00000030 00000000 00000000 00000000 00000000 ................ + +block ffb cluster 7 page: 6 ( 3fefe ) +NandBin::GetPage( 3fefe , true ) + +00000000 ff40a82f f3e32161 5f9e91e7 841daf5e .@./..!a_......^ +00000010 c74678b2 b540a82f f3e32161 5f9e91e7 .Fx..@./..!a_... +00000020 84000000 00000000 00000000 00000000 ................ +00000030 00000000 00000000 00000000 00000000 ................ +block ffb cluster 7 page: 7 ( 3feff ) +NandBin::GetPage( 3feff , true ) + +00000000 ff1daf5e c74678b2 b52000ae 0000ed15 ...^.Fx.. ...... +00000010 e892928e 766d0000 00000000 00022001 ....vm........ . +00000020 da000000 00000000 00000000 00000000 ................ +00000030 00000000 00000000 00000000 00000000 ................ + +block ffd cluster 7 page: 6 ( 3ff7e ) +NandBin::GetPage( 3ff7e , true ) + +00000000 ff80ded9 67d7c195 ffd65a8b 907ea776 ....g.....Z..~.v +00000010 8c56dc33 8280ded9 67d7c195 ffd65a8b .V.3....g.....Z. +00000020 90000000 00000000 00000000 00000000 ................ +00000030 00000000 00000000 00000000 00000000 ................ +block ffd cluster 7 page: 7 ( 3ff7f ) +NandBin::GetPage( 3ff7f , true ) + +00000000 ff7ea776 8c56dc33 82000000 00200091 .~.v.V.3..... .. +00000010 c0000000 40000000 002004f1 80000000 ....@.... ...... +00000020 00000000 00000000 00000000 00000000 ................ +00000030 00000000 00000000 00000000 00000000 ................ + +block fff cluster 7 page: 6 ( 3fffe ) +NandBin::GetPage( 3fffe , true ) + +00000000 ff9570f7 915460fe 3f32d363 9a1ebfa9 ..p..T`.?2.c.... +00000010 74d3e0a4 969570f7 915460fe 3f32d363 t.....p..T`.?2.c +00000020 9a000000 00000000 00000000 00000000 ................ +00000030 00000000 00000000 00000000 00000000 ................ +block fff cluster 7 page: 7 ( 3ffff ) +NandBin::GetPage( 3ffff , true ) + +00000000 ff1ebfa9 74d3e0a4 962004f8 80b8f3d4 ....t.... ...... +00000010 b94820bc f631c4c2 40c8e1da 12a29ba9 .H ..1..@....... +00000020 df000000 00000000 00000000 00000000 ................ +00000030 00000000 00000000 00000000 00000000 ................ + + */ diff --git a/nandExtract/nandExtract.pro b/nandExtract/nandExtract.pro index 00dc94f..89e5f5b 100755 --- a/nandExtract/nandExtract.pro +++ b/nandExtract/nandExtract.pro @@ -13,14 +13,16 @@ SOURCES += main.cpp \ ../WiiQt/aes.c \ ../WiiQt/sha1.c \ nandthread.cpp \ - boot2infodialog.cpp + boot2infodialog.cpp \ + ../WiiQt/nandspare.cpp HEADERS += nandwindow.h \ ../WiiQt/tiktmd.h \ ../WiiQt/nandbin.h \ ../WiiQt/tools.h \ nandthread.h \ - boot2infodialog.h + boot2infodialog.h \ + ../WiiQt/nandspare.h FORMS += nandwindow.ui \ boot2infodialog.ui