The new system will make it easier to port the deobfuscator to different
revisions.
There are two main changes:
- The addition of a Profile class, which contains a list of excluded
classes, methods and fields, and the maximum obfuscated name length.
It is passed to Transformers that require it with dependency
injection.
- New ClassFilter and MemberFilter infrastructure. The MemberFilter
class adds support for filtering fields and methods based on the
owner and descriptor, in addition to the name. This makes the filters
more precise than the previous system. It also supports globs, which
makes it easy to filter whole groups of classes, fields and methods
in one go.
The Profile class uses a ClassFilter and MemberFilters to
represent the list of excluded classes, methods and fields.
A separate benefit is the addition of a separate entry points filter
to the Profile class. Prior to this commit, many Transformers re-used
the excluded method filter to find entry points, which is less precise
(many of the excluded methods in 550 are not entry points).
Support for filtering methods by owner and descriptor in addition to
name allows the DEFAULT_PUBLIC_CTOR_CLASSES Set in VisibilityTransformer to
be combined with the entry points filter.
In the future it might be desirable to split the excluded method set
into three separate sets:
- One to represent methods that can't be renamed.
- One to represent methods whose signature can't be changed.
- One to represent methods that can't be removed.
Signed-off-by: Graham <gpe@openrs2.dev>
As I'm splitting it up into smaller modules (e.g. compress and crypto) I
think util is a more appropriate name for the remainder.
Signed-off-by: Graham <gpe@openrs2.dev>
GETSTATIC, PUTSTATIC and INVOKESTATIC (strangely) use the same field and
method resolution algorithms as their non-static equivalents.
While this doesn't cause problems for 550, as the *STATIC instructions
seem to always refer to the class containing the static definition,
Major reports that OSRS clients sometimes change the owner to a
subclass. This broke the old transformer.
This commit fixes it by applying the old to new owner mapping to an
entire disjoint set at a time.
Signed-off-by: Graham <gpe@openrs2.dev>
By moving all the static fields in a single class in one go, we can just
combine the <clinit> methods together. This allows us to remove all the
really complicated logic for extracting initializers, and also allows us
to move the last few array fields with complex initializers.
Depending on the class loading order, moving them can result in arrays
being empty, which breaks the client's functionality (e.g. it can't get
past the JS5 CRC check).
The client scrambles static fields and methods - moving each to a
random class where it does not logically belong.
This transformer moves all static methods to a new set of empty classes.
The intention is that the human refactoring the deobfuscated client can
move the static methods around with an IDE to classes where it makes
sense.
In theory we could use heuristics to move some methods around - e.g.
ideas I have include:
* If the method takes no arguments, move it to the same class as its
return type.
* If it's a void method that takes one argument, move it to the same
class as its single argument.
* Group related methods together based on where they are called.
However, some of the heuristics are probably fairly complicated to
implement. Furthermore, as they are heuristics, they will make mistakes.
In the naive approach, the Static* classes generated by this transformer
effectively act as a queue of methods that a human has yet to move to an
appropriate class. If the Static* classes are ever emptied after
refactoring, then we will know that all static methods have been moved
to an appropriate class.
We wouldn't be able to guarantee this if some methods were moved to
Class* classes with heuristics. The heuristics would also be fairly
complicated to implement. Therefore, the transformer does not use
heuristics.
Field scrambling support will be included in a future commit.