4 Commits

Author SHA1 Message Date
Matt Nadareski
b83293e8c9 Fix encrypt 2019-04-07 03:04:05 -07:00
Matt Nadareski
0190f3d316 Encrypt, comments 2019-04-07 02:10:16 -07:00
Matt Nadareski
5c6b303d41 DoFinal 2019-04-07 02:03:44 -07:00
Matt Nadareski
0800d93d22 Notes and minor 2019-04-07 01:32:04 -07:00
3 changed files with 50 additions and 47 deletions

View File

@@ -9,6 +9,9 @@ namespace ThreeDS.Data
public static byte[] ExefsCounter = new byte[] { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
public static byte[] RomfsCounter = new byte[] { 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
// Note: BigInteger requires the 0x00 at the end of each string in order to preserve the sign value
// Note: BigInteger requires that the values be in little endian format, the values in
// Big Endian - 0x1F, 0xF9, 0xE9, 0xAA, 0xC5, 0xFE, 0x04, 0x08, 0x02, 0x45, 0x91, 0xDC, 0x5D, 0x52, 0x76, 0x8A
// Little Endian - 0x8A, 0x76, 0x52, 0x5D, 0xDC, 0x91, 0x45, 0x02, 0x08, 0x04, 0xFE, 0xC5, 0xAA, 0xE9, 0xF9, 0x1F
public static BigInteger AESHardwareConstant = new BigInteger(new byte[] { 0x8A, 0x76, 0x52, 0x5D, 0xDC, 0x91, 0x45, 0x02, 0x08, 0x04, 0xFE, 0xC5, 0xAA, 0xE9, 0xF9, 0x1F });
@@ -37,7 +40,7 @@ namespace ThreeDS.Data
#endregion
#region Dev Keys (Must be converted to LE)
#region Dev Keys
// Dev KeyX 0x18 (New 3DS 9.3)
// Big Endian - 0x30, 0x4B, 0xF1, 0x46, 0x83, 0x72, 0xEE, 0x64, 0x11, 0x5E, 0xBD, 0x40, 0x93, 0xD8, 0x42, 0x76

View File

@@ -1,13 +1,17 @@
using System.IO;
using System.Linq;
using System.Text;
namespace ThreeDS.Headers
{
public class ExeFSFileHeader
{
private const string codeSegment = ".code\0\0\0";
private readonly byte[] codeSegmentBytes = new byte[] { 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x00, 0x00, 0x00 };
public string FileName;
public bool IsCodeBinary { get { return FileName == codeSegment; } }
public byte[] FileName = new byte[8];
public string ReadableFileName { get { return Encoding.ASCII.GetString(FileName); } }
public bool IsCodeBinary { get { return Enumerable.SequenceEqual(FileName, codeSegmentBytes); } }
public uint FileOffset;
public uint FileSize;
public byte[] FileHash = new byte[0x20];
@@ -18,7 +22,7 @@ namespace ThreeDS.Headers
try
{
header.FileName = new string(reader.ReadChars(8));
header.FileName = reader.ReadBytes(8);
header.FileOffset = reader.ReadUInt32();
header.FileSize = reader.ReadUInt32();
return header;

View File

@@ -122,7 +122,7 @@ namespace ThreeDS
var str = BitConverter.ToString(plainIV).Replace("-", "");
var exefsctrmode2C = CipherUtilities.GetCipher("AES/CTR"); // ("AES/CTR/NoPadding")
var exefsctrmode2C = CipherUtilities.GetCipher("AES/CTR");
exefsctrmode2C.Init(false, new ParametersWithIV(new KeyParameter(TakeSixteen(NormalKey2C)), plainIV));
Console.WriteLine("Partition {0} ExeFS: Decrypting: ExHeader", p);
@@ -137,7 +137,7 @@ namespace ThreeDS
f.BaseStream.Seek((header.PartitionsTable[p].Offset + partitionHeader.ExeFSOffsetInMediaUnits) * header.SectorSize, SeekOrigin.Begin);
g.BaseStream.Seek((header.PartitionsTable[p].Offset + partitionHeader.ExeFSOffsetInMediaUnits) * header.SectorSize, SeekOrigin.Begin);
var exefsctrmode2C = CipherUtilities.GetCipher("AES/CTR"); // ("AES/CTR/NoPadding")
var exefsctrmode2C = CipherUtilities.GetCipher("AES/CTR");
exefsctrmode2C.Init(false, new ParametersWithIV(new KeyParameter(TakeSixteen(NormalKey2C)), exefsIV));
g.Write(exefsctrmode2C.ProcessBytes(f.ReadBytes((int)header.SectorSize)));
@@ -162,10 +162,10 @@ namespace ThreeDS
byte[] exefsIVWithOffsetForHeader = AddToByteArray(exefsIV, (int)ctroffset);
var exefsctrmode = CipherUtilities.GetCipher("AES/CTR"); // ("AES/CTR/NoPadding")
var exefsctrmode = CipherUtilities.GetCipher("AES/CTR");
exefsctrmode.Init(false, new ParametersWithIV(new KeyParameter(TakeSixteen(NormalKey)), exefsIVWithOffsetForHeader));
exefsctrmode2C = CipherUtilities.GetCipher("AES/CTR"); // ("AES/CTR/NoPadding")
exefsctrmode2C = CipherUtilities.GetCipher("AES/CTR");
exefsctrmode2C.Init(true, new ParametersWithIV(new KeyParameter(TakeSixteen(NormalKey2C)), exefsIVWithOffsetForHeader));
f.BaseStream.Seek((((header.PartitionsTable[p].Offset + partitionHeader.ExeFSOffsetInMediaUnits) + 1) * header.SectorSize) + fileHeader.FileOffset, SeekOrigin.Begin);
@@ -177,17 +177,17 @@ namespace ThreeDS
{
g.Write(exefsctrmode2C.ProcessBytes(exefsctrmode.ProcessBytes(f.ReadBytes(1024 * 1024))));
g.Flush();
Console.Write("\rPartition {0} ExeFS: Decrypting: {1}... {2} / {3} mb...", p, fileHeader.FileName, i, datalenM + 1);
Console.Write("\rPartition {0} ExeFS: Decrypting: {1}... {2} / {3} mb...", p, fileHeader.ReadableFileName, i, datalenM + 1);
}
}
if (datalenB > 0)
{
g.Write(exefsctrmode2C.ProcessBytes(exefsctrmode.ProcessBytes(f.ReadBytes((int)datalenB))));
g.Write(exefsctrmode2C.DoFinal(exefsctrmode.DoFinal(f.ReadBytes((int)datalenB))));
g.Flush();
}
Console.Write("\rPartition {0} ExeFS: Decrypting: {1}... {2} / {3} mb... Done!\r\n", p, fileHeader.FileName, datalenM + 1, datalenM + 1);
Console.Write("\rPartition {0} ExeFS: Decrypting: {1}... {2} / {3} mb... Done!\r\n", p, fileHeader.ReadableFileName, datalenM + 1, datalenM + 1);
}
}
}
@@ -199,7 +199,7 @@ namespace ThreeDS
byte[] exefsIVWithOffset = AddToByteArray(exefsIV, ctroffsetE);
exefsctrmode2C = CipherUtilities.GetCipher("AES/CTR"); // ("AES/CTR/NoPadding")
exefsctrmode2C = CipherUtilities.GetCipher("AES/CTR");
exefsctrmode2C.Init(false, new ParametersWithIV(new KeyParameter(TakeSixteen(NormalKey2C)), exefsIVWithOffset));
f.BaseStream.Seek((header.PartitionsTable[p].Offset + partitionHeader.ExeFSOffsetInMediaUnits + 1) * header.SectorSize, SeekOrigin.Begin);
@@ -215,7 +215,7 @@ namespace ThreeDS
}
if (exefsSizeB > 0)
{
g.Write(exefsctrmode2C.ProcessBytes(f.ReadBytes(exefsSizeB)));
g.Write(exefsctrmode2C.DoFinal(f.ReadBytes(exefsSizeB)));
g.Flush();
}
@@ -231,7 +231,7 @@ namespace ThreeDS
int romfsSizeM = (int)(partitionHeader.RomFSSizeInMediaUnits * header.SectorSize) / (1024 * 1024);
int romfsSizeB = (int)(partitionHeader.RomFSSizeInMediaUnits * header.SectorSize) % (1024 * 1024);
var romfsctrmode = CipherUtilities.GetCipher("AES/CTR"); // ("AES/CTR/NoPadding")
var romfsctrmode = CipherUtilities.GetCipher("AES/CTR");
romfsctrmode.Init(false, new ParametersWithIV(new KeyParameter(TakeSixteen(NormalKey)), romfsIV));
f.BaseStream.Seek((header.PartitionsTable[p].Offset + partitionHeader.RomFSOffsetInMediaUnits) * header.SectorSize, SeekOrigin.Begin);
@@ -247,7 +247,7 @@ namespace ThreeDS
}
if (romfsSizeB > 0)
{
g.Write(romfsctrmode.ProcessBytes(f.ReadBytes(romfsSizeB)));
g.Write(romfsctrmode.DoFinal(f.ReadBytes(romfsSizeB)));
g.Flush();
}
@@ -277,9 +277,6 @@ namespace ThreeDS
}
}
/// <summary>
/// Writes wrong header values
/// </summary>
public void Encrypt()
{
if (!File.Exists(filename))
@@ -386,7 +383,7 @@ namespace ThreeDS
var str = BitConverter.ToString(plainIV).Replace("-", "");
var exefsctrmode2C = CipherUtilities.GetCipher("AES/CTR"); // ("AES/CTR/NoPadding")
var exefsctrmode2C = CipherUtilities.GetCipher("AES/CTR");
exefsctrmode2C.Init(true, new ParametersWithIV(new KeyParameter(TakeSixteen(NormalKey2C)), plainIV));
Console.WriteLine("Partition {0} ExeFS: Encrypting: ExHeader", p);
@@ -398,17 +395,6 @@ namespace ThreeDS
// Encrypt the ExeFS, if it exists
if (partitionHeader.ExeFSSizeInBytes > 0)
{
f.BaseStream.Seek((header.PartitionsTable[p].Offset + partitionHeader.ExeFSOffsetInMediaUnits) * header.SectorSize, SeekOrigin.Begin);
g.BaseStream.Seek((header.PartitionsTable[p].Offset + partitionHeader.ExeFSOffsetInMediaUnits) * header.SectorSize, SeekOrigin.Begin);
var exefsctrmode2C = CipherUtilities.GetCipher("AES/CTR"); // ("AES/CTR/NoPadding")
exefsctrmode2C.Init(true, new ParametersWithIV(new KeyParameter(TakeSixteen(NormalKey2C)), exefsIV));
g.Write(exefsctrmode2C.ProcessBytes(f.ReadBytes((int)header.SectorSize)));
g.Flush();
Console.WriteLine("Partition {0} ExeFS: Encrypting: ExeFS Filename Table", p);
if (backupFlags.CryptoMethod != CryptoMethod.Original)
{
f.BaseStream.Seek((header.PartitionsTable[p].Offset + partitionHeader.ExeFSOffsetInMediaUnits) * header.SectorSize, SeekOrigin.Begin);
@@ -426,10 +412,10 @@ namespace ThreeDS
byte[] exefsIVWithOffsetForHeader = AddToByteArray(exefsIV, (int)ctroffset);
var exefsctrmode = CipherUtilities.GetCipher("AES/CTR"); // ("AES/CTR/NoPadding")
var exefsctrmode = CipherUtilities.GetCipher("AES/CTR");
exefsctrmode.Init(true, new ParametersWithIV(new KeyParameter(TakeSixteen(NormalKey)), exefsIVWithOffsetForHeader));
exefsctrmode2C = CipherUtilities.GetCipher("AES/CTR"); // ("AES/CTR/NoPadding")
var exefsctrmode2C = CipherUtilities.GetCipher("AES/CTR");
exefsctrmode2C.Init(false, new ParametersWithIV(new KeyParameter(TakeSixteen(NormalKey2C)), exefsIVWithOffsetForHeader));
f.BaseStream.Seek((((header.PartitionsTable[p].Offset + partitionHeader.ExeFSOffsetInMediaUnits) + 1) * header.SectorSize) + fileHeader.FileOffset, SeekOrigin.Begin);
@@ -441,30 +427,42 @@ namespace ThreeDS
{
g.Write(exefsctrmode2C.ProcessBytes(exefsctrmode.ProcessBytes(f.ReadBytes(1024 * 1024))));
g.Flush();
Console.Write("\rPartition {0} ExeFS: Encrypting: {1}... {2} / {3} mb...", p, fileHeader.FileName, i, datalenM + 1);
Console.Write("\rPartition {0} ExeFS: Encrypting: {1}... {2} / {3} mb...", p, fileHeader.ReadableFileName, i, datalenM + 1);
}
}
if (datalenB > 0)
{
g.Write(exefsctrmode2C.ProcessBytes(exefsctrmode.ProcessBytes(f.ReadBytes((int)datalenB))));
g.Write(exefsctrmode2C.DoFinal(exefsctrmode.DoFinal(f.ReadBytes((int)datalenB))));
g.Flush();
}
Console.Write("\rPartition {0} ExeFS: Encrypting: {1}... {2} / {3} mb... Done!\r\n", p, fileHeader.FileName, datalenM + 1, datalenM + 1);
Console.Write("\rPartition {0} ExeFS: Encrypting: {1}... {2} / {3} mb... Done!\r\n", p, fileHeader.ReadableFileName, datalenM + 1, datalenM + 1);
}
}
}
// decrypt exefs
// encrypt exefs filename table
f.BaseStream.Seek((header.PartitionsTable[p].Offset + partitionHeader.ExeFSOffsetInMediaUnits) * header.SectorSize, SeekOrigin.Begin);
g.BaseStream.Seek((header.PartitionsTable[p].Offset + partitionHeader.ExeFSOffsetInMediaUnits) * header.SectorSize, SeekOrigin.Begin);
var exefsctrmode2C_2 = CipherUtilities.GetCipher("AES/CTR");
exefsctrmode2C_2.Init(true, new ParametersWithIV(new KeyParameter(TakeSixteen(NormalKey2C)), exefsIV));
g.Write(exefsctrmode2C_2.ProcessBytes(f.ReadBytes((int)header.SectorSize)));
g.Flush();
Console.WriteLine("Partition {0} ExeFS: Encrypting: ExeFS Filename Table", p);
// encrypt exefs
int exefsSizeM = (int)((partitionHeader.ExeFSSizeInMediaUnits - 1) * header.SectorSize) / (1024 * 1024);
int exefsSizeB = (int)((partitionHeader.ExeFSSizeInMediaUnits - 1) * header.SectorSize) % (1024 * 1024);
int ctroffsetE = (int)(header.SectorSize / 0x10);
byte[] exefsIVWithOffset = AddToByteArray(exefsIV, ctroffsetE);
exefsctrmode2C = CipherUtilities.GetCipher("AES/CTR"); // ("AES/CTR/NoPadding")
exefsctrmode2C.Init(true, new ParametersWithIV(new KeyParameter(TakeSixteen(NormalKey2C)), exefsIVWithOffset));
exefsctrmode2C_2 = CipherUtilities.GetCipher("AES/CTR");
exefsctrmode2C_2.Init(true, new ParametersWithIV(new KeyParameter(TakeSixteen(NormalKey2C)), exefsIVWithOffset));
f.BaseStream.Seek((header.PartitionsTable[p].Offset + partitionHeader.ExeFSOffsetInMediaUnits + 1) * header.SectorSize, SeekOrigin.Begin);
g.BaseStream.Seek((header.PartitionsTable[p].Offset + partitionHeader.ExeFSOffsetInMediaUnits + 1) * header.SectorSize, SeekOrigin.Begin);
@@ -472,14 +470,14 @@ namespace ThreeDS
{
for (int i = 0; i < exefsSizeM; i++)
{
g.Write(exefsctrmode2C.ProcessBytes(f.ReadBytes(1024 * 1024)));
g.Write(exefsctrmode2C_2.ProcessBytes(f.ReadBytes(1024 * 1024)));
g.Flush();
Console.Write("\rPartition {0} ExeFS: Encrypting: {1} / {2} mb", p, i, exefsSizeM + 1);
}
}
if (exefsSizeB > 0)
{
g.Write(exefsctrmode2C.ProcessBytes(f.ReadBytes(exefsSizeB)));
g.Write(exefsctrmode2C_2.DoFinal(f.ReadBytes(exefsSizeB)));
g.Flush();
}
@@ -510,7 +508,7 @@ namespace ThreeDS
}
}
var romfsctrmode = CipherUtilities.GetCipher("AES/CTR"); // ("AES/CTR/NoPadding")
var romfsctrmode = CipherUtilities.GetCipher("AES/CTR");
romfsctrmode.Init(true, new ParametersWithIV(new KeyParameter(TakeSixteen(NormalKey)), romfsIV));
f.BaseStream.Seek((header.PartitionsTable[p].Offset + partitionHeader.RomFSOffsetInMediaUnits) * header.SectorSize, SeekOrigin.Begin);
@@ -526,7 +524,7 @@ namespace ThreeDS
}
if (romfsSizeB > 0)
{
g.Write(romfsctrmode.ProcessBytes(f.ReadBytes(romfsSizeB)));
g.Write(romfsctrmode.DoFinal(f.ReadBytes(romfsSizeB)));
g.Flush();
}
@@ -571,13 +569,11 @@ namespace ThreeDS
private static string ToBytes(int num)
{
string numstr = "";
int tmp = num;
string numstr = string.Empty;
while (numstr.Length < 16)
{
numstr += (char)(tmp & 0xFF);
tmp >>= 8;
numstr += (char)(num & 0xFF);
num >>= 8;
}
return numstr;