diff --git a/BitcoinExprCracker.sln b/BitcoinExprCracker.sln new file mode 100644 index 0000000..ff2fe94 --- /dev/null +++ b/BitcoinExprCracker.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28307.902 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BitcoinExprCracker", "BitcoinExprCracker\BitcoinExprCracker.csproj", "{EFA130F7-552B-46D9-8558-B8C6DEFB5F54}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {EFA130F7-552B-46D9-8558-B8C6DEFB5F54}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EFA130F7-552B-46D9-8558-B8C6DEFB5F54}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EFA130F7-552B-46D9-8558-B8C6DEFB5F54}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EFA130F7-552B-46D9-8558-B8C6DEFB5F54}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {A9088E96-7B3F-4F0E-B420-60E5B6323DB5} + EndGlobalSection +EndGlobal diff --git a/BitcoinExprCracker/App.config b/BitcoinExprCracker/App.config new file mode 100644 index 0000000..88fa402 --- /dev/null +++ b/BitcoinExprCracker/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/BitcoinExprCracker/BitcoinExprCracker.csproj b/BitcoinExprCracker/BitcoinExprCracker.csproj new file mode 100644 index 0000000..056ed91 --- /dev/null +++ b/BitcoinExprCracker/BitcoinExprCracker.csproj @@ -0,0 +1,74 @@ + + + + + Debug + AnyCPU + {EFA130F7-552B-46D9-8558-B8C6DEFB5F54} + Exe + BitcoinExprCracker + BitcoinExprCracker + v4.5.2 + 512 + true + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + false + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\BigInteger.1.0.7\lib\net20\BigInteger.dll + + + ..\packages\Microsoft.Extensions.Logging.Abstractions.1.0.0\lib\netstandard1.1\Microsoft.Extensions.Logging.Abstractions.dll + + + ..\packages\NBitcoin.4.2.16\lib\net452\NBitcoin.dll + + + ..\packages\Newtonsoft.Json.11.0.1\lib\net45\Newtonsoft.Json.dll + + + + ..\packages\System.Buffers.4.5.0\lib\netstandard1.1\System.Buffers.dll + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/BitcoinExprCracker/Generator/Estrutura.cs b/BitcoinExprCracker/Generator/Estrutura.cs new file mode 100644 index 0000000..deb741e --- /dev/null +++ b/BitcoinExprCracker/Generator/Estrutura.cs @@ -0,0 +1,35 @@ +/* Criado por Jairo Paiva + * https://github.com/jairopaiva + * GNU GPLv3 + * */ +namespace BitcoinExprCracker.Generator +{ + public struct Operação + { + public Variável A; + public Variável B; + public char Operador; + public byte Resultado; + } + + public struct Variável + { + public byte Value; // Valor + public int Index; // Index em X ou Y + public char X_Y; // Se pertence a x ou Y + + public override string ToString() + { + return Value.ToString(); + } + } + + public struct ParsedPubKey + { + public byte[] X; + public byte[] Y; + public ulong[] xU; + public ulong[] yU; + public byte[] PublicKey; + } +} \ No newline at end of file diff --git a/BitcoinExprCracker/Generator/ExprGenerator.cs b/BitcoinExprCracker/Generator/ExprGenerator.cs new file mode 100644 index 0000000..aaf69b0 --- /dev/null +++ b/BitcoinExprCracker/Generator/ExprGenerator.cs @@ -0,0 +1,400 @@ +/* Criado por Jairo Paiva + * https://github.com/jairopaiva + * GNU GPLv3 + * */ + +using System; +using System.Collections.Generic; +using System.IO; + +namespace BitcoinExprCracker.Generator +{ + internal class ExprGenerator + { + /// + /// + /// + /// X[i] + /// Y[i] + /// + /// + + public static int Generate(ref ulong Hash, ref ulong Seed, ref ulong limitDeOperações, ref byte[] X, ref byte[] Y, out string expression) + { + string stringOperation = string.Empty; + List Operações = new List(); + + ulong elementsAdded = 0; + ulong insideTry = 0; + + for (ulong operações = 0; operações < limitDeOperações; operações++) + { + Operação op = new Operação(); + char Operador = GetOperand(true, Seed, ref insideTry, ref elementsAdded); + + stringOperation += "("; + + op.A = GenerateVariável(Seed, ref insideTry, ref elementsAdded, ref X, ref Y); + + if (Operador == Operands[6]) // ~ NOT + { + op.A.Value = (byte)((~op.A.Value) & 255); + + stringOperation += Operador + VariáveltoExpression(op.A) + " "; + Operador = GetOperand(false, Seed, ref insideTry, ref elementsAdded); + } + else + stringOperation += VariáveltoExpression(op.A) + " "; + + op.B = GenerateVariável(Seed, ref insideTry, ref elementsAdded, ref X, ref Y); + + stringOperation += Operador + " " + VariáveltoExpression(op.B) + " "; + + // op.Resultado = (byte)(operators[Operador](op.A.Value, op.B.Value) % 256); + op.Resultado = (byte)(CalcularOperação(Operador, new int[] { op.A.Value, op.B.Value }) % 256); + op.Operador = Operador; + Operações.Add(op); + + stringOperation += ") "; + + if (operações + 1 < limitDeOperações) + { + Operações.Add(new Operação() { Operador = GetOperand(false, Seed, ref insideTry, ref elementsAdded) }); + stringOperation += Operações[Operações.Count - 1].Operador + " "; + } + } + + // Agora calcular o resultado da expressão + + int resultado = CalcularResultadoOperações(Operações); + expression = stringOperation; + + return resultado; + } + + public static int Calculate(byte[] pubkey, ref string expression) + { + byte[] compareX = new byte[32]; + byte[] compareY = new byte[32]; + Utils.ParseXYfromPub(pubkey, out compareX, out compareY); + + return Calculate(compareX, compareY, ref expression); + } + + public static int Calculate(ParsedPubKey pubkey, ref string expression) + { + return Calculate(pubkey.X, pubkey.Y, ref expression); + } + + public static int Calculate(byte[] compareX, byte[] compareY, ref string expression) + { + List Operações = new List(); + // Vars = new List(); + + StringReader Reader = new StringReader(expression.Replace(" ", "")); + bool B = false; + + char c = (char)Reader.Peek(); + + while (Reader.Peek() != -1) + { + c = (char)Reader.Peek(); + + if (c == '(') + { + Operação op = new Operação(); // (~X[10] ^ ~Y[21] ) ^ (~Y[9] & ~X[24] ) + Reader.Read(); + + VOLTA: + + c = (char)Reader.Peek(); + + if (c == '~') + { + Reader.Read(); + + char Letra = (char)Reader.Peek(); + Reader.Read(); // [ + Reader.Read(); // index + + string numero = string.Empty; + int index = 0; + + while (char.IsNumber((char)Reader.Peek())) + { + numero += (char)Reader.Peek(); + Reader.Read(); + } + index = int.Parse(numero); + + Reader.Read(); // ] + + if (!B) + { + op.A = GetVariável(ref compareX, ref compareY, Letra, index, true); + // if(Vars != null) + // Vars.Add(op.A); + B = true; + goto VOLTA; + } + else // A já foi prenchido, agora B + { + op.B = GetVariável(ref compareX, ref compareY, Letra, index, true); + // if (Vars != null) + // Vars.Add(op.B); + } + + Reader.Read(); // ) + + if (B) + { + Operações.Add(op); + // op.Resultado = (byte)(operators[op.Operador](op.A.Value, op.B.Value) % 256); + op.Resultado = (byte)(CalcularOperação(op.Operador, new int[] { op.A.Value, op.B.Value }) % 256); + B = false; + continue; + } + } + else if (IsOperand(c)) + { + op.Operador = c; + Reader.Read(); + goto VOLTA; + } + else + { + char Letra = (char)Reader.Peek(); + Reader.Read(); // [ + Reader.Read(); // index + + string numero = string.Empty; + int index = 0; + + while (char.IsNumber((char)Reader.Peek())) + { + numero += (char)Reader.Peek(); + Reader.Read(); + } + + index = int.Parse(numero); + + Reader.Read(); // ] + + if (!B) + { + op.A = GetVariável(ref compareX, ref compareY, Letra, index); + // if (Vars != null) + // Vars.Add(op.A); + B = true; + goto VOLTA; ; + } + else // A já foi prenchido, agora B + { + op.B = GetVariável(ref compareX, ref compareY, Letra, index); + // if (Vars != null) + // Vars.Add(op.B); + } + + Reader.Read(); // ) + + if (B) + { + //op.Resultado = (byte)(operators[op.Operador](op.A.Value, op.B.Value) % 256); + op.Resultado = (byte)(CalcularOperação(op.Operador, new int[] { op.A.Value, op.B.Value }) % 256); + Operações.Add(op); + B = false; + continue; + } + } + } + else if (IsOperand(c)) + { + Operações.Add(new Operação() { Operador = c }); + Reader.Read(); // ( + } + } + + return CalcularResultadoOperações(Operações); + } + + private static int CalcularResultadoOperações(List Operações) + { + // Agora calcular o resultado da expressão + + aindaHáOperações: + List temp = new List(); + + for (int i = 0; i < Operações.Count; i++) + { + Operação a = Operações[i]; + i++; + char operador = Operações[i].Operador; + i++; + Operação b = Operações[i]; + + Operação resultado = new Operação(); + // resultado.Resultado = (byte)(operators[operador](a.Resultado, b.Resultado) % 256); + resultado.Resultado = (byte)(CalcularOperação(operador, new int[] { a.Resultado, b.Resultado }) % 256); + temp.Add(resultado); + + if (i == Operações.Count - 1) + break; + i++; + temp.Add(Operações[i]); + } + + if (temp.Count != 1) + { + Operações = temp; + goto aindaHáOperações; + } + + return (byte)temp[0].Resultado; + } + + private static Variável GetVariável(ref byte[] x, ref byte[] y, char x_y, int index, bool NOT = false) + { + Variável v = new Variável(); + if (x_y == 'X') + { + if (!NOT) + v.Value = x[index]; + else + v.Value = (byte)((~x[index]) & 255); + } + else // 'Y' + { + if (!NOT) + v.Value = y[index]; + else + v.Value = (byte)((~y[index]) & 255); + } + + v.X_Y = x_y; + v.Index = index; + return v; + } + + private static readonly char[] Operands = { '+', '-', '*', '%', '&', '|', '~', '^' }; + + private static bool IsOperand(char c) + { + if (Operands[0] == c || Operands[1] == c || Operands[2] == c || Operands[3] == c || Operands[4] == c || + Operands[5] == c || Operands[6] == c || Operands[7] == c) + return true; + + return false; + } + + private static int CalcularOperação(char op, int[] values) + { + switch (op) + { + case '+': + return values[0] + values[1]; + + case '-': + return values[0] - values[1]; + + case '*': + return values[0] * values[1]; + + case '%': + if (values[0] == 0) + { + if (values[1] != 0) + return values[1]; + else + return 0; + } + else if (values[1] == 0) + { + return 0; + } + else + return values[0] % values[1]; + + case '&': + return values[0] & values[1]; + + case '|': + return values[0] | values[1]; + + case '~': + return ~values[0]; + + case '^': + return values[0] ^ values[1]; + + default: + throw new Exception(); + } + } + + private static string VariáveltoExpression(Variável v) + { + string ret = v.X_Y + "[" + v.Index + "]"; + return ret; + } + + public static ulong Hash(byte[] bytes) + { + ulong x = 1; + for (int i = 0; i < bytes.Length; i++) + { + x ^= bytes[i]; + x ^= x * (x >> 3); + x += (x >> 3) ^ (x << 1); + } + return x; + } + + private static Variável GenerateVariável(ulong seed, ref ulong insideTry, ref ulong elementsAdded, ref byte[] X, ref byte[] Y) + { + Variável variável = new Variável(); + byte[] indexSeed = BitConverter.GetBytes(seed + insideTry + elementsAdded); + Array.Reverse(indexSeed); + + int Index = (int)(Hash(indexSeed) % 32); + ulong X_Y = ((ulong)Index + insideTry) % 2; + + if (X_Y == 0) + { + variável.Index = Index; + variável.Value = X[Index]; + variável.X_Y = 'X'; + } + else // X_Y == 1 + { + variável.Index = Index; + variável.Value = Y[Index]; + variável.X_Y = 'Y'; + } + + elementsAdded++; + return variável; + } + + public static char GetOperand(bool podeNot, ulong seed, ref ulong insideTry, ref ulong elementsAdded) + { + volta: + byte[] indexSeed = BitConverter.GetBytes(seed + insideTry + elementsAdded); + Array.Reverse(indexSeed); + int result = (int)(Hash(indexSeed) % 8); + + if (!podeNot && result == 6) + { + insideTry += 1; + goto volta; + } + elementsAdded++; + + return Operands[result]; + } + } +} + +/* Criado por Jairo Paiva + * https://github.com/jairopaiva + * GNU GPLv3 + * */ diff --git a/BitcoinExprCracker/Generator/GeneratorMethods.cs b/BitcoinExprCracker/Generator/GeneratorMethods.cs new file mode 100644 index 0000000..ee28885 --- /dev/null +++ b/BitcoinExprCracker/Generator/GeneratorMethods.cs @@ -0,0 +1,96 @@ +/* Criado por Jairo Paiva + * https://github.com/jairopaiva + * GNU GPLv3 + * */ + +using NBitcoin; +using System; + +namespace BitcoinExprCracker.Generator +{ + class GeneratorMethods + { + + public static byte[] ConvertTryesToPrivateKey(byte[] publicKey, ulong[] tryes) + { + ulong UintMax = 4294967296; + ParsedPubKey pubKey = Utils.ParseXYfromPub(publicKey, true); + byte[] prv = new byte[32]; + + for (int indexPrv = 0; indexPrv < 32; indexPrv++) + { + ulong targetX = pubKey.xU[Utils.GetPubUIndex(indexPrv)]; + ulong targetY = pubKey.yU[Utils.GetPubUIndex(indexPrv)]; + ulong Mult = targetX * targetY; + ulong SeedSum = (ulong)((new BigInteger(pubKey.X) % UintMax).LongValue() + (new BigInteger(pubKey.Y) % UintMax).LongValue()); + + ulong Try = tryes[indexPrv]; + + ulong Hash = Try + (Mult * ((ulong)indexPrv + Try)) % UintMax; + ulong limitDeOperações = (uint)Math.Pow(2d, (double)(Hash % 2) + 1d); + ulong SeedC = Try + Mult; + ulong Seed = ((Hash + SeedSum + SeedC) + Try) % UintMax; + + string Expr = string.Empty; + byte result = (byte)ExprGenerator.Generate(ref Hash, ref Seed, ref limitDeOperações, ref pubKey.X, ref pubKey.Y, out Expr); + + prv[indexPrv] = result; + } + + return prv; + } + + public static ulong[] GetPubKeyCorrectTryes(Key key, int limitPrvIndex = 32, bool PrintCorrectExpr = false) + { + ulong UintMax = 4294967296; + ParsedPubKey pubKey = Utils.ParseXYfromPub(key.PubKey.Decompress().ToBytes(), true); + byte[] prv = key.ToBytes(); + ulong[] CorrectTryes = new ulong[32]; + + for (int indexPrv = 0; indexPrv < limitPrvIndex; indexPrv++) + { + ulong targetX = pubKey.xU[Utils.GetPubUIndex(indexPrv)]; + ulong targetY = pubKey.yU[Utils.GetPubUIndex(indexPrv)]; + ulong Mult = targetX * targetY; + ulong SeedSum = (ulong)((new BigInteger(pubKey.X) % UintMax).LongValue() + (new BigInteger(pubKey.Y) % UintMax).LongValue()); + + for (ulong Try = 0; Try < ulong.MaxValue; Try++) + { + ulong Hash = Try + (Mult * ((ulong)indexPrv + Try)) % UintMax; + ulong limitDeOperações = (uint)Math.Pow(2d, (double)(Hash % 2) + 1d); + ulong SeedC = Try + Mult; + ulong Seed = ((Hash + SeedSum + SeedC) + Try) % UintMax; + + string Expr = string.Empty; + byte result = (byte)ExprGenerator.Generate(ref Hash, ref Seed, ref limitDeOperações, ref pubKey.X, ref pubKey.Y, out Expr); + + if (prv[indexPrv] == result) + { + CorrectTryes[indexPrv] = Try; + if (PrintCorrectExpr) + Console.WriteLine("Correct expression for index "+indexPrv + " = " +Expr); + break; + } + } + } + + return CorrectTryes; + } + + public static string TryesToString(ulong[] CorrectTryes) + { + string rett = ""; + for (int i = 0; i < CorrectTryes.Length; i++) + { + rett += (CorrectTryes[i] + ", "); + } + return rett; + } + + } +} + +/* Criado por Jairo Paiva + * https://github.com/jairopaiva + * GNU GPLv3 + * */ diff --git a/BitcoinExprCracker/Program.cs b/BitcoinExprCracker/Program.cs new file mode 100644 index 0000000..28eb5a8 --- /dev/null +++ b/BitcoinExprCracker/Program.cs @@ -0,0 +1,37 @@ +/* Criado por Jairo Paiva + * https://github.com/jairopaiva + * GNU GPLv3 + * */ + +using NBitcoin; +using System; + +namespace BitcoinExprCracker +{ + class Program + { + static void Main(string[] args) + { + + for (BigInteger priv = 1; priv < 2; priv++) + { + Key k = new Key(Utils.BigInt2Key(priv)); + byte[] PubKey = k.PubKey.Decompress().ToBytes(); + + ulong[] CorrectTryes = Generator.GeneratorMethods.GetPubKeyCorrectTryes(k, 32, true); + Console.WriteLine("PubKey = " + NBitcoin.DataEncoders.Encoders.Hex.EncodeData(PubKey)); + Console.WriteLine("PrvKey = " + NBitcoin.DataEncoders.Encoders.Hex.EncodeData(k.ToBytes())); + Console.WriteLine("Generated Tryes = " + Generator.GeneratorMethods.TryesToString(CorrectTryes)); + Console.WriteLine("Converted Tryes to PrvKey = " + NBitcoin.DataEncoders.Encoders.Hex.EncodeData(Generator.GeneratorMethods.ConvertTryesToPrivateKey(PubKey, CorrectTryes))); + Console.WriteLine(); + } + + Console.ReadKey(); + } + } +} + +/* Criado por Jairo Paiva + * https://github.com/jairopaiva + * GNU GPLv3 + * */ diff --git a/BitcoinExprCracker/Properties/AssemblyInfo.cs b/BitcoinExprCracker/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..d2800c7 --- /dev/null +++ b/BitcoinExprCracker/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// As informações gerais sobre um assembly são controladas por +// conjunto de atributos. Altere estes valores de atributo para modificar as informações +// associada a um assembly. +[assembly: AssemblyTitle("BitcoinExprCracker")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("BitcoinExprCracker")] +[assembly: AssemblyCopyright("Copyright © Jairo Paiva 2019")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Definir ComVisible como false torna os tipos neste assembly invisíveis +// para componentes COM. Caso precise acessar um tipo neste assembly de +// COM, defina o atributo ComVisible como true nesse tipo. +[assembly: ComVisible(false)] + +// O GUID a seguir será destinado à ID de typelib se este projeto for exposto para COM +[assembly: Guid("efa130f7-552b-46d9-8558-b8c6defb5f54")] + +// As informações da versão de um assembly consistem nos quatro valores a seguir: +// +// Versão Principal +// Versão Secundária +// Número da Versão +// Revisão +// +// É possível especificar todos os valores ou usar como padrão os Números de Build e da Revisão +// utilizando o "*" como mostrado abaixo: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/BitcoinExprCracker/Utils.cs b/BitcoinExprCracker/Utils.cs new file mode 100644 index 0000000..7002119 --- /dev/null +++ b/BitcoinExprCracker/Utils.cs @@ -0,0 +1,116 @@ +/* Criado por Jairo Paiva + * https://github.com/jairopaiva + * GNU GPLv3 + * */ + +using BitcoinExprCracker.Generator; +using System; + +namespace BitcoinExprCracker +{ + class Utils + { + + public static ParsedPubKey ParseXYfromPub(byte[] pub, bool AssignULong = false) + { + byte[] X = new byte[32]; + byte[] Y = new byte[32]; + ParsedPubKey result = new ParsedPubKey(); + + for (int i = 1; i < 33; i++) + { + X[i - 1] = pub[i]; + } + + for (int i = 0; i < 32; i++) + { + Y[i] = pub[i + 33]; + } + + result.X = X; + result.Y = Y; + + if (AssignULong) + { + result.xU = Utils.ByteArrayToULong32Bits(X); + result.yU = Utils.ByteArrayToULong32Bits(Y); + } + + result.PublicKey = pub; + + return result; + } + + public static void Resize(ref byte[] data, int lenght) + { + byte[] newdata = new byte[lenght]; + + int e = data.Length - 1; + int i = lenght - 1; + while (e != -1) + { + if (i != -1) + { + newdata[i] = data[e]; + i--; + e--; + } + } + data = newdata; + + } + + public static ulong[] ByteArrayToULong32Bits(byte[] array) + { + int total = array.Length / 4; + ulong[] result = new ulong[total]; + + for (int i = 0; i < total; i++) + { + byte[] arr = new byte[4]; + Buffer.BlockCopy(array, (i * 4), arr, 0, arr.Length); + Array.Reverse(arr); + result[i] = BitConverter.ToUInt32(arr, 0); + } + return result; + } + + public static byte[] BigInt2Key(BigInteger privatekey) + { + byte[] prv = privatekey.getBytes(); + if (prv.Length != 32) + Resize(ref prv, 32); + return prv; + } + + public static void ParseXYfromPub(byte[] pub, out byte[] x, out byte[] y) + { + byte[] X = new byte[32]; + byte[] Y = new byte[32]; + + for (int i = 1; i < 33; i++) + { + X[i - 1] = pub[i]; + } + + for (int i = 0; i < 32; i++) + { + Y[i] = pub[i + 33]; + } + + x = X; + y = Y; + } + + public static int GetPubUIndex(int prvIndex) + { + return (int)(prvIndex / 4); + } + + } +} + +/* Criado por Jairo Paiva + * https://github.com/jairopaiva + * GNU GPLv3 + * */ diff --git a/BitcoinExprCracker/packages.config b/BitcoinExprCracker/packages.config new file mode 100644 index 0000000..e8223f9 --- /dev/null +++ b/BitcoinExprCracker/packages.config @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Main.PNG b/Main.PNG new file mode 100644 index 0000000..afd1024 Binary files /dev/null and b/Main.PNG differ diff --git a/Main_MostrarExprs.PNG b/Main_MostrarExprs.PNG new file mode 100644 index 0000000..bafebaf Binary files /dev/null and b/Main_MostrarExprs.PNG differ