benf.org : other : cfr : Renaming fields - (For obfuscation or otherwise). |
I finally got around to handling this in CFR 0.92 - use '--renamedupmembers true'
nb: This is related to, but different from illegal field/method names and duplicate method renaming
Some decompiled code occasionally ends up with the same field name repeated multiple times - i.e.
/* * Duplicate member names - consider using --renamedupmembers true */ public class NameTest22 { public float fred; public int fred; public long fred; public NameTest22(int n) { this.fred = n + 1; this.fred = n + 3; this.fred = n + 4; } public String toString() { return "NameTest22{fred=" + this.fred + ", free=" + this.fred + ", fref=" + this.fred + '}'; } public static void main(String[] arrstring) { System.out.println(new NameTest22(3)); } }
(To reproduce this from legit java, you could (a) simply (as I have) use a hex editor to rename fields 'free' and 'fref' to 'fred', or (b) change the constpool entries so that they all point to the one 'fred' string.)
Using the excellent Hex-fiend editor | ||
![]() | → | ![]() |
There are many fine class file editors out there, but that's sort of out of scope!
The issue here is that these fields now apparently have exactly the same name - that's illegal java!
The JVM spec section 5.4.3.2 says the following: If C declares a field with the name and descriptor specified by the field reference, field lookup succeeds.
Note - BOTH name and descriptor (type information) are used for the JVM to uniquely identify a field. This means that according to the JVM, it's perfectly legitimate to have two fields of a different type with the same name. It's just an example where the constraints of the java language are slightly tighter than the constraints of the JVM.
Nope. Sad JVM - which is of course entirely consistent with the specification above.
Exception in thread "main" java.lang.ClassFormatError: Duplicate field name&signature in class file org/benf/cfr/tests/NameTest22 at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:760)
Maybe a bit much - I think this is about as effective an obfuscation as turning a sign saying 'Top secret base this way' upside down.
This one seems much more likely to me! In my example above, I hacked existing symbols so they had the same text. However, it would be equivalent to remove the duplicate symbols from the Const Pool altogether - which (obviously!) saves some space. Not much, but perhaps in the world of Mobile Java, this is still a thing worth having.
CFR will now decorate any class file it thinks suffers from this issue with this comment
/* * Duplicate member names - consider using --renamedupmembers true */
So.... just do that! Because the types of the fields are part of the key, this flag appends _type to any duplicate field.
/* * Decompiled with CFR */ package org.benf.cfr.tests; import java.io.PrintStream; public class NameTest22 { public float fred_float; public int fred_int; public long fred_long; public NameTest22(int n) { this.fred_int = n + 1; this.fred_float = n + 3; this.fred_long = n + 4; } public String toString() { return "NameTest22{fred=" + this.fred_float + ", free=" + this.fred_int + ", fref=" + this.fred_long + '}'; } public static void main(String[] arrstring) { System.out.println(new NameTest22(3)); } }
Please note: CFR will not automatically enable this flag.
Two reasons:
Last updated 01/2015 |