pondělí 10. listopadu 2014

Procyon příklady

Následující příklad ukazuje jednoduchou dekompilaci souboru .class na adrese /path/file.class. Výsledkem této dekompilace bude výpis dekompilovaného kódu zadaného souboru do terminálu.

1
2
3
4
5
6
7
8
9
import com.strobel.decompiler.*;

    public class test {
        public static void main(String[] args) {
            PlainTextOutput output = new PlainTextOutput();
            Decompiler.decompile("/path/file.class",output);
            System.out.print(output);
        }
    }

Více práce už dá, pokud chceme získat pomocí Procyon abstraktní syntaktický strom (AST). K tomuto účelu jsem si musel napsat vlastní metodu podobnou Decompiler.decompile(...) (viz zdrojáky Procyon) a výsledný AST procházet rekurzivně.

1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import com.strobel.assembler.InputTypeLoader;
import com.strobel.assembler.metadata.DeobfuscationUtilities;
import com.strobel.assembler.metadata.IMetadataResolver;
import com.strobel.assembler.metadata.ITypeLoader;
import com.strobel.assembler.metadata.MetadataParser;
import com.strobel.assembler.metadata.MetadataSystem;
import com.strobel.assembler.metadata.TypeDefinition;
import com.strobel.assembler.metadata.TypeReference;
import com.strobel.core.VerifyArgument;
import com.strobel.decompiler.*;
import com.strobel.decompiler.languages.java.JavaFormattingOptions;
import com.strobel.decompiler.languages.java.JavaLanguage;
import com.strobel.decompiler.languages.java.ast.AstNode;
import com.strobel.decompiler.languages.java.ast.CompilationUnit;
import com.strobel.decompiler.languages.java.ast.NodeType;

public class test {
	public static void main(String[] args) { 
  
		final String internalName = "/home/greg/workspace/test-procyon/bin/test.class";
  
		/////**** zkopirovano z metody  Decompiler.decompile(...)
		final DecompilerSettings settings = new DecompilerSettings();
  
		VerifyArgument.notNull(internalName, "internalName");
		VerifyArgument.notNull(settings, "settings");
  
		final ITypeLoader typeLoader = settings.getTypeLoader() != null ? settings.getTypeLoader() : new InputTypeLoader();
		final MetadataSystem metadataSystem = new MetadataSystem(typeLoader);
  
		final TypeReference type;
  
		if (internalName.length() == 1) {
			//
			// Hack to get around classes whose descriptors clash with primitive types.
			//

			final MetadataParser parser = new MetadataParser(IMetadataResolver.EMPTY);
			final TypeReference reference = parser.parseTypeDescriptor(internalName);

			type = metadataSystem.resolve(reference);
		}
		else {
			type = metadataSystem.lookupType(internalName);
		}
  
		final TypeDefinition resolvedType;

		if (type == null || (resolvedType = type.resolve()) == null) {
			System.out.println("!!! ERROR: Failed to load class "+ internalName+".");
			return;
		}

		DeobfuscationUtilities.processType(resolvedType);

		final DecompilationOptions options = new DecompilationOptions();

		options.setSettings(settings);
		options.setFullDecompilation(true);

		if (settings.getFormattingOptions() == null) {
			settings.setFormattingOptions(JavaFormattingOptions.createDefault());
		}
		//////******* konec casti zkopirovane z Decompiler.decompile(...)



		CompilationUnit cu = new CompilationUnit();
		JavaLanguage jl = new JavaLanguage();
		cu=jl.decompileTypeToAst(resolvedType, options); // misto decompileType dekompilujeme do AST


		AstNode an = null;
		if (cu.hasChildren()){
			an = cu.getChildren().iterator().next(); 
		}else{
			System.out.println("neni dalsi");
		}

		// pro vypis vsech urovni AST stromu bude tuto metodu potreba volat rekurzivne
		show_me_smtng(an,0);
 }
  
 /*
  * vypisuje a zanoruje se hloubeji do ast stromu
  */
	private static void show_me_smtng(AstNode an, int hloubka){
  
		while (an!=null){
			final String mezera = "  "; // identifikator hloubky ve strome

			for (int i = 0 ; i < hloubka ; i++) System.out.print(mezera);
			System.out.println(an.getRole()+"("+an.getNodeType()+")"+"--"+an.getRegion()); // vypis nejzajimavejsich informaci o uzlu

			// ignorovat vypis STATEMENT, TYPE_DECLARATION a MEMBER - zbytecne moc textu
			if (an.getNodeType()!=NodeType.STATEMENT && an.getNodeType()!=NodeType.TYPE_DECLARATION && an.getNodeType()!=NodeType.MEMBER){
				for (int i = 0 ; i < hloubka ; i++) System.out.print(mezera);
				if (an.getText()!=null) System.out.println(" \""+an.getText().replaceAll("\n", "")+"\"");
			}else{
				for (int i = 0 ; i < hloubka ; i++) System.out.print(mezera);
				System.out.println(" ...");
			}

			// zanoreni hloubeji do stromu
			if (an.hasChildren()){
				for (int i = 0 ; i < hloubka ; i++) System.out.print(mezera);
				System.out.println("+childs:");

				// v pripade potreby omezeni hloubky stromu
				/*if (hloubka > 2){
					an = an.getNextSibling();
					System.out.println("--utnuto--"); 
					continue;
				}*/

				show_me_smtng(an.getFirstChild(),hloubka+1);
			}else{
				for (int i = 0 ; i < hloubka ; i++) System.out.print(mezera);
				System.out.println("-nema potomky");
			}

			System.out.println("");
			an = an.getNextSibling(); // nasledujici soused
		}
	}
}



Zdroje:
https://bitbucket.org/mstrobel/procyon/wiki/Decompiler%20API

Žádné komentáře:

Okomentovat