Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/sn4k3/UVtools.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTiago Conceição <Tiago_caza@hotmail.com>2021-08-20 02:25:28 +0300
committerGitHub <noreply@github.com>2021-08-20 02:25:28 +0300
commit37c69932a090010e49fe511cb0510e35c42532cd (patch)
treea6862e6c3cb67b6d762f4ad6c5243d8c3e1750cc
parentf5fa8f9d8f9017e73ecad6e09abbbc481b81ae7b (diff)
parent1d9e8ec29c175786afb9fc9e384f072827fb0187 (diff)
Merge pull request #269 from tslater2006/master
Add Encrypt/Decrypt CTB command line
-rw-r--r--UVtools.Core/FileFormats/CTBEncryptedFile.cs148
-rw-r--r--UVtools.WPF/ConsoleArguments.cs8
2 files changed, 156 insertions, 0 deletions
diff --git a/UVtools.Core/FileFormats/CTBEncryptedFile.cs b/UVtools.Core/FileFormats/CTBEncryptedFile.cs
index 9c2b757..34cd550 100644
--- a/UVtools.Core/FileFormats/CTBEncryptedFile.cs
+++ b/UVtools.Core/FileFormats/CTBEncryptedFile.cs
@@ -166,6 +166,154 @@ namespace UVtools.Core.FileFormats
}
}
+ public static void CryptFile(string filePath, bool encrypt)
+ {
+ using (MemoryStream decryptedStream = new MemoryStream(File.ReadAllBytes(filePath)))
+ {
+ BinaryWriter writer = new BinaryWriter(decryptedStream);
+ using MemoryStream ms = new MemoryStream(File.ReadAllBytes(filePath));
+ BinaryReader reader = new BinaryReader(ms);
+
+ /* magic */
+ var magic = reader.ReadUInt32();
+ if (magic != MAGIC_CBT_ENCRYPTED)
+ {
+ Console.Write("File does not appear to be an encrypted CTB. Aborting.");
+ return;
+ }
+ writer.Write(magic);
+ var headerLength = reader.ReadUInt32();
+ writer.Write(headerLength);
+ var headerOffset = reader.ReadUInt32();
+ writer.Write(headerOffset);
+
+ /* pass through rest of data until encrypted header */
+ var bytesToPassthru = headerOffset - ms.Position;
+ var temp = reader.ReadBytes((int)bytesToPassthru);
+ writer.Write(temp);
+ uint printerNameLength = 0;
+
+ var originalHeader = reader.ReadBytes((int)headerLength);
+
+ if (encrypt)
+ {
+ printerNameLength = BitExtensions.ToUIntLittleEndian(originalHeader, 164);
+ }
+
+ /* decrypt header with recovered keys */
+ var cryptedData = CryptExtensions.AesCryptBytes(originalHeader, Kong, CipherMode.CBC, PaddingMode.None, encrypt, CookieMonster);
+ writer.Write(cryptedData);
+
+ /* get machine name length */
+ if (!encrypt)
+ {
+ printerNameLength = BitExtensions.ToUIntLittleEndian(cryptedData, 164);
+ }
+
+ /* pass through the next 2 dwords */
+ writer.Write(reader.ReadUInt32());
+ writer.Write(reader.ReadUInt32());
+
+ /* get offset and length of next section (not encrypted) */
+ var nextOffset = reader.ReadUInt32();
+ var nextLength = reader.ReadUInt32();
+
+ writer.Write(nextOffset);
+ writer.Write(nextLength);
+
+ /* how many bytes from current position till the next offset */
+ bytesToPassthru = nextOffset - ms.Position;
+ writer.Write(reader.ReadBytes((int)bytesToPassthru));
+
+ /* passthrough this whole block */
+ writer.Write(reader.ReadBytes((int)nextLength));
+
+ /* pass throught the next 2 dwords */
+ writer.Write(reader.ReadUInt32());
+ writer.Write(reader.ReadUInt32());
+
+ /* get offset and length of next section (not encrypted) */
+ nextOffset = reader.ReadUInt32();
+ nextLength = reader.ReadUInt32();
+
+ writer.Write(nextOffset);
+ writer.Write(nextLength);
+
+ /* how many bytes from current position till the next offset */
+ bytesToPassthru = nextOffset - ms.Position;
+ writer.Write(reader.ReadBytes((int)bytesToPassthru));
+
+ /* passthrough this whole block */
+ writer.Write(reader.ReadBytes((int)nextLength));
+
+ /* passes printer name and disclaimer */
+ var x = reader.ReadBytes((int)(CTB_DISCLAIMER_SIZE + printerNameLength));
+ writer.Write(x);
+
+ /* we're at the layer offset table now */
+ List<ulong> layerOffsets = new List<ulong>();
+ var startOfTable = ms.Position;
+ ulong layerOffset = reader.ReadUInt64();
+ ulong firstLayer = layerOffset;
+ while (ms.Position < (int)firstLayer)
+ {
+ layerOffsets.Add(layerOffset);
+ reader.ReadUInt64();
+ layerOffset = reader.ReadUInt64();
+ }
+
+ ms.Position = (int)startOfTable;
+
+ /* copy the rest of the file to the output memory stream, we'll decrypt layers next */
+ writer.Write(reader.ReadBytes((int)(ms.Length - ms.Position)));
+
+ byte[] cryptedFile = decryptedStream.ToArray();
+ var layerCounter = 0;
+ foreach (var offset in layerOffsets)
+ {
+ layerCounter++;
+ ms.Position = (int)(offset + 0x10);
+
+ ms.Position += 0x10;
+ var encryptedOffset = reader.ReadUInt32();
+ var encryptedLength = reader.ReadUInt32();
+ ms.Position -= 0x18;
+
+ if (encryptedLength > 0)
+ {
+ Debug.WriteLine($"Layer {layerCounter} has {encryptedLength} bytes of encrypted data. (Layer data offset: {encryptedOffset})");
+ var layerDataOffset = reader.ReadUInt32();
+
+ ms.Position = layerDataOffset + encryptedOffset;
+
+ byte[] encryptedLayerData = reader.ReadBytes((int)encryptedLength);
+
+ byte[] decryptedLayerData = CryptExtensions.AesCryptBytes(encryptedLayerData, Kong, CipherMode.CBC, PaddingMode.None, encrypt, CookieMonster);
+
+ Array.Copy(decryptedLayerData, 0, cryptedFile, layerDataOffset + encryptedOffset, encryptedLength);
+
+
+ /* update encrypted markers in the layer header */
+ byte[] empty = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 };
+ Array.Copy(empty, 0, cryptedFile, layerDataOffset - 0x38, 8);
+
+ }
+ else
+ {
+ Debug.WriteLine($"Layer {layerCounter} is not encrypted");
+ }
+ }
+
+ /* last 20 bytes are an encrypted sha256 */
+ byte[] cipheredHash = cryptedFile[^0x20..];
+
+ byte[] plainHash = CryptExtensions.AesCryptBytes(cipheredHash, Kong, CipherMode.CBC, PaddingMode.None, encrypt, CookieMonster);
+ Array.Copy(plainHash, 0, cryptedFile, cryptedFile.Length - 0x20, 0x20);
+
+ File.WriteAllBytes(filePath, cryptedFile);
+ }
+ }
+
public class LayerPointer
{
[FieldOrder(0)] public uint LayerOffset { get; set; }
diff --git a/UVtools.WPF/ConsoleArguments.cs b/UVtools.WPF/ConsoleArguments.cs
index cb8f691..50d9407 100644
--- a/UVtools.WPF/ConsoleArguments.cs
+++ b/UVtools.WPF/ConsoleArguments.cs
@@ -141,6 +141,14 @@ namespace UVtools.WPF
return true;
}
+ if (args[0] is "--encrypt-ctb" or "--decrypt-ctb")
+ {
+ bool isEncrypt = (args[0] is "--encrypt-ctb");
+
+
+ CTBEncryptedFile.CryptFile(args[1], isEncrypt);
+ return true;
+ }
return false;
}