using Extreme.Net; using RuriLib.LS; using System; using System.Collections.Generic; using System.Data; using System.Globalization; using System.IO; using System.Linq; using System.Net; using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Windows.Media; namespace RuriLib { /// /// A block that can execute a specific function on one or multiple inputs. /// public class BlockFunction : BlockBase { /// /// The function name. /// public enum Function { /// Simply replaced the variables of the input. Constant, /// Encodes an input as a base64 string. Base64Encode, /// Decodes the string from a base64-encoded input. Base64Decode, /// Hashes an input string. Hash, /// Generates a HMAC for a given string. HMAC, /// Translates words in a given string. Translate, /// Converts a formatted date to a unix timestamp. DateToUnixTime, /// Gets the length of a string. Length, /// Converts all uppercase caracters in a string to lowercase. ToLowercase, /// Converts all lowercase characters in a string to uppercase. ToUppercase, /// Replaces some text with something else, with or without using regex. Replace, /// Gets the first match for a specific regex pattern. RegexMatch, /// Encodes the input to be used in a URL. URLEncode, /// Decodes a URL-encoded input. URLDecode, /// Unescapes characters in a string. Unescape, /// Encodes the input to be displayed in HTML or XML. HTMLEntityEncode, /// Decoded an input containing HTML or XML entities. HTMLEntityDecode, /// Converts a unix timestamp to a formatted date. UnixTimeToDate, /// Retrieves the current time as a unix timestamp. CurrentUnixTime, /// Converts a unix timestamp to the ISO8601 format. UnixTimeToISO8601, /// Generates a random integer. RandomNum, /// Generates a random string based on a mask. RandomString, /// Rounds a decimal input to the upper integer. Ceil, /// Rounds a decimal input to the lower integer. Floor, /// Rounds a decimal input to the nearest integer. Round, /// Computes mathematical operations between decimal numbers. Compute, /// Counts the occurrences of a string in another string. CountOccurrences, /// Clears the cookie jar used for HTTP requests. ClearCookies, /// Encrypts a string with RSA given a Key. RSA, /// Waits a given amount of milliseconds. Delay, /// Retrieves the character at a given index in the input string. CharAt, /// Gets a substring of the input. Substring, /// Reverses the input string. ReverseString, /// Removes leading or trailing whitespaces from a string. Trim, /// Gets a valid random User-Agent header. GetRandomUA, /// Encrypts a string with AES. AESEncrypt, /// Decrypts an AES-encrypted string. AESDecrypt } /// /// The available hashing functions. /// public enum Hash { /// The MD5 hashing function (128 bits digest). MD5, /// The SHA-1 hashing function (160 bits digest). SHA1, /// The SHA-256 hashing function (256 bits digest). SHA256, /// The SHA-384 hashing function (384 bits digest). SHA384, /// The SHA-512 hashing function (512 bits digest). SHA512, } #region General Properties private string variableName = ""; /// The name of the output variable. public string VariableName { get { return variableName; } set { variableName = value; OnPropertyChanged(); } } private bool isCapture = false; /// Whether the output variable should be marked for Capture. public bool IsCapture { get { return isCapture; } set { isCapture = value; OnPropertyChanged(); } } private string inputString = ""; /// The input string on which the function will be executed (not always needed). public string InputString { get { return inputString; } set { inputString = value; OnPropertyChanged(); } } private Function functionType = Function.Constant; /// The function to execute. public Function FunctionType { get { return functionType; } set { functionType = value; OnPropertyChanged(); } } #endregion #region Function Specific Properties // -- Hash & Hmac private Hash hashType = Hash.SHA512; /// The hashing function to use. public Hash HashType { get { return hashType; } set { hashType = value; OnPropertyChanged(); } } // -- Hmac private string hmacKey = ""; /// The key used to authenticate the message. public string HmacKey { get { return hmacKey; } set { hmacKey = value; OnPropertyChanged(); } } private bool hmacBase64 = false; /// Whether to output the message as a base64-encoded string instead of a hex-encoded string. public bool HmacBase64 { get { return hmacBase64; } set { hmacBase64 = value; OnPropertyChanged(); } } // -- Translate private bool stopAfterFirstMatch = true; /// Whether to stop translating after the first match. public bool StopAfterFirstMatch { get { return stopAfterFirstMatch; } set { stopAfterFirstMatch = value; OnPropertyChanged(); } } /// The dictionary containing the words and their translation. public Dictionary TranslationDictionary { get; set; } = new Dictionary(); // -- Date to unix private string dateFormat = "yyyy-MM-dd:HH-mm-ss"; /// The format of the date (y = year, M = month, d = day, H = hour, m = minute, s = second). public string DateFormat { get { return dateFormat; } set { dateFormat = value; OnPropertyChanged(); } } // -- string replace private string replaceWhat = ""; /// The text to replace. public string ReplaceWhat { get { return replaceWhat; } set { replaceWhat = value; OnPropertyChanged(); } } private string replaceWith = ""; /// The replacement text. public string ReplaceWith { get { return replaceWith; } set { replaceWith = value; OnPropertyChanged(); } } private bool useRegex = false; /// Whether to use regex for replacing. public bool UseRegex { get { return useRegex; } set { useRegex = value; OnPropertyChanged(); } } // -- Regex Match private string regexMatch = ""; /// The regex pattern to match. public string RegexMatch { get { return regexMatch; } set { regexMatch = value; OnPropertyChanged(); } } // -- Random Number private int randomMin = 0; /// The minimum random number that can be generated. public int RandomMin { get { return randomMin; } set { randomMin = value; OnPropertyChanged(); } } private int randomMax = 0; /// The maximum random number that can be generated. public int RandomMax { get { return randomMax; } set { randomMax = value; OnPropertyChanged(); } } // -- CountOccurrences private string stringToFind = ""; /// The string to count the occurrences of. public string StringToFind { get { return stringToFind; } set { stringToFind = value; OnPropertyChanged(); } } // -- RSA private string rsaMod = ""; /// The modulus of the RSA key. public string RSAMod { get { return rsaMod; } set { rsaMod = value; OnPropertyChanged(); } } private string rsaExp = ""; /// The exponent of the RSA key. public string RSAExp { get { return rsaExp; } set { rsaExp = value; OnPropertyChanged(); } } // --- CharAt private string charIndex = "0"; /// The index of the wanted character. public string CharIndex { get { return charIndex; } set { charIndex = value; OnPropertyChanged(); } } // -- Substring private string substringIndex = "0"; /// The starting index for the substring. public string SubstringIndex { get { return substringIndex; } set { substringIndex = value; OnPropertyChanged(); } } private string substringLength = "1"; /// The length of the wanted substring. public string SubstringLength { get { return substringLength; } set { substringLength = value; OnPropertyChanged(); } } // -- AES private string aesKey = ""; /// The keys used for AES encryption and decryption. public string AesKey { get { return aesKey; } set { aesKey = value; OnPropertyChanged(); } } #endregion /// /// Creates a Function block. /// public BlockFunction() { Label = "FUNCTION"; } /// public override BlockBase FromLS(string line) { // Trim the line var input = line.Trim(); // Parse the label if (input.StartsWith("#")) Label = LineParser.ParseLabel(ref input); /* * Syntax: * FUNCTION Name [ARGUMENTS] ["INPUT STRING"] [-> VAR/CAP "NAME"] * */ // Parse the function FunctionType = (Function)LineParser.ParseEnum(ref input, "Function Name", typeof(Function)); // Parse specific function parameters switch (FunctionType) { case Function.Hash: HashType = LineParser.ParseEnum(ref input, "Hash Type", typeof(Hash)); break; case Function.HMAC: HashType = LineParser.ParseEnum(ref input, "Hash Type", typeof(Hash)); HmacKey = LineParser.ParseLiteral(ref input, "HMAC Key"); while (LineParser.Lookahead(ref input) == TokenType.Boolean) LineParser.SetBool(ref input, this); break; case Function.Translate: if (LineParser.Lookahead(ref input) == TokenType.Boolean) LineParser.SetBool(ref input, this); TranslationDictionary = new Dictionary(); while (input != "" && LineParser.Lookahead(ref input) == TokenType.Parameter) { LineParser.EnsureIdentifier(ref input, "KEY"); var k = LineParser.ParseLiteral(ref input, "Key"); LineParser.EnsureIdentifier(ref input, "VALUE"); var v = LineParser.ParseLiteral(ref input, "Value"); TranslationDictionary[k] = v; } break; case Function.DateToUnixTime: DateFormat = LineParser.ParseLiteral(ref input, "DATE FORMAT"); break; case Function.Replace: ReplaceWhat = LineParser.ParseLiteral(ref input, "What"); ReplaceWith = LineParser.ParseLiteral(ref input, "With"); if (LineParser.Lookahead(ref input) == TokenType.Boolean) LineParser.SetBool(ref input, this); break; case Function.RegexMatch: RegexMatch = LineParser.ParseLiteral(ref input, "Pattern"); break; case Function.RandomNum: RandomMin = LineParser.ParseInt(ref input, "Minimum"); RandomMax = LineParser.ParseInt(ref input, "Maximum"); break; case Function.CountOccurrences: StringToFind = LineParser.ParseLiteral(ref input, "string to find"); break; case Function.CharAt: CharIndex = LineParser.ParseLiteral(ref input, "Index"); break; case Function.Substring: SubstringIndex = LineParser.ParseLiteral(ref input, "Index"); SubstringLength = LineParser.ParseLiteral(ref input, "Length"); break; case Function.RSA: RSAMod = LineParser.ParseLiteral(ref input, "Modulus"); RSAExp = LineParser.ParseLiteral(ref input, "Exponent"); break; case Function.AESDecrypt: case Function.AESEncrypt: AesKey = LineParser.ParseLiteral(ref input, "AES Key"); break; default: break; } // Try to parse the input string if (LineParser.Lookahead(ref input) == TokenType.Literal) InputString = LineParser.ParseLiteral(ref input, "INPUT"); // Try to parse the arrow, otherwise just return the block as is with default var name and var / cap choice if (LineParser.ParseToken(ref input, TokenType.Arrow, false) == "") return this; // Parse the VAR / CAP try { var varType = LineParser.ParseToken(ref input, TokenType.Parameter, true); if (varType.ToUpper() == "VAR" || varType.ToUpper() == "CAP") IsCapture = varType.ToUpper() == "CAP"; } catch { throw new ArgumentException("Invalid or missing variable type"); } // Parse the variable/capture name try { VariableName = LineParser.ParseToken(ref input, TokenType.Literal, true); } catch { throw new ArgumentException("Variable name not specified"); } return this; } /// public override string ToLS(bool indent = true) { var writer = new BlockWriter(GetType(), indent, Disabled); writer .Label(Label) .Token("FUNCTION") .Token(FunctionType); switch (FunctionType) { case Function.Hash: writer .Token(HashType); break; case Function.HMAC: writer .Token(HashType) .Literal(HmacKey) .Boolean(HmacBase64, "HmacBase64"); break; case Function.Translate: writer .Boolean(StopAfterFirstMatch, "StopAfterFirstMatch"); foreach (var t in TranslationDictionary) writer .Indent() .Token("KEY") .Literal(t.Key) .Token("VALUE") .Literal(t.Value); writer .Indent(); break; case Function.DateToUnixTime: writer .Literal(DateFormat, "DateFormat"); break; case Function.Replace: writer .Literal(ReplaceWhat) .Literal(ReplaceWith) .Boolean(UseRegex, "UseRegex"); break; case Function.RegexMatch: writer .Literal(RegexMatch, "RegexMatch"); break; case Function.RandomNum: writer .Integer(RandomMin) .Integer(RandomMax); break; case Function.CountOccurrences: writer .Literal(StringToFind); break; case Function.CharAt: writer .Literal(CharIndex); break; case Function.Substring: writer .Literal(SubstringIndex) .Literal(SubstringLength); break; case Function.RSA: writer .Literal(RSAMod) .Literal(RSAExp); break; case Function.AESDecrypt: case Function.AESEncrypt: writer .Literal(AesKey); break; } writer .Literal(InputString, "InputString"); if (!writer.CheckDefault(VariableName, "VariableName")) writer .Arrow() .Token(IsCapture ? "CAP" : "VAR") .Literal(VariableName); return writer.ToString(); } /// public override void Process(BotData data) { base.Process(data); var style = NumberStyles.Number | NumberStyles.AllowCurrencySymbol; var provider = new CultureInfo("en-US"); var localInputStrings = ReplaceValuesRecursive(inputString, data); var outputs = new List(); for(int i = 0; i < localInputStrings.Count; i++) { var localInputString = localInputStrings[i]; var outputString = ""; switch (FunctionType) { case Function.Constant: outputString = localInputString; break; case Function.Base64Encode: outputString = Base64Encode(localInputString); break; case Function.Base64Decode: outputString = Base64Decode(localInputString); break; case Function.HTMLEntityEncode: outputString = WebUtility.HtmlEncode(localInputString); break; case Function.HTMLEntityDecode: outputString = WebUtility.HtmlDecode(localInputString); break; case Function.Hash: outputString = GetHash(localInputString, hashType).ToLower(); break; case Function.HMAC: outputString = Hmac(localInputString, hashType, ReplaceValues(hmacKey, data), hmacBase64); break; case Function.Translate: outputString = localInputString; foreach (var entry in TranslationDictionary.OrderBy(e => e.Key.Length).Reverse()) { if (outputString.Contains(entry.Key)) { outputString = outputString.Replace(entry.Key, entry.Value); if (StopAfterFirstMatch) break; } } break; case Function.DateToUnixTime: outputString = (DateTime.ParseExact(localInputString, dateFormat, new CultureInfo("en-US"), DateTimeStyles.AllowWhiteSpaces) .Subtract(new DateTime(1970, 1, 1))) .TotalSeconds .ToString(); break; case Function.Length: outputString = localInputString.Length.ToString(); break; case Function.ToLowercase: outputString = localInputString.ToLower(); break; case Function.ToUppercase: outputString = localInputString.ToUpper(); break; case Function.Replace: if (useRegex) outputString = Regex.Replace(localInputString, ReplaceValues(replaceWhat, data), ReplaceValues(replaceWith, data)); else outputString = localInputString.Replace(ReplaceValues(replaceWhat, data), ReplaceValues(replaceWith, data)); break; case Function.RegexMatch: outputString = Regex.Match(localInputString, ReplaceValues(regexMatch, data)).Value; break; case Function.Unescape: outputString = Regex.Unescape(localInputString); break; case Function.URLEncode: outputString = System.Uri.EscapeDataString(localInputString); break; case Function.URLDecode: outputString = System.Uri.UnescapeDataString(localInputString); break; case Function.UnixTimeToDate: try { var loc = localInputString; if (localInputString.Length > 10) loc = localInputString.Substring(0, 10); DateTime dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); dtDateTime = dtDateTime.AddSeconds(int.Parse(loc)).ToLocalTime(); outputString = dtDateTime.ToShortDateString(); } catch { } break; case Function.CurrentUnixTime: outputString = Math.Round((DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds).ToString(); break; case Function.UnixTimeToISO8601: var loc2 = localInputString; if (localInputString.Length > 10) loc2 = localInputString.Substring(0, 10); DateTime dateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); dateTime = dateTime.AddSeconds(int.Parse(loc2)).ToLocalTime(); outputString = dateTime.ToString("yyyy-MM-ddTHH\\:mm\\:ss.fffZ"); break; case Function.RandomNum: outputString = (data.Random.Next(randomMin, randomMax)).ToString(); break; case Function.RandomString: var reserved = new string[] { "?l", "?u", "?d", "?s", "?h", "?a", "?m", "?i" }; var lowercase = "abcdefghijklmnopqrstuvwxyz"; var uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; var digits = "0123456789"; var symbols = "\\!\"£$%&/()=?^'{}[]@#,;.:-_*+"; var hex = digits + "abcdef"; var allchars = lowercase + uppercase + digits + symbols; var udchars = uppercase + digits; var ludchars = lowercase + uppercase + digits; outputString = localInputString; while (reserved.Any(r => outputString.Contains(r))){ if (outputString.Contains("?l")) outputString = ReplaceFirst(outputString, "?l", lowercase[data.Random.Next(0, lowercase.Length)].ToString()); else if (outputString.Contains("?u")) outputString = ReplaceFirst(outputString, "?u", uppercase[data.Random.Next(0, uppercase.Length)].ToString()); else if (outputString.Contains("?d")) outputString = ReplaceFirst(outputString, "?d", digits[data.Random.Next(0, digits.Length)].ToString()); else if (outputString.Contains("?s")) outputString = ReplaceFirst(outputString, "?s", symbols[data.Random.Next(0, symbols.Length)].ToString()); else if (outputString.Contains("?h")) outputString = ReplaceFirst(outputString, "?h", hex[data.Random.Next(0, hex.Length)].ToString()); else if (outputString.Contains("?a")) outputString = ReplaceFirst(outputString, "?a", allchars[data.Random.Next(0, allchars.Length)].ToString()); else if (outputString.Contains("?m")) outputString = ReplaceFirst(outputString, "?m", udchars[data.Random.Next(0, udchars.Length)].ToString()); else if (outputString.Contains("?i")) outputString = ReplaceFirst(outputString, "?i", ludchars[data.Random.Next(0, ludchars.Length)].ToString()); } break; case Function.Ceil: outputString = Math.Ceiling(Decimal.Parse(localInputString, style, provider)).ToString(); break; case Function.Floor: outputString = Math.Floor(Decimal.Parse(localInputString, style, provider)).ToString(); break; case Function.Round: outputString = Math.Round(Decimal.Parse(localInputString, style, provider), 0, MidpointRounding.AwayFromZero).ToString(); break; case Function.Compute: outputString = new DataTable().Compute(localInputString.Replace(',', '.'), null).ToString(); break; case Function.CountOccurrences: outputString = CountStringOccurrences(localInputString, stringToFind).ToString(); break; case Function.ClearCookies: data.Cookies.Clear(); break; case Function.RSA: try { while (outputString.Length < 2 || outputString.Substring(outputString.Length - 2) != "==") { outputString = SteamRSAEncrypt(new RsaParameters { Exponent = ReplaceValues(RSAExp, data), Modulus = ReplaceValues(RSAMod, data), Password = localInputString }); } } catch (Exception ex) { outputString = ex.ToString(); } break; case Function.Delay: try { Thread.Sleep(int.Parse(localInputString)); } catch { } break; case Function.CharAt: outputString = localInputString.ToCharArray()[int.Parse(ReplaceValues(charIndex, data))].ToString(); break; case Function.Substring: outputString = localInputString.Substring(int.Parse(ReplaceValues(substringIndex, data)), int.Parse(ReplaceValues(substringLength,data))); break; case Function.ReverseString: char[] charArray = localInputString.ToCharArray(); Array.Reverse(charArray); outputString = new string(charArray); break; case Function.Trim: outputString = localInputString.Trim(); break; case Function.GetRandomUA: outputString = RandomUserAgent(data.Random); break; case Function.AESEncrypt: outputString = AESEncrypt(ReplaceValues(aesKey, data), localInputString); break; case Function.AESDecrypt: outputString = AESDecrypt(ReplaceValues(aesKey, data), localInputString); break; } data.Log(new LogEntry(string.Format("Executed function {0} on input {1} with outcome {2}", functionType, localInputString, outputString), Colors.GreenYellow)); // Add to the outputs outputs.Add(outputString); } var isList = outputs.Count > 1 || InputString.Contains("[*]") || InputString.Contains("(*)") || InputString.Contains("{*}"); InsertVariables(data, isCapture, isList, outputs, variableName, "", "", false, true); } #region Base64 /// /// Encodes a string to base64. /// /// The string to encode /// The base64-encoded string public static string Base64Encode(string plainText) { var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText); return System.Convert.ToBase64String(plainTextBytes); } /// /// Decodes a base64-encoded string. /// /// The base64-encoded string /// The decoded string public static string Base64Decode(string base64EncodedData) { var toDecode = base64EncodedData.Replace(".", ""); var remainder = toDecode.Length % 4; if (remainder != 0) toDecode = toDecode.PadRight(toDecode.Length + remainder, '='); var base64EncodedBytes = System.Convert.FromBase64String(toDecode); return System.Text.Encoding.UTF8.GetString(base64EncodedBytes); } #endregion #region Hash and Hmac /// /// Hashes a string using the specified hashing function. /// /// The string to hash /// The hashing function /// The hash digest as a hex-encoded string public static string GetHash(string baseString, Hash type) { switch (type) { case Hash.MD5: return MD5(baseString); case Hash.SHA1: return SHA1(baseString); case Hash.SHA256: return SHA256(baseString); case Hash.SHA384: return SHA384(baseString); case Hash.SHA512: return SHA512(baseString); default: return "UNRECOGNIZED HASH TYPE"; } } /// /// Gets the HMAC signature of a message given a key and a hashing function. /// /// The message to sign /// The hashing function /// The HMAC key /// Whether the output should be encrypted as a base64 string /// The HMAC signature public static string Hmac(string baseString, Hash type, string key, bool base64) { switch (type) { case Hash.MD5: return HMACMD5(baseString, key, base64); case Hash.SHA1: return HMACSHA1(baseString, key, base64); case Hash.SHA256: return HMACSHA256(baseString, key, base64); case Hash.SHA384: return HMACSHA384(baseString, key, base64); case Hash.SHA512: return HMACSHA512(baseString, key, base64); default: return "UNRECOGNIZED HASH TYPE"; } } private static string MD5(string input) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input); byte[] hash = md5.ComputeHash(inputBytes); StringBuilder sb = new StringBuilder(); foreach (byte b in hash) sb.Append(b.ToString("X2")); return sb.ToString(); } private static string HMACMD5(string input, string key, bool base64) { HMACMD5 hmac = new HMACMD5(System.Text.Encoding.ASCII.GetBytes(key)); var hash = hmac.ComputeHash(System.Text.Encoding.ASCII.GetBytes(input)); if (base64) { return Convert.ToBase64String(hash); } else { return ToHex(hash); } } private static string SHA1(string input) { using (SHA1Managed sha1 = new SHA1Managed()) { var hash = sha1.ComputeHash(Encoding.UTF8.GetBytes(input)); var sb = new StringBuilder(hash.Length * 2); foreach (byte b in hash) sb.Append(b.ToString("X2")); return sb.ToString(); } } private static string HMACSHA1(string input, string key, bool base64) { HMACSHA1 hmac = new HMACSHA1(System.Text.Encoding.ASCII.GetBytes(key)); var hash = hmac.ComputeHash(System.Text.Encoding.ASCII.GetBytes(input)); if (base64) { return Convert.ToBase64String(hash); } else { return ToHex(hash); } } private static string SHA256(string input) { using (SHA256Managed sha256 = new SHA256Managed()) { var hash = sha256.ComputeHash(Encoding.UTF8.GetBytes(input)); var sb = new StringBuilder(hash.Length * 2); foreach (byte b in hash) sb.Append(b.ToString("X2")); return sb.ToString(); } } private static string HMACSHA256(string input, string key, bool base64) { HMACSHA256 hmac = new HMACSHA256(System.Text.Encoding.ASCII.GetBytes(key)); var hash = hmac.ComputeHash(System.Text.Encoding.ASCII.GetBytes(input)); if (base64) { return Convert.ToBase64String(hash); } else { return ToHex(hash); } } private static string SHA384(string input) { using (SHA384Managed sha384 = new SHA384Managed()) { var hash = sha384.ComputeHash(Encoding.UTF8.GetBytes(input)); var sb = new StringBuilder(hash.Length * 2); foreach (byte b in hash) sb.Append(b.ToString("X2")); return sb.ToString(); } } private static string HMACSHA384(string input, string key, bool base64) { HMACSHA384 hmac = new HMACSHA384(System.Text.Encoding.ASCII.GetBytes(key)); var hash = hmac.ComputeHash(System.Text.Encoding.ASCII.GetBytes(input)); if (base64) { return Convert.ToBase64String(hash); } else { return ToHex(hash); } } private static string SHA512(string input) { using (SHA512Managed sha512 = new SHA512Managed()) { var hash = sha512.ComputeHash(Encoding.UTF8.GetBytes(input)); var sb = new StringBuilder(hash.Length * 2); foreach (byte b in hash) sb.Append(b.ToString("X2")); return sb.ToString(); } } private static string HMACSHA512(string input, string key, bool base64) { HMACSHA512 hmac = new HMACSHA512(System.Text.Encoding.ASCII.GetBytes(key)); var hash = hmac.ComputeHash(System.Text.Encoding.ASCII.GetBytes(input)); if (base64) { return Convert.ToBase64String(hash); } else { return ToHex(hash); } } private static string ToHex(byte[] bytes) { var sb = new StringBuilder(bytes.Length * 2); foreach (byte b in bytes) sb.Append(b.ToString("X2")); return sb.ToString(); } #endregion #region RSA private string RSAEncrypt(string input, int size) { var data = Encoding.UTF8.GetBytes(input); using (var rsa = new RSACryptoServiceProvider(size)) { try { rsa.FromXmlString(input); var encryptedData = rsa.Encrypt(data, true); Console.WriteLine(Convert.ToString(encryptedData)); return Convert.ToString(encryptedData); } catch (Exception ex) { Console.WriteLine(ex.ToString()); return ""; } finally { rsa.PersistKeyInCsp = false; } } } private string RSADecrypt(string input, int size) { var data = Encoding.UTF8.GetBytes(input); using (var rsa = new RSACryptoServiceProvider(size)) { try { rsa.FromXmlString(input); var resultBytes = System.Text.Encoding.ASCII.GetBytes(input); var decryptedBytes = rsa.Decrypt(resultBytes, true); return Encoding.UTF8.GetString(decryptedBytes); } finally { rsa.PersistKeyInCsp = false; } } } private string SteamRSAEncrypt(RsaParameters rsaParam) { // Convert the public keys to BigIntegers var modulus = CreateBigInteger(rsaParam.Modulus); var exponent = CreateBigInteger(rsaParam.Exponent); // (modulus.ToByteArray().Length - 1) * 8 //modulus has 256 bytes multiplied by 8 bits equals 2048 var encryptedNumber = Pkcs1Pad2(rsaParam.Password, (2048 + 7) >> 3); // And now, the RSA encryption encryptedNumber = System.Numerics.BigInteger.ModPow(encryptedNumber, exponent, modulus); //Reverse number and convert to base64 var encryptedString = Convert.ToBase64String(encryptedNumber.ToByteArray().Reverse().ToArray()); return encryptedString; } private static System.Numerics.BigInteger CreateBigInteger(string hex) { return System.Numerics.BigInteger.Parse("00" + hex, NumberStyles.AllowHexSpecifier); } private static System.Numerics.BigInteger Pkcs1Pad2(string data, int keySize) { if (keySize < data.Length + 11) return new System.Numerics.BigInteger(); var buffer = new byte[256]; var i = data.Length - 1; while (i >= 0 && keySize > 0) { buffer[--keySize] = (byte)data[i--]; } // Padding, I think var random = new Random(); buffer[--keySize] = 0; while (keySize > 2) { buffer[--keySize] = (byte)random.Next(1, 256); //buffer[--keySize] = 5; } buffer[--keySize] = 2; buffer[--keySize] = 0; Array.Reverse(buffer); return new System.Numerics.BigInteger(buffer); } #endregion #region Translation /// /// Builds a string containing translation keys. /// /// One translation key per line, with name and value separated by a colon public string GetDictionary() { StringBuilder sb = new StringBuilder(); foreach (var pair in TranslationDictionary) { sb.Append($"{pair.Key}: {pair.Value}"); if (!pair.Equals(TranslationDictionary.Last())) sb.Append(Environment.NewLine); } return sb.ToString(); } /// /// Sets translation keys from an array of lines. /// /// The lines containing the colon-separated name and value of the translation keys public void SetDictionary(string[] lines) { TranslationDictionary.Clear(); foreach (var line in lines) { if (line.Contains(':')) { var split = line.Split(new[] { ':' }, 2); var key = split[0]; var val = split[1].TrimStart(); TranslationDictionary[key] = val; } } } #endregion #region Count Occurrences /// /// Counts how many times a string occurs inside another string. /// /// The long string /// The text to search /// How many times the text appears in the long string public static int CountStringOccurrences(string input, string text) { // Loop through all instances of the string 'text'. int count = 0; int i = 0; while ((i = input.IndexOf(text, i)) != -1) { i += text.Length; count++; } return count; } #endregion #region RandomString private string ReplaceFirst(string text, string search, string replace) { int pos = text.IndexOf(search); if (pos < 0) { return text; } return text.Substring(0, pos) + replace + text.Substring(pos + search.Length); } #endregion #region AES /// /// Encrypts a string with AES. /// /// The encryption key /// The data to encrypt /// The AES-encrypted string public static string AESEncrypt(string key, string data) { string encData = null; byte[][] keys = GetHashKeys(key); try { encData = EncryptStringToBytes_Aes(data, keys[0], keys[1]); } catch (CryptographicException) { } catch (ArgumentNullException) { } return encData; } /// /// Decrypts an AES-encrypted string. /// /// The decryption key /// The AES-encrypted data /// The plaintext string public static string AESDecrypt(string key, string data) { string decData = null; byte[][] keys = GetHashKeys(key); try { decData = DecryptStringFromBytes_Aes(data, keys[0], keys[1]); } catch (CryptographicException) { } catch (ArgumentNullException) { } return decData; } private static byte[][] GetHashKeys(string key) { byte[][] result = new byte[2][]; Encoding enc = Encoding.UTF8; SHA256 sha2 = new SHA256CryptoServiceProvider(); byte[] rawKey = enc.GetBytes(key); byte[] rawIV = enc.GetBytes(key); byte[] hashKey = sha2.ComputeHash(rawKey); byte[] hashIV = sha2.ComputeHash(rawIV); Array.Resize(ref hashIV, 16); result[0] = hashKey; result[1] = hashIV; return result; } private static string EncryptStringToBytes_Aes(string plainText, byte[] Key, byte[] IV) { if (plainText == null || plainText.Length <= 0) throw new ArgumentNullException("plainText"); if (Key == null || Key.Length <= 0) throw new ArgumentNullException("Key"); if (IV == null || IV.Length <= 0) throw new ArgumentNullException("IV"); byte[] encrypted; using (AesManaged aesAlg = new AesManaged()) { aesAlg.Key = Key; aesAlg.IV = IV; ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV); using (MemoryStream msEncrypt = new MemoryStream()) { using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) { using (StreamWriter swEncrypt = new StreamWriter(csEncrypt)) { swEncrypt.Write(plainText); } encrypted = msEncrypt.ToArray(); } } } return Convert.ToBase64String(encrypted); } private static string DecryptStringFromBytes_Aes(string cipherTextString, byte[] Key, byte[] IV) { byte[] cipherText = Convert.FromBase64String(cipherTextString); if (cipherText == null || cipherText.Length <= 0) throw new ArgumentNullException("cipherText"); if (Key == null || Key.Length <= 0) throw new ArgumentNullException("Key"); if (IV == null || IV.Length <= 0) throw new ArgumentNullException("IV"); string plaintext = null; using (Aes aesAlg = Aes.Create()) { aesAlg.Key = Key; aesAlg.IV = IV; ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV); using (MemoryStream msDecrypt = new MemoryStream(cipherText)) { using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) { using (StreamReader srDecrypt = new StreamReader(csDecrypt)) { plaintext = srDecrypt.ReadToEnd(); } } } } return plaintext; } #endregion #region RandomUA // All credits for this method goes to the Leaf.xNet fork of Extreme.NET // https://github.com/csharp-leaf/Leaf.xNet /// /// Gets a random User-Agent header. /// /// A random number generator /// A randomly generated User-Agent header public static string RandomUserAgent(Random rand) { int random = rand.Next(99) + 1; // Chrome = 70% if (random >= 1 && random <= 70) return Http.ChromeUserAgent(); // Firefox = 15% if (random > 70 && random <= 85) return Http.FirefoxUserAgent(); // IE = 6% if (random > 85 && random <= 91) return Http.IEUserAgent(); // Opera 12 = 5% if (random > 91 && random <= 96) return Http.OperaUserAgent(); // Opera mini = 4% return Http.OperaMiniUserAgent(); } #endregion } /// /// The RSA parameters. /// struct RsaParameters { /// The key exponent. public string Exponent; /// The key modulus. public string Modulus; /// The encryption password. public string Password; } }