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