mirror of
https://github.com/SabreTools/NDecrypt.git
synced 2026-02-06 21:29:33 +00:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b83293e8c9 | ||
|
|
0190f3d316 | ||
|
|
5c6b303d41 | ||
|
|
0800d93d22 |
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user