diff --git a/AaxDecrypter/AaxDecrypter.csproj b/AaxDecrypter/AaxDecrypter.csproj index d8b57fcf..6ca88326 100644 --- a/AaxDecrypter/AaxDecrypter.csproj +++ b/AaxDecrypter/AaxDecrypter.csproj @@ -10,57 +10,11 @@ - - - - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - Always diff --git a/AaxDecrypter/AaxToM4bConverter.cs b/AaxDecrypter/AaxToM4bConverter.cs index 6baf6637..8dffb706 100644 --- a/AaxDecrypter/AaxToM4bConverter.cs +++ b/AaxDecrypter/AaxToM4bConverter.cs @@ -62,16 +62,18 @@ namespace AaxDecrypter public Tags tags { get; private set; } public EncodingInfo encodingInfo { get; private set; } - public static async Task CreateAsync(string inputFile, string decryptKey, Chapters chapters = null) + private Func> getKeyFuncAsync { get; } + + public static async Task CreateAsync(string inputFile, string decryptKey, Func> getKeyFunc, Chapters chapters = null) { - var converter = new AaxToM4bConverter(inputFile, decryptKey); + var converter = new AaxToM4bConverter(inputFile, decryptKey, getKeyFunc); converter.chapters = chapters ?? new AAXChapters(inputFile); await converter.prelimProcessing(); converter.printPrelim(); return converter; } - private AaxToM4bConverter(string inputFile, string decryptKey) + private AaxToM4bConverter(string inputFile, string decryptKey, Func> getKeyFunc) { ArgumentValidator.EnsureNotNullOrWhiteSpace(inputFile, nameof(inputFile)); if (!File.Exists(inputFile)) @@ -93,6 +95,7 @@ namespace AaxDecrypter inputFileName = inputFile; this.decryptKey = decryptKey; + this.getKeyFuncAsync = getKeyFunc; } private async Task prelimProcessing() @@ -209,22 +212,12 @@ namespace AaxDecrypter private int getKey_decrypt(string tempRipFile) { - getKey(); + decryptKey = getKey(); return decrypt(tempRipFile); } - private void getKey() - { - Console.WriteLine("Discovering decrypt key"); - Console.WriteLine("Getting file hash"); - var checksum = BytesCracker.GetChecksum(inputFileName); - Console.WriteLine("File hash calculated: " + checksum); - - Console.WriteLine("Cracking activation bytes"); - var activation_bytes = BytesCracker.GetActivationBytes(checksum); - decryptKey = activation_bytes; - Console.WriteLine("Activation bytes cracked. Decrypt key: " + activation_bytes); - } + // I am NOT happy about doing async this way. Async needs to be added to Step framework + string getKey() => getKeyFuncAsync().GetAwaiter().GetResult(); private int decrypt(string tempRipFile) { diff --git a/AaxDecrypter/BytesCracker.cs b/AaxDecrypter/BytesCracker.cs deleted file mode 100644 index a9752b14..00000000 --- a/AaxDecrypter/BytesCracker.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Text; -using System.Threading.Tasks; -using Dinah.Core; -using Dinah.Core.Diagnostics; - -namespace AaxDecrypter -{ - public static class BytesCracker - { - public static string GetChecksum(string aaxPath) - { - var info = new ProcessStartInfo - { - FileName = BytesCrackerSupportLibraries.ffprobePath, - Arguments = aaxPath.SurroundWithQuotes(), - WorkingDirectory = Directory.GetCurrentDirectory() - }; - - // checksum is in the debug info. ffprobe's debug info is written to stderr, not stdout - var ffprobeStderr = info.RunHidden().Error; - - // example checksum line: - // ... [aax] file checksum == 0c527840c4f18517157eb0b4f9d6f9317ce60cd1 - var checksum = ffprobeStderr.ExtractString("file checksum == ", 40); - - return checksum; - } - - /// use checksum to get activation bytes. activation bytes are unique per audible customer. only have to do this 1x/customer - public static string GetActivationBytes(string checksum) - { - var info = new ProcessStartInfo - { - FileName = BytesCrackerSupportLibraries.rcrackPath, - Arguments = @". -h " + checksum, - WorkingDirectory = Directory.GetCurrentDirectory() - }; - - var rcrackStdout = info.RunHidden().Output; - - // example result - // 0c527840c4f18517157eb0b4f9d6f9317ce60cd1 \xbd\x89X\x09 hex:bd895809 - var activation_bytes = rcrackStdout.ExtractString("hex:", 8); - - return activation_bytes; - } - } -} diff --git a/AaxDecrypter/BytesCrackerLib/alglib1.dll b/AaxDecrypter/BytesCrackerLib/alglib1.dll deleted file mode 100644 index 6da4ca52..00000000 Binary files a/AaxDecrypter/BytesCrackerLib/alglib1.dll and /dev/null differ diff --git a/AaxDecrypter/BytesCrackerLib/audible_byte#4-4_0_10000x789935_0.rtc b/AaxDecrypter/BytesCrackerLib/audible_byte#4-4_0_10000x789935_0.rtc deleted file mode 100644 index 6359b7a3..00000000 Binary files a/AaxDecrypter/BytesCrackerLib/audible_byte#4-4_0_10000x789935_0.rtc and /dev/null differ diff --git a/AaxDecrypter/BytesCrackerLib/audible_byte#4-4_1_10000x791425_0.rtc b/AaxDecrypter/BytesCrackerLib/audible_byte#4-4_1_10000x791425_0.rtc deleted file mode 100644 index 57aa2b11..00000000 Binary files a/AaxDecrypter/BytesCrackerLib/audible_byte#4-4_1_10000x791425_0.rtc and /dev/null differ diff --git a/AaxDecrypter/BytesCrackerLib/audible_byte#4-4_2_10000x790991_0.rtc b/AaxDecrypter/BytesCrackerLib/audible_byte#4-4_2_10000x790991_0.rtc deleted file mode 100644 index 0ab3c43a..00000000 Binary files a/AaxDecrypter/BytesCrackerLib/audible_byte#4-4_2_10000x790991_0.rtc and /dev/null differ diff --git a/AaxDecrypter/BytesCrackerLib/audible_byte#4-4_3_10000x792120_0.rtc b/AaxDecrypter/BytesCrackerLib/audible_byte#4-4_3_10000x792120_0.rtc deleted file mode 100644 index 8e0438c8..00000000 Binary files a/AaxDecrypter/BytesCrackerLib/audible_byte#4-4_3_10000x792120_0.rtc and /dev/null differ diff --git a/AaxDecrypter/BytesCrackerLib/audible_byte#4-4_4_10000x790743_0.rtc b/AaxDecrypter/BytesCrackerLib/audible_byte#4-4_4_10000x790743_0.rtc deleted file mode 100644 index 1e169c3e..00000000 Binary files a/AaxDecrypter/BytesCrackerLib/audible_byte#4-4_4_10000x790743_0.rtc and /dev/null differ diff --git a/AaxDecrypter/BytesCrackerLib/audible_byte#4-4_5_10000x790568_0.rtc b/AaxDecrypter/BytesCrackerLib/audible_byte#4-4_5_10000x790568_0.rtc deleted file mode 100644 index 77c2a193..00000000 Binary files a/AaxDecrypter/BytesCrackerLib/audible_byte#4-4_5_10000x790568_0.rtc and /dev/null differ diff --git a/AaxDecrypter/BytesCrackerLib/audible_byte#4-4_6_10000x791458_0.rtc b/AaxDecrypter/BytesCrackerLib/audible_byte#4-4_6_10000x791458_0.rtc deleted file mode 100644 index 4f7b21c9..00000000 Binary files a/AaxDecrypter/BytesCrackerLib/audible_byte#4-4_6_10000x791458_0.rtc and /dev/null differ diff --git a/AaxDecrypter/BytesCrackerLib/audible_byte#4-4_7_10000x791707_0.rtc b/AaxDecrypter/BytesCrackerLib/audible_byte#4-4_7_10000x791707_0.rtc deleted file mode 100644 index f4b7b061..00000000 Binary files a/AaxDecrypter/BytesCrackerLib/audible_byte#4-4_7_10000x791707_0.rtc and /dev/null differ diff --git a/AaxDecrypter/BytesCrackerLib/audible_byte#4-4_8_10000x790202_0.rtc b/AaxDecrypter/BytesCrackerLib/audible_byte#4-4_8_10000x790202_0.rtc deleted file mode 100644 index e279ee04..00000000 Binary files a/AaxDecrypter/BytesCrackerLib/audible_byte#4-4_8_10000x790202_0.rtc and /dev/null differ diff --git a/AaxDecrypter/BytesCrackerLib/audible_byte#4-4_9_10000x791022_0.rtc b/AaxDecrypter/BytesCrackerLib/audible_byte#4-4_9_10000x791022_0.rtc deleted file mode 100644 index 18e558f2..00000000 Binary files a/AaxDecrypter/BytesCrackerLib/audible_byte#4-4_9_10000x791022_0.rtc and /dev/null differ diff --git a/AaxDecrypter/BytesCrackerLib/ffmpeg.exe b/AaxDecrypter/BytesCrackerLib/ffmpeg.exe deleted file mode 100644 index 57ceafbc..00000000 Binary files a/AaxDecrypter/BytesCrackerLib/ffmpeg.exe and /dev/null differ diff --git a/AaxDecrypter/BytesCrackerLib/ffprobe.exe b/AaxDecrypter/BytesCrackerLib/ffprobe.exe deleted file mode 100644 index 42721143..00000000 Binary files a/AaxDecrypter/BytesCrackerLib/ffprobe.exe and /dev/null differ diff --git a/AaxDecrypter/BytesCrackerLib/rcrack.exe b/AaxDecrypter/BytesCrackerLib/rcrack.exe deleted file mode 100644 index a67724e5..00000000 Binary files a/AaxDecrypter/BytesCrackerLib/rcrack.exe and /dev/null differ diff --git a/AaxDecrypter/BytesCrackerSupportLibraries.cs b/AaxDecrypter/BytesCrackerSupportLibraries.cs deleted file mode 100644 index 256b97cb..00000000 --- a/AaxDecrypter/BytesCrackerSupportLibraries.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System.IO; - -namespace AaxDecrypter -{ - public static class BytesCrackerSupportLibraries - { - // GetActivationBytes dependencies - // rcrack.exe - // alglib1.dll - // RainbowCrack files to recover your own Audible activation data (activation_bytes) in an offline manner - // audible_byte#4-4_0_10000x789935_0.rtc - // audible_byte#4-4_1_10000x791425_0.rtc - // audible_byte#4-4_2_10000x790991_0.rtc - // audible_byte#4-4_3_10000x792120_0.rtc - // audible_byte#4-4_4_10000x790743_0.rtc - // audible_byte#4-4_5_10000x790568_0.rtc - // audible_byte#4-4_6_10000x791458_0.rtc - // audible_byte#4-4_7_10000x791707_0.rtc - // audible_byte#4-4_8_10000x790202_0.rtc - // audible_byte#4-4_9_10000x791022_0.rtc - - private static string appPath_ { get; } = Path.GetDirectoryName(Dinah.Core.Exe.FileLocationOnDisk); - private static string bytesCrackerLib_ { get; } = Path.Combine(appPath_, "BytesCrackerLib"); - - public static string ffprobePath { get; } = Path.Combine(bytesCrackerLib_, "ffprobe.exe"); - public static string rcrackPath { get; } = Path.Combine(bytesCrackerLib_, "rcrack.exe"); - } -} diff --git a/FileLiberator/DecryptBook.cs b/FileLiberator/DecryptBook.cs index b331d137..835c3444 100644 --- a/FileLiberator/DecryptBook.cs +++ b/FileLiberator/DecryptBook.cs @@ -4,6 +4,7 @@ using System.IO; using System.Linq; using System.Threading.Tasks; using AaxDecrypter; +using AudibleApi; using DataLayer; using Dinah.Core; using Dinah.Core.ErrorHandling; @@ -56,9 +57,11 @@ namespace FileLiberator if (AudibleFileStorage.Audio.Exists(libraryBook.Book.AudibleProductId)) return new StatusHandler { "Cannot find decrypt. Final audio file already exists" }; - var chapters = await downloadChapterNames(libraryBook); + var api = await AudibleApiActions.GetApiAsync(libraryBook.Account, libraryBook.Book.Locale); - var outputAudioFilename = await aaxToM4bConverterDecrypt(aaxFilename, libraryBook, chapters); + var chapters = await downloadChapterNames(libraryBook, api); + + var outputAudioFilename = await aaxToM4bConverterDecrypt(aaxFilename, libraryBook, chapters, api); // decrypt failed if (outputAudioFilename == null) @@ -92,7 +95,23 @@ namespace FileLiberator } } - private async Task aaxToM4bConverterDecrypt(string aaxFilename, LibraryBook libraryBook, Chapters chapters = null) + private static async Task downloadChapterNames(LibraryBook libraryBook, Api api) + { + try + { + var contentMetadata = await api.GetLibraryBookMetadataAsync(libraryBook.Book.AudibleProductId); + if (contentMetadata?.ChapterInfo is null) + return null; + + return new DownloadedChapters(contentMetadata.ChapterInfo); + } + catch + { + return null; + } + } + + private async Task aaxToM4bConverterDecrypt(string aaxFilename, LibraryBook libraryBook, Chapters chapters, Api api) { DecryptBegin?.Invoke(this, $"Begin decrypting {aaxFilename}"); @@ -104,7 +123,7 @@ namespace FileLiberator .AccountsSettings .GetAccount(libraryBook.Account, libraryBook.Book.Locale); - var converter = await AaxToM4bConverter.CreateAsync(aaxFilename, account.DecryptKey, chapters); + var converter = await AaxToM4bConverter.CreateAsync(aaxFilename, account.DecryptKey, api.GetActivationBytesAsync, chapters); converter.AppName = "Libation"; TitleDiscovered?.Invoke(this, converter.tags.title); @@ -134,23 +153,6 @@ namespace FileLiberator } } - private async Task downloadChapterNames(LibraryBook libraryBook) - { - try - { - var api = await AudibleApiActions.GetApiAsync(libraryBook.Account, libraryBook.Book.Locale); - var contentMetadata = await api.GetLibraryBookMetadataAsync(libraryBook.Book.AudibleProductId); - - if (contentMetadata?.ChapterInfo != null) - return new DownloadedChapters(contentMetadata.ChapterInfo); - return null; - } - catch - { - return null; - } - } - private static string moveFilesToBooksDir(Book product, string outputAudioFilename) { // create final directory. move each file into it. MOVE AUDIO FILE LAST diff --git a/LibationLauncher/LibationLauncher.csproj b/LibationLauncher/LibationLauncher.csproj index 25781d94..fbd552c1 100644 --- a/LibationLauncher/LibationLauncher.csproj +++ b/LibationLauncher/LibationLauncher.csproj @@ -13,7 +13,7 @@ win-x64 - 4.3.0.4 + 4.4.0.5 diff --git a/_Demos/ffmpeg decrypt/Form1.cs b/_Demos/ffmpeg decrypt/Form1.cs index aa6e1262..f2714444 100644 --- a/_Demos/ffmpeg decrypt/Form1.cs +++ b/_Demos/ffmpeg decrypt/Form1.cs @@ -10,8 +10,6 @@ namespace ffmpeg_decrypt { public partial class Form1 : Form { - public static string resdir { get; } = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "res"); - public Form1() { InitializeComponent(); @@ -47,10 +45,10 @@ namespace ffmpeg_decrypt inputPnl.Enabled = false; statuslbl.Text = "Getting File Hash..."; - var checksum = await GetChecksum(inputdisplay.Text); + var checksum = await RCrack.GetChecksum(inputdisplay.Text); statuslbl.Text = "Cracking Activation Bytes..."; - var activation_bytes = await GetActivationBytes(checksum); + var activation_bytes = await RCrack.GetActivationBytes(checksum); statuslbl.Text = "Converting File..."; var encodeTo @@ -70,81 +68,6 @@ namespace ffmpeg_decrypt statuslbl.Text = "Conversion Complete!"; } - private static async Task GetChecksum(string aaxPath) - { - Extract("ffprobe.exe"); - - var startInfo = new ProcessStartInfo - { - FileName = Path.Combine(resdir, "ffprobe.exe"), - Arguments = aaxPath.SurroundWithQuotes(), - CreateNoWindow = true, - RedirectStandardOutput = true, - RedirectStandardError = true, - UseShellExecute = false, - WorkingDirectory = Directory.GetCurrentDirectory() - }; - - using var ffp = new Process { StartInfo = startInfo }; - ffp.Start(); - - // checksum is in the debug info. ffprobe's debug info is written to stderr, not stdout - var ffprobeStderr = ffp.StandardError.ReadToEnd(); - - await Task.Run(() => ffp.WaitForExit()); - - ffp.Close(); - - // example checksum line: - // ... [aax] file checksum == 0c527840c4f18517157eb0b4f9d6f9317ce60cd1 - var checksum = ffprobeStderr.ExtractString("file checksum == ", 40); - - return checksum; - } - - /// use checksum to get activation bytes. activation bytes are unique per audible customer. only have to do this 1x/customer - private static async Task GetActivationBytes(string checksum) - { - Extract("rcrack.exe"); - - Extract("alglib1.dll"); - // RainbowCrack files to recover your own Audible activation data (activation_bytes) in an offline manner - Extract("audible_byte#4-4_0_10000x789935_0.rtc"); - Extract("audible_byte#4-4_1_10000x791425_0.rtc"); - Extract("audible_byte#4-4_2_10000x790991_0.rtc"); - Extract("audible_byte#4-4_3_10000x792120_0.rtc"); - Extract("audible_byte#4-4_4_10000x790743_0.rtc"); - Extract("audible_byte#4-4_5_10000x790568_0.rtc"); - Extract("audible_byte#4-4_6_10000x791458_0.rtc"); - Extract("audible_byte#4-4_7_10000x791707_0.rtc"); - Extract("audible_byte#4-4_8_10000x790202_0.rtc"); - Extract("audible_byte#4-4_9_10000x791022_0.rtc"); - - var startInfo = new ProcessStartInfo - { - FileName = Path.Combine(resdir, "rcrack.exe"), - Arguments = @". -h " + checksum, - CreateNoWindow = true, - RedirectStandardOutput = true, - UseShellExecute = false, - WorkingDirectory = Directory.GetCurrentDirectory() - }; - - using var rcr = new Process { StartInfo = startInfo }; - rcr.Start(); - - var rcrackStdout = rcr.StandardOutput.ReadToEnd(); - - await Task.Run(() => rcr.WaitForExit()); - rcr.Close(); - - // example result - // 0c527840c4f18517157eb0b4f9d6f9317ce60cd1 \xbd\x89X\x09 hex:bd895809 - var activation_bytes = rcrackStdout.ExtractString("hex:", 8); - - return activation_bytes; - } - // ProcessStartInfo.Arguments: use Escaper.EscapeArguments instead of .SurroundWithQuotes() // see also: https://stackoverflow.com/questions/4291912/process-start-how-to-get-the-output @@ -164,7 +87,7 @@ namespace ffmpeg_decrypt private static async Task decryptAndSaveFile(string activation_bytes, string inputPath, string outputPath, TextBoxBase debugWindow, EncodeTo encodeTo, int encodeQuality = 80) { - Extract("ffmpeg.exe"); + Resources.Extract("ffmpeg.exe"); var fileBase = Path.Combine(outputPath, Path.GetFileNameWithoutExtension(inputPath)); @@ -186,7 +109,7 @@ namespace ffmpeg_decrypt // nothing in stdout. progress/debug info is in stderr var startInfo = new ProcessStartInfo { - FileName = Path.Combine(resdir, "ffmpeg.exe"), + FileName = Path.Combine(Resources.resdir, "ffmpeg.exe"), Arguments = arguments, CreateNoWindow = true, RedirectStandardError = true, @@ -203,24 +126,6 @@ namespace ffmpeg_decrypt ffm.Close(); } - /// extract embedded resource to file if it doesn't already exist - private static void Extract(string resourceName) - { - // first determine whether files exist already in res dir - if (File.Exists(Path.Combine(resdir, resourceName))) - return; - - // extract embedded resource - // this technique works but there are easier ways: - // https://stackoverflow.com/questions/13031778/how-can-i-extract-a-file-from-an-embedded-resource-and-save-it-to-disk - Directory.CreateDirectory(resdir); - using var resource = System.Reflection.Assembly.GetCallingAssembly().GetManifestResourceStream($"{nameof(ffmpeg_decrypt)}.res." + resourceName); - using var reader = new BinaryReader(resource); - using var file = new FileStream(Path.Combine(resdir, resourceName), FileMode.OpenOrCreate); - using var writer = new BinaryWriter(file); - writer.Write(reader.ReadBytes((int)resource.Length)); - } - private void decryptConvertRb_CheckedChanged(object sender, EventArgs e) => convertGb.Enabled = convertRb.Checked; } } diff --git a/_Demos/ffmpeg decrypt/RCrack.cs b/_Demos/ffmpeg decrypt/RCrack.cs new file mode 100644 index 00000000..1783b061 --- /dev/null +++ b/_Demos/ffmpeg decrypt/RCrack.cs @@ -0,0 +1,85 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Threading.Tasks; + +namespace ffmpeg_decrypt +{ + public static class RCrack + { + public static async Task GetChecksum(string aaxPath) + { + Resources.Extract("ffprobe.exe"); + + var startInfo = new ProcessStartInfo + { + FileName = Path.Combine(Resources.resdir, "ffprobe.exe"), + Arguments = aaxPath.SurroundWithQuotes(), + CreateNoWindow = true, + RedirectStandardOutput = true, + RedirectStandardError = true, + UseShellExecute = false, + WorkingDirectory = Directory.GetCurrentDirectory() + }; + + using var ffp = new Process { StartInfo = startInfo }; + ffp.Start(); + + // checksum is in the debug info. ffprobe's debug info is written to stderr, not stdout + var ffprobeStderr = ffp.StandardError.ReadToEnd(); + + await ffp.WaitForExitAsync(); + + ffp.Close(); + + // example checksum line: + // ... [aax] file checksum == 0c527840c4f18517157eb0b4f9d6f9317ce60cd1 + var checksum = ffprobeStderr.ExtractString("file checksum == ", 40); + + return checksum; + } + + /// use checksum to get activation bytes. activation bytes are unique per audible customer. only have to do this 1x/customer + public static async Task GetActivationBytes(string checksum) + { + Resources.Extract("rcrack.exe"); + + Resources.Extract("alglib1.dll"); + // RainbowCrack files to recover your own Audible activation data (activation_bytes) in an offline manner + Resources.Extract("audible_byte#4-4_0_10000x789935_0.rtc"); + Resources.Extract("audible_byte#4-4_1_10000x791425_0.rtc"); + Resources.Extract("audible_byte#4-4_2_10000x790991_0.rtc"); + Resources.Extract("audible_byte#4-4_3_10000x792120_0.rtc"); + Resources.Extract("audible_byte#4-4_4_10000x790743_0.rtc"); + Resources.Extract("audible_byte#4-4_5_10000x790568_0.rtc"); + Resources.Extract("audible_byte#4-4_6_10000x791458_0.rtc"); + Resources.Extract("audible_byte#4-4_7_10000x791707_0.rtc"); + Resources.Extract("audible_byte#4-4_8_10000x790202_0.rtc"); + Resources.Extract("audible_byte#4-4_9_10000x791022_0.rtc"); + + var startInfo = new ProcessStartInfo + { + FileName = Path.Combine(Resources.resdir, "rcrack.exe"), + Arguments = @". -h " + checksum, + CreateNoWindow = true, + RedirectStandardOutput = true, + UseShellExecute = false, + WorkingDirectory = Directory.GetCurrentDirectory() + }; + + using var rcr = new Process { StartInfo = startInfo }; + rcr.Start(); + + var rcrackStdout = rcr.StandardOutput.ReadToEnd(); + + await rcr.WaitForExitAsync(); + rcr.Close(); + + // example result + // 0c527840c4f18517157eb0b4f9d6f9317ce60cd1 \xbd\x89X\x09 hex:bd895809 + var activation_bytes = rcrackStdout.ExtractString("hex:", 8); + + return activation_bytes; + } + } +} diff --git a/_Demos/ffmpeg decrypt/Resources.cs b/_Demos/ffmpeg decrypt/Resources.cs new file mode 100644 index 00000000..35d2c6fe --- /dev/null +++ b/_Demos/ffmpeg decrypt/Resources.cs @@ -0,0 +1,28 @@ +using System; +using System.IO; + +namespace ffmpeg_decrypt +{ + public static class Resources + { + public static string resdir { get; } = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "res"); + + /// extract embedded resource to file if it doesn't already exist + public static void Extract(string resourceName) + { + // first determine whether files exist already in res dir + if (File.Exists(Path.Combine(resdir, resourceName))) + return; + + // extract embedded resource + // this technique works but there are easier ways: + // https://stackoverflow.com/questions/13031778/how-can-i-extract-a-file-from-an-embedded-resource-and-save-it-to-disk + Directory.CreateDirectory(resdir); + using var resource = System.Reflection.Assembly.GetCallingAssembly().GetManifestResourceStream($"{nameof(ffmpeg_decrypt)}.res." + resourceName); + using var reader = new BinaryReader(resource); + using var file = new FileStream(Path.Combine(resdir, resourceName), FileMode.OpenOrCreate); + using var writer = new BinaryWriter(file); + writer.Write(reader.ReadBytes((int)resource.Length)); + } + } +} diff --git a/_Demos/inAudibleLite/Form1.cs b/_Demos/inAudibleLite/Form1.cs index 89c1c4b6..ca95fd2b 100644 --- a/_Demos/inAudibleLite/Form1.cs +++ b/_Demos/inAudibleLite/Form1.cs @@ -66,6 +66,14 @@ namespace inAudibleLite Console.SetOut(multiLogger); } + string aaxPath; + public async Task getActivationBytes() + { + var checksum = await ffmpeg_decrypt.RCrack.GetChecksum(aaxPath); + var activationBytes = await ffmpeg_decrypt.RCrack.GetActivationBytes(checksum); + return activationBytes; + } + private async void btnSelectFile_Click(object sender, EventArgs e) { var openFileDialog = new OpenFileDialog { Filter = "Audible files (*.aax)|*.aax" }; @@ -75,7 +83,8 @@ namespace inAudibleLite this.rtbLog.Clear(); this.txtInputFile.Text = openFileDialog.FileName; - converter = await AaxToM4bConverter.CreateAsync(this.txtInputFile.Text, this.decryptKeyTb.Text); + aaxPath = this.txtInputFile.Text; + converter = await AaxToM4bConverter.CreateAsync(this.txtInputFile.Text, this.decryptKeyTb.Text, getActivationBytes); pictureBox1.Image = Dinah.Core.Drawing.ImageReader.ToImage(converter.coverBytes); @@ -90,7 +99,7 @@ namespace inAudibleLite // only re-process prelim stats if input filename was changed //also pick up new decrypt key, etc//if (this.txtInputFile.Text != converter?.inputFileName) - converter = await AaxToM4bConverter.CreateAsync(this.txtInputFile.Text, this.decryptKeyTb.Text); + converter = await AaxToM4bConverter.CreateAsync(this.txtInputFile.Text, this.decryptKeyTb.Text, getActivationBytes); converter.AppName = APP_NAME; converter.SetOutputFilename(this.txtOutputFile.Text); diff --git a/_Demos/inAudibleLite/inAudibleLite.csproj b/_Demos/inAudibleLite/inAudibleLite.csproj index 9c9dd707..e38de6b0 100644 --- a/_Demos/inAudibleLite/inAudibleLite.csproj +++ b/_Demos/inAudibleLite/inAudibleLite.csproj @@ -9,6 +9,7 @@ + \ No newline at end of file