Hacking Decrypting Wii VC nfs files

  • Thread starter Thread starter JaGoTu10
  • Start date Start date
  • Views Views 38,096
  • Replies Replies 208
  • Likes Likes 23
It requires a valid ticket for the eshop to recognize it. This file is for something else.

The only extra info i could find is that the fst secondary header includes the Title and Group Ids for install, but not all the header fields have that. There is no reference for this file on the rpx too, so rebuild it doesn't seem to be necessary for injecting isos straight into a installed vc. Just a guess.
 
@Pachee @JaceCearK1 I looked It a bit and the two interesting things I could see were:
1.- It has a random letter (p, q, s...) In the 03 section
2.- In the middle I saw that it includes all files in the game like this:
code.app.cos.meta.xml.content.pack.static.pack..... It describes the files in each folder
Bye!
 
Just by looking off the bat with zero information whatsoever, I wonder how the following would work by using the encrypt command instead of decrypting:

openssl enc -e -aes-128-cbc -K "[key]"-iv 0-nopad -in game.wbfs -out hif.nfs

Then manually add the EGGS-SGGE header back in, resplit the files into their chunks, and try injecting.
 
Last edited by TeconMoon,
  • Like
Reactions: CatmanFan
Just by looking off the bat with zero information whatsoever, I wonder how the following would work by using the encrypt command instead of decrypting:

openssl enc -e -aes-128-cbc -K "[key]"-iv 0-nopad -in game.wbfs -out hif.nfs

Then manually add the EGGS-SGGE header back in, resplit the files into their chunks, and try injecting.
Likely it will freeze because the EGGS header has a bunch of extra info, you will notice there is a pattern there:

4547 4753 0001 1011 696D FBEC 8930 2BA3
0000 0009 0000 0000 0000 0001 0000 0008
0000 0002 0000 1F00 0000 1F58 0000 3E5A
0000 001A 0000 3E77 0000 004D 0000 3EC6
0000 0051 0000 3F18 0000 0018 0000 3F31
0000 00E2 0000 4014 0000 730C FFFF FFFF

These bytes always increase, never less than the ones following them, but also never exact to them.
 
Just by looking off the bat with zero information whatsoever, I wonder how the following would work by using the encrypt command instead of decrypting:

openssl enc -e -aes-128-cbc -K "[key]"-iv 0-nopad -in game.wbfs -out hif.nfs

Then manually add the EGGS-SGGE header back in, resplit the files into their chunks, and try injecting.

Likely it will freeze because the EGGS header has a bunch of extra info, you will notice there is a pattern there:

4547 4753 0001 1011 696D FBEC 8930 2BA3
0000 0009 0000 0000 0000 0001 0000 0008
0000 0002 0000 1F00 0000 1F58 0000 3E5A
0000 001A 0000 3E77 0000 004D 0000 3EC6
0000 0051 0000 3F18 0000 0018 0000 3F31
0000 00E2 0000 4014 0000 730C FFFF FFFF

These bytes always increase, never less than the ones following them, but also never exact to them.

We could just copy those EGGS bytes into the new .nfs file, but how are we going to split them?
 
We could just copy those EGGS bytes into the new .nfs file, but how are we going to split them?
No, this is not how it works!
Every Wii-VC game its own header (the "EGGS bytes"). You can't just copy them and expect it to work, they contain certain pieces of information which need to be 'decoded' (their purpose needs to be found out)! Then we will know how to decrypt the remaining .nfs-files and in what way we have to put them together.
Splitting files is relatively easy when you have good Hexeditor (like HxD) lying around.
Maybe Windows has a tool to split files natively installed, I'm not sure.
What I do know, is that merging files together under Windows works, even without Hexeditors. (should be sth like: "COPY /B fileA.nfs + fileB.nfs [...]")
 
I think injecting modded games should work at least.

If not, then there's surely a check that needs to be patched.

Bye.
Eventually, yes! But at this point in time no-one except NERD and some engineers at Nintendo Tokio know the complete file-formats for this!
 
Eventually, yes! But at this point in time no-one except NERD and some engineers at Nintendo Tokio know the complete file-formats for this!
Reverse-engineering is the way to go ATM.

Good luck though, reverse-engineering Nintendo's modern formats is a nightmare.

Don't even get me started on how hard reverse-engineering the GX2 Texture (gtx) file format was. >.>
(As I was the first person to make a working GX2 Texture extractor, and also the first to document the format)

Good luck, I can help a bit, but not now at least.
 
Last edited by AboodXD,
Reverse-engineering is the way to go ATM.

Good luck though, reverse-engineering Nintendo's modern formats is a nightmare.

Don't even get me started on how hard reverse-engineering the GX2 Texture (gtx) file format was. >.>
(As I was the first person to make a working GX2 Texture extractor, and also the first to document the format)

Good luck, I can help a bit, but not now at least.
Yeah, I tried going into that with IDA + a RPX-Plugin.
Sadly the only Assembly Language I'm really familiar with is ARM and somewhat x86 (but also not too much), so I need to dive a little more into that! :P
At least I found out that the "/vol/content/hif_%06d.nfs" files get loaded via the nn_hai_user.rpl, allegedly.
At least that's the only of the two code-files that includes the (exact) file-string. :unsure:
 
Yeah, I tried going into that with IDA + a RPX-Plugin.
Sadly the only Assembly Language I'm really familiar with is ARM and somewhat x86 (but also not too much), so I need to dive a little more into that! :P
At least I found out that the "/vol/content/hif_%06d.nfs" files get loaded via the nn_hai_user.rpl, allegedly.
At least that's the only of the two code-files that includes the (exact) file-string. :unsure:
nn_hai_user.rpl does load the file, but then sends it through HAI and CMPT and all the decrypting is done in the IOSU.
 
NFS Encryption:
- AES-128-CBC, key = htk.bin, iv = 16 * 0x00
The whole file is encrypted, but to correctly decrypt and encrypt it,
you need to read 0x8000 byte, then decrypt/encrypt it and then reset iv
otherwise the first 16 byte of each sector is wrong, so don't use openssl for it,
write a custom tool/script.

after decrypting, NFS incorrect wii header fixing:
0x0 - 0x400 = Wii Iso Header
0x8000 - 0x8400 = Wii Partition Table, this needs to be moved to 0x40000
0x10000 - ??? = unknown data, not present in wii isos's
0x16000 - 0x16020 = region settings and age rating, the age rating is missing, this need to be moved to 0x4E000
0x17FFC - 4 byte = Magic Number, this need to be moved to 0x4FFFC

MBR table says that the game partition is at 0xF800000,
so move all data from 0x18000 till end of file to 0xF800000 or fix the offset
after you do this, you have generated a correct wii iso (not wbfs).

But there is a big problem, the TMD inside the game partition has the "encryption" flag set to false
-> Game partition is not encrypted.

This is a problem, because EVERY SINGLE (public) wii tool ignores TMD flags and trys to decrypt it,
this includes the Dolphin Emu. They will all say that something is wrong or crash, big fail....

To fix this, you need to set the encryption flag to true and correctly encrypt the game partition.

To inject wii iso's, simply do the opposite.
- decrypt game partition (maybe not needed, if the wiiu checks tmd flags...)
- generate incorrect wii header
- encrypt nfs
- add eggs header, seems to be the same for all.

I tested this with "Kirby's Return to Dream Land" Wii VC iso and successfully converted it to a working wii iso.
But i don't have a WiiU to test the opposite.
 
This looks like something to look into!
Thanks for sharing what you found out! :)

Edit: So iv should always be zero?
 
Last edited by JaceCearK1,
Edit: So iv should always be zero?
Yes:
C# Code:
Code:
  public const int SECTOR_SIZE = 0x8000;
   
  public static void DecryptNFS(string InFile, string OutFile, byte[] key, byte[] iv)
  {
  using (var er = new BinaryReader(File.OpenRead(InFile)))
  using (var ew = new BinaryWriter(File.OpenWrite(OutFile)))
  {
  byte[] Sector = new byte[SECTOR_SIZE];

  //init size
  long leftSize = er.BaseStream.Length;
  do
  {
  //read encrypted sector
  Sector = er.ReadBytes(leftSize > SECTOR_SIZE ? SECTOR_SIZE : (int)leftSize);

  //decrypt it, note: this is needed to reset iv
  Sector = aes_128_cbc_dec(key, iv, Sector);

  //write it to outfile
  ew.Write(Sector);

  //decrease remaining size
  leftSize -= SECTOR_SIZE;

  //loop till end of file
  } while (leftSize > 0);
  }
  }

  public static byte[] aes_128_cbc_dec(byte[] key, byte[] iv, byte[] data)
  {
  byte[] result = new byte[data.Length];

  try
  {
  System.Security.Cryptography.RijndaelManaged rm = new System.Security.Cryptography.RijndaelManaged();
  rm.Mode = System.Security.Cryptography.CipherMode.CBC;
  rm.Padding = System.Security.Cryptography.PaddingMode.None;
  rm.KeySize = 128;
  rm.BlockSize = 128;
  rm.Key = key;
  rm.IV = iv;

  using (System.Security.Cryptography.ICryptoTransform itc = rm.CreateDecryptor())
  {
  result = itc.TransformFinalBlock(data, 0, data.Length);
  }

  rm.Clear();

  return result;
  }
  catch (System.Security.Cryptography.CryptographicException e)
  {
  Console.WriteLine("A Cryptographic error occurred: {0}", e.Message);
  return null;
  }
  }
 

Site & Scene News

Popular threads in this forum