Example #1
0
        static void Main(string[] args)
        {
            // TOOD: Point this to the disassembled directory
            const string dir = @"..\..\..\..\NemID\disassembled";

            {
                JavaApp app = new JavaApp();
                string[] files = Directory.GetFiles(dir, "*.j", SearchOption.AllDirectories);

                // Read files initially
                {
                    Console.WriteLine("Parsing " + files.Length + " classes");

                    HashSet<string> allReferencedTypes = new HashSet<string>();
                    Regex constRegex = new Regex(@"^\.const .*$", RegexOptions.Multiline | RegexOptions.Compiled);

                    foreach (string file in files)
                    {
                        JavaClass container = new JavaClass(file);

                        // Substitute constants
                        if (container.Constants.Any())
                        {
                            // This is a test
                            string fileText = File.ReadAllText(file);
                            List<string> keys = container.Constants.Keys.ToList();

                            foreach (string key in keys)
                            {
                                container.Constants[key].Value = container.ResolveConstants(container.Constants[key].Value);
                            }

                            foreach (string key in keys)
                            {
                                if ((container.Constants[key].Type == "String" || container.Constants[key].Type == "Utf8") && !container.Constants[key].Value.StartsWith("'") && !container.Constants[key].Value.StartsWith("\""))
                                {
                                    // Enquote
                                    container.Constants[key].Value = "'" + container.Constants[key].Value + "'";
                                }
                            }

                            fileText = constRegex.Replace(fileText, string.Empty);
                            fileText = fileText.Trim();

                            foreach (string key in keys)
                            {
                                string firstToken = container.Constants[key].Value.Split(' ').First();
                                if (!firstToken.Contains("\"") && !firstToken.Contains("/") && !firstToken.Contains("'"))
                                    Console.WriteLine(firstToken);

                                fileText = fileText.Replace(key, container.Constants[key].Value);
                            }

                            File.WriteAllText(file, fileText);

                            container = new JavaClass(file);
                        }

                        foreach (string referencedType in container.ReferencedTypes)
                            allReferencedTypes.Add(referencedType);

                        app.Classes.Add(container.FullName, container);
                    }

                    foreach (JavaClass javaClassContainer in app.Classes.Values)
                        allReferencedTypes.Remove(javaClassContainer.FullName);

                    List<string> allTypes = allReferencedTypes.ToList();
                    foreach (string type in allTypes)
                        if (type.StartsWith("java"))
                            allReferencedTypes.Remove(type);

                    foreach (string allReferencedType in allReferencedTypes)
                        Console.WriteLine(allReferencedType);

                    Console.WriteLine("Parsed all " + app.Classes.Count + " classes");
                }

                // Process files
                {
                    Queue<JavaClass> classQueue = new Queue<JavaClass>(app.Classes.Values);

                    int methodNum = 0;
                    int fieldNum = 0;

                    while (classQueue.Any())
                    {
                        JavaClass currentClass = classQueue.Dequeue();

                        // Is waiting for super?
                        if (classQueue.Any(s => s.FullName == currentClass.SuperClass))
                        {
                            // Yes, requeue
                            classQueue.Enqueue(currentClass);
                            continue;
                        }

                        // Is waiting for interface?
                        if (classQueue.Any(s => currentClass.Interfaces.Any(x => x == s.FullName)))
                        {
                            // Yes, requeue
                            classQueue.Enqueue(currentClass);
                            continue;
                        }

                        // Process
                        if (app.Classes.ContainsKey(currentClass.SuperClass))
                        {
                            // Copy down fields / methods
                            JavaClass superClass = app.Classes[currentClass.SuperClass];

                            List<JavaMethod> superMethods = superClass.Methods.Where(s => !currentClass.Methods.Any(x => x.Name == s.Name && x.Type == s.Type)).ToList();
                            List<JavaField> superFields = superClass.Fields.Where(s => !currentClass.Fields.Any(x => x.Name == s.Name && x.Type == s.Type)).ToList();

                            foreach (JavaMethod method in superMethods)
                            {
                                JavaMethod newMethod = new JavaMethod(currentClass, method.Declaration);

                                currentClass.Methods.Add(newMethod);
                            }

                            foreach (JavaField field in superFields)
                            {
                                JavaField newField = new JavaField(currentClass, field.Declaration);

                                currentClass.Fields.Add(newField);
                            }
                        }

                        // Class name
                        if (ShouldRename(currentClass.Name))
                        {
                            // Rename class
                            app.ClassRenames.Add(currentClass.FullName, currentClass.FullName.Replace(currentClass.Name, "OrigClass_" + currentClass.Name));
                        }

                        // Method names
                        foreach (JavaMethod method in currentClass.Methods)
                        {
                            JavaMethod parentMethod = app.FindMethod(currentClass, method.Name, method.Type);

                            if (method.Name == "<init>" || method.Name == "<clinit>")
                                continue;

                            if (ShouldRename(parentMethod))
                            {
                                parentMethod.SetNewName("OrigMethod" + methodNum++);
                            }
                        }

                        // Field names
                        foreach (JavaField field in currentClass.Fields)
                        {
                            JavaField parentField = app.FindField(currentClass, field.Name, field.Type);

                            if (ShouldRename(parentField))
                            {
                                parentField.SetNewName("OrigField" + fieldNum++);
                            }
                        }
                    }

                    Console.WriteLine("Processed all " + app.Classes.Count + " classes");
                    Console.WriteLine("Total class renames: " + app.ClassRenames.Count);
                }

                // Rename fields and methods
                {
                    Console.WriteLine("Beginning rename pass 1");

                    // Actual renaming
                    foreach (JavaClass classContainer in app.Classes.Values)
                    {
                        string fileText = File.ReadAllText(classContainer.FileName);

                        // Method renames
                        // Single methods
                        foreach (JavaMethod method in classContainer.Methods)
                        {
                            JavaMethod parentMethod = app.FindMethod(classContainer, method.Name, method.Type);

                            if (!parentMethod.IsRenamed)
                                // No need for renaming
                                continue;

                            method.SetNewName(parentMethod.NewName);

                            string oldDec = method.Declaration;
                            string newDec = method.NewDeclaration;

                            fileText = fileText.Replace(oldDec, newDec);
                        }

                        // Field renames
                        // Single fields
                        foreach (JavaField field in classContainer.Fields)
                        {
                            JavaField parentField = app.FindField(classContainer, field.Name, field.Type);

                            if (!parentField.IsRenamed)
                                // No need for renaming
                                continue;

                            field.SetNewName(parentField.NewName);

                            string oldDec = field.Declaration;
                            string newDec = field.NewDeclaration;

                            fileText = fileText.Replace(oldDec, newDec);
                        }

                        File.WriteAllText(classContainer.FileName, fileText);
                    }

                    Console.WriteLine("Completed rename pass 1");

                    List<JavaMethod> allMethodRenames = app.Classes.Values.SelectMany(s => s.Methods.Where(x => x.IsRenamed)).ToList();
                    List<JavaField> allFieldRenames = app.Classes.Values.SelectMany(s => s.Fields.Where(x => x.IsRenamed)).ToList();

                    Console.WriteLine("Total method renames: " + allMethodRenames.Count);
                    Console.WriteLine("Total field renames: " + allFieldRenames.Count);

                    Console.WriteLine("Beginning rename pass 2");

                    foreach (JavaClass classContainer in app.Classes.Values)
                    {
                        string fileText = File.ReadAllText(classContainer.FileName);

                        // All other methods
                        foreach (JavaMethod method in allMethodRenames)
                        {
                            // Rename
                            List<string> typeSubstitutes = classContainer.Constants.Where(s => s.Value.Value == method.Type).Select(s => s.Key).ToList();
                            typeSubstitutes.Add(method.Type);

                            foreach (string typeSubstitute in typeSubstitutes)
                            {
                                string oldUsage = method.OwningClass.FullName + " " + method.Name + " " + typeSubstitute;
                                string newUsage = method.OwningClass.FullName + " " + method.NewName + " " + typeSubstitute;

                                fileText = fileText.Replace(oldUsage, newUsage);
                            }
                        }

                        // All other fields
                        foreach (JavaField field in allFieldRenames)
                        {
                            // Rename
                            List<string> typeSubstitutes = classContainer.Constants.Where(s => s.Value.Value == field.Type).Select(s => s.Key).ToList();
                            typeSubstitutes.Add(field.Type);

                            foreach (string typeSubstitute in typeSubstitutes)
                            {
                                string oldUsage = field.OwningClass.FullName + " " + field.Name + " " + typeSubstitute;
                                string newUsage = field.OwningClass.FullName + " " + field.NewName + " " + typeSubstitute;

                                fileText = fileText.Replace(oldUsage, newUsage);
                            }
                        }

                        File.WriteAllText(classContainer.FileName, fileText);
                    }

                    Console.WriteLine("Completed rename pass 2");
                }

                // Rename classes
                {
                    Console.WriteLine("Beginning class rename");

                    foreach (JavaClass classContainer in app.Classes.Values)
                    {
                        string fileText = File.ReadAllText(classContainer.FileName);

                        foreach (KeyValuePair<string, string> map in app.ClassRenames)
                        {
                            fileText = fileText.Replace(map.Key, map.Value);
                        }

                        File.WriteAllText(classContainer.FileName, fileText);
                    }

                    // Move files
                    foreach (KeyValuePair<string, string> map in app.ClassRenames)
                    {
                        File.Move(Path.Combine(dir, map.Key + ".j"), Path.Combine(dir, map.Value + ".j"));
                    }

                    Console.WriteLine("Completed class rename");
                }
            }

            // Replace string encryption
            // TODO: If you're not working with NemID, comment out the line below.
            DecryptStrings(dir);

            Console.WriteLine("All done.");
        }
Example #2
0
        static void Main(string[] args)
        {
            // TOOD: Point this to the disassembled directory
            const string dir = @"..\..\..\..\NemID\disassembled";

            {
                JavaApp  app   = new JavaApp();
                string[] files = Directory.GetFiles(dir, "*.j", SearchOption.AllDirectories);

                // Read files initially
                {
                    Console.WriteLine("Parsing " + files.Length + " classes");

                    HashSet <string> allReferencedTypes = new HashSet <string>();
                    Regex            constRegex         = new Regex(@"^\.const .*$", RegexOptions.Multiline | RegexOptions.Compiled);

                    foreach (string file in files)
                    {
                        JavaClass container = new JavaClass(file);

                        // Substitute constants
                        if (container.Constants.Any())
                        {
                            // This is a test
                            string        fileText = File.ReadAllText(file);
                            List <string> keys     = container.Constants.Keys.ToList();

                            foreach (string key in keys)
                            {
                                container.Constants[key].Value = container.ResolveConstants(container.Constants[key].Value);
                            }

                            foreach (string key in keys)
                            {
                                if ((container.Constants[key].Type == "String" || container.Constants[key].Type == "Utf8") && !container.Constants[key].Value.StartsWith("'") && !container.Constants[key].Value.StartsWith("\""))
                                {
                                    // Enquote
                                    container.Constants[key].Value = "'" + container.Constants[key].Value + "'";
                                }
                            }

                            fileText = constRegex.Replace(fileText, string.Empty);
                            fileText = fileText.Trim();

                            foreach (string key in keys)
                            {
                                string firstToken = container.Constants[key].Value.Split(' ').First();
                                if (!firstToken.Contains("\"") && !firstToken.Contains("/") && !firstToken.Contains("'"))
                                {
                                    Console.WriteLine(firstToken);
                                }

                                fileText = fileText.Replace(key, container.Constants[key].Value);
                            }

                            File.WriteAllText(file, fileText);

                            container = new JavaClass(file);
                        }

                        foreach (string referencedType in container.ReferencedTypes)
                        {
                            allReferencedTypes.Add(referencedType);
                        }

                        app.Classes.Add(container.FullName, container);
                    }

                    foreach (JavaClass javaClassContainer in app.Classes.Values)
                    {
                        allReferencedTypes.Remove(javaClassContainer.FullName);
                    }

                    List <string> allTypes = allReferencedTypes.ToList();
                    foreach (string type in allTypes)
                    {
                        if (type.StartsWith("java"))
                        {
                            allReferencedTypes.Remove(type);
                        }
                    }

                    foreach (string allReferencedType in allReferencedTypes)
                    {
                        Console.WriteLine(allReferencedType);
                    }

                    Console.WriteLine("Parsed all " + app.Classes.Count + " classes");
                }

                // Process files
                {
                    Queue <JavaClass> classQueue = new Queue <JavaClass>(app.Classes.Values);

                    int methodNum = 0;
                    int fieldNum  = 0;

                    while (classQueue.Any())
                    {
                        JavaClass currentClass = classQueue.Dequeue();

                        // Is waiting for super?
                        if (classQueue.Any(s => s.FullName == currentClass.SuperClass))
                        {
                            // Yes, requeue
                            classQueue.Enqueue(currentClass);
                            continue;
                        }

                        // Is waiting for interface?
                        if (classQueue.Any(s => currentClass.Interfaces.Any(x => x == s.FullName)))
                        {
                            // Yes, requeue
                            classQueue.Enqueue(currentClass);
                            continue;
                        }

                        // Process
                        if (app.Classes.ContainsKey(currentClass.SuperClass))
                        {
                            // Copy down fields / methods
                            JavaClass superClass = app.Classes[currentClass.SuperClass];

                            List <JavaMethod> superMethods = superClass.Methods.Where(s => !currentClass.Methods.Any(x => x.Name == s.Name && x.Type == s.Type)).ToList();
                            List <JavaField>  superFields  = superClass.Fields.Where(s => !currentClass.Fields.Any(x => x.Name == s.Name && x.Type == s.Type)).ToList();

                            foreach (JavaMethod method in superMethods)
                            {
                                JavaMethod newMethod = new JavaMethod(currentClass, method.Declaration);

                                currentClass.Methods.Add(newMethod);
                            }

                            foreach (JavaField field in superFields)
                            {
                                JavaField newField = new JavaField(currentClass, field.Declaration);

                                currentClass.Fields.Add(newField);
                            }
                        }

                        // Class name
                        if (ShouldRename(currentClass.Name))
                        {
                            // Rename class
                            app.ClassRenames.Add(currentClass.FullName, currentClass.FullName.Replace(currentClass.Name, "OrigClass_" + currentClass.Name));
                        }

                        // Method names
                        foreach (JavaMethod method in currentClass.Methods)
                        {
                            JavaMethod parentMethod = app.FindMethod(currentClass, method.Name, method.Type);

                            if (method.Name == "<init>" || method.Name == "<clinit>")
                            {
                                continue;
                            }

                            if (ShouldRename(parentMethod))
                            {
                                parentMethod.SetNewName("OrigMethod" + methodNum++);
                            }
                        }

                        // Field names
                        foreach (JavaField field in currentClass.Fields)
                        {
                            JavaField parentField = app.FindField(currentClass, field.Name, field.Type);

                            if (ShouldRename(parentField))
                            {
                                parentField.SetNewName("OrigField" + fieldNum++);
                            }
                        }
                    }

                    Console.WriteLine("Processed all " + app.Classes.Count + " classes");
                    Console.WriteLine("Total class renames: " + app.ClassRenames.Count);
                }

                // Rename fields and methods
                {
                    Console.WriteLine("Beginning rename pass 1");

                    // Actual renaming
                    foreach (JavaClass classContainer in app.Classes.Values)
                    {
                        string fileText = File.ReadAllText(classContainer.FileName);

                        // Method renames
                        // Single methods
                        foreach (JavaMethod method in classContainer.Methods)
                        {
                            JavaMethod parentMethod = app.FindMethod(classContainer, method.Name, method.Type);

                            if (!parentMethod.IsRenamed)
                            {
                                // No need for renaming
                                continue;
                            }

                            method.SetNewName(parentMethod.NewName);

                            string oldDec = method.Declaration;
                            string newDec = method.NewDeclaration;

                            fileText = fileText.Replace(oldDec, newDec);
                        }

                        // Field renames
                        // Single fields
                        foreach (JavaField field in classContainer.Fields)
                        {
                            JavaField parentField = app.FindField(classContainer, field.Name, field.Type);

                            if (!parentField.IsRenamed)
                            {
                                // No need for renaming
                                continue;
                            }

                            field.SetNewName(parentField.NewName);

                            string oldDec = field.Declaration;
                            string newDec = field.NewDeclaration;

                            fileText = fileText.Replace(oldDec, newDec);
                        }

                        File.WriteAllText(classContainer.FileName, fileText);
                    }

                    Console.WriteLine("Completed rename pass 1");

                    List <JavaMethod> allMethodRenames = app.Classes.Values.SelectMany(s => s.Methods.Where(x => x.IsRenamed)).ToList();
                    List <JavaField>  allFieldRenames  = app.Classes.Values.SelectMany(s => s.Fields.Where(x => x.IsRenamed)).ToList();

                    Console.WriteLine("Total method renames: " + allMethodRenames.Count);
                    Console.WriteLine("Total field renames: " + allFieldRenames.Count);

                    Console.WriteLine("Beginning rename pass 2");

                    foreach (JavaClass classContainer in app.Classes.Values)
                    {
                        string fileText = File.ReadAllText(classContainer.FileName);

                        // All other methods
                        foreach (JavaMethod method in allMethodRenames)
                        {
                            // Rename
                            List <string> typeSubstitutes = classContainer.Constants.Where(s => s.Value.Value == method.Type).Select(s => s.Key).ToList();
                            typeSubstitutes.Add(method.Type);

                            foreach (string typeSubstitute in typeSubstitutes)
                            {
                                string oldUsage = method.OwningClass.FullName + " " + method.Name + " " + typeSubstitute;
                                string newUsage = method.OwningClass.FullName + " " + method.NewName + " " + typeSubstitute;

                                fileText = fileText.Replace(oldUsage, newUsage);
                            }
                        }

                        // All other fields
                        foreach (JavaField field in allFieldRenames)
                        {
                            // Rename
                            List <string> typeSubstitutes = classContainer.Constants.Where(s => s.Value.Value == field.Type).Select(s => s.Key).ToList();
                            typeSubstitutes.Add(field.Type);

                            foreach (string typeSubstitute in typeSubstitutes)
                            {
                                string oldUsage = field.OwningClass.FullName + " " + field.Name + " " + typeSubstitute;
                                string newUsage = field.OwningClass.FullName + " " + field.NewName + " " + typeSubstitute;

                                fileText = fileText.Replace(oldUsage, newUsage);
                            }
                        }

                        File.WriteAllText(classContainer.FileName, fileText);
                    }

                    Console.WriteLine("Completed rename pass 2");
                }

                // Rename classes
                {
                    Console.WriteLine("Beginning class rename");

                    foreach (JavaClass classContainer in app.Classes.Values)
                    {
                        string fileText = File.ReadAllText(classContainer.FileName);

                        foreach (KeyValuePair <string, string> map in app.ClassRenames)
                        {
                            fileText = fileText.Replace(map.Key, map.Value);
                        }

                        File.WriteAllText(classContainer.FileName, fileText);
                    }

                    // Move files
                    foreach (KeyValuePair <string, string> map in app.ClassRenames)
                    {
                        File.Move(Path.Combine(dir, map.Key + ".j"), Path.Combine(dir, map.Value + ".j"));
                    }

                    Console.WriteLine("Completed class rename");
                }
            }

            // Replace string encryption
            // TODO: If you're not working with NemID, comment out the line below.
            DecryptStrings(dir);

            Console.WriteLine("All done.");
        }