public void KDF() { // Decrypt packet salt if (ecmID != prevEcmID) { byte[] saltHmacKey = sha1.ComputeHash(F4FOldMethod.AppendBuf(sessionKey, packetIV)); if (debug) { Program.DebugLog("SaltHmacKey : " + Hexlify(saltHmacKey)); } shaSalt.Key = saltHmacKey; saltAesKey = F4FOldMethod.BlockCopy(shaSalt.ComputeHash(hmacData1), 0, 16); if (debug) { Program.DebugLog("SaltAesKey : " + Hexlify(saltAesKey)); } prevEcmID = ecmID; } if (debug) { Program.DebugLog("EncryptedSalt: " + Hexlify(packetSalt)); } byte[] decryptedSalt = AesDecrypt(packetSalt, saltAesKey, packetIV); if (decryptedSalt == null) { Program.Quit("<c:Red>Error ocurred while decription salt of fagment."); } if (debug) { Program.DebugLog("DecryptedSalt: " + Hexlify(decryptedSalt)); } decryptBytes = F4FOldMethod.ReadInt32(ref decryptedSalt, 0); if (debug) { Program.DebugLog("DecryptBytes : " + decryptBytes); } byte[] decryptedSalt2 = F4FOldMethod.BlockCopy(decryptedSalt, 4, 16); if (debug) { Program.DebugLog("DecryptedSalt: " + Hexlify(decryptedSalt2)); } // Generate final packet decryption key byte[] finalHmacKey = sha1.ComputeHash(decryptedSalt2); if (debug) { Program.DebugLog("FinalHmacKey : " + Hexlify(finalHmacKey)); } finalsha.Key = finalHmacKey; packetKey = F4FOldMethod.BlockCopy(finalsha.ComputeHash(hmacData2), 0, 16); if (debug) { Program.DebugLog("PacketKey : " + Hexlify(packetKey)); } }
public byte[] Decrypt(byte[] data, long pos, string baseUrl, string auth) { if (debug) { Program.DebugLog("\n----- Akamai Decryption Start -----"); } byte[] decryptedData = new byte[0]; // Parse packet header using (MemoryStream ms = new MemoryStream(data)) { ms.Position = pos; using (HDSBinaryReader br = new HDSBinaryReader(ms)) { int b = br.ReadByte(); ecmVersion = (b >> 4); if (ecmVersion != 11) { ecmVersion = b; } ecmID = br.ReadInt32(); ecmTimestamp = (uint)br.ReadInt32(); kdfVersion = br.ReadInt16(); dccAccReserved = br.ReadByte(); if (debug) { Program.DebugLog("ECM Version : " + ecmVersion + ", ECM ID: " + ecmID + ", ECM Timestamp: " + ecmTimestamp + ", KDF Version: " + kdfVersion + ", DccAccReserved: " + dccAccReserved); } b = br.ReadByte(); bool iv = ((b & 2) > 0); bool key = ((b & 4) > 0); if (iv) { packetIV = br.ReadBytes(16); if (debug) { Program.DebugLog("PacketIV : " + Hexlify(packetIV)); } } if (key) { sessionKeyUrl = br.ReadString(); if (debug) { Program.DebugLog("SessionKeyUrl: " + sessionKeyUrl); } string keyPath = sessionKeyUrl.Substring(sessionKeyUrl.LastIndexOf('/')); string keyUrl = HTTP.JoinUrl(baseUrl, keyPath) + auth; // Download key file if required if (sessionKeyUrl != lastKeyUrl) { if ((baseUrl.Length == 0) && (sessionKey.Length == 0)) { if (debug) { Program.DebugLog("Unable to download session key without manifest url. you must specify it manually using 'adkey' switch."); } } else { if (baseUrl.Length > 0) { if (debug) { Program.DebugLog("Downloading new session key from " + keyUrl); } byte[] downloadedData = HTTP.TryGETData(keyUrl, out int retCode, out string status); if (retCode == 200) { sessionID = "_" + keyPath.Substring("/key_".Length); sessionKey = downloadedData; } else { if (debug) { Program.DebugLog("Failed to download new session key, Status: " + status + " (" + retCode + ")"); } sessionID = ""; } } } lastKeyUrl = sessionKeyUrl; if (sessionKey == null || sessionKey.Length == 0) { Program.Quit("Failed to download akamai session decryption key"); } } } if (debug) { Program.DebugLog("SessionKey : " + Hexlify(sessionKey)); } if (sessionKey == null || sessionKey.Length < 1) { Program.Quit("ERROR: Fragments can't be decrypted properly without corresponding session key."); } byte reserved; byte[] reservedBlock1, reservedBlock2, encryptedData, lastBlockData; reserved = br.ReadByte(); packetSalt = br.ReadBytes(32); reservedBlock1 = br.ReadBytes(20); reservedBlock2 = br.ReadBytes(20); if (debug) { Program.DebugLog("ReservedByte : " + reserved + ", ReservedBlock1: " + Hexlify(reservedBlock1) + ", ReservedBlock2: " + Hexlify(reservedBlock2)); } // Generate packet decryption key KDF(); // Decrypt packet data encryptedData = br.ReadBytes((int)decryptBytes); lastBlockData = br.ReadToEnd(); if (decryptBytes > 0) { decryptedData = AesDecrypt(encryptedData, packetKey, packetIV); } decryptedData = F4FOldMethod.AppendBuf(decryptedData, lastBlockData); if (debug) { Program.DebugLog("EncryptedData: " + Hexlify(encryptedData, 64)); Program.DebugLog("DecryptedData: " + Hexlify(decryptedData, 64)); Program.DebugLog("----- Akamai Decryption End -----\n"); } } // using (HDSBinaryReader br = new HDSBinaryReader(ms)) } // using (MemoryStream ms = new MemoryStream(data)) return(decryptedData); }
public static void Main(string[] args) { System.Net.ServicePointManager.UseNagleAlgorithm = true; System.Net.ServicePointManager.CheckCertificateRevocationList = false; System.Net.ServicePointManager.DefaultConnectionLimit = 20; System.Net.ServicePointManager.Expect100Continue = false; try { AppDomain.CurrentDomain.UnhandledException += (sender, e) => FatalExceptionObject(e.ExceptionObject); try { isRedirected = Console.CursorVisible && false; } catch { isRedirected = true; } if (isRedirected) { Console.SetOut(new StreamWriter(Console.OpenStandardError()) { AutoFlush = true }); } Check4Redirect2Process(ref args); CLI cli = new CLI(args); if (cli.ChkParam("help")) { cli.DisplayHelpAndQuit(); } if (cli.ChkParam("version")) { cli.DisplayVersionAndQuit(); } if (cli.ChkParam("waitkey")) { waitkey = true; } if (cli.ChkParam("nowaitkey")) { waitkey = false; } if (cli.ChkParam("filesize")) { uint.TryParse(cli.GetParam("filesize"), out filesize); } if (cli.ChkParam("threads")) { int.TryParse(cli.GetParam("threads"), out threads); } if (cli.ChkParam("start")) { uint.TryParse(cli.GetParam("start"), out start); } if (cli.ChkParam("auth")) { auth = "?" + cli.GetParam("auth"); } if (cli.ChkParam("headers")) { headers = cli.GetParam("headers"); } if (cli.ChkParam("urlbase")) { baseUrl = cli.GetParam("urlbase"); } if (cli.ChkParam("quality")) { quality = cli.GetParam("quality"); } if (cli.ChkParam("manifest")) { manifestUrl = cli.GetParam("manifest"); } if (cli.ChkParam("outdir")) { outDir = cli.GetParam("outdir"); } if (cli.ChkParam("outfile")) { outFile = cli.GetParam("outfile"); } if (cli.ChkParam("logfile")) { logfile = cli.GetParam("logfile"); } if (cli.ChkParam("skip")) { fromTimestamp = GetTimestampFromString(cli.GetParam("skip")); } if (cli.ChkParam("duration")) { duration = GetTimestampFromString(cli.GetParam("duration")); } if (cli.ChkParam("debug")) { debug = true; } if (cli.ChkParam("play")) { play = true; } if (cli.ChkParam("showtime")) { showtime = true; } if (cli.ChkParam("fproxy")) { fproxy = true; } if (cli.ChkParam("continue")) { fcontinue = true; } if (cli.ChkParam("verbose")) { verbose = true; } if (cli.ChkParam("testalt")) { testalt = true; } if (cli.ChkParam("quiet")) { quiet = true; } if (cli.ChkParam("postdata")) { postData = cli.GetParam("postdata"); } if (cli.ChkParam("referer")) { HTTP.Referer = cli.GetParam("referer"); } if (cli.ChkParam("cookies")) { HTTP.Cookies = cli.GetParam("cookies"); } if (cli.ChkParam("useragent")) { HTTP.Useragent = cli.GetParam("useragent"); } if (cli.ChkParam("username")) { HTTP.Username = cli.GetParam("username"); } if (cli.ChkParam("password")) { HTTP.Password = cli.GetParam("password"); } if (cli.ChkParam("proxy")) { HTTP.Proxy = cli.GetParam("proxy"); } if (cli.ChkParam("proxyuser")) { HTTP.ProxyUsername = cli.GetParam("proxyuser"); } if (cli.ChkParam("proxypass")) { HTTP.ProxyPassword = cli.GetParam("proxypass"); } if (cli.ChkParam("osproxy")) { HTTP.UseSystemProxy = true; } if (cli.ChkParam("adkey")) { sessionKey = AkamaiDecryptor.Unhexlify(cli.GetParam("adkey")); } if (cli.ChkParam("lang")) { lang = cli.GetParam("lang"); } if (cli.ChkParam("alt")) { alt = cli.GetParam("alt"); } //if (HTTP.Referer == "") { // var m = Regex.Match(manifestUrl, @"^(.*?://.*?/)"); // if (m.Success) HTTP.Referer = m.Groups[1].Value; //} if (!string.IsNullOrEmpty(headers)) { foreach (string header in headers.Split(new char[] { '|', '$' })) { Match m = Regex.Match(header, "(.*?):(.*)"); if (m.Success) { string name = m.Groups[1].Value; string value = m.Groups[2].Value; switch (name.ToLower()) { case "referer": HTTP.Referer = value; break; case "useragent": case "user-agent": HTTP.Useragent = value; break; default: HTTP.Headers.Set(name, value); break; } } } } ShowHeader("HDSdump by WendyH v<c:White>" + Version); if (manifestUrl == "") { Quit("<c:Red>Please specify the manifest. (switch '<c:White>-h</c>' or '<c:White>--help</c>' for help message)"); } if (showtime) { ShowTimeElapsed("", true); } Check4KnownLinks(manifestUrl); cli.Params["manifest"] = manifestUrl; if (HTTP.Referer.Length > 0) { cli.Params["referer"] = HTTP.Referer; } bool usePipe = outFile.IndexOf(@"\\.\pipe\") == 0; cli.Params["threads"] = threads.ToString(); cli.Params["outfile"] = redir2Prog != null ? redir2Prog.ProcessName : (isRedirected && !usePipe ? "<redirected>" : outFile); cli.EchoSetsParameters(); if (!cli.ChkParam("oldmethod")) { HDSDumper HdsDumper = new HDSDumper(); HdsDumper.FLVFile.outFile = outDir + outFile; HdsDumper.FLVFile.play = play; HdsDumper.FLVFile.usePipe = usePipe; HdsDumper.Downloader.maxThreads = threads; HdsDumper.duration = duration; HdsDumper.filesize = filesize; HdsDumper.start = start; HdsDumper.auth = auth; HdsDumper.baseUrl = baseUrl; HdsDumper.quality = quality; HdsDumper.postData = postData; HdsDumper.lang = lang; HdsDumper.alt = alt; HdsDumper.testalt = testalt; HdsDumper.fromTimestamp = fromTimestamp; HdsDumper.sessionKey = sessionKey; if (fcontinue) { HdsDumper.FLVFile.GetLastTimestampFromExistingFile(); HdsDumper.fromTimestamp = HdsDumper.FLVFile.LastTimestamp; } if (ConsolePresent) { Console.CancelKeyPress += delegate { HdsDumper?.ShowMessageAtTheEnd(); HdsDumper?.FixFileMetadata(); }; } try { Message("Processing manifest info..."); HdsDumper.StartDownload(manifestUrl); } catch (Exception e) { HdsDumper.DestroyUpdateStatusTimer(); Message("\r\n<c:Red>" + e.Message); } finally { HdsDumper.ShowMessageAtTheEnd(); HdsDumper.FixFileMetadata(); } if (!string.IsNullOrEmpty(HdsDumper.Status)) { Quit(HdsDumper.Status); } else { Quit("Done."); } } // ========== OLD METHOD ========== F4FOldMethod f4f = new F4FOldMethod(); // Disable metadata if it invalidates the stream duration if ((f4f.fromTimestamp > 0) || (start > 0) || (duration > 0) || (filesize > 0)) { f4f.metadata = false; } f4f.fromTimestamp = fromTimestamp; f4f.usePipe = usePipe; f4f.play = play; f4f.threads = threads; f4f.duration = (int)duration; f4f.filesize = (int)filesize; f4f.start = (int)start; f4f.ad.sessionKey = sessionKey; f4f.auth = auth; f4f.baseUrl = baseUrl; f4f.quality = quality; f4f.PostData = postData; f4f.Lang = lang; f4f.alt = alt; if (fcontinue) { f4f.CheckLastTSExistingFile(); } f4f.DownloadFragments(manifestUrl); Quit("Done."); } catch (Exception huh) { FatalExceptionObject(huh); } }