├── App.ico ├── ChangeName.cs ├── JavaDeObfuscator.sln ├── AssemblyInfo.cs ├── ChangeName.Designer.cs ├── README ├── JavaDeObfuscator.csproj ├── ChangeName.resx ├── MainForm.resx ├── MainForm.cs ├── Common.cs └── Objects.cs /App.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fileoffset/JDO/HEAD/App.ico -------------------------------------------------------------------------------- /ChangeName.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Drawing; 6 | using System.Text; 7 | using System.Windows.Forms; 8 | 9 | namespace JavaDeObfuscator 10 | { 11 | public partial class ChangeName : Form 12 | { 13 | public ChangeName() 14 | { 15 | InitializeComponent(); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /JavaDeObfuscator.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 11.00 2 | # Visual Studio 2010 3 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JavaDeObfuscator", "JavaDeObfuscator.csproj", "{C36082EB-3218-4572-9AFF-3DF4187E1DDB}" 4 | EndProject 5 | Global 6 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 7 | Debug|Any CPU = Debug|Any CPU 8 | Release|Any CPU = Release|Any CPU 9 | EndGlobalSection 10 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 11 | {C36082EB-3218-4572-9AFF-3DF4187E1DDB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 12 | {C36082EB-3218-4572-9AFF-3DF4187E1DDB}.Debug|Any CPU.Build.0 = Debug|Any CPU 13 | {C36082EB-3218-4572-9AFF-3DF4187E1DDB}.Release|Any CPU.ActiveCfg = Release|Any CPU 14 | {C36082EB-3218-4572-9AFF-3DF4187E1DDB}.Release|Any CPU.Build.0 = Release|Any CPU 15 | EndGlobalSection 16 | GlobalSection(SolutionProperties) = preSolution 17 | HideSolutionNode = FALSE 18 | EndGlobalSection 19 | EndGlobal 20 | -------------------------------------------------------------------------------- /AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | 4 | // 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | // 9 | [assembly: AssemblyTitle("")] 10 | [assembly: AssemblyDescription("")] 11 | [assembly: AssemblyConfiguration("")] 12 | [assembly: AssemblyCompany("")] 13 | [assembly: AssemblyProduct("")] 14 | [assembly: AssemblyCopyright("")] 15 | [assembly: AssemblyTrademark("")] 16 | [assembly: AssemblyCulture("")] 17 | 18 | // 19 | // Version information for an assembly consists of the following four values: 20 | // 21 | // Major Version 22 | // Minor Version 23 | // Build Number 24 | // Revision 25 | // 26 | // You can specify all the values or you can default the Revision and Build Numbers 27 | // by using the '*' as shown below: 28 | 29 | [assembly: AssemblyVersion("1.0.*")] 30 | 31 | // 32 | // In order to sign your assembly you must specify a key to use. Refer to the 33 | // Microsoft .NET Framework documentation for more information on assembly signing. 34 | // 35 | // Use the attributes below to control which key is used for signing. 36 | // 37 | // Notes: 38 | // (*) If no key is specified, the assembly is not signed. 39 | // (*) KeyName refers to a key that has been installed in the Crypto Service 40 | // Provider (CSP) on your machine. KeyFile refers to a file which contains 41 | // a key. 42 | // (*) If the KeyFile and the KeyName values are both specified, the 43 | // following processing occurs: 44 | // (1) If the KeyName can be found in the CSP, that key is used. 45 | // (2) If the KeyName does not exist and the KeyFile does exist, the key 46 | // in the KeyFile is installed into the CSP and used. 47 | // (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility. 48 | // When specifying the KeyFile, the location of the KeyFile should be 49 | // relative to the project output directory which is 50 | // %Project Directory%\obj\. For example, if your KeyFile is 51 | // located in the project directory, you would specify the AssemblyKeyFile 52 | // attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")] 53 | // (*) Delay Signing is an advanced option - see the Microsoft .NET Framework 54 | // documentation for more information on this. 55 | // 56 | [assembly: AssemblyDelaySign(false)] 57 | [assembly: AssemblyKeyFile("")] 58 | [assembly: AssemblyKeyName("")] 59 | -------------------------------------------------------------------------------- /ChangeName.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace JavaDeObfuscator 2 | { 3 | partial class ChangeName 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.label1 = new System.Windows.Forms.Label(); 32 | this.SaveButton = new System.Windows.Forms.Button(); 33 | this.NameBox = new System.Windows.Forms.TextBox(); 34 | this.CancelButton = new System.Windows.Forms.Button(); 35 | this.SuspendLayout(); 36 | // 37 | // label1 38 | // 39 | this.label1.AutoSize = true; 40 | this.label1.Location = new System.Drawing.Point(11, 22); 41 | this.label1.Name = "label1"; 42 | this.label1.Size = new System.Drawing.Size(101, 13); 43 | this.label1.TabIndex = 0; 44 | this.label1.Text = "Component Name : "; 45 | // 46 | // SaveButton 47 | // 48 | this.SaveButton.DialogResult = System.Windows.Forms.DialogResult.OK; 49 | this.SaveButton.Location = new System.Drawing.Point(368, 45); 50 | this.SaveButton.Name = "SaveButton"; 51 | this.SaveButton.Size = new System.Drawing.Size(83, 24); 52 | this.SaveButton.TabIndex = 2; 53 | this.SaveButton.Text = "&Save"; 54 | this.SaveButton.UseVisualStyleBackColor = true; 55 | // 56 | // NameBox 57 | // 58 | this.NameBox.Location = new System.Drawing.Point(119, 19); 59 | this.NameBox.Name = "NameBox"; 60 | this.NameBox.Size = new System.Drawing.Size(334, 20); 61 | this.NameBox.TabIndex = 3; 62 | // 63 | // CancelButton 64 | // 65 | this.CancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; 66 | this.CancelButton.Location = new System.Drawing.Point(270, 45); 67 | this.CancelButton.Name = "CancelButton"; 68 | this.CancelButton.Size = new System.Drawing.Size(83, 24); 69 | this.CancelButton.TabIndex = 4; 70 | this.CancelButton.Text = "&Cancel"; 71 | this.CancelButton.UseVisualStyleBackColor = true; 72 | // 73 | // ChangeName 74 | // 75 | this.AcceptButton = this.SaveButton; 76 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 77 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 78 | this.ClientSize = new System.Drawing.Size(463, 78); 79 | this.Controls.Add(this.CancelButton); 80 | this.Controls.Add(this.NameBox); 81 | this.Controls.Add(this.SaveButton); 82 | this.Controls.Add(this.label1); 83 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow; 84 | this.Name = "ChangeName"; 85 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; 86 | this.Text = "Change Name..."; 87 | this.ResumeLayout(false); 88 | this.PerformLayout(); 89 | 90 | } 91 | 92 | #endregion 93 | 94 | private System.Windows.Forms.Label label1; 95 | private System.Windows.Forms.Button SaveButton; 96 | public System.Windows.Forms.TextBox NameBox; 97 | private new System.Windows.Forms.Button CancelButton; 98 | } 99 | } -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Java DeObfuscator (aka JDO) 2 | 3 | When reversing Java, you will invariably run up against a fairly common form of data obscuring techniques: obfuscated code. 4 | 5 | See, it goes like this: 6 | 7 | Java programs come in a 'class' format, which can be decompiled by decompilers like Jad and DJ Java Decompiler, which in the majority of cases produce extremely good replications of the original source code. Due to this, reversers (and well.. almost anyone really) could decompile Java program and poke through the entire source tree, often able to make changes and recompile the code for their own research. 8 | 9 | In came data obfuscation to the rescue! Not only does it make it more difficult to Reverse Engineer and decompile java applications, it also shrinks the size of the class. 10 | 11 | Data Obfuscation attempts to obscure and obfuscate the variable names, class names, method names, strings and sometimes even the actual byte code in an attempt to thwart decompilers. And some of them even work. 12 | 13 | Consider the following code, taken from a freely available (obfuscated) java library and decompiled with Jad: 14 | 15 | private static int _mthchar(int i1) 16 | { 17 | int j1 = 0; 18 | int k1 = (1 << i1) - 1; 19 | if(i1 > _fldchar) 20 | { 21 | i1 -= _fldchar; 22 | j1 = _fldnew[bL++] << i1 & k1; 23 | _fldchar = 32; 24 | } 25 | _fldchar -= i1; 26 | j1 |= _fldnew[bL] >> _fldchar & (1 << i1) - 1; 27 | j1 &= k1; 28 | return j1; 29 | } 30 | 31 | Due to Jad's solid engine, it is able to create correct code by prepending '_fld' to indicate the variable is a field and '_mth' to indicate its a method. A lesser decompiler may have got confused and produced garbled results or crashed, at the very least confusing the reader with interesting snippets of code like: 32 | 33 | private static int char(int i1) 34 | { 35 | int j1 = 0; 36 | int k1 = (1 << i1) - 1; 37 | if(i1 > char) 38 | { 39 | i1 -= char; 40 | j1 = new[bL++] << i1 & k1; 41 | char = 32; 42 | } 43 | char -= i1; 44 | j1 |= new[bL] >> char & (1 << i1) - 1; 45 | j1 &= k1; 46 | return j1; 47 | } 48 | 49 | As you can see this is not exactly easy to reverse! One gets stuck constantly backtracking, resolving variables, methods and classes to their proper variables instead of getting to the heart of the problem. Jad does well to make it a step easier with its extra labels but its still quite tiresome to reverse. Obfuscation is a fairly common method to "cheaply" thwart the impatient and slap-dash reverse engineers, but with patience anything can be unravelled. Fortunately JDO makes it that little bit easier. 50 | 51 | For example, this is the exact same method after running the class files through JDO: 52 | 53 | private static int sub_2374(int i) 54 | { 55 | int j = 0; 56 | int k = (1 << i) - 1; 57 | if(i > var_2354) 58 | { 59 | i -= var_2354; 60 | j = var_1dd4[var_234c++] << i & k; 61 | var_2354 = 32; 62 | } 63 | var_2354 -= i; 64 | j |= var_1dd4[var_234c] >> var_2354 & (1 << i) - 1; 65 | j &= k; 66 | return j; 67 | } 68 | 69 | As you can see the code structure does not change, but suddenly it seems that little bit easier to understand. 70 | 71 | Currently JDO does the following: 72 | - renames obfuscated methods, variables, constants and class names to be unique and more indicative of their type 73 | - propogates changes throughout the entire source tree (beta) 74 | - has an easy to use GUI 75 | - allow you to specify the name for a field, method and class (new feature!) 76 | 77 | Currently JDO does not do the following (but it might one day) 78 | - modify method bytecode in any way 79 | 80 | Instructions 81 | ------------ 82 | 83 | The program is easy to use. If you have a single .class file, u can simply open it and select [Deobfuscate] the file will be automatically deobfuscated and overwritten. 84 | 85 | However if you have references to other obfuscated files in the same project, they will not be properly deobfuscated (nor changes from one file propogated). So if you have a few files in your project (or a .jar file) simply: 86 | 87 | 1. Unzip the .jar to a temp directory (if your files didn't come in a .jar, skip this step) 88 | 2. Run JDO 89 | 3. Click the '...' button and Add all the class files to the project (including any in sub directories) 90 | 4. Repeat Step 3 until all class files from the project are listed in the display 91 | 5. Click [Deobfuscate] it should give you a successful message and all of the files will be automatically deobfuscated and overwritten 92 | 93 | Note: To specify the name that a method, field or class gets renamed to, simply right click the node in the tree, specify the new name and hit 'Save'. It will turn Blue in the display, this is to indicate that the field will be forced renamed on next deobfuscation. Fields or Methods displayed in Red indicate they will be auto-renamed on the next deobfuscation. 94 | 95 | Thats it! 96 | 97 | Comments and Suggestions 98 | ------------------------ 99 | 100 | Feel free to email any comments or suggestions or bugs or reversing info to me by reversing this: 101 | moc.tesffoelif (ta) odj 102 | 103 | -------------------------------------------------------------------------------- /JavaDeObfuscator.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Local 5 | 8.0.50727 6 | 2.0 7 | {C36082EB-3218-4572-9AFF-3DF4187E1DDB} 8 | Debug 9 | AnyCPU 10 | App.ico 11 | 12 | 13 | JavaDeObfuscator 14 | 15 | 16 | JScript 17 | Grid 18 | IE50 19 | false 20 | WinExe 21 | JavaDeObfuscator 22 | OnBuildSuccess 23 | JavaDeObfuscator.MainForm 24 | 25 | 26 | 27 | 28 | http://localhost/JavaDeObfuscator/ 29 | true 30 | Web 31 | true 32 | Foreground 33 | 7 34 | Days 35 | false 36 | false 37 | true 38 | 1.0.0.* 39 | true 40 | true 41 | v2.0 42 | 2.0 43 | 44 | 45 | bin\Debug\ 46 | false 47 | 285212672 48 | false 49 | 50 | 51 | DEBUG;TRACE 52 | 53 | 54 | true 55 | 4096 56 | false 57 | 58 | 59 | true 60 | false 61 | false 62 | false 63 | 2 64 | 65 | 66 | bin\Release\ 67 | false 68 | 285212672 69 | false 70 | 71 | 72 | TRACE 73 | 74 | 75 | false 76 | 4096 77 | false 78 | 79 | 80 | true 81 | false 82 | false 83 | false 84 | 4 85 | 86 | 87 | 88 | System 89 | 90 | 91 | System.Data 92 | 93 | 94 | System.Drawing 95 | 96 | 97 | 98 | System.Windows.Forms 99 | 100 | 101 | System.XML 102 | 103 | 104 | 105 | 106 | 107 | Code 108 | 109 | 110 | Form 111 | 112 | 113 | ChangeName.cs 114 | 115 | 116 | Code 117 | 118 | 119 | Form 120 | 121 | 122 | Code 123 | 124 | 125 | Designer 126 | ChangeName.cs 127 | 128 | 129 | MainForm.cs 130 | Designer 131 | 132 | 133 | 134 | 135 | False 136 | .NET Framework 2.0 Beta 137 | true 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | -------------------------------------------------------------------------------- /ChangeName.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /MainForm.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 17, 17 122 | 123 | 124 | 143, 17 125 | 126 | 127 | 37 128 | 129 | -------------------------------------------------------------------------------- /MainForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using System.Collections; 4 | using System.ComponentModel; 5 | using System.Windows.Forms; 6 | using System.IO; 7 | 8 | namespace JavaDeObfuscator 9 | { 10 | public class MainForm : System.Windows.Forms.Form 11 | { 12 | TDeObfuscator DeObfuscator = null; 13 | ArrayList Files = null; 14 | RenameDatabase RenameStore = null; 15 | 16 | private Label label1; 17 | private OpenFileDialog OpenFileDialog; 18 | private TextBox ClassFileTextBox; 19 | private Button ButtonFileBrowse; 20 | private TreeView TreeClassView; 21 | private Button ProcessButton; 22 | private ToolTip ToolTip; 23 | private CheckBox RenameClassCheckBox; 24 | private CheckBox SmartRenameMethods; 25 | private ProgressBar Progress; 26 | private TextBox txtOutput; 27 | private Button btnOutput; 28 | private Label label2; 29 | private FolderBrowserDialog dlgOutput; 30 | private CheckBox chkUseUniqueNums; 31 | private IContainer components; 32 | 33 | /// 34 | /// The main entry point for the application. 35 | /// 36 | [STAThread] 37 | static void Main() 38 | { 39 | Application.EnableVisualStyles(); 40 | Application.Run(new MainForm()); 41 | } 42 | 43 | 44 | public MainForm() 45 | { 46 | // 47 | // Required for Windows Form Designer support 48 | // 49 | InitializeComponent(); 50 | 51 | // 52 | // TODO: Add any constructor code after InitializeComponent call 53 | // 54 | } 55 | 56 | /// 57 | /// Clean up any resources being used. 58 | /// 59 | protected override void Dispose(bool disposing) 60 | { 61 | if (disposing) 62 | { 63 | if (components != null) 64 | { 65 | components.Dispose(); 66 | } 67 | } 68 | base.Dispose(disposing); 69 | } 70 | 71 | #region Windows Form Designer generated code 72 | /// 73 | /// Required method for Designer support - do not modify 74 | /// the contents of this method with the code editor. 75 | /// 76 | private void InitializeComponent() 77 | { 78 | this.components = new System.ComponentModel.Container(); 79 | this.ClassFileTextBox = new System.Windows.Forms.TextBox(); 80 | this.label1 = new System.Windows.Forms.Label(); 81 | this.ButtonFileBrowse = new System.Windows.Forms.Button(); 82 | this.TreeClassView = new System.Windows.Forms.TreeView(); 83 | this.OpenFileDialog = new System.Windows.Forms.OpenFileDialog(); 84 | this.ProcessButton = new System.Windows.Forms.Button(); 85 | this.ToolTip = new System.Windows.Forms.ToolTip(this.components); 86 | this.RenameClassCheckBox = new System.Windows.Forms.CheckBox(); 87 | this.SmartRenameMethods = new System.Windows.Forms.CheckBox(); 88 | this.Progress = new System.Windows.Forms.ProgressBar(); 89 | this.txtOutput = new System.Windows.Forms.TextBox(); 90 | this.btnOutput = new System.Windows.Forms.Button(); 91 | this.label2 = new System.Windows.Forms.Label(); 92 | this.dlgOutput = new System.Windows.Forms.FolderBrowserDialog(); 93 | this.chkUseUniqueNums = new System.Windows.Forms.CheckBox(); 94 | this.SuspendLayout(); 95 | // 96 | // ClassFileTextBox 97 | // 98 | this.ClassFileTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 99 | | System.Windows.Forms.AnchorStyles.Right))); 100 | this.ClassFileTextBox.Location = new System.Drawing.Point(82, 16); 101 | this.ClassFileTextBox.Name = "ClassFileTextBox"; 102 | this.ClassFileTextBox.Size = new System.Drawing.Size(448, 20); 103 | this.ClassFileTextBox.TabIndex = 0; 104 | // 105 | // label1 106 | // 107 | this.label1.AutoSize = true; 108 | this.label1.Location = new System.Drawing.Point(13, 20); 109 | this.label1.Name = "label1"; 110 | this.label1.Size = new System.Drawing.Size(57, 13); 111 | this.label1.TabIndex = 1; 112 | this.label1.Text = "Add Class:"; 113 | // 114 | // ButtonFileBrowse 115 | // 116 | this.ButtonFileBrowse.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); 117 | this.ButtonFileBrowse.Location = new System.Drawing.Point(532, 16); 118 | this.ButtonFileBrowse.Name = "ButtonFileBrowse"; 119 | this.ButtonFileBrowse.Size = new System.Drawing.Size(24, 20); 120 | this.ButtonFileBrowse.TabIndex = 1; 121 | this.ButtonFileBrowse.Text = "..."; 122 | this.ButtonFileBrowse.Click += new System.EventHandler(this.button1_Click); 123 | // 124 | // TreeClassView 125 | // 126 | this.TreeClassView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 127 | | System.Windows.Forms.AnchorStyles.Left) 128 | | System.Windows.Forms.AnchorStyles.Right))); 129 | this.TreeClassView.Font = new System.Drawing.Font("Courier New", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 130 | this.TreeClassView.Location = new System.Drawing.Point(8, 69); 131 | this.TreeClassView.Name = "TreeClassView"; 132 | this.TreeClassView.ShowNodeToolTips = true; 133 | this.TreeClassView.Size = new System.Drawing.Size(546, 330); 134 | this.TreeClassView.TabIndex = 4; 135 | this.TreeClassView.NodeMouseClick += new System.Windows.Forms.TreeNodeMouseClickEventHandler(this.TreeClassView_NodeMouseClick); 136 | // 137 | // OpenFileDialog 138 | // 139 | this.OpenFileDialog.Filter = "Class Files|*.class"; 140 | this.OpenFileDialog.Multiselect = true; 141 | // 142 | // ProcessButton 143 | // 144 | this.ProcessButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); 145 | this.ProcessButton.Location = new System.Drawing.Point(454, 405); 146 | this.ProcessButton.Name = "ProcessButton"; 147 | this.ProcessButton.Size = new System.Drawing.Size(100, 23); 148 | this.ProcessButton.TabIndex = 8; 149 | this.ProcessButton.Text = "Deobfuscate"; 150 | this.ProcessButton.Click += new System.EventHandler(this.ProcessButton_Click); 151 | // 152 | // ToolTip 153 | // 154 | this.ToolTip.IsBalloon = true; 155 | // 156 | // RenameClassCheckBox 157 | // 158 | this.RenameClassCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); 159 | this.RenameClassCheckBox.AutoSize = true; 160 | this.RenameClassCheckBox.Checked = true; 161 | this.RenameClassCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; 162 | this.RenameClassCheckBox.Location = new System.Drawing.Point(12, 409); 163 | this.RenameClassCheckBox.Name = "RenameClassCheckBox"; 164 | this.RenameClassCheckBox.Size = new System.Drawing.Size(105, 17); 165 | this.RenameClassCheckBox.TabIndex = 6; 166 | this.RenameClassCheckBox.Text = "Rename Classes"; 167 | // 168 | // SmartRenameMethods 169 | // 170 | this.SmartRenameMethods.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); 171 | this.SmartRenameMethods.AutoSize = true; 172 | this.SmartRenameMethods.Checked = true; 173 | this.SmartRenameMethods.CheckState = System.Windows.Forms.CheckState.Checked; 174 | this.SmartRenameMethods.Enabled = false; 175 | this.SmartRenameMethods.Location = new System.Drawing.Point(252, 410); 176 | this.SmartRenameMethods.Name = "SmartRenameMethods"; 177 | this.SmartRenameMethods.Size = new System.Drawing.Size(140, 17); 178 | this.SmartRenameMethods.TabIndex = 7; 179 | this.SmartRenameMethods.Text = "Smart Rename Methods"; 180 | // 181 | // Progress 182 | // 183 | this.Progress.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) 184 | | System.Windows.Forms.AnchorStyles.Right))); 185 | this.Progress.Location = new System.Drawing.Point(12, 433); 186 | this.Progress.Name = "Progress"; 187 | this.Progress.Size = new System.Drawing.Size(546, 15); 188 | this.Progress.Step = 1; 189 | this.Progress.TabIndex = 9; 190 | this.Progress.Visible = false; 191 | // 192 | // txtOutput 193 | // 194 | this.txtOutput.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 195 | | System.Windows.Forms.AnchorStyles.Right))); 196 | this.txtOutput.Location = new System.Drawing.Point(82, 43); 197 | this.txtOutput.Name = "txtOutput"; 198 | this.txtOutput.Size = new System.Drawing.Size(448, 20); 199 | this.txtOutput.TabIndex = 2; 200 | // 201 | // btnOutput 202 | // 203 | this.btnOutput.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); 204 | this.btnOutput.Location = new System.Drawing.Point(532, 43); 205 | this.btnOutput.Name = "btnOutput"; 206 | this.btnOutput.Size = new System.Drawing.Size(24, 20); 207 | this.btnOutput.TabIndex = 3; 208 | this.btnOutput.Text = "..."; 209 | this.btnOutput.Click += new System.EventHandler(this.btnOutput_Click); 210 | // 211 | // label2 212 | // 213 | this.label2.AutoSize = true; 214 | this.label2.Location = new System.Drawing.Point(12, 46); 215 | this.label2.Name = "label2"; 216 | this.label2.Size = new System.Drawing.Size(58, 13); 217 | this.label2.TabIndex = 23; 218 | this.label2.Text = "Output Dir:"; 219 | // 220 | // dlgOutput 221 | // 222 | this.dlgOutput.Description = "Select output folder"; 223 | // 224 | // chkUseUniqueNums 225 | // 226 | this.chkUseUniqueNums.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); 227 | this.chkUseUniqueNums.AutoSize = true; 228 | this.chkUseUniqueNums.Checked = true; 229 | this.chkUseUniqueNums.CheckState = System.Windows.Forms.CheckState.Checked; 230 | this.chkUseUniqueNums.Location = new System.Drawing.Point(123, 409); 231 | this.chkUseUniqueNums.Name = "chkUseUniqueNums"; 232 | this.chkUseUniqueNums.Size = new System.Drawing.Size(123, 17); 233 | this.chkUseUniqueNums.TabIndex = 7; 234 | this.chkUseUniqueNums.Text = "Use unique numbers"; 235 | // 236 | // MainForm 237 | // 238 | this.ClientSize = new System.Drawing.Size(565, 451); 239 | this.Controls.Add(this.label2); 240 | this.Controls.Add(this.txtOutput); 241 | this.Controls.Add(this.Progress); 242 | this.Controls.Add(this.chkUseUniqueNums); 243 | this.Controls.Add(this.SmartRenameMethods); 244 | this.Controls.Add(this.RenameClassCheckBox); 245 | this.Controls.Add(this.ProcessButton); 246 | this.Controls.Add(this.TreeClassView); 247 | this.Controls.Add(this.btnOutput); 248 | this.Controls.Add(this.ButtonFileBrowse); 249 | this.Controls.Add(this.label1); 250 | this.Controls.Add(this.ClassFileTextBox); 251 | this.Name = "MainForm"; 252 | this.Text = "Java DeObfuscator v1.6b2"; 253 | this.Load += new System.EventHandler(this.Form1_Load); 254 | this.ResumeLayout(false); 255 | this.PerformLayout(); 256 | 257 | } 258 | #endregion 259 | 260 | private void button1_Click(object sender, EventArgs e) 261 | { 262 | if (OpenFileDialog.ShowDialog() == DialogResult.OK) 263 | { 264 | if (Files == null) 265 | Files = new ArrayList(); 266 | 267 | foreach (String fn in OpenFileDialog.FileNames) 268 | { 269 | Files.Add(fn); 270 | } 271 | 272 | UpdateTree(); 273 | } 274 | } 275 | 276 | private void UpdateTree() 277 | { 278 | TreeClassView.Nodes.Clear(); 279 | 280 | DeObfuscator = new TDeObfuscator(Files); 281 | 282 | foreach (string fn in Files) 283 | { 284 | TClassFile ClassFile = new TClassFile(fn); 285 | 286 | if (!ClassFile.Open()) 287 | { 288 | TreeClassView.Nodes.Add("Invalid class file: " + fn); 289 | continue; 290 | } 291 | 292 | if (ClassFile != null) 293 | { 294 | TreeNode bigroot; 295 | 296 | // check if the user wants to rename the class file 297 | string original_class_name = ClassFile.ThisClassName + " : " + ClassFile.SuperClassName; 298 | string class_name = RenameStore.GetNewClassName(original_class_name); 299 | 300 | if (class_name == null) 301 | { 302 | class_name = original_class_name; 303 | bigroot = TreeClassView.Nodes.Add(class_name); 304 | } 305 | else 306 | { 307 | bigroot = TreeClassView.Nodes.Add(class_name); 308 | bigroot.BackColor = Color.DodgerBlue; 309 | } 310 | 311 | bigroot.Tag = original_class_name; 312 | 313 | TreeNode root = bigroot.Nodes.Add("Constants"); 314 | TreeNode methodsroot = root.Nodes.Add("Methods/Interfaces/Fields"); 315 | TreeNode methods = methodsroot.Nodes.Add("Methods"); 316 | TreeNode interfaces = methodsroot.Nodes.Add("Interfaces"); 317 | TreeNode fields = methodsroot.Nodes.Add("Fields"); 318 | TreeNode variables = root.Nodes.Add("Values"); 319 | TreeNode classes = root.Nodes.Add("Classes"); 320 | 321 | for (int i = 0; i < ClassFile.ConstantPool.MaxItems(); i++) 322 | { 323 | ConstantPoolInfo cc = ClassFile.ConstantPool.Item(i); 324 | 325 | if (cc is ConstantPoolMethodInfo) 326 | { 327 | if (cc is ConstantMethodrefInfo) 328 | { 329 | TreeNode temp = methods.Nodes.Add("\"" + ((ConstantMethodrefInfo)cc).NameAndType.Name + "\""); 330 | temp.Nodes.Add("Descriptor = " + ((ConstantMethodrefInfo)cc).NameAndType.Descriptor); 331 | temp.Nodes.Add("Parent = " + ((ConstantMethodrefInfo)cc).ParentClass.Name); 332 | 333 | if (DeObfuscator.DoRename(((ConstantMethodrefInfo)cc).NameAndType.Name)) 334 | temp.BackColor = Color.Red; 335 | 336 | continue; 337 | } 338 | 339 | if (cc is ConstantInterfaceMethodrefInfo) 340 | { 341 | TreeNode temp = interfaces.Nodes.Add("\"" + ((ConstantInterfaceMethodrefInfo)cc).NameAndType.Name + "\""); 342 | temp.Nodes.Add("Descriptor = " + ((ConstantInterfaceMethodrefInfo)cc).NameAndType.Descriptor); 343 | temp.Nodes.Add("Parent = " + ((ConstantInterfaceMethodrefInfo)cc).ParentClass.Name); 344 | 345 | if (DeObfuscator.DoRename(((ConstantInterfaceMethodrefInfo)cc).NameAndType.Name)) 346 | temp.BackColor = Color.Red; 347 | 348 | continue; 349 | } 350 | 351 | if (cc is ConstantFieldrefInfo) 352 | { 353 | TreeNode temp = fields.Nodes.Add("\"" + ((ConstantFieldrefInfo)cc).NameAndType.Name + "\""); 354 | temp.Nodes.Add("Descriptor = " + ((ConstantFieldrefInfo)cc).NameAndType.Descriptor); 355 | if (((ConstantFieldrefInfo)cc).ParentClass != null) 356 | temp.Nodes.Add("Parent = " + ((ConstantFieldrefInfo)cc).ParentClass.Name); 357 | 358 | if (DeObfuscator.DoRename(((ConstantFieldrefInfo)cc).NameAndType.Name)) 359 | temp.BackColor = Color.Red; 360 | 361 | continue; 362 | } 363 | } 364 | else 365 | if (cc is ConstantPoolVariableInfo) 366 | { 367 | TreeNode temp = variables.Nodes.Add("\"" + ((ConstantPoolVariableInfo)cc).Value.ToString() + "\""); 368 | temp.Nodes.Add("References = " + cc.References); 369 | } 370 | else 371 | if (cc is ConstantClassInfo) 372 | { 373 | TreeNode temp = classes.Nodes.Add("\"" + ((ConstantClassInfo)cc).Name + "\""); 374 | temp.Nodes.Add("References = " + cc.References); 375 | } 376 | } 377 | 378 | root = bigroot.Nodes.Add("Interfaces"); 379 | foreach (InterfaceInfo ii in ClassFile.Interfaces.Items) 380 | { 381 | root.Nodes.Add(ii.Interface.Name); 382 | } 383 | 384 | root = bigroot.Nodes.Add("Fields"); 385 | foreach (FieldInfo fi in ClassFile.Fields.Items) 386 | { 387 | RenameData rd = RenameStore.GetNewFieldInfo( 388 | original_class_name, 389 | fi.Descriptor, 390 | fi.Name.Value); 391 | if (rd != null) 392 | { 393 | TreeNode temp = root.Nodes.Add(rd.FieldName); 394 | temp.Nodes.Add(rd.FieldType); 395 | temp.BackColor = Color.DodgerBlue; 396 | } 397 | else 398 | { 399 | TreeNode temp = root.Nodes.Add(fi.Name.Value); 400 | temp.Nodes.Add(fi.Descriptor); 401 | temp.Tag = fi.Name.Value; 402 | 403 | if (DeObfuscator.DoRename(fi.Name.Value)) 404 | temp.BackColor = Color.Red; 405 | } 406 | } 407 | 408 | root = bigroot.Nodes.Add("Methods"); 409 | foreach (MethodInfo mi in ClassFile.Methods.Items) 410 | { 411 | RenameData rd = RenameStore.GetNewMethodInfo( 412 | original_class_name, 413 | mi.Descriptor, 414 | mi.Name.Value); 415 | if (rd != null) 416 | { 417 | TreeNode temp = root.Nodes.Add(rd.FieldName); 418 | temp.Nodes.Add(rd.FieldType); 419 | temp.BackColor = Color.DodgerBlue; 420 | } 421 | else 422 | { 423 | TreeNode temp = root.Nodes.Add(mi.Name.Value); 424 | temp.Nodes.Add(mi.Descriptor); 425 | temp.Tag = mi.Name.Value; 426 | //temp.Nodes.Add(String.Format("Offset = {0:X}", mi.Offset)); 427 | 428 | if (DeObfuscator.DoRename(mi.Name.Value)) 429 | temp.BackColor = Color.Red; 430 | } 431 | } 432 | } 433 | } 434 | } 435 | 436 | private void ProcessButton_Click(object sender, EventArgs e) 437 | { 438 | if (Files == null) 439 | return; 440 | 441 | if (!Directory.Exists(txtOutput.Text)) 442 | { 443 | MessageBox.Show("Output dir doesn't exists!", "Output", MessageBoxButtons.OK, MessageBoxIcon.Error); 444 | return; 445 | } 446 | 447 | 448 | DeObfuscator = new TDeObfuscator(Files); 449 | DeObfuscator.RenameClasses = RenameClassCheckBox.Checked; 450 | 451 | DeObfuscator.OutputDir = txtOutput.Text; 452 | DeObfuscator.UseUniqueNums = chkUseUniqueNums.Checked; 453 | 454 | Progress.Maximum = Files.Count; 455 | Progress.Visible = true; 456 | 457 | TDeObfuscator.Progress += new TDeObfuscator.ProgressHandler(OnProgress); 458 | 459 | // update the classfile with the new deobfuscated version 460 | ArrayList NewFileList = DeObfuscator.DeObfuscateAll(RenameStore); 461 | if (NewFileList != null) 462 | { 463 | MessageBox.Show("DeObfuscated everything ok!", "DeObfuscator"); 464 | Files = NewFileList; 465 | } 466 | else 467 | MessageBox.Show("Error!!!", "DeObfuscator"); 468 | 469 | Progress.Visible = false; 470 | RenameStore = new RenameDatabase(); 471 | UpdateTree(); 472 | } 473 | 474 | private void OnProgress(int progress) 475 | { 476 | // Progress 477 | if (progress > Progress.Maximum) 478 | Progress.Value = 0; 479 | 480 | Progress.Value = progress; 481 | } 482 | 483 | private void TreeClassView_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e) 484 | { 485 | // detect right click on a valid member to popup a 'change name' box. 486 | if (e.Button == MouseButtons.Right && e.Node.Parent != null && e.Node.Parent.Parent != null) 487 | { 488 | ChangeName FChangeName = new ChangeName(); 489 | FChangeName.NameBox.Text = e.Node.Text; 490 | // get the full path of the node we clicked on, so we have all the information 491 | // relating to it 492 | // get parentmost node 493 | TreeNode pn = e.Node; 494 | while (pn.Parent != null) 495 | { 496 | pn = pn.Parent; 497 | } 498 | 499 | // get trailing node 500 | TreeNode tn = e.Node; 501 | while (tn.Nodes.Count > 0) 502 | { 503 | tn = tn.Nodes[0]; 504 | } 505 | 506 | string class_name = pn.Tag.ToString(); // classname 507 | 508 | string[] sl = tn.FullPath.Split('\\'); 509 | string type = sl[1]; 510 | string old_name = tn.Parent.Tag.ToString(); 511 | 512 | if (class_name == null || type == null || 513 | old_name == null) 514 | { 515 | return; 516 | } 517 | 518 | // check which subsection we are in, so we can add it to the right list 519 | if ((type == "Methods" || type == "Fields") && // section 520 | (FChangeName.ShowDialog() == DialogResult.OK)) 521 | { 522 | string old_descriptor = sl[3]; 523 | 524 | if (old_descriptor == null) 525 | return; 526 | 527 | if (type == "Methods") 528 | { 529 | RenameStore.AddRenameMethod(class_name, old_descriptor, old_name, 530 | old_descriptor, FChangeName.NameBox.Text); 531 | } 532 | else if (type == "Fields") 533 | { 534 | RenameStore.AddRenameField(class_name, old_descriptor, old_name, 535 | old_descriptor, FChangeName.NameBox.Text); 536 | } 537 | 538 | // update the tree without reloading it 539 | tn.Parent.Text = FChangeName.NameBox.Text; 540 | tn.Parent.ToolTipText = "was '" + tn.Parent.Tag.ToString() + "'"; 541 | tn.Parent.BackColor = Color.DodgerBlue; 542 | } 543 | } 544 | else if (e.Button == MouseButtons.Right && e.Node.Parent == null) 545 | { 546 | ChangeName FChangeName = new ChangeName(); 547 | string[] s = e.Node.Text.Split(':'); 548 | 549 | string old_name = s[0].Trim(); 550 | string old_descriptor = s[1].Trim(); 551 | 552 | if (s.Length == 0) 553 | return; 554 | 555 | FChangeName.NameBox.Text = old_name; 556 | 557 | // change the class name, since its a root node 558 | if (FChangeName.ShowDialog() == DialogResult.OK) 559 | { 560 | string new_name_and_type = FChangeName.NameBox.Text + " : " + old_descriptor; 561 | RenameStore.AddRenameClass(e.Node.Tag.ToString(), new_name_and_type); 562 | 563 | e.Node.BackColor = Color.DodgerBlue; 564 | e.Node.Text = new_name_and_type; 565 | e.Node.ToolTipText = "was '" + e.Node.Tag.ToString() + "'"; 566 | } 567 | } 568 | } 569 | 570 | private void Form1_Load(object sender, EventArgs e) 571 | { 572 | RenameStore = new RenameDatabase(); 573 | } 574 | 575 | private void btnOutput_Click(object sender, EventArgs e) 576 | { 577 | if (dlgOutput.ShowDialog() == DialogResult.OK) 578 | { 579 | txtOutput.Text = dlgOutput.SelectedPath; 580 | } 581 | } 582 | 583 | 584 | } 585 | } 586 | -------------------------------------------------------------------------------- /Common.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.IO; 4 | using System.Text; 5 | 6 | namespace JavaDeObfuscator 7 | { 8 | // important enums 9 | enum AccessFlags 10 | { 11 | ACC_PUBLIC = 0x0001, 12 | ACC_FINAL = 0x0010, 13 | ACC_SUPER = 0x0020, 14 | ACC_INTERFACE = 0x0200, 15 | ACC_ABSTRACT = 0x0400 16 | } 17 | 18 | enum FieldAccessFlags 19 | { 20 | ACC_PUBLIC = 0x0001, // Declared public; may be accessed from outside its package. 21 | ACC_PRIVATE = 0x0002, // Declared private; usable only within the defining class. 22 | ACC_PROTECTED = 0x0004, // Declared protected; may be accessed within subclasses. 23 | ACC_STATIC = 0x0008, // Declared static. 24 | ACC_FINAL = 0x0010, // Declared final; no further assignment after initialization. 25 | ACC_VOLATILE = 0x0040, // Declared volatile; cannot be cached. 26 | ACC_TRANSIENT = 0x0080 // Declared transient; not written or read by a persistent object manager. 27 | } 28 | 29 | enum ConstantPoolInfoTag 30 | { 31 | ConstantClass = 7, 32 | ConstantFieldref = 9, 33 | ConstantMethodref = 10, 34 | ConstantInterfaceMethodref = 11, 35 | ConstantString = 8, 36 | ConstantInteger = 3, 37 | ConstantFloat = 4 , 38 | ConstantLong = 5, 39 | ConstantDouble = 6, 40 | ConstantNameAndType = 12, 41 | ConstantUtf8 = 1 42 | } 43 | 44 | struct AttributeType 45 | { 46 | public const string ConstantValue = "ConstantValue"; 47 | public const string Code = "Code"; 48 | public const string Exceptions = "Exceptions"; 49 | public const string InnerClasses = "InnerClasses"; 50 | public const string Synthetic = "Synthetic"; 51 | public const string SourceFile = "SourceFile"; 52 | public const string LineNumberTable = "LineNumberTable"; 53 | public const string LocalVariableTable = "LocalVariableTable"; 54 | public const string Deprecated = "Deprecated"; 55 | } 56 | 57 | // ******************************************************************************** // 58 | // ************************* CONSTANT POOL STRUCTURES ***************************** // 59 | // ******************************************************************************** // 60 | 61 | abstract class ConstantPoolInfo 62 | { 63 | public byte Tag; 64 | public int References; 65 | public abstract bool Read(byte tag, BinaryReader Reader); 66 | public abstract bool Resolve(ArrayList FItems); 67 | } 68 | abstract class ConstantPoolMethodInfo : ConstantPoolInfo 69 | { 70 | public ConstantClassInfo ParentClass; 71 | public ConstantNameAndTypeInfo NameAndType; 72 | //private ushort ClassIndex; 73 | //private ushort NameAndTypeIndex; 74 | 75 | public abstract void SetNameAndType(ushort Index, TConstantPool ConstantPool); 76 | public abstract void SetParent(ushort Index, TConstantPool ConstantPool); 77 | } 78 | abstract class ConstantPoolVariableInfo : ConstantPoolInfo 79 | { 80 | public Object Value; 81 | } 82 | class ConstantClassInfo : ConstantPoolInfo 83 | { 84 | public ushort NameIndex; 85 | public string Name; 86 | 87 | public ConstantClassInfo() 88 | { 89 | Name = ""; 90 | NameIndex = 0; 91 | Tag = (byte) ConstantPoolInfoTag.ConstantClass; 92 | References = 0; 93 | } 94 | public override bool Read(byte tag, BinaryReader Reader) 95 | { 96 | try 97 | { 98 | Tag = tag; 99 | NameIndex = Common.ReadWord(Reader); 100 | NameIndex--; 101 | return true; 102 | } 103 | catch (Exception e) 104 | { 105 | return false; 106 | } 107 | } 108 | public void Write(BinaryWriter Writer) 109 | { 110 | // write the tag 111 | Common.WriteByte(Writer, Tag); 112 | Common.WriteWord(Writer, NameIndex + 1); 113 | } 114 | public override bool Resolve(ArrayList FItems) 115 | { 116 | // use the index into the constant pool table 117 | // to find our UTF8 encoded class or interface name 118 | if (NameIndex < FItems.Count) 119 | { 120 | Object o = FItems[NameIndex]; 121 | if (o is ConstantUtf8Info) 122 | { 123 | Name = Encoding.UTF8.GetString(((ConstantUtf8Info)o).Bytes); 124 | ((ConstantPoolInfo)o).References++; 125 | 126 | return true; 127 | } 128 | } 129 | 130 | return false; 131 | } 132 | public void SetName(ushort Index, TConstantPool ConstantPool) 133 | { 134 | NameIndex = Index; 135 | Name = ((ConstantUtf8Info)ConstantPool.Item(Index)).Value; 136 | References++; 137 | } 138 | } 139 | class ConstantFieldrefInfo : ConstantPoolMethodInfo 140 | { 141 | private ushort ClassIndex; 142 | private ushort NameAndTypeIndex; 143 | 144 | public override bool Read(byte tag, BinaryReader Reader) 145 | { 146 | try 147 | { 148 | Tag = tag; 149 | ClassIndex = Common.ReadWord(Reader); 150 | NameAndTypeIndex = Common.ReadWord(Reader); 151 | ClassIndex--; 152 | NameAndTypeIndex--; 153 | return true; 154 | } 155 | catch (Exception e) 156 | { 157 | return false; 158 | } 159 | } 160 | public void Write(BinaryWriter Writer) 161 | { 162 | // write the tag 163 | Common.WriteByte(Writer, Tag); 164 | Common.WriteWord(Writer, ClassIndex + 1); 165 | Common.WriteWord(Writer, NameAndTypeIndex + 1); 166 | } 167 | public override bool Resolve(ArrayList FItems) 168 | { 169 | // use the index into the constant pool table 170 | // to find our UTF8 encoded class or interface name 171 | if (ClassIndex < FItems.Count && NameAndTypeIndex < FItems.Count) 172 | { 173 | Object o = FItems[ClassIndex]; 174 | if (o is ConstantClassInfo) 175 | { 176 | ParentClass = (ConstantClassInfo) o; 177 | ((ConstantPoolInfo)o).References++; 178 | } 179 | 180 | o = FItems[NameAndTypeIndex]; 181 | if (o is ConstantNameAndTypeInfo) 182 | { 183 | NameAndType = (ConstantNameAndTypeInfo) o; 184 | ((ConstantPoolInfo)o).References++; 185 | } 186 | 187 | return true; 188 | } 189 | 190 | return false; 191 | } 192 | public override void SetNameAndType(ushort Index, TConstantPool ConstantPool) 193 | { 194 | NameAndTypeIndex = Index; 195 | NameAndType = (ConstantNameAndTypeInfo)ConstantPool.Item(Index); 196 | NameAndType.References++; 197 | } 198 | public override void SetParent(ushort Index, TConstantPool ConstantPool) 199 | { 200 | ClassIndex = Index; 201 | ParentClass = (ConstantClassInfo)ConstantPool.Item(Index); 202 | ParentClass.References++; 203 | } 204 | } 205 | class ConstantMethodrefInfo : ConstantPoolMethodInfo 206 | { 207 | private ushort ClassIndex; 208 | private ushort NameAndTypeIndex; 209 | 210 | public override bool Read(byte tag, BinaryReader Reader) 211 | { 212 | try 213 | { 214 | Tag = tag; 215 | ClassIndex = Common.ReadWord(Reader); 216 | NameAndTypeIndex = Common.ReadWord(Reader); 217 | ClassIndex--; 218 | NameAndTypeIndex--; 219 | return true; 220 | } 221 | catch (Exception e) 222 | { 223 | return false; 224 | } 225 | } 226 | public void Write(BinaryWriter Writer) 227 | { 228 | // write the tag 229 | Common.WriteByte(Writer, Tag); 230 | Common.WriteWord(Writer, ClassIndex + 1); 231 | Common.WriteWord(Writer, NameAndTypeIndex + 1); 232 | } 233 | public override bool Resolve(ArrayList FItems) 234 | { 235 | // use the index into the constant pool table 236 | // to find our UTF8 encoded class or interface name 237 | if (ClassIndex < FItems.Count && NameAndTypeIndex < FItems.Count) 238 | { 239 | Object o = FItems[ClassIndex]; 240 | if (o is ConstantClassInfo) 241 | { 242 | ParentClass = (ConstantClassInfo) o; 243 | ((ConstantPoolInfo)o).References++; 244 | } 245 | 246 | o = FItems[NameAndTypeIndex]; 247 | if (o is ConstantNameAndTypeInfo) 248 | { 249 | NameAndType = (ConstantNameAndTypeInfo) o; 250 | ((ConstantPoolInfo)o).References++; 251 | } 252 | 253 | return true; 254 | } 255 | 256 | return false; 257 | } 258 | public override void SetNameAndType(ushort Index, TConstantPool ConstantPool) 259 | { 260 | NameAndTypeIndex = Index; 261 | NameAndType = (ConstantNameAndTypeInfo)ConstantPool.Item(Index); 262 | NameAndType.References++; 263 | } 264 | public override void SetParent(ushort Index, TConstantPool ConstantPool) 265 | { 266 | ClassIndex = Index; 267 | ParentClass = (ConstantClassInfo)ConstantPool.Item(Index); 268 | ParentClass.References++; 269 | } 270 | } 271 | class ConstantInterfaceMethodrefInfo : ConstantPoolMethodInfo 272 | { 273 | private ushort ClassIndex; 274 | private ushort NameAndTypeIndex; 275 | 276 | public override bool Read(byte tag, BinaryReader Reader) 277 | { 278 | try 279 | { 280 | Tag = tag; 281 | ClassIndex = Common.ReadWord(Reader); 282 | NameAndTypeIndex = Common.ReadWord(Reader); 283 | ClassIndex--; 284 | NameAndTypeIndex--; 285 | return true; 286 | } 287 | catch (Exception e) 288 | { 289 | return false; 290 | } 291 | } 292 | public void Write(BinaryWriter Writer) 293 | { 294 | // write the tag 295 | Common.WriteByte(Writer, Tag); 296 | Common.WriteWord(Writer, ClassIndex + 1); 297 | Common.WriteWord(Writer, NameAndTypeIndex + 1); 298 | } 299 | public override bool Resolve(ArrayList FItems) 300 | { 301 | // use the index into the constant pool table 302 | // to find our UTF8 encoded class or interface name 303 | if (ClassIndex <= FItems.Count && NameAndTypeIndex <= FItems.Count) 304 | { 305 | Object o = FItems[ClassIndex]; 306 | if (o is ConstantClassInfo) 307 | { 308 | ParentClass = (ConstantClassInfo) o; 309 | ((ConstantPoolInfo)o).References++; 310 | } 311 | 312 | o = FItems[NameAndTypeIndex]; 313 | if (o is ConstantNameAndTypeInfo) 314 | { 315 | NameAndType = (ConstantNameAndTypeInfo) o; 316 | ((ConstantPoolInfo)o).References++; 317 | } 318 | 319 | return true; 320 | } 321 | 322 | return false; 323 | } 324 | public override void SetNameAndType(ushort Index, TConstantPool ConstantPool) 325 | { 326 | NameAndTypeIndex = Index; 327 | } 328 | public override void SetParent(ushort Index, TConstantPool ConstantPool) 329 | { 330 | ClassIndex = Index; 331 | } 332 | } 333 | class ConstantStringInfo : ConstantPoolVariableInfo 334 | { 335 | private ushort NameIndex; 336 | 337 | public ConstantStringInfo() 338 | { 339 | NameIndex = 0; 340 | Value = ""; 341 | } 342 | 343 | public override bool Read(byte tag, BinaryReader Reader) 344 | { 345 | try 346 | { 347 | Tag = tag; 348 | NameIndex = Common.ReadWord(Reader); 349 | NameIndex--; 350 | return true; 351 | } 352 | catch (Exception e) 353 | { 354 | return false; 355 | } 356 | } 357 | public void Write(BinaryWriter Writer) 358 | { 359 | // write the tag 360 | Common.WriteByte(Writer, Tag); 361 | Common.WriteWord(Writer, NameIndex + 1); 362 | } 363 | public override bool Resolve(ArrayList FItems) 364 | { 365 | // use the index into the constant pool table 366 | // to find our UTF8 encoded class or interface name 367 | if (NameIndex < FItems.Count) 368 | { 369 | Object o = FItems[NameIndex]; 370 | if (o is ConstantUtf8Info) 371 | { 372 | Value = Encoding.UTF8.GetString(((ConstantUtf8Info)o).Bytes); 373 | ((ConstantPoolInfo)o).References++; 374 | 375 | return true; 376 | } 377 | } 378 | 379 | return false; 380 | } 381 | } 382 | class ConstantIntegerInfo : ConstantPoolVariableInfo 383 | { 384 | private uint Bytes; 385 | 386 | public override bool Read(byte tag, BinaryReader Reader) 387 | { 388 | try 389 | { 390 | Tag = tag; 391 | Bytes = Common.ReadDWord(Reader); 392 | return true; 393 | } 394 | catch (Exception e) 395 | { 396 | return false; 397 | } 398 | } 399 | public void Write(BinaryWriter Writer) 400 | { 401 | // write the tag 402 | Common.WriteByte(Writer, Tag); 403 | Common.WriteDWord(Writer, Bytes); 404 | } 405 | public override bool Resolve(ArrayList FItems) 406 | { 407 | Value = (int) Bytes; 408 | return true; 409 | } 410 | } 411 | class ConstantFloatInfo : ConstantPoolVariableInfo 412 | { 413 | private uint Bytes; 414 | 415 | public override bool Read(byte tag, BinaryReader Reader) 416 | { 417 | try 418 | { 419 | Tag = tag; 420 | Bytes = Common.ReadDWord(Reader); 421 | return true; 422 | } 423 | catch (Exception e) 424 | { 425 | return false; 426 | } 427 | } 428 | public void Write(BinaryWriter Writer) 429 | { 430 | // write the tag 431 | Common.WriteByte(Writer, Tag); 432 | Common.WriteDWord(Writer, Bytes); 433 | } 434 | public override bool Resolve(ArrayList FItems) 435 | { 436 | Value = Convert.ToSingle(Bytes); 437 | return true; 438 | } 439 | } 440 | class ConstantLongInfo : ConstantPoolVariableInfo 441 | { 442 | private uint HighBytes; 443 | private uint LowBytes; 444 | 445 | public override bool Read(byte tag, BinaryReader Reader) 446 | { 447 | try 448 | { 449 | Tag = tag; 450 | HighBytes = Common.ReadDWord(Reader); 451 | LowBytes = Common.ReadDWord(Reader); 452 | Value = ((long)HighBytes << 32) + LowBytes; 453 | return true; 454 | } 455 | catch (Exception e) 456 | { 457 | Value = "ERROR_GETTING_LONG"; 458 | return true; 459 | } 460 | } 461 | public void Write(BinaryWriter Writer) 462 | { 463 | // write the tag 464 | Common.WriteByte(Writer, Tag); 465 | Common.WriteDWord(Writer, HighBytes); 466 | Common.WriteDWord(Writer, LowBytes); 467 | } 468 | public override bool Resolve(ArrayList FItems) 469 | { 470 | return true; 471 | } 472 | } 473 | class ConstantDoubleInfo : ConstantPoolVariableInfo 474 | { 475 | private uint HighBytes; 476 | private uint LowBytes; 477 | 478 | public override bool Read(byte tag, BinaryReader Reader) 479 | { 480 | try 481 | { 482 | Tag = tag; 483 | HighBytes = Common.ReadDWord(Reader); 484 | LowBytes = Common.ReadDWord(Reader); 485 | Value = "NOT_IMPLEMENTED"; 486 | return true; 487 | } 488 | catch (Exception e) 489 | { 490 | Value = "ERROR_GETTING_DOUBLE"; 491 | return false; 492 | } 493 | } 494 | public void Write(BinaryWriter Writer) 495 | { 496 | // write the tag 497 | Common.WriteByte(Writer, Tag); 498 | Common.WriteDWord(Writer, HighBytes); 499 | Common.WriteDWord(Writer, LowBytes); 500 | } 501 | public override bool Resolve(ArrayList FItems) 502 | { 503 | Value = Convert.ToDouble(((long)HighBytes << 32) + LowBytes); 504 | return true; 505 | } 506 | } 507 | class ConstantNameAndTypeInfo : ConstantPoolInfo 508 | { 509 | private ushort FNameIndex; 510 | private ushort FDescriptorIndex; 511 | public string Name; 512 | public string Descriptor; 513 | 514 | public ConstantNameAndTypeInfo() 515 | { 516 | Tag = (byte) ConstantPoolInfoTag.ConstantNameAndType; 517 | FNameIndex = 0; 518 | FDescriptorIndex = 0; 519 | Name = ""; 520 | Descriptor = ""; 521 | } 522 | public ConstantNameAndTypeInfo(ushort IndexName, ushort IndexType, TConstantPool ConstantPool) 523 | { 524 | Tag = (byte)ConstantPoolInfoTag.ConstantNameAndType; 525 | FNameIndex = IndexName; 526 | FDescriptorIndex = IndexType; 527 | Name = Encoding.UTF8.GetString(((ConstantUtf8Info)ConstantPool.Item(IndexName)).Bytes); 528 | ConstantPool.Item(IndexName).References++; 529 | Descriptor = Encoding.UTF8.GetString(((ConstantUtf8Info)ConstantPool.Item(IndexType)).Bytes); 530 | ConstantPool.Item(IndexType).References++; 531 | } 532 | public void SetName(ushort Index, TConstantPool ConstantPool) 533 | { 534 | // where index is a valid index into the constant pool table 535 | FNameIndex = Index; 536 | Name = Encoding.UTF8.GetString(((ConstantUtf8Info)ConstantPool.Item(Index)).Bytes); 537 | ConstantPool.Item(Index).References++; 538 | } 539 | public void SetType(ushort Index, TConstantPool ConstantPool) 540 | { 541 | // where index is a valid index into the constant pool table 542 | FDescriptorIndex = Index; 543 | Descriptor = Encoding.UTF8.GetString(((ConstantUtf8Info)ConstantPool.Item(Index)).Bytes); 544 | ConstantPool.Item(Index).References++; 545 | } 546 | public override bool Read(byte tag, BinaryReader Reader) 547 | { 548 | try 549 | { 550 | Tag = tag; 551 | FNameIndex = Common.ReadWord(Reader); 552 | FNameIndex--; 553 | FDescriptorIndex = Common.ReadWord(Reader); 554 | FDescriptorIndex--; 555 | return true; 556 | } 557 | catch (Exception e) 558 | { 559 | return false; 560 | } 561 | } 562 | public void Write(BinaryWriter Writer) 563 | { 564 | // write the tag 565 | Common.WriteByte(Writer, Tag); 566 | Common.WriteWord(Writer, FNameIndex + 1); 567 | Common.WriteWord(Writer, FDescriptorIndex + 1); 568 | } 569 | public override bool Resolve(ArrayList FItems) 570 | { 571 | try 572 | { 573 | Name = null; 574 | 575 | if (FNameIndex < FItems.Count) 576 | { 577 | Object o = FItems[FNameIndex]; 578 | if (o is ConstantUtf8Info) 579 | { 580 | Name = Encoding.UTF8.GetString(((ConstantUtf8Info)o).Bytes); 581 | ((ConstantPoolInfo)o).References++; 582 | } 583 | } 584 | 585 | } 586 | catch (Exception e) 587 | { 588 | if (Name == null) 589 | Name = "Error retrieving Name!"; 590 | } 591 | 592 | try 593 | { 594 | Descriptor = null; 595 | 596 | if (FDescriptorIndex < FItems.Count) 597 | { 598 | Object o = FItems[FDescriptorIndex]; 599 | if (o is ConstantUtf8Info) 600 | { 601 | Descriptor = Encoding.UTF8.GetString(((ConstantUtf8Info)o).Bytes); 602 | ((ConstantPoolInfo)o).References++; 603 | } 604 | } 605 | } 606 | catch (Exception e) 607 | { 608 | if (Descriptor == null) 609 | Descriptor = "Error retrieving Descriptor!"; 610 | } 611 | 612 | return true; 613 | } 614 | public ushort NameIndex 615 | { 616 | get 617 | { 618 | return FNameIndex; 619 | } 620 | } 621 | public ushort TypeIndex 622 | { 623 | get 624 | { 625 | return FDescriptorIndex; 626 | } 627 | } 628 | } 629 | class ConstantUtf8Info : ConstantPoolInfo 630 | { 631 | public ushort Length; 632 | public byte[] Bytes; 633 | public string Value; 634 | 635 | public ConstantUtf8Info() 636 | { 637 | Bytes = null; 638 | Length = 0; 639 | Tag = (byte) ConstantPoolInfoTag.ConstantUtf8; 640 | References = 0; 641 | } 642 | public ConstantUtf8Info(string Text) 643 | { 644 | Tag = (byte) ConstantPoolInfoTag.ConstantUtf8; 645 | Bytes = UTF8Encoding.UTF8.GetBytes(Text); 646 | Length = (ushort) Bytes.Length; 647 | Value = Encoding.UTF8.GetString(Bytes); 648 | } 649 | public void SetName(string Text) 650 | { 651 | Bytes = UTF8Encoding.UTF8.GetBytes(Text); 652 | Length = (ushort)Bytes.Length; 653 | Value = Encoding.UTF8.GetString(Bytes); 654 | } 655 | public override bool Read(byte tag, BinaryReader Reader) 656 | { 657 | try 658 | { 659 | Tag = tag; 660 | Length = Common.ReadWord(Reader); 661 | Bytes = Reader.ReadBytes(Length); 662 | 663 | Value = Encoding.UTF8.GetString(Bytes); 664 | return true; 665 | } 666 | catch (Exception e) 667 | { 668 | return false; 669 | } 670 | } 671 | public void Write(BinaryWriter Writer) 672 | { 673 | // write the tag 674 | Common.WriteByte(Writer, Tag); 675 | Common.WriteWord(Writer, Length); 676 | Writer.Write(Bytes); 677 | } 678 | public override bool Resolve(ArrayList FItems) 679 | { 680 | return true; 681 | } 682 | } 683 | 684 | // ******************************************************************************** // 685 | // ***************************** FIELD STRUCTURES ********************************* // 686 | // ******************************************************************************** // 687 | 688 | class FieldInfo 689 | { 690 | ushort FAccessFlags; 691 | ushort FNameIndex; 692 | ushort FDescriptorIndex; 693 | ConstantUtf8Info FName; 694 | ConstantUtf8Info FDescriptor; 695 | TAttributes FAttributes; 696 | // my vars 697 | long FOffset; 698 | 699 | public FieldInfo(BinaryReader Reader, TConstantPool ConstantPool) 700 | { 701 | FAccessFlags = 0; 702 | FNameIndex = 0; 703 | FDescriptorIndex = 0; 704 | FName = null; 705 | FDescriptor = null; 706 | FAttributes = null; 707 | FOffset = 0; 708 | 709 | try 710 | { 711 | FOffset = Reader.BaseStream.Position; 712 | FAccessFlags = Common.ReadWord(Reader); 713 | FNameIndex = Common.ReadWord(Reader); 714 | FNameIndex--; 715 | FDescriptorIndex = Common.ReadWord(Reader); 716 | FDescriptorIndex--; 717 | // resolve the references 718 | FDescriptor = (ConstantUtf8Info)ConstantPool.Item(FDescriptorIndex); 719 | FDescriptor.References++; 720 | FName = (ConstantUtf8Info)ConstantPool.Item(FNameIndex); 721 | FName.References++; 722 | // Attributes should be able to handle any/all attribute streams 723 | FAttributes = new TAttributes(Reader, ConstantPool); 724 | } 725 | catch (Exception e) 726 | { 727 | // do nothing for now 728 | } 729 | } 730 | public void SetName(ushort index, TConstantPool ConstantPool) 731 | { 732 | FNameIndex = index; 733 | FName = (ConstantUtf8Info)ConstantPool.Item(FNameIndex); 734 | FName.References++; 735 | } 736 | public ConstantUtf8Info Name 737 | { 738 | get 739 | { 740 | return FName; 741 | } 742 | } 743 | public void Write(BinaryWriter Writer) 744 | { 745 | try 746 | { 747 | FOffset = Writer.BaseStream.Position; 748 | Common.WriteWord(Writer, FAccessFlags); 749 | Common.WriteWord(Writer, FNameIndex + 1); 750 | Common.WriteWord(Writer, FDescriptorIndex + 1); 751 | 752 | // Attributes should be able to handle any/all attribute streams 753 | FAttributes.Write(Writer); 754 | } 755 | catch (Exception e) 756 | { 757 | // do nothing for now 758 | } 759 | } 760 | public string Descriptor 761 | { 762 | get 763 | { 764 | return FDescriptor.Value; 765 | } 766 | } 767 | public ushort NameIndex 768 | { 769 | get 770 | { 771 | return FNameIndex; 772 | } 773 | } 774 | public TAttributes Attributes 775 | { 776 | get 777 | { 778 | return FAttributes; 779 | } 780 | } 781 | public long Offset 782 | { 783 | get 784 | { 785 | return FOffset; 786 | } 787 | } 788 | public FieldInfo Clone() 789 | { 790 | return (FieldInfo) MemberwiseClone(); 791 | } 792 | public void SetType(ushort index, TConstantPool ConstantPool) 793 | { 794 | FDescriptorIndex = index; 795 | FDescriptor = (ConstantUtf8Info)ConstantPool.Item(FDescriptorIndex); 796 | FDescriptor.References++; 797 | } 798 | } 799 | 800 | // ******************************************************************************** // 801 | // *************************** METHODINFO STRUCTURES ****************************** // 802 | // ******************************************************************************** // 803 | 804 | class MethodInfo 805 | { 806 | ushort FAccessFlags; 807 | ushort FNameIndex; 808 | ushort FDescriptorIndex; 809 | ConstantUtf8Info FName; 810 | ConstantUtf8Info FDescriptor; 811 | TAttributes FAttributes; 812 | 813 | public MethodInfo(BinaryReader Reader, TConstantPool ConstantPool) 814 | { 815 | FAccessFlags = 0; 816 | FNameIndex = 0; 817 | FDescriptorIndex = 0; 818 | FName = null; 819 | FDescriptor = null; 820 | FAttributes = null; 821 | 822 | try 823 | { 824 | FAccessFlags = Common.ReadWord(Reader); 825 | FNameIndex = Common.ReadWord(Reader); 826 | FNameIndex--; 827 | FDescriptorIndex = Common.ReadWord(Reader); 828 | FDescriptorIndex--; 829 | // resolve the references 830 | FDescriptor = (ConstantUtf8Info)ConstantPool.Item(FDescriptorIndex); 831 | FName = (ConstantUtf8Info)ConstantPool.Item(FNameIndex); 832 | FDescriptor.References++; 833 | FName.References++; 834 | // Attributes should be able to handle any/all attribute streams 835 | FAttributes = new TAttributes(Reader, ConstantPool); 836 | } 837 | catch (Exception e) 838 | { 839 | // do nothing for now 840 | } 841 | } 842 | public void SetName(ushort index, TConstantPool ConstantPool) 843 | { 844 | FNameIndex = index; 845 | FName = (ConstantUtf8Info)ConstantPool.Item(FNameIndex); 846 | FName.References++; 847 | } 848 | public void Write(BinaryWriter Writer) 849 | { 850 | try 851 | { 852 | Common.WriteWord(Writer, FAccessFlags); 853 | Common.WriteWord(Writer, FNameIndex + 1); 854 | Common.WriteWord(Writer, FDescriptorIndex + 1); 855 | 856 | // Attributes should be able to handle any/all attribute streams 857 | FAttributes.Write(Writer); 858 | } 859 | catch (Exception e) 860 | { 861 | // do nothing for now 862 | } 863 | } 864 | public ConstantUtf8Info Name 865 | { 866 | get 867 | { 868 | return FName; 869 | } 870 | } 871 | public string Descriptor 872 | { 873 | get 874 | { 875 | return FDescriptor.Value; 876 | } 877 | } 878 | public TAttributes Attributes 879 | { 880 | get 881 | { 882 | return FAttributes; 883 | } 884 | } 885 | public long Offset 886 | { 887 | get 888 | { 889 | if (Attributes != null && Attributes.Items.Count > 0) 890 | { 891 | try 892 | { 893 | return ((CodeAttributeInfo)Attributes.Items[0]).CodeOffset; 894 | } 895 | catch (Exception e) 896 | { 897 | } 898 | } 899 | 900 | return 0; 901 | } 902 | } 903 | public ushort NameIndex 904 | { 905 | get 906 | { 907 | return FNameIndex; 908 | } 909 | } 910 | public MethodInfo Clone() 911 | { 912 | return (MethodInfo) MemberwiseClone(); 913 | } 914 | public void SetType(ushort index, TConstantPool ConstantPool) 915 | { 916 | FDescriptorIndex = index; 917 | FDescriptor = (ConstantUtf8Info)ConstantPool.Item(FDescriptorIndex); 918 | FDescriptor.References++; 919 | } 920 | } 921 | 922 | // ******************************************************************************** // 923 | // *************************** ATTRIBUTE STRUCTURES ******************************* // 924 | // ******************************************************************************** // 925 | 926 | abstract class AttributeInfo 927 | { 928 | //ushort AttributeNameIndex; 929 | //ConstantUtf8Info AttributeName; 930 | //uint AttributeLength; 931 | //byte[] Bytes; 932 | 933 | public abstract void Write(BinaryWriter Writer); 934 | } 935 | class UnknownAttributeInfo : AttributeInfo 936 | { 937 | ushort AttributeNameIndex; 938 | ConstantUtf8Info AttributeName; 939 | uint AttributeLength; 940 | byte[] Bytes; 941 | 942 | public UnknownAttributeInfo(int NameIndex, BinaryReader Reader, TConstantPool ConstantPool) 943 | { 944 | AttributeNameIndex = 0; 945 | AttributeName = null; 946 | AttributeLength = 0; 947 | Bytes = null; 948 | 949 | try 950 | { 951 | AttributeNameIndex = (ushort)NameIndex; 952 | AttributeLength = Common.ReadDWord(Reader); 953 | Bytes = Reader.ReadBytes((int)AttributeLength); 954 | // resolve references 955 | AttributeName = (ConstantUtf8Info)ConstantPool.Item(AttributeNameIndex); 956 | AttributeName.References++; 957 | } 958 | catch (Exception e) 959 | { 960 | // do nothing 961 | } 962 | } 963 | public override void Write(BinaryWriter Writer) 964 | { 965 | Common.WriteWord(Writer, AttributeNameIndex + 1); 966 | Common.WriteDWord(Writer, AttributeLength); 967 | Writer.Write(Bytes); 968 | } 969 | } 970 | class ConstantValueAttributeInfo : AttributeInfo 971 | { 972 | ushort AttributeNameIndex; 973 | uint AttributeLength; 974 | ConstantUtf8Info AttributeName; 975 | ushort ConstantValueIndex; 976 | ConstantPoolVariableInfo ConstantValue; 977 | 978 | public ConstantValueAttributeInfo(int NameIndex, BinaryReader Reader, TConstantPool ConstantPool) 979 | { 980 | AttributeNameIndex = 0; 981 | AttributeLength = 0; 982 | AttributeName = null; 983 | ConstantValueIndex = 0; 984 | ConstantValue = null; 985 | 986 | try 987 | { 988 | AttributeNameIndex = (ushort) NameIndex; 989 | AttributeLength = Common.ReadDWord(Reader); 990 | ConstantValueIndex = Common.ReadWord(Reader); 991 | ConstantValueIndex--; 992 | // resolve references 993 | AttributeName = (ConstantUtf8Info)ConstantPool.Item(AttributeNameIndex); 994 | AttributeName.References++; 995 | ConstantValue = (ConstantPoolVariableInfo)ConstantPool.Item(ConstantValueIndex); 996 | ConstantValue.References++; 997 | } 998 | catch (Exception e) 999 | { 1000 | // do nothing 1001 | } 1002 | } 1003 | public override void Write(BinaryWriter Writer) 1004 | { 1005 | Common.WriteWord(Writer, AttributeNameIndex + 1); 1006 | Common.WriteDWord(Writer, AttributeLength); 1007 | Common.WriteWord(Writer, ConstantValueIndex + 1); 1008 | } 1009 | } 1010 | class CodeAttributeInfo : AttributeInfo 1011 | { 1012 | // stuff we need 1013 | ushort AttributeNameIndex; 1014 | ConstantUtf8Info AttributeName; 1015 | uint AttributeLength; 1016 | ushort MaxStack; 1017 | ushort MaxLocals; 1018 | uint CodeLength; 1019 | byte[] Code; 1020 | ushort ExceptionTableLength; 1021 | TExceptionTable[] ExceptionTable; 1022 | TAttributes Attributes; 1023 | // stuff i want 1024 | long FOffsetOfCode; 1025 | 1026 | public CodeAttributeInfo(int NameIndex, BinaryReader Reader, TConstantPool ConstantPool) 1027 | { 1028 | AttributeNameIndex = 0; 1029 | AttributeName = null; 1030 | AttributeLength = 0; 1031 | MaxStack = 0; 1032 | MaxLocals = 0; 1033 | CodeLength = 0; 1034 | Code = null; 1035 | ExceptionTableLength = 0; 1036 | ExceptionTable = null; 1037 | Attributes = null; 1038 | 1039 | try 1040 | { 1041 | AttributeNameIndex = (ushort) NameIndex; 1042 | AttributeLength = Common.ReadDWord(Reader); 1043 | 1044 | MaxStack = Common.ReadWord(Reader); 1045 | MaxLocals = Common.ReadWord(Reader); 1046 | CodeLength = Common.ReadDWord(Reader); 1047 | 1048 | // save the offset of the code stream 1049 | FOffsetOfCode = Reader.BaseStream.Position; 1050 | 1051 | Code = Reader.ReadBytes((int) CodeLength); 1052 | 1053 | ExceptionTableLength = Common.ReadWord(Reader); 1054 | ExceptionTable = new TExceptionTable[ExceptionTableLength]; 1055 | // fucking nested arrays! ;/ 1056 | for (int i = 0; i < ExceptionTableLength; i++) 1057 | { 1058 | ExceptionTable[i] = new TExceptionTable(Reader, ConstantPool); 1059 | } 1060 | 1061 | Attributes = new TAttributes(Reader, ConstantPool); 1062 | 1063 | // resolve references 1064 | AttributeName = (ConstantUtf8Info)ConstantPool.Item(AttributeNameIndex); 1065 | AttributeName.References++; 1066 | } 1067 | catch (Exception e) 1068 | { 1069 | // do nothing 1070 | } 1071 | } 1072 | public override void Write(BinaryWriter Writer) 1073 | { 1074 | Common.WriteWord(Writer, AttributeNameIndex + 1); 1075 | Common.WriteDWord(Writer, AttributeLength); 1076 | 1077 | Common.WriteWord(Writer, MaxStack); 1078 | Common.WriteWord(Writer, MaxLocals); 1079 | Common.WriteDWord(Writer, CodeLength); 1080 | Writer.Write(Code); 1081 | 1082 | Common.WriteWord(Writer, ExceptionTableLength); 1083 | 1084 | for (int i = 0; i < ExceptionTableLength; i++) 1085 | { 1086 | ExceptionTable[i].Write(Writer); 1087 | } 1088 | 1089 | Attributes.Write(Writer); 1090 | } 1091 | public long CodeOffset 1092 | { 1093 | get 1094 | { 1095 | return FOffsetOfCode; 1096 | } 1097 | } 1098 | } 1099 | class ExceptionsAttributeInfo : AttributeInfo 1100 | { 1101 | ushort AttributeNameIndex; 1102 | ConstantUtf8Info AttributeName; 1103 | uint AttributeLength; 1104 | ushort NumberOfExceptions; 1105 | TException[] ExceptionTable; 1106 | 1107 | public ExceptionsAttributeInfo(int NameIndex, BinaryReader Reader, TConstantPool ConstantPool) 1108 | { 1109 | AttributeNameIndex = 0; 1110 | AttributeName = null; 1111 | AttributeLength = 0; 1112 | NumberOfExceptions = 0; 1113 | ExceptionTable = null; 1114 | 1115 | try 1116 | { 1117 | AttributeNameIndex = (ushort) NameIndex; 1118 | AttributeLength = Common.ReadDWord(Reader); 1119 | 1120 | NumberOfExceptions = Common.ReadWord(Reader); 1121 | ExceptionTable = new TException[NumberOfExceptions]; 1122 | // fucking nested arrays! ;/ 1123 | for (int i = 0; i < NumberOfExceptions; i++) 1124 | { 1125 | ExceptionTable[i] = new TException(Reader, ConstantPool); 1126 | } 1127 | // resolve references 1128 | AttributeName = (ConstantUtf8Info)ConstantPool.Item(AttributeNameIndex); 1129 | AttributeName.References++; 1130 | } 1131 | catch (Exception e) 1132 | { 1133 | // do nothing 1134 | } 1135 | } 1136 | public override void Write(BinaryWriter Writer) 1137 | { 1138 | Common.WriteWord(Writer, AttributeNameIndex + 1); 1139 | Common.WriteDWord(Writer, AttributeLength); 1140 | 1141 | Common.WriteWord(Writer, NumberOfExceptions); 1142 | 1143 | for (int i = 0; i < NumberOfExceptions; i++) 1144 | { 1145 | ExceptionTable[i].Write(Writer); 1146 | } 1147 | } 1148 | } 1149 | class InnerClassesAttributeInfo : AttributeInfo 1150 | { 1151 | ushort AttributeNameIndex; 1152 | ConstantUtf8Info AttributeName; 1153 | uint AttributeLength; 1154 | ushort NumberOfClasses; 1155 | TClasses[] Classes; 1156 | 1157 | public InnerClassesAttributeInfo(int NameIndex, BinaryReader Reader, TConstantPool ConstantPool) 1158 | { 1159 | AttributeNameIndex = 0; 1160 | AttributeName = null; 1161 | AttributeLength = 0; 1162 | NumberOfClasses = 0; 1163 | Classes = null; 1164 | 1165 | try 1166 | { 1167 | AttributeNameIndex = (ushort) NameIndex; 1168 | AttributeLength = Common.ReadDWord(Reader); 1169 | 1170 | NumberOfClasses = Common.ReadWord(Reader); 1171 | Classes = new TClasses[NumberOfClasses]; 1172 | // fucking nested arrays! ;/ 1173 | for (int i = 0; i < NumberOfClasses; i++) 1174 | { 1175 | Classes[i] = new TClasses(Reader, ConstantPool); 1176 | } 1177 | // resolve references 1178 | AttributeName = (ConstantUtf8Info)ConstantPool.Item(AttributeNameIndex); 1179 | AttributeName.References++; 1180 | } 1181 | catch (Exception e) 1182 | { 1183 | // do nothing 1184 | } 1185 | } 1186 | public override void Write(BinaryWriter Writer) 1187 | { 1188 | Common.WriteWord(Writer, AttributeNameIndex + 1); 1189 | Common.WriteDWord(Writer, AttributeLength); 1190 | 1191 | Common.WriteWord(Writer, NumberOfClasses); 1192 | for (int i = 0; i < NumberOfClasses; i++) 1193 | { 1194 | Classes[i].Write(Writer); 1195 | } 1196 | } 1197 | } 1198 | class SyntheticAttributeInfo : AttributeInfo 1199 | { 1200 | ushort AttributeNameIndex; 1201 | ConstantUtf8Info AttributeName; 1202 | uint AttributeLength; 1203 | 1204 | public SyntheticAttributeInfo(int NameIndex, BinaryReader Reader, TConstantPool ConstantPool) 1205 | { 1206 | AttributeNameIndex = 0; 1207 | AttributeName = null; 1208 | AttributeLength = 0; 1209 | 1210 | try 1211 | { 1212 | AttributeNameIndex = (ushort) NameIndex; 1213 | AttributeLength = Common.ReadDWord(Reader); 1214 | 1215 | // resolve references 1216 | AttributeName = (ConstantUtf8Info)ConstantPool.Item(AttributeNameIndex); 1217 | AttributeName.References++; 1218 | } 1219 | catch (Exception e) 1220 | { 1221 | // do nothing 1222 | } 1223 | } 1224 | public override void Write(BinaryWriter Writer) 1225 | { 1226 | Common.WriteWord(Writer, AttributeNameIndex + 1); 1227 | Common.WriteDWord(Writer, AttributeLength); 1228 | } 1229 | } 1230 | class SourceFileAttributeInfo : AttributeInfo 1231 | { 1232 | ushort AttributeNameIndex; 1233 | ConstantUtf8Info AttributeName; 1234 | uint AttributeLength; 1235 | ushort SourceFileIndex; 1236 | ConstantUtf8Info SourceFile; 1237 | 1238 | public SourceFileAttributeInfo(int NameIndex, BinaryReader Reader, TConstantPool ConstantPool) 1239 | { 1240 | AttributeNameIndex = 0; 1241 | AttributeName = null; 1242 | AttributeLength = 0; 1243 | SourceFileIndex = 0; 1244 | SourceFile = null; 1245 | 1246 | try 1247 | { 1248 | AttributeNameIndex = (ushort) NameIndex; 1249 | AttributeLength = Common.ReadDWord(Reader); 1250 | SourceFileIndex = Common.ReadWord(Reader); 1251 | SourceFileIndex--; 1252 | // resolve references 1253 | AttributeName = (ConstantUtf8Info)ConstantPool.Item(AttributeNameIndex); 1254 | AttributeName.References++; 1255 | SourceFile = (ConstantUtf8Info)ConstantPool.Item(AttributeNameIndex); 1256 | SourceFile.References++; 1257 | } 1258 | catch (Exception e) 1259 | { 1260 | // do nothing 1261 | } 1262 | } 1263 | public override void Write(BinaryWriter Writer) 1264 | { 1265 | Common.WriteWord(Writer, AttributeNameIndex + 1); 1266 | Common.WriteDWord(Writer, AttributeLength); 1267 | Common.WriteWord(Writer, SourceFileIndex + 1); 1268 | } 1269 | } 1270 | class LineNumberAttributeInfo : AttributeInfo 1271 | { 1272 | ushort AttributeNameIndex; 1273 | ConstantUtf8Info AttributeName; 1274 | uint AttributeLength; 1275 | ushort LineNumberTableLength; 1276 | TLineNumberTable[] LineNumberTable; 1277 | long OriginalPos; 1278 | 1279 | public LineNumberAttributeInfo(int NameIndex, BinaryReader Reader, TConstantPool ConstantPool) 1280 | { 1281 | AttributeNameIndex = 0; 1282 | AttributeName = null; 1283 | AttributeLength = 0; 1284 | LineNumberTableLength = 0; 1285 | LineNumberTable = null; 1286 | OriginalPos = 0; 1287 | 1288 | try 1289 | { 1290 | AttributeNameIndex = (ushort) NameIndex; 1291 | AttributeLength = Common.ReadDWord(Reader); 1292 | OriginalPos = Reader.BaseStream.Position; 1293 | 1294 | LineNumberTableLength = Common.ReadWord(Reader); 1295 | LineNumberTable = new TLineNumberTable[LineNumberTableLength]; 1296 | // fucking nested arrays! ;/ 1297 | for (int i = 0; i < LineNumberTableLength; i++) 1298 | { 1299 | LineNumberTable[i] = new TLineNumberTable(Reader); 1300 | } 1301 | // resolve references 1302 | AttributeName = (ConstantUtf8Info)ConstantPool.Item(AttributeNameIndex); 1303 | AttributeName.References++; 1304 | 1305 | Reader.BaseStream.Position = OriginalPos + AttributeLength; 1306 | } 1307 | catch (Exception e) 1308 | { 1309 | // do nothing 1310 | } 1311 | } 1312 | public override void Write(BinaryWriter Writer) 1313 | { 1314 | Common.WriteWord(Writer, AttributeNameIndex + 1); 1315 | Common.WriteDWord(Writer, AttributeLength); 1316 | 1317 | Common.WriteWord(Writer, LineNumberTableLength); 1318 | for (int i = 0; i < LineNumberTableLength; i++) 1319 | { 1320 | LineNumberTable[i].Write(Writer); 1321 | } 1322 | } 1323 | } 1324 | class LocalVariablesAttributeInfo : AttributeInfo 1325 | { 1326 | ushort AttributeNameIndex; 1327 | ConstantUtf8Info AttributeName; 1328 | uint AttributeLength; 1329 | ushort LocalVariableTableLength; 1330 | TLocalVariableTable[] LocalVariableTable; 1331 | 1332 | public LocalVariablesAttributeInfo(int NameIndex, BinaryReader Reader, TConstantPool ConstantPool) 1333 | { 1334 | AttributeNameIndex = 0; 1335 | AttributeName = null; 1336 | AttributeLength = 0; 1337 | LocalVariableTableLength = 0; 1338 | LocalVariableTable = null; 1339 | 1340 | try 1341 | { 1342 | AttributeNameIndex = (ushort) NameIndex; 1343 | AttributeLength = Common.ReadDWord(Reader); 1344 | 1345 | LocalVariableTableLength = Common.ReadWord(Reader); 1346 | LocalVariableTable = new TLocalVariableTable[LocalVariableTableLength]; 1347 | // fucking nested arrays! ;/ 1348 | for (int i = 0; i < LocalVariableTableLength; i++) 1349 | { 1350 | LocalVariableTable[i] = new TLocalVariableTable(Reader, ConstantPool); 1351 | } 1352 | // resolve references 1353 | AttributeName = (ConstantUtf8Info)ConstantPool.Item(AttributeNameIndex); 1354 | AttributeName.References++; 1355 | } 1356 | catch (Exception e) 1357 | { 1358 | // do nothing 1359 | } 1360 | } 1361 | 1362 | public override void Write(BinaryWriter Writer) 1363 | { 1364 | Common.WriteWord(Writer, AttributeNameIndex + 1); 1365 | Common.WriteDWord(Writer, AttributeLength); 1366 | 1367 | Common.WriteWord(Writer, LocalVariableTableLength); 1368 | for (int i = 0; i < LocalVariableTableLength; i++) 1369 | { 1370 | LocalVariableTable[i].Write(Writer); 1371 | } 1372 | } 1373 | } 1374 | class DeprecatedAttributeInfo : AttributeInfo 1375 | { 1376 | ushort AttributeNameIndex; 1377 | ConstantUtf8Info AttributeName; 1378 | uint AttributeLength; 1379 | 1380 | public DeprecatedAttributeInfo(int NameIndex, BinaryReader Reader, TConstantPool ConstantPool) 1381 | { 1382 | AttributeNameIndex = 0; 1383 | AttributeName = null; 1384 | AttributeLength = 0; 1385 | 1386 | try 1387 | { 1388 | AttributeNameIndex = (ushort) NameIndex; 1389 | // length should be zero.. 1390 | // TODO: maybe put a check in?? probably no need at this point.. 1391 | AttributeLength = Common.ReadDWord(Reader); 1392 | // resolve references 1393 | AttributeName = (ConstantUtf8Info)ConstantPool.Item(AttributeNameIndex); 1394 | AttributeName.References++; 1395 | } 1396 | catch (Exception e) 1397 | { 1398 | // do nothing 1399 | } 1400 | } 1401 | public override void Write(BinaryWriter Writer) 1402 | { 1403 | Common.WriteWord(Writer, AttributeNameIndex + 1); 1404 | Common.WriteDWord(Writer, AttributeLength); 1405 | } 1406 | } 1407 | 1408 | // the inner attribute classes 1409 | class TLocalVariableTable 1410 | { 1411 | ushort StartPC; 1412 | ushort Length; 1413 | ushort NameIndex; 1414 | ConstantUtf8Info Name; 1415 | ushort DescriptorIndex; 1416 | ConstantUtf8Info Descriptor; 1417 | ushort Index; 1418 | 1419 | public TLocalVariableTable(BinaryReader Reader, TConstantPool ConstantPool) 1420 | { 1421 | StartPC = 0; 1422 | Length = 0; 1423 | NameIndex = 0; 1424 | Name = null; 1425 | DescriptorIndex = 0; 1426 | Descriptor = null; 1427 | Index = 0; 1428 | 1429 | try 1430 | { 1431 | StartPC = Common.ReadWord(Reader); 1432 | StartPC--; 1433 | Length = Common.ReadWord(Reader); 1434 | NameIndex = Common.ReadWord(Reader); 1435 | NameIndex--; 1436 | DescriptorIndex = Common.ReadWord(Reader); 1437 | DescriptorIndex--; 1438 | Index = Common.ReadWord(Reader); 1439 | Index--; 1440 | // resolve references 1441 | Name = (ConstantUtf8Info)ConstantPool.Item(NameIndex); 1442 | Name.References++; 1443 | Descriptor = (ConstantUtf8Info)ConstantPool.Item(DescriptorIndex); 1444 | Descriptor.References++; 1445 | } 1446 | catch (Exception e) 1447 | { 1448 | // do nothing 1449 | } 1450 | } 1451 | public void Write(BinaryWriter Writer) 1452 | { 1453 | Common.WriteWord(Writer, StartPC); 1454 | Common.WriteWord(Writer, Length); 1455 | Common.WriteWord(Writer, NameIndex + 1); 1456 | Common.WriteWord(Writer, DescriptorIndex + 1); 1457 | Common.WriteWord(Writer, Index + 1); 1458 | } 1459 | } 1460 | class TLineNumberTable 1461 | { 1462 | ushort StartPC; 1463 | ushort LineNumber; 1464 | 1465 | public TLineNumberTable(BinaryReader Reader) 1466 | { 1467 | LineNumber = 0; 1468 | StartPC = 0; 1469 | 1470 | try 1471 | { 1472 | StartPC = Common.ReadWord(Reader); 1473 | LineNumber = Common.ReadWord(Reader); 1474 | } 1475 | catch (Exception e) 1476 | { 1477 | // do nothing 1478 | } 1479 | } 1480 | 1481 | public void Write(BinaryWriter Writer) 1482 | { 1483 | Common.WriteWord(Writer, StartPC); 1484 | Common.WriteWord(Writer, LineNumber); 1485 | } 1486 | } 1487 | class TClasses 1488 | { 1489 | ushort InnerClassInfoIndex; 1490 | ConstantClassInfo InnerClassInfo; 1491 | ushort OuterClassInfoIndex; 1492 | ConstantClassInfo OuterClassInfo; 1493 | ushort InnerNameIndex; 1494 | ConstantUtf8Info InnerName; 1495 | ushort InnerClassAccessFlags; 1496 | 1497 | public TClasses(BinaryReader Reader, TConstantPool ConstantPool) 1498 | { 1499 | InnerClassInfoIndex = 0; 1500 | InnerClassInfo = null; 1501 | OuterClassInfoIndex = 0; ; 1502 | OuterClassInfo = null; 1503 | InnerNameIndex = 0; ; 1504 | InnerName = null; 1505 | InnerClassAccessFlags = 0; ; 1506 | 1507 | try 1508 | { 1509 | InnerClassInfoIndex = Common.ReadWord(Reader); 1510 | InnerClassInfoIndex--; 1511 | OuterClassInfoIndex = Common.ReadWord(Reader); 1512 | OuterClassInfoIndex--; 1513 | InnerNameIndex = Common.ReadWord(Reader); 1514 | InnerNameIndex--; 1515 | InnerClassAccessFlags = Common.ReadWord(Reader); 1516 | 1517 | // resolve references 1518 | if (InnerNameIndex >= 0) 1519 | { 1520 | InnerName = (ConstantUtf8Info)ConstantPool.Item(InnerNameIndex); 1521 | InnerName.References++; 1522 | } 1523 | if (InnerNameIndex >= 0) 1524 | { 1525 | InnerClassInfo = (ConstantClassInfo)ConstantPool.Item(InnerClassInfoIndex); 1526 | InnerClassInfo.References++; 1527 | } 1528 | if (InnerNameIndex >= 0) 1529 | { 1530 | OuterClassInfo = (ConstantClassInfo)ConstantPool.Item(OuterClassInfoIndex); 1531 | OuterClassInfo.References++; 1532 | } 1533 | } 1534 | catch (Exception e) 1535 | { 1536 | // do nothing 1537 | } 1538 | } 1539 | public void Write(BinaryWriter Writer) 1540 | { 1541 | Common.WriteWord(Writer, InnerClassInfoIndex + 1); 1542 | Common.WriteWord(Writer, OuterClassInfoIndex + 1); 1543 | Common.WriteWord(Writer, InnerNameIndex + 1); 1544 | Common.WriteWord(Writer, InnerClassAccessFlags); 1545 | } 1546 | } 1547 | class TException 1548 | { 1549 | ushort ExceptionIndex; 1550 | ConstantClassInfo Exception; 1551 | 1552 | public TException(BinaryReader Reader, TConstantPool ConstantPool) 1553 | { 1554 | ExceptionIndex = 0; 1555 | 1556 | try 1557 | { 1558 | ExceptionIndex = Common.ReadWord(Reader); 1559 | ExceptionIndex--; 1560 | // resolve references 1561 | Exception = (ConstantClassInfo)ConstantPool.Item(ExceptionIndex); 1562 | } 1563 | catch (Exception e) 1564 | { 1565 | Exception = null; 1566 | } 1567 | } 1568 | public void Write(BinaryWriter Writer) 1569 | { 1570 | Common.WriteWord(Writer, ExceptionIndex + 1); 1571 | } 1572 | } 1573 | class TExceptionTable 1574 | { 1575 | ushort StartPC; 1576 | ushort EndPC; 1577 | ushort HandlerPC; 1578 | ushort CatchType; 1579 | ConstantClassInfo Catch; 1580 | 1581 | public TExceptionTable(BinaryReader Reader, TConstantPool ConstantPool) 1582 | { 1583 | StartPC = 0; 1584 | EndPC = 0; 1585 | HandlerPC = 0; 1586 | CatchType = 0; 1587 | Catch = null; 1588 | 1589 | try 1590 | { 1591 | StartPC = Common.ReadWord(Reader); 1592 | StartPC--; 1593 | EndPC = Common.ReadWord(Reader); 1594 | EndPC--; 1595 | HandlerPC = Common.ReadWord(Reader); 1596 | HandlerPC--; 1597 | CatchType = Common.ReadWord(Reader); 1598 | CatchType--; 1599 | 1600 | if (CatchType >= 0) 1601 | { 1602 | Catch = (ConstantClassInfo)ConstantPool.Item(CatchType); 1603 | } 1604 | } 1605 | catch (Exception e) 1606 | { 1607 | } 1608 | } 1609 | public void Write(BinaryWriter Writer) 1610 | { 1611 | Common.WriteWord(Writer, StartPC + 1); 1612 | Common.WriteWord(Writer, EndPC + 1); 1613 | Common.WriteWord(Writer, HandlerPC + 1); 1614 | Common.WriteWord(Writer, CatchType + 1); 1615 | } 1616 | } 1617 | 1618 | // ******************************************************************************** // 1619 | // *************************** INTERFACE STRUCTURES ******************************* // 1620 | // ******************************************************************************** // 1621 | 1622 | struct InterfaceInfo 1623 | { 1624 | private ushort FValue; 1625 | private ConstantClassInfo FInterface; 1626 | 1627 | public InterfaceInfo(BinaryReader Reader, TConstantPool ConstantPool) 1628 | { 1629 | try 1630 | { 1631 | FValue = Common.ReadWord(Reader); 1632 | FValue--; 1633 | 1634 | FInterface = (ConstantClassInfo)ConstantPool.Item(FValue); 1635 | } 1636 | catch (Exception e) 1637 | { 1638 | FValue = 0; 1639 | FInterface = null; 1640 | } 1641 | } 1642 | 1643 | public void Write(BinaryWriter Writer) 1644 | { 1645 | try 1646 | { 1647 | Common.WriteWord(Writer, FValue + 1); 1648 | } 1649 | catch (Exception e) 1650 | { 1651 | } 1652 | } 1653 | 1654 | public int Value 1655 | { 1656 | get 1657 | { 1658 | return FValue; 1659 | } 1660 | } 1661 | 1662 | public ConstantClassInfo Interface 1663 | { 1664 | get 1665 | { 1666 | return FInterface; 1667 | } 1668 | } 1669 | 1670 | public string Name 1671 | { 1672 | get 1673 | { 1674 | if (FInterface != null) 1675 | { 1676 | return FInterface.Name; 1677 | } 1678 | 1679 | return ""; 1680 | } 1681 | } 1682 | 1683 | public void SetName(string NewName) 1684 | { 1685 | 1686 | } 1687 | } 1688 | 1689 | // ******************************************************************************** // 1690 | // ***************************** COMMON FUNCTIONS ********************************* // 1691 | // ******************************************************************************** // 1692 | 1693 | class RenameData 1694 | { 1695 | string FType; 1696 | string FName; 1697 | 1698 | public RenameData(string Type, string Name) 1699 | { 1700 | FType = Type; 1701 | FName = Name; 1702 | } 1703 | public string[] GetData() 1704 | { 1705 | string[] s = new string[2]; 1706 | s[0] = FType; 1707 | s[1] = FName; 1708 | 1709 | return s; 1710 | } 1711 | public string FieldType 1712 | { 1713 | get { return FType; } 1714 | set { FType = value; } 1715 | } 1716 | public string FieldName 1717 | { 1718 | get { return FName; } 1719 | set { FName = value; } 1720 | } 1721 | } 1722 | class RenameDatabase 1723 | { 1724 | private Hashtable FRenameMethods = null; 1725 | private Hashtable FRenameFields = null; 1726 | private Hashtable FRenameClass = null; 1727 | 1728 | public RenameDatabase() 1729 | { 1730 | FRenameMethods = new Hashtable(); 1731 | FRenameFields = new Hashtable(); 1732 | FRenameClass = new Hashtable(); 1733 | } 1734 | public void AddRename(Hashtable DestTable, string ClassName, string OldDescriptor, string OldName, string NewDescriptor, string NewName) 1735 | { 1736 | ArrayList al = (ArrayList)DestTable[ClassName]; 1737 | 1738 | if (al == null) 1739 | { 1740 | al = new ArrayList(); 1741 | DestTable[ClassName] = al; 1742 | } 1743 | else 1744 | { 1745 | // make sure it doesnt already exist 1746 | for (int i = 0; i < al.Count; i += 2) 1747 | { 1748 | RenameData rd = (RenameData)al[i]; 1749 | 1750 | if (rd.FieldName == OldName && rd.FieldType == OldDescriptor) 1751 | { 1752 | // if it does, overwrite it, don't add in a new one 1753 | rd.FieldName = NewName; 1754 | return; 1755 | } 1756 | } 1757 | } 1758 | 1759 | al.Add(new RenameData(OldDescriptor, OldName)); 1760 | al.Add(new RenameData(NewDescriptor, NewName)); 1761 | } 1762 | public RenameData GetRenameInfo(Hashtable DestTable, string ClassName, string OldDescriptor, string OldName) 1763 | { 1764 | ArrayList al = (ArrayList)DestTable[ClassName]; 1765 | 1766 | if (al == null) 1767 | return null; 1768 | 1769 | for (int i = 0; i < al.Count; i += 2) 1770 | { 1771 | RenameData rd = (RenameData)al[i]; 1772 | 1773 | if (rd.FieldName == OldName && rd.FieldType == OldDescriptor) 1774 | { 1775 | return (RenameData)al[i + 1]; 1776 | } 1777 | } 1778 | 1779 | return null; 1780 | } 1781 | public void AddRenameMethod(string ClassName, string OldDescriptor, string OldName, string NewDescriptor, string NewName) 1782 | { 1783 | AddRename(FRenameMethods, ClassName, OldDescriptor, OldName, NewDescriptor, NewName); 1784 | } 1785 | public void AddRenameField(string ClassName, string OldDescriptor, string OldName, string NewDescriptor, string NewName) 1786 | { 1787 | AddRename(FRenameFields, ClassName, OldDescriptor, OldName, NewDescriptor, NewName); 1788 | } 1789 | public RenameData GetNewMethodInfo(string ClassName, string OldDescriptor, string OldName) 1790 | { 1791 | // searches for a matching method in the methodlist 1792 | return GetRenameInfo(FRenameMethods, ClassName, OldDescriptor, OldName); 1793 | } 1794 | public RenameData GetNewFieldInfo(string ClassName, string OldDescriptor, string OldName) 1795 | { 1796 | // searches for a matching method in the methodlist 1797 | return GetRenameInfo(FRenameFields, ClassName, OldDescriptor, OldName); 1798 | } 1799 | public void AddRenameClass(string OldClassName, string NewClassName) 1800 | { 1801 | FRenameClass[OldClassName] = NewClassName; 1802 | } 1803 | public string GetNewClassName(string OldClassName) 1804 | { 1805 | return (string) FRenameClass[OldClassName]; 1806 | } 1807 | public string GetNewClassNameOnly(string OldClassName) 1808 | { 1809 | string temp = GetNewClassName(OldClassName); 1810 | 1811 | if (temp == null) 1812 | return null; 1813 | 1814 | string[] strspl = temp.Split(':'); 1815 | 1816 | if (strspl.Length > 0) 1817 | { 1818 | return strspl[0].Trim(); 1819 | } 1820 | 1821 | return null; 1822 | } 1823 | /*public bool ReadFromFile(string FileName) 1824 | { 1825 | // serialize this to read in .xml file ? 1826 | return false; 1827 | }*/ 1828 | } 1829 | class Common 1830 | { 1831 | public static string GetClassName(string FullName) 1832 | { 1833 | // gets the class name from a class path 1834 | if (FullName.Contains("/")) 1835 | return FullName.Substring(FullName.LastIndexOf('/') + 1, FullName.Length - FullName.LastIndexOf('/') - 1); 1836 | else 1837 | return FullName; 1838 | } 1839 | public static string GetClassPath(string FullName) 1840 | { 1841 | // gets the class name from a class path 1842 | return FullName.Substring(0, FullName.LastIndexOf('/') + 1); 1843 | } 1844 | public static string NewClassName(string OriginalClassName, string NewName) 1845 | { 1846 | NewName = Common.GetClassName(NewName); 1847 | // new name should be the short name 1848 | // original class name should be original long name 1849 | if (OriginalClassName.LastIndexOf('/') > 0) 1850 | { 1851 | //string old_name = OriginalClassName.Substring(OriginalClassName.LastIndexOf('/') + 1, OriginalClassName.Length - OriginalClassName.LastIndexOf('/') - 1); 1852 | OriginalClassName = OriginalClassName.Remove(OriginalClassName.LastIndexOf('/') + 1, OriginalClassName.Length - OriginalClassName.LastIndexOf('/') - 1); 1853 | //OriginalClassName += NewName + old_name; 1854 | OriginalClassName += NewName; 1855 | 1856 | return OriginalClassName; 1857 | } 1858 | 1859 | //return NewName + OriginalClassName; 1860 | return NewName; 1861 | } 1862 | public static string FixDescriptor(string Descriptor, string OldClassName, string NewClassName) 1863 | { 1864 | return Descriptor.Replace("L" + OldClassName + ";", "L" + NewClassName + ";"); 1865 | } 1866 | private static ushort SwapBytes(ushort value) 1867 | { 1868 | ushort a = (ushort) (value >> 8); 1869 | ushort b = (ushort) (value << 8); 1870 | 1871 | return ((ushort) (a | b)); 1872 | } 1873 | public static ushort ReadWord(BinaryReader Reader) 1874 | { 1875 | if (Reader == null) 1876 | return 0; 1877 | 1878 | ushort val = (ushort) Reader.ReadInt16(); 1879 | val = SwapBytes(val); 1880 | 1881 | return val; 1882 | } 1883 | public static void WriteWord(BinaryWriter Writer, int Data) 1884 | { 1885 | if (Writer == null) 1886 | return; 1887 | 1888 | //convert the data from small endian to big endian 1889 | Data = SwapBytes((ushort)Data); 1890 | 1891 | Writer.Write((ushort)Data); 1892 | } 1893 | public static uint ReadDWord(BinaryReader Reader) 1894 | { 1895 | if (Reader == null) 1896 | return 0; 1897 | 1898 | // get the value, and then change it from big endian to small endian 1899 | uint val = (uint) Reader.ReadInt32(); 1900 | uint temp = val >> 16; 1901 | temp = SwapBytes((ushort) temp); 1902 | val = val & 0x0FFFF; 1903 | val = SwapBytes((ushort) val); 1904 | val = (val << 16) | temp; 1905 | 1906 | return val; 1907 | } 1908 | public static void WriteDWord(BinaryWriter Writer, uint Data) 1909 | { 1910 | if (Writer == null) 1911 | return; 1912 | 1913 | //convert the data from small endian to big endian 1914 | uint temp = Data >> 16; 1915 | temp = SwapBytes((ushort)temp); 1916 | Data = Data & 0x0FFFF; 1917 | Data = SwapBytes((ushort)Data); 1918 | Data = (Data << 16) | temp; 1919 | 1920 | Writer.Write(Data); 1921 | } 1922 | public static byte ReadByte(BinaryReader Reader) 1923 | { 1924 | if (Reader == null) 1925 | return 0; 1926 | 1927 | return Reader.ReadByte(); 1928 | } 1929 | public static void WriteByte(BinaryWriter Writer, byte Data) 1930 | { 1931 | if (Writer == null) 1932 | return; 1933 | 1934 | Writer.Write(Data); 1935 | } 1936 | } 1937 | } -------------------------------------------------------------------------------- /Objects.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.IO; 4 | 5 | namespace JavaDeObfuscator 6 | { 7 | // ******************************************************************************** // 8 | // ************************** ACTUAL DEOBFUSCATOR ******************************** // 9 | // ******************************************************************************** // 10 | // These class does the actual deobfuscation 11 | 12 | class TDeObfuscator 13 | { 14 | // event delegates 15 | public delegate void ProgressHandler(int Progress); 16 | public static event ProgressHandler Progress; 17 | 18 | // private variables 19 | private ArrayList FFiles; 20 | private ArrayList FClassFiles; 21 | private ArrayList FInterfaces; 22 | private ArrayList FChangeList; 23 | private bool FThoroughMode; 24 | private bool FRenameClasses; 25 | 26 | public bool UseUniqueNums { get; set; } 27 | public string OutputDir { get; set; } 28 | 29 | /// 30 | /// The DeObfuscating engine 31 | /// 32 | /// All of the files in the project. Must be full path + filename 33 | public TDeObfuscator(ArrayList Files) 34 | { 35 | if (Files == null) 36 | return; 37 | 38 | FFiles = Files; 39 | 40 | foreach (string f in FFiles) 41 | { 42 | if (!File.Exists(f)) 43 | return; 44 | } 45 | 46 | FThoroughMode = true; 47 | FRenameClasses = true; 48 | } 49 | public bool DoRename(string Name) 50 | { 51 | ArrayList bad_names; 52 | 53 | bad_names = new ArrayList(); 54 | bad_names.Add("for"); 55 | bad_names.Add("char"); 56 | bad_names.Add("void"); 57 | bad_names.Add("byte"); 58 | bad_names.Add("do"); 59 | bad_names.Add("int"); 60 | bad_names.Add("long"); 61 | bad_names.Add("else"); 62 | bad_names.Add("case"); 63 | bad_names.Add("new"); 64 | bad_names.Add("goto"); 65 | bad_names.Add("try"); 66 | bad_names.Add("null"); 67 | 68 | Name = Common.GetClassName(Name); 69 | 70 | 71 | if (Name[0] == '<') 72 | return false; 73 | 74 | if (Name.Length > 0 && Name.Length <= 2) 75 | return true; 76 | 77 | if (Name.Length > 0 && Name.Length <= 3 && Name.Contains("$")) 78 | return true; 79 | 80 | foreach (string s in bad_names) 81 | { 82 | if (s == Name) 83 | return true; 84 | } 85 | 86 | return false; 87 | } 88 | private bool ClassNameExists(String Name) 89 | { 90 | foreach (Object ClassFile in FClassFiles.ToArray()) 91 | { 92 | if (((TClassFile)ClassFile).ThisClassName == Name) 93 | return true; 94 | } 95 | 96 | return false; 97 | } 98 | private ArrayList DeObfuscateSingleFile(int index, RenameDatabase RenameStore) 99 | { 100 | TClassFile ClassFile = (TClassFile)FClassFiles[index]; 101 | 102 | if (ClassFile == null) 103 | return null; 104 | 105 | // add the class name to the head of the changelist 106 | FChangeList = new ArrayList(); 107 | FChangeList.Add(ClassFile.ThisClassName); 108 | 109 | string OriginalClassName = ClassFile.ThisClassName; 110 | string OriginalClassAndType = ClassFile.ThisClassName + " : " + ClassFile.SuperClassName; 111 | 112 | // rename the class and add the new class name to the changelist at [1] 113 | if (FRenameClasses && RenameStore.GetNewClassNameOnly(OriginalClassAndType) != null) 114 | { 115 | // check if we need to use a user-supplied class name first 116 | string NewClassName = RenameStore.GetNewClassNameOnly(OriginalClassAndType); 117 | 118 | while (ClassNameExists(NewClassName)) 119 | { 120 | NewClassName += "_"; 121 | } 122 | FChangeList.Add(ClassFile.ChangeClassName(NewClassName)); 123 | } 124 | else if (FRenameClasses && DoRename(OriginalClassName)) 125 | { 126 | string NewClassName; 127 | 128 | if (UseUniqueNums) 129 | { 130 | string format = "{0:D" + (FClassFiles.Count.ToString().Length + 2) + "}"; 131 | string uniqueNum = string.Format(format, Convert.ToInt64(ClassFile.ThisClassCode.ToString() + index.ToString())); 132 | 133 | NewClassName = String.Format("Class_{0}_{1}", Common.GetClassName(OriginalClassName), uniqueNum); 134 | } 135 | else 136 | NewClassName = String.Format("Class_{0}", Common.GetClassName(OriginalClassName)); 137 | 138 | // test if the filename we are changing to hasnt already been used! 139 | while (ClassNameExists(NewClassName)) 140 | { 141 | NewClassName += "_"; 142 | } 143 | FChangeList.Add(ClassFile.ChangeClassName(NewClassName)); 144 | } 145 | else 146 | FChangeList.Add(OriginalClassName); 147 | 148 | // process the Methods 149 | for (int i = 0; i < ClassFile.Methods.Items.Count; i++) 150 | { 151 | MethodInfo mi = (MethodInfo)ClassFile.Methods.Items[i]; 152 | RenameData rd = RenameStore.GetNewMethodInfo(OriginalClassAndType, mi.Descriptor, mi.Name.Value); 153 | 154 | // this is the rule for renaming 155 | if (DoRename(mi.Name.Value) || rd != null) 156 | { 157 | // clone the original method 158 | TMethodChangeRecord mcr = new TMethodChangeRecord(mi); 159 | // rename all of the functions something meaningful 160 | string NewName; 161 | // if the offset is zero, it probably means its an abstract method 162 | if (ClassFile.AccessFlags == AccessFlags.ACC_INTERFACE) 163 | NewName = String.Format("sub_iface_{0:x}", i); 164 | else if (mi.Offset != 0) 165 | NewName = String.Format("sub_{0:x}", mi.Offset); 166 | else 167 | NewName = String.Format("sub_null_{0:x}", i); 168 | 169 | /*if (FThoroughMode) 170 | { 171 | int j = 0; 172 | while (ClassFile.Methods.MethodNameExists(NewName)) 173 | { 174 | // rename the method 175 | NewName = NewName + "_" + j; 176 | j++; 177 | } 178 | }*/ 179 | 180 | // user supplied names take precedence 181 | if (rd != null) 182 | { 183 | NewName = rd.FieldName; 184 | } 185 | 186 | // change the method name 187 | ClassFile.ChangeMethodName(i, NewName); 188 | // set the 189 | mcr.ChangedTo(mi); 190 | FChangeList.Add(mcr); 191 | } 192 | 193 | // fix the descriptor regardless 194 | ClassFile.ChangeMethodParam(i, OriginalClassName, ClassFile.ThisClassName); 195 | } 196 | 197 | // process the Fields 198 | for (int i = 0; i < ClassFile.Fields.Items.Count; i++) 199 | { 200 | FieldInfo fi = (FieldInfo)ClassFile.Fields.Items[i]; 201 | RenameData rd = RenameStore.GetNewFieldInfo(OriginalClassAndType, fi.Descriptor, fi.Name.Value); 202 | 203 | if (DoRename(fi.Name.Value) || rd != null) 204 | { 205 | // clone the original method 206 | TFieldChangeRecord fcr = new TFieldChangeRecord(fi); 207 | // rename all of the fields something meaningful 208 | string NewName; 209 | // if the offset is zero, it probably means its a null/abstract method 210 | if (fi.Offset != 0) 211 | NewName = String.Format("var_{0:x}", fi.Offset); 212 | else 213 | NewName = String.Format("var_null_{0:x}", fi.Offset); 214 | 215 | /*if (FThoroughMode) 216 | { 217 | int j = 0; 218 | while (ClassFile.Methods.FieldNameExists(NewName)) 219 | { 220 | // rename the field 221 | NewName = NewName + "_" + j; 222 | j++; 223 | } 224 | }*/ 225 | 226 | if (rd != null) 227 | { 228 | NewName = rd.FieldName; 229 | } 230 | 231 | ClassFile.ChangeFieldName(i, NewName); 232 | 233 | fcr.ChangedTo(fi); 234 | FChangeList.Add(fcr); 235 | } 236 | 237 | // fix the descriptor regardless 238 | ClassFile.ChangeFieldType(i, OriginalClassName, ClassFile.ThisClassName); 239 | } 240 | 241 | return FChangeList; 242 | } 243 | /// 244 | /// This function runs over a class, fixing up any references from a deobfuscated file. 245 | /// 246 | /// This is the index of the ClassFile to have its references updated 247 | /// This is a list of before/after values from a previously deobfuscated file 248 | private void FixReferencePass1(int Index, ArrayList ChangeList, ArrayList OwnerChangeList) 249 | { 250 | /* the first pass does the following: 251 | * - replaces the Super Class name (if it needs replacing) 252 | * - replaces any constant method/field names (if they need replacing) 253 | * - replaces the class field names (if needed) 254 | * it does NOT change the original class name */ 255 | TClassFile ClassFile = (TClassFile)FClassFiles[Index]; 256 | 257 | if (ClassFile == null) 258 | return; 259 | 260 | // - ChangeList[0] is always a string, which is the parent name of the deobfuscated class 261 | // - ChangeList[1] is always the deobfuscated (new) class name... yes i know this is lame :P 262 | string OldParentName = (string)ChangeList[0]; 263 | string NewParentName = (string)ChangeList[1]; 264 | 265 | // check the Super class name if it needs renaming 266 | if (ClassFile.SuperClassName == OldParentName) 267 | { 268 | ClassFile.ChangeSuperClassName(NewParentName); 269 | } 270 | 271 | // loop through the constant pool for field/method references 272 | // check the parent of each, and if the parent is the class we have 273 | // just modified, try and match it to one of the changes 274 | // in the changearray 275 | for (int i = 0; i < ClassFile.ConstantPool.MaxItems(); i++) 276 | { 277 | if (ClassFile.ConstantPool.Item(i) is ConstantPoolMethodInfo) 278 | { 279 | ConstantPoolMethodInfo ci = (ConstantPoolMethodInfo)ClassFile.ConstantPool.Item(i); 280 | 281 | // check its parent 282 | if (ci.ParentClass.Name == OldParentName || ci.ParentClass.Name == NewParentName) 283 | { 284 | // check the descriptor 285 | // - for fields this is the field type 286 | // - for methods this is the parameter list 287 | 288 | // if parents are the same, check the name and descriptor 289 | // against the list of originals 290 | for (int j = 2; j < ChangeList.Count; j++) 291 | { 292 | if ((ChangeList[j] is TMethodChangeRecord) && (ci is ConstantMethodrefInfo || ci is ConstantInterfaceMethodrefInfo)) 293 | { 294 | if (ci is ConstantInterfaceMethodrefInfo) 295 | { 296 | // handle interface references differently 297 | TMethodChangeRecord mcr = (TMethodChangeRecord)ChangeList[j]; 298 | 299 | // if found update it to the overridden version 300 | if (mcr.OriginalMethod.Name.Value == ci.NameAndType.Name && 301 | mcr.OriginalMethod.Descriptor == ci.NameAndType.Descriptor) 302 | { 303 | // find the overridden version 304 | for (int k = 2; k < OwnerChangeList.Count; k++) 305 | { 306 | if (OwnerChangeList[k] is TMethodChangeRecord) 307 | { 308 | TMethodChangeRecord mcr2 = (TMethodChangeRecord)OwnerChangeList[k]; 309 | if (mcr2.OriginalMethod.Name.Value == mcr.OriginalMethod.Name.Value && 310 | mcr2.OriginalMethod.Descriptor == mcr.OriginalMethod.Descriptor) 311 | { 312 | ClassFile.ChangeConstantFieldName(i, mcr2.NewMethod.Name.Value); 313 | break; 314 | } 315 | } 316 | } 317 | } 318 | } 319 | else 320 | { 321 | TMethodChangeRecord mcr = (TMethodChangeRecord)ChangeList[j]; 322 | 323 | // if found update it to the new version... 324 | if (mcr.OriginalMethod.Name.Value == ci.NameAndType.Name && 325 | mcr.OriginalMethod.Descriptor == ci.NameAndType.Descriptor) 326 | { 327 | ClassFile.ChangeConstantFieldName(i, mcr.NewMethod.Name.Value); 328 | break; 329 | } 330 | } 331 | } 332 | else if ((ChangeList[j] is TFieldChangeRecord) && (ci is ConstantFieldrefInfo)) 333 | { 334 | TFieldChangeRecord fcr = (TFieldChangeRecord)ChangeList[j]; 335 | 336 | // if found update it to the new version... 337 | if (fcr.OriginalField.Name.Value == ci.NameAndType.Name && 338 | fcr.OriginalField.Descriptor == ci.NameAndType.Descriptor) 339 | { 340 | ClassFile.ChangeConstantFieldName(i, fcr.NewField.Name.Value); 341 | break; 342 | } 343 | } 344 | } 345 | } 346 | } 347 | } 348 | 349 | // also loop through the Fields array to change all the Types 350 | for (int i = 0; i < ClassFile.Fields.MaxItems(); i++) 351 | { 352 | ClassFile.ChangeFieldType(i, OldParentName, NewParentName); 353 | } 354 | // do the same for methods (fix the parameter list) 355 | for (int i = 0; i < ClassFile.Methods.MaxItems(); i++) 356 | { 357 | ClassFile.ChangeMethodParam(i, OldParentName, NewParentName); 358 | } 359 | // and the same for all the interfaces 360 | for (int i = 0; i < ClassFile.Interfaces.Items.Count; i++) 361 | { 362 | if (ClassFile.Interfaces.Item(i).Name == OldParentName) 363 | ClassFile.ChangeInterfaceName(i, NewParentName); 364 | } 365 | } 366 | /// 367 | /// Stage 2 simply goes through the constant pool searching for a ClassInfo structure that matches 368 | /// the obfuscated class name, and replaces it with the de-obfuscated class name. 369 | /// 370 | /// This is to ensure that any field/variable that references that class will be updated, simply by 371 | /// changing the class info structure at the source. 372 | /// 373 | /// Index of the class file we want to update 374 | /// The array of changes we made deobfuscating a file 375 | private void FixReferencePass2(int Index, ArrayList ChangeList) 376 | { 377 | TClassFile ClassFile = (TClassFile)FClassFiles[Index]; 378 | 379 | if (ClassFile == null) 380 | return; 381 | 382 | string OldParentName = (string)ChangeList[0]; 383 | string NewParentName = (string)ChangeList[1]; 384 | 385 | // iterate through the constant pool looking for class references 386 | // that match the old class name 387 | for (int i = 0; i < ClassFile.ConstantPool.MaxItems(); i++) 388 | { 389 | if (ClassFile.ConstantPool.Item(i) is ConstantClassInfo) 390 | { 391 | ConstantClassInfo ci = (ConstantClassInfo)ClassFile.ConstantPool.Item(i); 392 | 393 | // if we found a ClassInfo constant with the same name as the old name 394 | if (ci.Name == OldParentName) 395 | { 396 | // create a new UTF string constant 397 | ConstantUtf8Info ui = new ConstantUtf8Info(); 398 | // set it to the new parent name 399 | ui.SetName(NewParentName); 400 | // add it to the constant pool 401 | ushort index = ClassFile.ConstantPool.Add(ui); 402 | // set our original ClassInfo constant's name to the newly added UTF string constant 403 | ci.SetName(index, ClassFile.ConstantPool); 404 | } 405 | // special condition for array type references 406 | else if (ci.Name.IndexOf("L" + OldParentName + ";") >= 0) 407 | { 408 | // create a new UTF string constant 409 | ConstantUtf8Info ui = new ConstantUtf8Info(); 410 | // set it to the new parent name 411 | ui.SetName(ci.Name.Replace("L" + OldParentName + ";", "L" + NewParentName + ";")); 412 | // add it to the constant pool 413 | ushort index = ClassFile.ConstantPool.Add(ui); 414 | // set our original ClassInfo constant's name to the newly added UTF string constant 415 | ci.SetName(index, ClassFile.ConstantPool); 416 | 417 | } 418 | } 419 | else if (ClassFile.ConstantPool.Item(i) is ConstantPoolMethodInfo) 420 | { 421 | // check the descriptor 422 | // - for fields this is the field type 423 | // - for methods this is the parameter list 424 | ClassFile.ChangeConstantFieldType(i, OldParentName, NewParentName); 425 | } 426 | } 427 | } 428 | private void FixReferences(ArrayList MasterChangeList) 429 | { 430 | // loop through the change record's and apply them to each file 431 | // (except itself) 432 | for (int i = 0; i < FClassFiles.Count; i++) 433 | { 434 | for (int j = 0; j < MasterChangeList.Count; j++) 435 | { 436 | FixReferencePass1(i, (ArrayList)MasterChangeList[j], (ArrayList)MasterChangeList[i]); 437 | } 438 | } 439 | 440 | for (int i = 0; i < FClassFiles.Count; i++) 441 | { 442 | for (int j = 0; j < MasterChangeList.Count; j++) 443 | { 444 | FixReferencePass2(i, (ArrayList)MasterChangeList[j]); 445 | } 446 | } 447 | } 448 | /// 449 | /// Find the index of the parent of the classfile, if it exists in the project. 450 | /// Returns: positive integer index if found, else -1 if not found 451 | /// 452 | /// Index of class file to find parent of 453 | /// 454 | int FindParent(int Index) 455 | { 456 | string ParentName = ((TClassFile)FClassFiles[Index]).SuperClassName; 457 | 458 | for (int i = 0; i < FClassFiles.Count; i++) 459 | { 460 | if (i != Index && ((TClassFile)FClassFiles[i]).ThisClassName == ParentName) 461 | { 462 | return i; 463 | } 464 | } 465 | 466 | return -1; 467 | } 468 | /*int FindClass(string ClassName) 469 | { 470 | for (int i = 0; i < FClassFiles.Count; i++) 471 | { 472 | if (((TClassFile)FClassFiles[i]).ThisClassName == ClassName) 473 | { 474 | return i; 475 | } 476 | } 477 | 478 | return -1; 479 | }*/ 480 | int FindInterface(string ClassName) 481 | { 482 | for (int i = 0; i < FClassFiles.Count; i++) 483 | { 484 | if (((TClassFile)FClassFiles[i]).AccessFlags == AccessFlags.ACC_INTERFACE && 485 | ((TClassFile)FClassFiles[i]).ThisClassName == ClassName) 486 | { 487 | return i; 488 | } 489 | } 490 | 491 | return -1; 492 | } 493 | ArrayList AddInheritance(int Index, ArrayList MasterChangeList) 494 | { 495 | int Parent = FindParent(Index); 496 | 497 | if (Parent >= 0) 498 | { 499 | ArrayList OriginalChangeList = (ArrayList)MasterChangeList[Index]; 500 | ArrayList ParentChangeList = (ArrayList)MasterChangeList[Parent]; 501 | 502 | for (int i = 2; i < ParentChangeList.Count; i++) 503 | { 504 | // add the rest of the parent entries to the original 505 | OriginalChangeList.Add(ParentChangeList[i]); 506 | } 507 | 508 | // last of all, if the parent has another parent, recurse and do it all again 509 | if (FindParent(Parent) >= 0) 510 | { 511 | MasterChangeList = AddInheritance(Parent, MasterChangeList); 512 | } 513 | } 514 | 515 | return MasterChangeList; 516 | } 517 | ArrayList AddInterfaces(int Index, ArrayList MasterChangeList) 518 | { 519 | // this needs to work differently to inheritance 520 | // it does the following: 521 | // 1. loop through each interface 522 | // 2. check the MasterChangeList for a matching interface 523 | // 3. if found, for all methods in the deobfuscated interface, find corresponding entry in 524 | // current classes change list, and update it 525 | // 526 | TClassFile ClassFile = (TClassFile)FClassFiles[Index]; 527 | 528 | // for each class file, check each of its interfaces 529 | for (int i = 0; i < ClassFile.Interfaces.Items.Count; i++) 530 | { 531 | // check each interface if it matches any deobfuscated classfile/interface in the project 532 | for (int j = 0; j < FClassFiles.Count; j++) 533 | { 534 | string OldName = (string)((ArrayList)MasterChangeList[j])[0]; 535 | 536 | if (OldName == ClassFile.Interfaces.Item(i).Name) 537 | { 538 | ArrayList OriginalChangeList = (ArrayList)MasterChangeList[Index]; 539 | ArrayList InterfaceChangeList = (ArrayList)MasterChangeList[j]; 540 | 541 | for (int k = 2; k < InterfaceChangeList.Count; k++) 542 | { 543 | // add the rest of the parent entries to the original 544 | // NOTE: this might work best if added to the START of the list! 545 | OriginalChangeList.Insert(2, InterfaceChangeList[k]); 546 | } 547 | 548 | break; 549 | } 550 | } 551 | } 552 | 553 | return MasterChangeList; 554 | } 555 | ArrayList FixInheritance(ArrayList MasterChangeList) 556 | { 557 | for (int i = 0; i < FClassFiles.Count; i++) 558 | { 559 | MasterChangeList = AddInheritance(i, MasterChangeList); 560 | //MasterChangeList = AddInterfaces(i, MasterChangeList); 561 | } 562 | 563 | return MasterChangeList; 564 | } 565 | public ArrayList DeObfuscateAll() 566 | { 567 | return DeObfuscateAll(null); 568 | } 569 | public ArrayList DeObfuscateAll(RenameDatabase RenameStore) 570 | { 571 | FClassFiles = new ArrayList(); 572 | FInterfaces = new ArrayList(); 573 | ArrayList MasterChangeList = new ArrayList(); 574 | ArrayList NewFileNameList = new ArrayList(); 575 | int curr_progress = 0; 576 | 577 | Progress(0); 578 | 579 | // open each class file and add to array 580 | foreach (string fn in FFiles) 581 | { 582 | TClassFile cf = new TClassFile(fn); 583 | 584 | if (cf != null) 585 | { 586 | if (cf.Open()) 587 | { 588 | FClassFiles.Add(cf); 589 | 590 | Progress(++curr_progress); 591 | } 592 | } 593 | } 594 | 595 | // do all the work in memory 596 | for (int i = 0; i < FClassFiles.Count; i++) 597 | { 598 | // this deobfuscates a single class, and keeps a record of all the changes 599 | // in an arraylist of ChangeRecords 600 | // 601 | // we need more here! 602 | // 603 | // first, if the file we deobfuscated had a parent, we have to add the entire change list 604 | // from the parent to the end of the current (recursively), minus the old/new name 605 | // note: this duplications of data fixes problems with inheritance 606 | // 607 | MasterChangeList.Add(DeObfuscateSingleFile(i, RenameStore)); 608 | 609 | Progress(i + 1); 610 | } 611 | 612 | Progress(0); 613 | curr_progress = 0; 614 | 615 | // iterate through all the class files using the change records saved 616 | // after the deobfuscation was done 617 | MasterChangeList = FixInheritance(MasterChangeList); 618 | 619 | // iterate through all the class files using the change records saved 620 | // after the deobfuscation was done 621 | FixReferences(MasterChangeList); 622 | 623 | // save all the class files 624 | for (int i = 0; i < FClassFiles.Count; i++) 625 | { 626 | TClassFile cf = (TClassFile)FClassFiles[i]; 627 | 628 | // extract the actual filename from the path and replace it with the new ClassName 629 | string file_name;//= Path.GetDirectoryName(cf.FileName) + Path.DirectorySeparatorChar + Common.GetClassName(cf.ThisClassName) + ".class"; 630 | 631 | file_name = Path.Combine(this.OutputDir, Common.GetClassName(cf.ThisClassName) + ".class"); 632 | 633 | 634 | if (File.Exists(file_name)) 635 | { 636 | file_name = Path.Combine(this.OutputDir, Common.GetClassName(cf.ThisClassName) + cf.ThisClassCode + ".class"); 637 | } 638 | 639 | if (File.Exists(file_name)) 640 | { 641 | file_name = Path.Combine(this.OutputDir, Common.GetClassName(cf.ThisClassName) + ((i * cf.ThisClassCode) + i) + ".class"); 642 | } 643 | 644 | 645 | //file_name = file_name.Replace('/', '\\'); 646 | 647 | //if ((file_name != cf.FileName) && FCleanup) 648 | //{ 649 | // File.Delete(cf.FileName); 650 | //} 651 | 652 | 653 | // if for some reason the directory doesn't exist, create it 654 | if (!Directory.Exists(Path.GetDirectoryName(file_name))) 655 | Directory.CreateDirectory(Path.GetDirectoryName(file_name)); 656 | 657 | cf.Save(file_name); 658 | 659 | // return the new filename so the main gui knows what to reload 660 | NewFileNameList.Add(file_name); 661 | 662 | Progress(++curr_progress); 663 | } 664 | 665 | return NewFileNameList; 666 | } 667 | 668 | public bool ThoroughMode 669 | { 670 | get 671 | { 672 | return FThoroughMode; 673 | } 674 | set 675 | { 676 | FThoroughMode = value; 677 | } 678 | } 679 | public bool RenameClasses 680 | { 681 | get 682 | { 683 | return FRenameClasses; 684 | } 685 | set 686 | { 687 | FRenameClasses = value; 688 | } 689 | } 690 | } 691 | 692 | // ******************************************************************************** // 693 | // *************************** JAVA CLASS WRAPPER ******************************** // 694 | // ******************************************************************************** // 695 | // These class encapsulates the java .class file 696 | // With a few special methods jammed in to help rename methods and fields (and refs) 697 | 698 | class TClassFile 699 | { 700 | // my internal variables 701 | string FThisClassName; 702 | string FSuperClassName; 703 | // internal class file members as designated by Sun 704 | private uint FMagic; 705 | private ushort FMinorVersion; 706 | private ushort FMajorVersion; 707 | //private ushort FConstantPoolCount; 708 | private TConstantPool FConstantPool; 709 | private AccessFlags FAccessFlags; 710 | private ushort FThisClass; 711 | private ushort FSuperClass; 712 | //private ushort FInterfacesCount; 713 | private TInterfaces FInterfaces; 714 | //private ushort FFieldsCount; 715 | private TFields FFields; 716 | //private ushort FMethodsCount; 717 | private TMethods FMethods; 718 | //private ushort FAttributesCount; 719 | private TAttributes FAttributes; 720 | 721 | // internal variables 722 | private string FClassFileName = ""; 723 | private BinaryReader FReader = null; 724 | public ushort ThisClassCode 725 | { 726 | get { return FThisClass; } 727 | } 728 | 729 | public TClassFile(String ClassFileName) 730 | { 731 | FClassFileName = ClassFileName; 732 | //FHasBeenOpened = false; 733 | FThisClassName = ""; 734 | FSuperClassName = ""; 735 | } 736 | 737 | public bool Open() 738 | { 739 | if (File.Exists(FClassFileName)) 740 | { 741 | try 742 | { 743 | // read the .class file systematically 744 | FileStream fs = new FileStream(FClassFileName, FileMode.Open, FileAccess.Read); 745 | FReader = new BinaryReader(fs); 746 | // read header 747 | FMagic = Common.ReadDWord(FReader); 748 | 749 | if (FMagic != 0x0CAFEBABE) 750 | return false; 751 | 752 | FMinorVersion = Common.ReadWord(FReader); 753 | FMajorVersion = Common.ReadWord(FReader); 754 | // read constant pool 755 | // this also reads the "FConstantPoolCount" 756 | // so instead use FConstantPool.MaxItems or somesuch 757 | FConstantPool = new TConstantPool(FReader); 758 | // more constants 759 | FAccessFlags = (AccessFlags)Common.ReadWord(FReader); 760 | FThisClass = Common.ReadWord(FReader); 761 | FThisClass--; 762 | FSuperClass = Common.ReadWord(FReader); 763 | FSuperClass--; 764 | 765 | FThisClassName = ((ConstantClassInfo)FConstantPool.Item(FThisClass)).Name; 766 | (FConstantPool.Item(FThisClass)).References++; 767 | FSuperClassName = ((ConstantClassInfo)FConstantPool.Item(FSuperClass)).Name; 768 | (FConstantPool.Item(FSuperClass)).References++; 769 | 770 | FInterfaces = new TInterfaces(FReader, FConstantPool); 771 | FFields = new TFields(FReader, FConstantPool); 772 | FMethods = new TMethods(FReader, FConstantPool); 773 | FAttributes = new TAttributes(FReader, FConstantPool); 774 | 775 | //FHasBeenOpened = true; 776 | 777 | fs.Close(); 778 | return true; 779 | } 780 | catch (Exception e) 781 | { 782 | // catch any unhandled exceptions here 783 | // and exit gracefully. 784 | // garbage collection does the rest ;D 785 | return false; 786 | } 787 | } 788 | 789 | return false; 790 | } 791 | public bool Save(string FileName) 792 | { 793 | if (true)//FHasBeenOpened) 794 | { 795 | try 796 | { 797 | // read the .class file systematically 798 | FileStream fs = new FileStream(FileName, FileMode.Create, FileAccess.Write); 799 | BinaryWriter FWriter = new BinaryWriter(fs); 800 | // write header 801 | Common.WriteDWord(FWriter, FMagic); 802 | 803 | Common.WriteWord(FWriter, FMinorVersion); 804 | Common.WriteWord(FWriter, FMajorVersion); 805 | // write constant pool 806 | // this also writes the "FConstantPoolCount" 807 | FConstantPool.Write(FWriter); 808 | // more constants 809 | Common.WriteWord(FWriter, (int)FAccessFlags); 810 | Common.WriteWord(FWriter, FThisClass + 1); 811 | Common.WriteWord(FWriter, FSuperClass + 1); 812 | 813 | FInterfaces.Write(FWriter); 814 | FFields.Write(FWriter); 815 | FMethods.Write(FWriter); 816 | FAttributes.Write(FWriter); 817 | 818 | FWriter.Close(); 819 | return true; 820 | } 821 | catch (Exception e) 822 | { 823 | // catch any unhandled exceptions here 824 | // and exit gracefully. 825 | // garbage collection does the rest ;D 826 | return false; 827 | } 828 | } 829 | } 830 | public uint Magic 831 | { 832 | get 833 | { 834 | return FMagic; 835 | } 836 | set 837 | { 838 | FMagic = value; 839 | } 840 | } 841 | public string Version() 842 | { 843 | return FMajorVersion.ToString() + "." + FMinorVersion.ToString(); 844 | } 845 | public string FileName 846 | { 847 | get 848 | { 849 | return FClassFileName; 850 | } 851 | } 852 | public AccessFlags AccessFlags 853 | { 854 | get 855 | { 856 | return FAccessFlags; 857 | } 858 | } 859 | 860 | public TConstantPool ConstantPool 861 | { 862 | get 863 | { 864 | return FConstantPool; 865 | } 866 | } 867 | public TInterfaces Interfaces 868 | { 869 | get 870 | { 871 | return FInterfaces; 872 | } 873 | } 874 | public TFields Fields 875 | { 876 | get 877 | { 878 | return FFields; 879 | } 880 | } 881 | public TMethods Methods 882 | { 883 | get 884 | { 885 | return FMethods; 886 | } 887 | } 888 | public TAttributes Attributes 889 | { 890 | get 891 | { 892 | return FAttributes; 893 | } 894 | } 895 | 896 | public TChangeRecord ChangeMethodName(int MethodNumber, string NewName) 897 | { 898 | MethodInfo Method = (MethodInfo)FMethods.Items[MethodNumber]; 899 | //MethodInfo OriginalMethod = Method.Clone(); 900 | //MethodInfo NewMethod = null; 901 | TChangeRecord Result = null; 902 | ConstantMethodrefInfo MethodRef = null; 903 | ushort NewNameIndex; 904 | 905 | // first we need to loop through the constant pool for method 906 | // references that match our new method name 907 | for (int i = 0; i < FConstantPool.MaxItems(); i++) 908 | { 909 | if (FConstantPool.Item(i).Tag == (byte)ConstantPoolInfoTag.ConstantMethodref) 910 | { 911 | MethodRef = (ConstantMethodrefInfo)FConstantPool.Item(i); 912 | if (MethodRef.ParentClass.Name == FThisClassName && 913 | MethodRef.NameAndType.Name == Method.Name.Value && 914 | MethodRef.NameAndType.Descriptor == Method.Descriptor) 915 | { 916 | // jackpot, we found the reference! 917 | // there should be only one, so we will break and fix it up after we generate the new name 918 | break; 919 | } 920 | } 921 | 922 | MethodRef = null; 923 | } 924 | 925 | Method.Name.References--; 926 | // add a new string constant to the pool 927 | ConstantUtf8Info NewUtf = new ConstantUtf8Info(NewName); 928 | 929 | NewNameIndex = ConstantPool.Add(NewUtf); 930 | 931 | // set the method its new name 932 | Method.SetName(NewNameIndex, ConstantPool); 933 | Method.Name.References = 1; 934 | 935 | //NewMethod = Method.Clone(); 936 | 937 | if (MethodRef == null) 938 | return Result; 939 | 940 | if (MethodRef.NameAndType.References <= 1) 941 | { 942 | // if this is the only reference to the name/type descriptor 943 | // we can overwrite the value 944 | MethodRef.NameAndType.SetName(NewNameIndex, FConstantPool); 945 | } 946 | else 947 | { 948 | // we have to make a new one ! 949 | MethodRef.NameAndType.References--; 950 | // add a new string constant to the pool 951 | ConstantNameAndTypeInfo NewNaT = new ConstantNameAndTypeInfo(NewNameIndex, MethodRef.NameAndType.TypeIndex, FConstantPool); 952 | 953 | ushort NewIndex = ConstantPool.Add(NewNaT); 954 | 955 | // set the method its new name 956 | MethodRef.SetNameAndType(NewIndex, ConstantPool); 957 | MethodRef.NameAndType.References = 1; 958 | } 959 | 960 | return Result; 961 | } 962 | public TChangeRecord ChangeFieldName(int FieldNumber, string NewName) 963 | { 964 | FieldInfo Field = (FieldInfo)FFields.Items[FieldNumber]; 965 | //FieldInfo OriginalFieldInfo = Field.Clone(); 966 | //FieldInfo NewField = null; 967 | TChangeRecord Result = null; 968 | ConstantFieldrefInfo FieldRef = null; 969 | ushort NewNameIndex; 970 | 971 | // first we need to loop through the constant pool for method 972 | // references that match our new method name 973 | for (int i = 0; i < FConstantPool.MaxItems(); i++) 974 | { 975 | if (FConstantPool.Item(i).Tag == (byte)ConstantPoolInfoTag.ConstantFieldref) 976 | { 977 | FieldRef = (ConstantFieldrefInfo)FConstantPool.Item(i); 978 | if (FieldRef.ParentClass.Name == FThisClassName && 979 | FieldRef.NameAndType.Name == Field.Name.Value && 980 | FieldRef.NameAndType.Descriptor == Field.Descriptor) 981 | { 982 | // jackpot, we found the reference! 983 | // there should be only one, so we will break and fix it up after we generate the new name 984 | break; 985 | } 986 | } 987 | 988 | FieldRef = null; 989 | } 990 | 991 | Field.Name.References--; 992 | 993 | // add a new string constant to the pool 994 | ConstantUtf8Info NewUtf = new ConstantUtf8Info(NewName); 995 | 996 | NewNameIndex = ConstantPool.Add(NewUtf); 997 | 998 | // set the method its new name 999 | Field.SetName(NewNameIndex, ConstantPool); 1000 | Field.Name.References = 1; 1001 | 1002 | //NewField = Field.Clone(); 1003 | 1004 | if (FieldRef == null) 1005 | return Result; 1006 | 1007 | if (FieldRef.NameAndType.References <= 1) 1008 | { 1009 | // if this is the only reference to the name/type descriptor 1010 | // we can overwrite the value 1011 | FieldRef.NameAndType.SetName(NewNameIndex, FConstantPool); 1012 | } 1013 | else 1014 | { 1015 | // we have to make a new one ! 1016 | FieldRef.NameAndType.References--; 1017 | // add a new string constant to the pool 1018 | ConstantNameAndTypeInfo NewNaT = new ConstantNameAndTypeInfo(NewNameIndex, FieldRef.NameAndType.TypeIndex, FConstantPool); 1019 | 1020 | ushort NewIndex = ConstantPool.Add(NewNaT); 1021 | 1022 | // set the method its new name 1023 | FieldRef.SetNameAndType(NewIndex, ConstantPool); 1024 | FieldRef.NameAndType.References = 1; 1025 | } 1026 | 1027 | return Result; 1028 | } 1029 | public void ChangeConstantFieldName(int FieldNumber, string NewName) 1030 | { 1031 | // takes an index into the constantpool 1032 | // simple changes the name of a method/field in the constant pool 1033 | // always create new name 1034 | // TODO: check this! 1035 | 1036 | ConstantPoolMethodInfo FieldRef = (ConstantPoolMethodInfo)FConstantPool.Item(FieldNumber); 1037 | 1038 | ConstantUtf8Info NewNameString = new ConstantUtf8Info(NewName); 1039 | ushort NewNameIndex = FConstantPool.Add(NewNameString); 1040 | 1041 | // we have to make a new one ! 1042 | FieldRef.NameAndType.References--; 1043 | // add a new string constant to the pool 1044 | ConstantNameAndTypeInfo NewNaT = new ConstantNameAndTypeInfo(NewNameIndex, FieldRef.NameAndType.TypeIndex, FConstantPool); 1045 | 1046 | ushort NewIndex = FConstantPool.Add(NewNaT); 1047 | 1048 | // set the method its new name 1049 | FieldRef.SetNameAndType(NewIndex, FConstantPool); 1050 | FieldRef.NameAndType.References = 1; 1051 | } 1052 | public void ChangeConstantFieldParent(int FieldNumber, int ParentNumber) 1053 | { 1054 | ConstantPoolMethodInfo FieldRef = (ConstantPoolMethodInfo)FConstantPool.Item(FieldNumber); 1055 | 1056 | FieldRef.ParentClass.References--; 1057 | FieldRef.SetParent((ushort)ParentNumber, FConstantPool); 1058 | } 1059 | public void ChangeConstantFieldType(int FieldNumber, string OldParentName, string NewParentName) 1060 | { 1061 | // takes an index into the constantpool 1062 | // simple changes the name of a method/field in the constant pool 1063 | // always create new name 1064 | // TODO: check this! 1065 | 1066 | ConstantPoolMethodInfo FieldRef = (ConstantPoolMethodInfo)FConstantPool.Item(FieldNumber); 1067 | string OldName = FieldRef.NameAndType.Descriptor; 1068 | string NewName = Common.FixDescriptor(FieldRef.NameAndType.Descriptor, OldParentName, NewParentName); 1069 | 1070 | if (OldName == NewName) 1071 | return; 1072 | 1073 | ConstantUtf8Info NewTypeString = new ConstantUtf8Info(NewName); 1074 | ushort NewTypeIndex = FConstantPool.Add(NewTypeString); 1075 | 1076 | FieldRef.NameAndType.SetType(NewTypeIndex, FConstantPool); 1077 | } 1078 | public void ChangeFieldType(int FieldNumber, string OldParentName, string NewParentName) 1079 | { 1080 | // takes an index into the constantpool 1081 | // simple changes the name of a method/field in the constant pool 1082 | // TODO: check this! 1083 | 1084 | FieldInfo FieldRef = FFields.Item(FieldNumber); 1085 | 1086 | string OldName = FieldRef.Descriptor; 1087 | string NewName = Common.FixDescriptor(FieldRef.Descriptor, OldParentName, NewParentName); 1088 | 1089 | if (OldName == NewName) 1090 | return; 1091 | 1092 | ConstantUtf8Info NewTypeString = new ConstantUtf8Info(NewName); 1093 | ushort NewTypeIndex = FConstantPool.Add(NewTypeString); 1094 | 1095 | // set the method its new name 1096 | FieldRef.SetType(NewTypeIndex, FConstantPool); 1097 | } 1098 | public void ChangeMethodParam(int MethodNumber, string OldParentName, string NewParentName) 1099 | { 1100 | // takes an index into the constantpool 1101 | // simple changes the name of a method/field in the constant pool 1102 | // TODO: check this! 1103 | 1104 | MethodInfo MethodRef = FMethods.Item(MethodNumber); 1105 | 1106 | string OldName = MethodRef.Descriptor; 1107 | string NewName = Common.FixDescriptor(MethodRef.Descriptor, OldParentName, NewParentName); 1108 | 1109 | if (OldName == NewName) 1110 | return; 1111 | 1112 | ConstantUtf8Info NewTypeString = new ConstantUtf8Info(NewName); 1113 | ushort NewTypeIndex = FConstantPool.Add(NewTypeString); 1114 | 1115 | // set the method its new name 1116 | MethodRef.SetType(NewTypeIndex, FConstantPool); 1117 | } 1118 | public void ChangeInterfaceName(int InterfaceNumber, string NewName) 1119 | { 1120 | // takes an index into the interface list 1121 | // simple changes the name of a method/field in the constant pool 1122 | // TODO: check this! 1123 | 1124 | InterfaceInfo IntInfo = FInterfaces.Item(InterfaceNumber); 1125 | 1126 | if (IntInfo.Name == NewName) 1127 | return; 1128 | 1129 | ConstantUtf8Info NewTypeString = new ConstantUtf8Info(NewName); 1130 | ushort NewTypeIndex = FConstantPool.Add(NewTypeString); 1131 | 1132 | // set the interface its new name 1133 | ConstantClassInfo cci = (ConstantClassInfo)ConstantPool.Item(IntInfo.Value); 1134 | cci.SetName(NewTypeIndex, FConstantPool); 1135 | } 1136 | public string ThisClassName 1137 | { 1138 | get 1139 | { 1140 | return FThisClassName; 1141 | } 1142 | } 1143 | public string SuperClassName 1144 | { 1145 | get 1146 | { 1147 | return FSuperClassName; 1148 | } 1149 | } 1150 | public string ChangeClassName(string Name) 1151 | { 1152 | ConstantClassInfo ClassInfo = (ConstantClassInfo)FConstantPool.Item(FThisClass); 1153 | ConstantUtf8Info UtfInfo = (ConstantUtf8Info)FConstantPool.Item(ClassInfo.NameIndex); 1154 | 1155 | // change the class name, not the directory structure 1156 | Name = Common.NewClassName(ThisClassName, Name); 1157 | 1158 | // we have to make a new one ! 1159 | UtfInfo.References--; 1160 | // add a new string constant to the pool 1161 | ConstantUtf8Info NewUtf = new ConstantUtf8Info(Name); 1162 | 1163 | ushort NewIndex = ConstantPool.Add(NewUtf); 1164 | 1165 | // set the method its new name 1166 | ClassInfo.SetName(NewIndex, FConstantPool); 1167 | NewUtf.References = 1; 1168 | 1169 | FThisClassName = ((ConstantClassInfo)FConstantPool.Item(FThisClass)).Name; 1170 | 1171 | return Name; 1172 | } 1173 | public int ChangeSuperClassName(string NewName) 1174 | { 1175 | ConstantClassInfo ClassInfo = (ConstantClassInfo)FConstantPool.Item(FSuperClass); 1176 | ConstantUtf8Info UtfInfo = (ConstantUtf8Info)FConstantPool.Item(ClassInfo.NameIndex); 1177 | 1178 | // skip this coz we already passing the full name in 1179 | //NewName = Common.NewClassName(FSuperClassName, NewName); 1180 | 1181 | if (UtfInfo.References <= 1) 1182 | { 1183 | // if this is the only reference to the name/type descriptor 1184 | // we can overwrite the value 1185 | UtfInfo.SetName(NewName); 1186 | } 1187 | else 1188 | { 1189 | // we have to make a new one ! 1190 | UtfInfo.References--; 1191 | // add a new string constant to the pool 1192 | ConstantUtf8Info NewUtf = new ConstantUtf8Info(NewName); 1193 | 1194 | ushort NewIndex = ConstantPool.Add(NewUtf); 1195 | 1196 | // set the method its new name 1197 | ClassInfo.NameIndex = NewIndex; 1198 | NewUtf.References = 1; 1199 | } 1200 | 1201 | FSuperClassName = ((ConstantClassInfo)FConstantPool.Item(FSuperClass)).Name; 1202 | 1203 | return FSuperClass; 1204 | } 1205 | public int AddConstantClassName(string NewName) 1206 | { 1207 | ConstantClassInfo ClassInfo = new ConstantClassInfo(); 1208 | ConstantUtf8Info UtfInfo = new ConstantUtf8Info(); 1209 | 1210 | ushort NewClassIndex = FConstantPool.Add(ClassInfo); 1211 | ushort NewUtfIndex = FConstantPool.Add(UtfInfo); 1212 | 1213 | UtfInfo.SetName(NewName); 1214 | ClassInfo.SetName(NewUtfIndex, FConstantPool); 1215 | 1216 | return NewClassIndex; 1217 | } 1218 | 1219 | } 1220 | 1221 | // ******************************************************************************** // 1222 | // *************************** CLASS CHANGE RECORD ******************************** // 1223 | // ******************************************************************************** // 1224 | // These classes are used to keep track of all the changes i make during deobfuscation 1225 | // of a single class. They are then used to iterate through all the rest of the files 1226 | // in the current "project" and fix up any references to the methods/fields we changed 1227 | 1228 | abstract class TChangeRecord { } 1229 | class TMethodChangeRecord : TChangeRecord 1230 | { 1231 | // just a simple class to hold the information temporarily 1232 | private MethodInfo FOriginalMethod; 1233 | private MethodInfo FNewMethod; 1234 | 1235 | public TMethodChangeRecord(MethodInfo Original) 1236 | { 1237 | FOriginalMethod = Original.Clone(); 1238 | } 1239 | public void ChangedTo(MethodInfo New) 1240 | { 1241 | FNewMethod = New.Clone(); 1242 | } 1243 | public MethodInfo OriginalMethod 1244 | { 1245 | get 1246 | { 1247 | return FOriginalMethod; 1248 | } 1249 | } 1250 | public MethodInfo NewMethod 1251 | { 1252 | get 1253 | { 1254 | return FNewMethod; 1255 | } 1256 | } 1257 | } 1258 | class TFieldChangeRecord : TChangeRecord 1259 | { 1260 | // just a simple class to hold the information temporarily 1261 | private FieldInfo FOriginalField; 1262 | private FieldInfo FNewField; 1263 | 1264 | public TFieldChangeRecord(FieldInfo Original) 1265 | { 1266 | FOriginalField = Original.Clone(); 1267 | } 1268 | public void ChangedTo(FieldInfo New) 1269 | { 1270 | FNewField = New.Clone(); 1271 | } 1272 | public FieldInfo OriginalField 1273 | { 1274 | get 1275 | { 1276 | return FOriginalField; 1277 | } 1278 | } 1279 | public FieldInfo NewField 1280 | { 1281 | get 1282 | { 1283 | return FNewField; 1284 | } 1285 | } 1286 | } 1287 | 1288 | // ******************************************************************************** // 1289 | // **************************** INDIVIDUAL CLASSES ******************************** // 1290 | // ******************************************************************************** // 1291 | // These are all used by TClassFile to import each of its major sections 1292 | 1293 | class TConstantPool 1294 | { 1295 | BinaryReader FReader; 1296 | ArrayList FItems = null; 1297 | 1298 | int FMaxItems = 0; 1299 | 1300 | public TConstantPool(BinaryReader Reader) 1301 | { 1302 | FReader = Reader; 1303 | 1304 | FMaxItems = Common.ReadWord(FReader) - 1; 1305 | FItems = new ArrayList(); 1306 | int count = 0; 1307 | 1308 | // goes from 1 -> constantpoolcount - 1 1309 | while (count < FMaxItems) 1310 | { 1311 | byte tag = Common.ReadByte(FReader); 1312 | 1313 | switch (tag) 1314 | { 1315 | case (byte)ConstantPoolInfoTag.ConstantClass: 1316 | { 1317 | ConstantClassInfo cc = new ConstantClassInfo(); 1318 | cc.Read(tag, FReader); 1319 | FItems.Add(cc); 1320 | break; 1321 | } 1322 | case (byte)ConstantPoolInfoTag.ConstantString: 1323 | { 1324 | ConstantStringInfo cc = new ConstantStringInfo(); 1325 | cc.Read(tag, FReader); 1326 | FItems.Add(cc); 1327 | break; 1328 | } 1329 | case (byte)ConstantPoolInfoTag.ConstantFieldref: 1330 | { 1331 | ConstantFieldrefInfo cc = new ConstantFieldrefInfo(); 1332 | cc.Read(tag, FReader); 1333 | FItems.Add(cc); 1334 | break; 1335 | } 1336 | case (byte)ConstantPoolInfoTag.ConstantMethodref: 1337 | { 1338 | ConstantMethodrefInfo cc = new ConstantMethodrefInfo(); 1339 | cc.Read(tag, FReader); 1340 | FItems.Add(cc); 1341 | break; 1342 | } 1343 | case (byte)ConstantPoolInfoTag.ConstantInterfaceMethodref: 1344 | { 1345 | ConstantInterfaceMethodrefInfo cc = new ConstantInterfaceMethodrefInfo(); 1346 | cc.Read(tag, FReader); 1347 | FItems.Add(cc); 1348 | break; 1349 | } 1350 | case (byte)ConstantPoolInfoTag.ConstantInteger: 1351 | { 1352 | ConstantIntegerInfo cc = new ConstantIntegerInfo(); 1353 | cc.Read(tag, FReader); 1354 | FItems.Add(cc); 1355 | break; 1356 | } 1357 | case (byte)ConstantPoolInfoTag.ConstantFloat: 1358 | { 1359 | ConstantFloatInfo cc = new ConstantFloatInfo(); 1360 | cc.Read(tag, FReader); 1361 | FItems.Add(cc); 1362 | break; 1363 | } 1364 | case (byte)ConstantPoolInfoTag.ConstantLong: 1365 | { 1366 | ConstantLongInfo cc = new ConstantLongInfo(); 1367 | cc.Read(tag, FReader); 1368 | FItems.Add(cc); 1369 | // longs take up two entries in the pool table 1370 | count++; 1371 | FItems.Add(cc); 1372 | break; 1373 | } 1374 | case (byte)ConstantPoolInfoTag.ConstantDouble: 1375 | { 1376 | ConstantDoubleInfo cc = new ConstantDoubleInfo(); 1377 | cc.Read(tag, FReader); 1378 | FItems.Add(cc); 1379 | // so do doubles 1380 | count++; 1381 | FItems.Add(cc); 1382 | break; 1383 | } 1384 | case (byte)ConstantPoolInfoTag.ConstantNameAndType: 1385 | { 1386 | ConstantNameAndTypeInfo cc = new ConstantNameAndTypeInfo(); 1387 | cc.Read(tag, FReader); 1388 | FItems.Add(cc); 1389 | break; 1390 | } 1391 | case (byte)ConstantPoolInfoTag.ConstantUtf8: 1392 | { 1393 | ConstantUtf8Info cc = new ConstantUtf8Info(); 1394 | cc.Read(tag, FReader); 1395 | FItems.Add(cc); 1396 | break; 1397 | } 1398 | 1399 | default: 1400 | // fail safe ? 1401 | count++; 1402 | break; 1403 | } 1404 | 1405 | count++; 1406 | } 1407 | 1408 | foreach (ConstantPoolInfo cc in FItems) 1409 | { 1410 | cc.Resolve(FItems); 1411 | } 1412 | } 1413 | public void Write(BinaryWriter Writer) 1414 | { 1415 | // i am assuming we have a valid constant pool list... 1416 | // i dont do any error checking here except bare minimum! 1417 | 1418 | // write the number of constant pool entries 1419 | Common.WriteWord(Writer, FMaxItems + 1); 1420 | int count = 0; 1421 | 1422 | // goes from 1 -> constantpoolcount - 1 1423 | while (count < FMaxItems) 1424 | { 1425 | ConstantPoolInfo Item = (ConstantPoolInfo)FItems[count]; 1426 | 1427 | switch (Item.Tag) 1428 | { 1429 | case (byte)ConstantPoolInfoTag.ConstantClass: 1430 | { 1431 | ConstantClassInfo cc = (ConstantClassInfo)Item; 1432 | cc.Write(Writer); 1433 | 1434 | break; 1435 | } 1436 | case (byte)ConstantPoolInfoTag.ConstantString: 1437 | { 1438 | ConstantStringInfo cc = (ConstantStringInfo)Item; 1439 | cc.Write(Writer); 1440 | 1441 | break; 1442 | } 1443 | case (byte)ConstantPoolInfoTag.ConstantFieldref: 1444 | { 1445 | ConstantFieldrefInfo cc = (ConstantFieldrefInfo)Item; 1446 | cc.Write(Writer); 1447 | 1448 | break; 1449 | } 1450 | case (byte)ConstantPoolInfoTag.ConstantMethodref: 1451 | { 1452 | ConstantMethodrefInfo cc = (ConstantMethodrefInfo)Item; 1453 | cc.Write(Writer); 1454 | 1455 | break; 1456 | } 1457 | case (byte)ConstantPoolInfoTag.ConstantInterfaceMethodref: 1458 | { 1459 | ConstantInterfaceMethodrefInfo cc = (ConstantInterfaceMethodrefInfo)Item; 1460 | cc.Write(Writer); 1461 | 1462 | break; 1463 | } 1464 | case (byte)ConstantPoolInfoTag.ConstantInteger: 1465 | { 1466 | ConstantIntegerInfo cc = (ConstantIntegerInfo)Item; 1467 | cc.Write(Writer); 1468 | 1469 | break; 1470 | } 1471 | case (byte)ConstantPoolInfoTag.ConstantFloat: 1472 | { 1473 | ConstantFloatInfo cc = (ConstantFloatInfo)Item; 1474 | cc.Write(Writer); 1475 | 1476 | break; 1477 | } 1478 | case (byte)ConstantPoolInfoTag.ConstantLong: 1479 | { 1480 | ConstantLongInfo cc = (ConstantLongInfo)Item; 1481 | cc.Write(Writer); 1482 | 1483 | // longs take up two entries in the pool table 1484 | count++; 1485 | break; 1486 | } 1487 | case (byte)ConstantPoolInfoTag.ConstantDouble: 1488 | { 1489 | ConstantDoubleInfo cc = (ConstantDoubleInfo)Item; 1490 | cc.Write(Writer); 1491 | 1492 | // so do doubles 1493 | count++; 1494 | break; 1495 | } 1496 | case (byte)ConstantPoolInfoTag.ConstantNameAndType: 1497 | { 1498 | ConstantNameAndTypeInfo cc = (ConstantNameAndTypeInfo)Item; 1499 | cc.Write(Writer); 1500 | 1501 | break; 1502 | } 1503 | case (byte)ConstantPoolInfoTag.ConstantUtf8: 1504 | { 1505 | ConstantUtf8Info cc = (ConstantUtf8Info)Item; 1506 | cc.Write(Writer); 1507 | 1508 | break; 1509 | } 1510 | 1511 | default: 1512 | // fail safe ? 1513 | // BADDDDDDDDDDDDDDDDDDDDD, prolly should check/fix this 1514 | count++; 1515 | break; 1516 | } 1517 | 1518 | count++; 1519 | } 1520 | } 1521 | public int MaxItems() 1522 | { 1523 | return FMaxItems; 1524 | } 1525 | public ConstantPoolInfo Item(int Index) 1526 | { 1527 | if (FItems != null && Index < FMaxItems) 1528 | return (ConstantPoolInfo)FItems[Index]; 1529 | 1530 | return null; 1531 | } 1532 | public ushort Add(ConstantPoolInfo NewItem) 1533 | { 1534 | FItems.Add(NewItem); 1535 | FMaxItems++; 1536 | return (ushort)(FItems.Count - 1); 1537 | } 1538 | } 1539 | class TInterfaces 1540 | { 1541 | BinaryReader FReader; 1542 | ArrayList FItems = null; 1543 | 1544 | int FMaxItems = 0; 1545 | 1546 | public TInterfaces(BinaryReader Reader, TConstantPool ConstantPool) 1547 | { 1548 | FReader = Reader; 1549 | 1550 | FMaxItems = Common.ReadWord(FReader) - 1; 1551 | FItems = new ArrayList(); 1552 | int count = 0; 1553 | 1554 | // goes from 1 -> interfacecount - 1 1555 | while (count <= FMaxItems) 1556 | { 1557 | InterfaceInfo ii = new InterfaceInfo(FReader, ConstantPool); 1558 | FItems.Add(ii); 1559 | 1560 | count++; 1561 | } 1562 | } 1563 | 1564 | public void Write(BinaryWriter Writer) 1565 | { 1566 | Common.WriteWord(Writer, FMaxItems + 1); 1567 | 1568 | int count = 0; 1569 | 1570 | // goes from 1 -> interfacecount - 1 1571 | while (count <= FMaxItems) 1572 | { 1573 | InterfaceInfo ii = (InterfaceInfo)FItems[count]; 1574 | ii.Write(Writer); 1575 | 1576 | count++; 1577 | } 1578 | } 1579 | 1580 | public int MaxItems() 1581 | { 1582 | return FMaxItems; 1583 | } 1584 | 1585 | public InterfaceInfo Item(int Index) 1586 | { 1587 | if (Index >= 0 && Index < FItems.Count) 1588 | return (InterfaceInfo)FItems[Index]; 1589 | 1590 | // TODO: fix this fucking gay piece of shit 1591 | return (InterfaceInfo)FItems[0]; 1592 | } 1593 | 1594 | public ArrayList Items 1595 | { 1596 | get 1597 | { 1598 | return FItems; 1599 | } 1600 | } 1601 | } 1602 | class TFields 1603 | { 1604 | BinaryReader FReader; 1605 | ArrayList FItems = null; 1606 | 1607 | int FMaxItems = 0; 1608 | 1609 | public TFields(BinaryReader Reader, TConstantPool ConstantPool) 1610 | { 1611 | FReader = Reader; 1612 | 1613 | FMaxItems = Common.ReadWord(FReader); 1614 | FItems = new ArrayList(); 1615 | int count = 0; 1616 | 1617 | // goes from 1 -> fieldcount - 1 1618 | while (count < FMaxItems) 1619 | { 1620 | FieldInfo fi = new FieldInfo(FReader, ConstantPool); 1621 | FItems.Add(fi); 1622 | 1623 | count++; 1624 | } 1625 | } 1626 | 1627 | public void Write(BinaryWriter Writer) 1628 | { 1629 | Common.WriteWord(Writer, FMaxItems); 1630 | 1631 | int count = 0; 1632 | 1633 | // goes from 1 -> fieldcount - 1 1634 | while (count < FMaxItems) 1635 | { 1636 | FieldInfo fi = (FieldInfo)FItems[count]; 1637 | fi.Write(Writer); 1638 | 1639 | count++; 1640 | } 1641 | } 1642 | 1643 | public int MaxItems() 1644 | { 1645 | return FMaxItems; 1646 | } 1647 | 1648 | public FieldInfo Item(int Index) 1649 | { 1650 | if (FItems != null && Index < FMaxItems) 1651 | return (FieldInfo)FItems[Index]; 1652 | 1653 | return null; 1654 | } 1655 | 1656 | public ArrayList Items 1657 | { 1658 | get 1659 | { 1660 | return FItems; 1661 | } 1662 | } 1663 | } 1664 | class TMethods 1665 | { 1666 | BinaryReader FReader; 1667 | ArrayList FItems = null; 1668 | 1669 | int FMaxItems = 0; 1670 | 1671 | public TMethods(BinaryReader Reader, TConstantPool ConstantPool) 1672 | { 1673 | FReader = Reader; 1674 | 1675 | FMaxItems = Common.ReadWord(FReader); 1676 | FItems = new ArrayList(); 1677 | int count = 0; 1678 | 1679 | // goes from 1 -> fieldcount - 1 1680 | while (count < FMaxItems) 1681 | { 1682 | MethodInfo mi = new MethodInfo(FReader, ConstantPool); 1683 | FItems.Add(mi); 1684 | 1685 | count++; 1686 | } 1687 | } 1688 | 1689 | public void Write(BinaryWriter Writer) 1690 | { 1691 | Common.WriteWord(Writer, FMaxItems); 1692 | 1693 | int count = 0; 1694 | 1695 | // goes from 1 -> fieldcount - 1 1696 | while (count < FMaxItems) 1697 | { 1698 | MethodInfo mi = (MethodInfo)FItems[count]; 1699 | mi.Write(Writer); 1700 | 1701 | count++; 1702 | } 1703 | } 1704 | 1705 | public int MaxItems() 1706 | { 1707 | return FMaxItems; 1708 | } 1709 | 1710 | public MethodInfo Item(int Index) 1711 | { 1712 | if (FItems != null && Index < FMaxItems) 1713 | return (MethodInfo)FItems[Index]; 1714 | 1715 | return null; 1716 | } 1717 | 1718 | public ArrayList Items 1719 | { 1720 | get 1721 | { 1722 | return FItems; 1723 | } 1724 | } 1725 | 1726 | public bool MethodNameExists(string Name) 1727 | { 1728 | for (int i = 0; i < FMaxItems; i++) 1729 | { 1730 | if (Name == ((MethodInfo)FItems[i]).Name.Value) 1731 | return true; 1732 | } 1733 | 1734 | return false; 1735 | } 1736 | 1737 | public bool FieldNameExists(string Name) 1738 | { 1739 | for (int i = 0; i < FMaxItems; i++) 1740 | { 1741 | if (Name == ((FieldInfo)FItems[i]).Name.Value) 1742 | return true; 1743 | } 1744 | 1745 | return false; 1746 | } 1747 | } 1748 | class TAttributes 1749 | { 1750 | BinaryReader FReader; 1751 | ArrayList FItems = null; 1752 | 1753 | int FMaxItems = 0; 1754 | 1755 | public TAttributes(BinaryReader Reader, TConstantPool ConstantPool) 1756 | { 1757 | FReader = Reader; 1758 | 1759 | FMaxItems = Common.ReadWord(FReader) - 1; 1760 | FItems = new ArrayList(); 1761 | int count = 0; 1762 | 1763 | // goes from 1 -> attributescount - 1 1764 | while (count <= FMaxItems) 1765 | { 1766 | ushort NameIndex = Common.ReadWord(FReader); 1767 | NameIndex--; 1768 | ConstantUtf8Info Name = (ConstantUtf8Info)ConstantPool.Item(NameIndex); 1769 | 1770 | switch (Name.Value) 1771 | { 1772 | case AttributeType.Code: 1773 | { 1774 | CodeAttributeInfo ai = new CodeAttributeInfo(NameIndex, FReader, ConstantPool); 1775 | 1776 | FItems.Add(ai); 1777 | break; 1778 | } 1779 | case AttributeType.ConstantValue: 1780 | { 1781 | ConstantValueAttributeInfo ai = new ConstantValueAttributeInfo(NameIndex, FReader, ConstantPool); 1782 | 1783 | FItems.Add(ai); 1784 | break; 1785 | } 1786 | case AttributeType.Deprecated: 1787 | { 1788 | DeprecatedAttributeInfo ai = new DeprecatedAttributeInfo(NameIndex, FReader, ConstantPool); 1789 | 1790 | FItems.Add(ai); 1791 | break; 1792 | } 1793 | case AttributeType.Exceptions: 1794 | { 1795 | ExceptionsAttributeInfo ai = new ExceptionsAttributeInfo(NameIndex, FReader, ConstantPool); 1796 | 1797 | FItems.Add(ai); 1798 | break; 1799 | } 1800 | case AttributeType.InnerClasses: 1801 | { 1802 | InnerClassesAttributeInfo ai = new InnerClassesAttributeInfo(NameIndex, FReader, ConstantPool); 1803 | 1804 | FItems.Add(ai); 1805 | break; 1806 | } 1807 | case AttributeType.LineNumberTable: 1808 | { 1809 | LineNumberAttributeInfo ai = new LineNumberAttributeInfo(NameIndex, FReader, ConstantPool); 1810 | 1811 | FItems.Add(ai); 1812 | break; 1813 | } 1814 | case AttributeType.LocalVariableTable: 1815 | { 1816 | LocalVariablesAttributeInfo ai = new LocalVariablesAttributeInfo(NameIndex, FReader, ConstantPool); 1817 | 1818 | FItems.Add(ai); 1819 | break; 1820 | } 1821 | case AttributeType.SourceFile: 1822 | { 1823 | SourceFileAttributeInfo ai = new SourceFileAttributeInfo(NameIndex, FReader, ConstantPool); 1824 | 1825 | FItems.Add(ai); 1826 | break; 1827 | } 1828 | case AttributeType.Synthetic: 1829 | { 1830 | SyntheticAttributeInfo ai = new SyntheticAttributeInfo(NameIndex, FReader, ConstantPool); 1831 | 1832 | FItems.Add(ai); 1833 | break; 1834 | } 1835 | 1836 | default: 1837 | { 1838 | AttributeInfo ai = new UnknownAttributeInfo(NameIndex, FReader, ConstantPool); 1839 | 1840 | FItems.Add(ai); 1841 | break; 1842 | } 1843 | } 1844 | 1845 | count++; 1846 | } 1847 | } 1848 | 1849 | public void Write(BinaryWriter Writer) 1850 | { 1851 | Common.WriteWord(Writer, FMaxItems + 1); 1852 | 1853 | int count = 0; 1854 | 1855 | // goes from 1 -> attributescount - 1 1856 | while (count <= FMaxItems) 1857 | { 1858 | AttributeInfo Item = (AttributeInfo)FItems[count]; 1859 | 1860 | Item.Write(Writer); 1861 | 1862 | count++; 1863 | } 1864 | } 1865 | 1866 | public ArrayList Items 1867 | { 1868 | get 1869 | { 1870 | return FItems; 1871 | } 1872 | } 1873 | } 1874 | 1875 | } // end --------------------------------------------------------------------------------