git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@1269 379699f6-c40d-0410-875b-85095c16579emaster
parent
1a0fc97111
commit
571bb071fe
@ -0,0 +1,96 @@ |
|||||||
|
options = tabwidth,indent,style,linewidth,import,verbose,lvt,inner,anonymous,push,pretty,decrypt,onetime,immediate,verify,contrafo,debug |
||||||
|
|
||||||
|
tabwidth.0=<n> |
||||||
|
tabwidth.1=Set tab width to n. |
||||||
|
tabwidth.2=This means that Jode uses tabs to replace n spaces. \ |
||||||
|
Don't confound this with the indent option. Use 0 if you don't want \ |
||||||
|
tabs. Default is 8. |
||||||
|
|
||||||
|
indent.0=<n> |
||||||
|
indent.1=Indent blocks by n spaces. |
||||||
|
|
||||||
|
style.0={sun|gnu} |
||||||
|
style.1=Specify indentation style. |
||||||
|
|
||||||
|
linewidth.0=<n> |
||||||
|
linewidth.1=Set maximum line width to n. |
||||||
|
linewidth.2=Jode breaks lines that are longer than this. It tries it's best \ |
||||||
|
to make all lines fit in this limit, but sometimes this won't succeed. |
||||||
|
|
||||||
|
import.0=<pkglimit>,<clslimit> |
||||||
|
import.1=import classes if they occur more than clslimit times and packages \ |
||||||
|
with more than pkglimit used classes. Default is 0,1 which means that all \ |
||||||
|
used classes are imported, but never a whole package. |
||||||
|
|
||||||
|
verbose.0=<n> |
||||||
|
verbose.1=Be verbose (higher n means more verbose). |
||||||
|
verbose.2=This prints some information about the currently decompiled \ |
||||||
|
class or method to the console. |
||||||
|
|
||||||
|
debug.0=<flag>,... |
||||||
|
debug.1=Enable debugging options. Useful to track errors in the decompiler. |
||||||
|
debug.2=Possible flags are: \ |
||||||
|
"bytecode", to print raw bytecode. \ |
||||||
|
"lvt", dump LocalVariableTable. \ |
||||||
|
"verifier", to trace bytecode verification. \ |
||||||
|
"check", do time consuming sanity checks; useful to spot serious errors. \ |
||||||
|
"types", to see the type intersections. \ |
||||||
|
"flow", for a very verbose trace of the decompile process. \ |
||||||
|
"analyze", briefly inform about "T1/T2" analyzation. \ |
||||||
|
"inout", to view the in/out local variable analyzation. \ |
||||||
|
"locals", to see how local variable merging is done. \ |
||||||
|
"constructors", to trace constructor transformation. \ |
||||||
|
"interpreter", to follow the execution of the interpreter \ |
||||||
|
(the interpreter is used for string decryption). |
||||||
|
|
||||||
|
inner.0={yes|no} |
||||||
|
inner.1=(Don't) decompiler inner classes. |
||||||
|
|
||||||
|
anonymous.0={yes|no} |
||||||
|
anonymous.1=(Don't) decompiler method scoped classes. |
||||||
|
|
||||||
|
contrafo.0={yes|no} |
||||||
|
contrafo.1=(Don't) transform constructors. |
||||||
|
|
||||||
|
lvt.0={yes|no} |
||||||
|
lvt.1=(Don't) use the local variable table. |
||||||
|
lvt.2=Turning it off is useful if an obfuscator filled it with bogus values. |
||||||
|
|
||||||
|
pretty.0={yes|no} |
||||||
|
pretty.1=(Don't) use `pretty' names for local variables. |
||||||
|
pretty.2=The non pretty names have the advantage, that their names are \ |
||||||
|
unique. This make search & replace possible. |
||||||
|
|
||||||
|
push.0={yes|no} |
||||||
|
push.1=Allow PUSH pseudo instructions in output. |
||||||
|
push.2=Sometimes, when methods were inlined, Jode can't reconstruct \ |
||||||
|
the original expression. It has to split a complex expression into \ |
||||||
|
several ones, using temporary variables. If this option is on, it won't \ |
||||||
|
use the temporary variables, but uses pseudo PUSH/POP instructions instead, \ |
||||||
|
as they are in the bytecode. |
||||||
|
|
||||||
|
decrypt.0={yes|no} |
||||||
|
decrypt.1=(Don't) decrypt encrypted strings. |
||||||
|
decrypt.2=Some obfuscators encrypt all strings. To decrypt them at runtime \ |
||||||
|
they add a small decryption routine to the code. If Jode detects such a \ |
||||||
|
decryption routine it interprets it to decrypt the strings at decompile time. |
||||||
|
|
||||||
|
onetime.0={yes|no} |
||||||
|
onetime.1=(Don't) remove locals that written and then immediately read. |
||||||
|
onetime.2=When javac inlines a method it uses temporary local variables for \ |
||||||
|
the parameters. Often these local variables can be removed, which makes \ |
||||||
|
the code much better to read. |
||||||
|
|
||||||
|
immediate.0={yes|no} |
||||||
|
immediate.1=Output the source immediately as it gets decompiled. |
||||||
|
immediate.2=This leads to more instant output, but has many disadvantages.\ |
||||||
|
For one the import statements can't be correct. But it also may lead to \ |
||||||
|
buggy code. The advantage is, that you can get partial output even if an |
||||||
|
exception is thrown. |
||||||
|
|
||||||
|
verify.0={yes|no} |
||||||
|
verify.1=(Don't) verify code before decompiling it. |
||||||
|
verify.2=Jode assumes at many places that your byte code is legal. To \ |
||||||
|
be sure it verifies it before decompiling. If verification fails it \ |
||||||
|
rejects the code. Since verification can fail for legal code if the \ |
||||||
|
type hierarchy is not known, you can turn this option off. |
@ -0,0 +1,50 @@ |
|||||||
|
/* IdentityRenamer Copyright (C) 1999 Jochen Hoenicke. |
||||||
|
* |
||||||
|
* This program is free software; you can redistribute it and/or modify |
||||||
|
* it under the terms of the GNU General Public License as published by |
||||||
|
* the Free Software Foundation; either version 2, or (at your option) |
||||||
|
* any later version. |
||||||
|
* |
||||||
|
* This program is distributed in the hope that it will be useful, |
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
* GNU General Public License for more details. |
||||||
|
* |
||||||
|
* You should have received a copy of the GNU General Public License |
||||||
|
* along with this program; see the file COPYING. If not, write to |
||||||
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. |
||||||
|
* |
||||||
|
* $Id$ |
||||||
|
*/ |
||||||
|
|
||||||
|
package jode.obfuscator.modules; |
||||||
|
import jode.obfuscator.Renamer; |
||||||
|
import jode.obfuscator.Identifier; |
||||||
|
///#def COLLECTIONS java.util
|
||||||
|
import java.util.Iterator; |
||||||
|
///#enddef
|
||||||
|
///#def COLLECTIONEXTRA java.lang
|
||||||
|
import java.lang.UnsupportedOperationException; |
||||||
|
///#enddef
|
||||||
|
|
||||||
|
public class IdentityRenamer implements Renamer { |
||||||
|
public Iterator generateNames(Identifier ident) { |
||||||
|
final String base = ident.getName(); |
||||||
|
return new Iterator() { |
||||||
|
int last = 0; |
||||||
|
|
||||||
|
public boolean hasNext() { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
public Object next() { |
||||||
|
return (last++ == 0 ? base : base + last); |
||||||
|
} |
||||||
|
|
||||||
|
public void remove() { |
||||||
|
throw new UnsupportedOperationException(); |
||||||
|
} |
||||||
|
}; |
||||||
|
} |
||||||
|
} |
||||||
|
|
@ -0,0 +1,134 @@ |
|||||||
|
#!/usr/bin/perl |
||||||
|
# createStackDelta.pl Copyright (C) 1999 Jochen Hoenicke. |
||||||
|
# |
||||||
|
# This program is free software; you can redistribute it and/or modify |
||||||
|
# it under the terms of the GNU General Public License as published by |
||||||
|
# the Free Software Foundation; either version 2, or (at your option) |
||||||
|
# any later version. |
||||||
|
# |
||||||
|
# This program is distributed in the hope that it will be useful, |
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
# GNU General Public License for more details. |
||||||
|
# |
||||||
|
# You should have received a copy of the GNU General Public License |
||||||
|
# along with this program; see the file COPYING. If not, write to |
||||||
|
# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. |
||||||
|
# |
||||||
|
# $Id$ |
||||||
|
|
||||||
|
# This perl script creates the stackDelta string needed by |
||||||
|
# jode.bytecode.Instruction. |
||||||
|
|
||||||
|
my $OPCODEFILE="jode/bytecode/Opcodes.java"; |
||||||
|
my @delta; |
||||||
|
my $lastOpcode = 0; |
||||||
|
my $nr; |
||||||
|
|
||||||
|
open OPCODES, "<$OPCODEFILE"; |
||||||
|
while (<OPCODES>) { |
||||||
|
next unless /opc_([a-z0-9_]+)\s*=\s*(\d+)/; |
||||||
|
|
||||||
|
$_ = $1; |
||||||
|
$nr = $2; |
||||||
|
if (/^(nop|iinc)$/) { |
||||||
|
# no pop, no push |
||||||
|
$delta[$nr] = "000"; |
||||||
|
} elsif (/^([aif](const|load).*|[sb]ipush|ldc(_w)?)$/) { |
||||||
|
# no pop, one push |
||||||
|
$delta[$nr] = "010"; |
||||||
|
} elsif (/^([ld](const|load).*|ldc2_w)$/) { |
||||||
|
# no pop, two push |
||||||
|
$delta[$nr] = "020"; |
||||||
|
} elsif (/^([aif]store.*|pop)$/) { |
||||||
|
# one pop, no push |
||||||
|
$delta[$nr] = "001"; |
||||||
|
} elsif (/^([ld]store.*|pop2)$/) { |
||||||
|
# two pop, no push |
||||||
|
$delta[$nr] = "002"; |
||||||
|
} elsif (/^[aifbcs]aload$/) { |
||||||
|
# two pop, one push |
||||||
|
$delta[$nr] = "012"; |
||||||
|
} elsif (/^[dl]aload$/) { |
||||||
|
# two pop, two push |
||||||
|
$delta[$nr] = "022"; |
||||||
|
} elsif (/^[aifbcs]astore$/) { |
||||||
|
# three pop, no push |
||||||
|
$delta[$nr] = "003"; |
||||||
|
} elsif (/^[dl]astore$/) { |
||||||
|
# four pop, no push |
||||||
|
$delta[$nr] = "004"; |
||||||
|
} elsif (/^dup(2)?(_x([12]))?$/) { |
||||||
|
$count = $1 ? 2 : 1; |
||||||
|
$depth = $2 ? $3 : 0; |
||||||
|
$pop = $count + $depth; |
||||||
|
$push = $pop + $count; |
||||||
|
$delta[$nr] = "0".$push.$pop; |
||||||
|
} elsif (/^swap$/) { |
||||||
|
# two pop, two push |
||||||
|
$delta[$nr] = "022"; |
||||||
|
} elsif (/^[if](add|sub|mul|div|rem|u?sh[lr]|and|or|xor)$/) { |
||||||
|
# two pop, one push |
||||||
|
$delta[$nr] = "012"; |
||||||
|
} elsif (/^[ld](add|sub|mul|div|rem|and|or|xor)$/) { |
||||||
|
# four pop, two push |
||||||
|
$delta[$nr] = "024"; |
||||||
|
} elsif (/^[if]neg$/) { |
||||||
|
# one pop, one push |
||||||
|
$delta[$nr] = "011"; |
||||||
|
} elsif (/^[ld]neg$/) { |
||||||
|
# two pop, two push |
||||||
|
$delta[$nr] = "022"; |
||||||
|
} elsif (/^lu?sh[lr]$/) { |
||||||
|
# 3 pop, two push |
||||||
|
$delta[$nr] = "023"; |
||||||
|
} elsif (/^[if]2[ifbcs]$/) { |
||||||
|
# one pop, one push |
||||||
|
$delta[$nr] = "011"; |
||||||
|
} elsif (/^[if]2[ld]$/) { |
||||||
|
# one pop, two push |
||||||
|
$delta[$nr] = "021"; |
||||||
|
} elsif (/^[ld]2[if]$/) { |
||||||
|
# two pop, one push |
||||||
|
$delta[$nr] = "012"; |
||||||
|
} elsif (/^[ld]2[ld]$/) { |
||||||
|
# two pop, two push |
||||||
|
$delta[$nr] = "022"; |
||||||
|
} elsif (/^fcmp[lg]$/) { |
||||||
|
$delta[$nr] = "012"; |
||||||
|
} elsif (/^[ld]cmp[lg]?$/) { |
||||||
|
$delta[$nr] = "014"; |
||||||
|
} elsif (/^if_[ia]cmp(eq|ne|lt|ge|le|gt)$/) { |
||||||
|
$delta[$nr] = "002"; |
||||||
|
} elsif (/^(if(eq|ne|lt|ge|le|gt|(non)?null)|tableswitch|lookupswitch)$/) { |
||||||
|
# order does matter |
||||||
|
$delta[$nr] = "001"; |
||||||
|
} elsif (/^(goto(_w)?|jsr(_w)?|ret|return)$/) { |
||||||
|
$delta[$nr] = "000"; |
||||||
|
} elsif (/^([ifa]return)$/) { |
||||||
|
$delta[$nr] = "001"; |
||||||
|
} elsif (/^([ld]return)$/) { |
||||||
|
$delta[$nr] = "002"; |
||||||
|
} elsif (/^(new)$/) { |
||||||
|
$delta[$nr] = "010"; |
||||||
|
} elsif (/^(multianewarray|(get|put|invoke).*)$/) { |
||||||
|
# unknown |
||||||
|
$delta[$nr] = "100"; |
||||||
|
} elsif (/^(athrow|monitor(enter|exit))$/) { |
||||||
|
$delta[$nr] = "001"; |
||||||
|
} elsif (/^(a?newarray|arraylength|checkcast|instanceof)$/) { |
||||||
|
$delta[$nr] = "011"; |
||||||
|
} else { |
||||||
|
# illegal |
||||||
|
next; |
||||||
|
} |
||||||
|
$lastOpcode = $nr |
||||||
|
if ($nr > $lastOpcode); |
||||||
|
} |
||||||
|
|
||||||
|
print " private final static String stackDelta = \n\t\""; |
||||||
|
for ($nr = 0; $nr <= $lastOpcode; $nr ++) { |
||||||
|
defined $delta[$nr] or $delta[$nr] = "177"; |
||||||
|
print "\\$delta[$nr]"; |
||||||
|
} |
||||||
|
print "\";\n"; |
@ -0,0 +1,40 @@ |
|||||||
|
|
||||||
|
|
||||||
|
public class CheckPrivate { |
||||||
|
private class InnerClass { |
||||||
|
private int field; |
||||||
|
|
||||||
|
private InnerClass(int j) { |
||||||
|
field = j; |
||||||
|
} |
||||||
|
|
||||||
|
private int method(int a) { |
||||||
|
int old = field; |
||||||
|
field = a; |
||||||
|
return old; |
||||||
|
} |
||||||
|
|
||||||
|
private void test() { |
||||||
|
outerField = 4; |
||||||
|
outerMethod(); |
||||||
|
System.err.println(outerField); |
||||||
|
new CheckPrivate(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private int outerField; |
||||||
|
|
||||||
|
private int outerMethod() { |
||||||
|
return outerField; |
||||||
|
} |
||||||
|
|
||||||
|
private CheckPrivate() { |
||||||
|
InnerClass inner = new InnerClass(1); |
||||||
|
inner.field = 3; |
||||||
|
inner.method(inner.field); |
||||||
|
} |
||||||
|
|
||||||
|
public static void main(String[] test) { |
||||||
|
new CheckPrivate(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,28 @@ |
|||||||
|
public class CheckSuperRemove { |
||||||
|
public class Inner { |
||||||
|
public void test() { |
||||||
|
class MyInner extends Inner { |
||||||
|
} |
||||||
|
MyInner myInner = new MyInner(); |
||||||
|
Inner anonInner = new Inner() { |
||||||
|
public void test() {} |
||||||
|
}; |
||||||
|
MyInner anonInner2 = new MyInner() { |
||||||
|
public void test() {} |
||||||
|
}; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public class SubInner extends Inner { |
||||||
|
public SubInner(int a) { |
||||||
|
} |
||||||
|
|
||||||
|
public SubInner() { |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static void main(String[] param) { |
||||||
|
new CheckSuperRemove().new SubInner(); |
||||||
|
new CheckSuperRemove().new SubInner(1); |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue