I think it is better to be explicit here, instead of relying on ASM's
current lack of equals()/hashCode() methods in the AbstractInsnNode
class.
Signed-off-by: Graham <gpe@openrs2.dev>
This will make naming libraries easier, as we won't have to thread
library names through every Library{Reader,Writer} implementation.
Signed-off-by: Graham <gpe@openrs2.dev>
JS5 seems to refer to many things, so I'm intending to name Jagex's
custom class file format "packclass" instead of "js5". My reasoning is
that the tool for unpacking it is called unpackclass. If you use the
same logic behind naming the Pack200 packer unpack200, then "packclass"
is a reasonable name for Jagex's class file format.
Signed-off-by: Graham <gpe@openrs2.dev>
This change paves the way to feed the NameMap into the TypedRemapper,
such that refactored names (and static member movements) are preserved
across deobfuscator runs.
Signed-off-by: Graham <gpe@openrs2.dev>
We don't need to track the class version and maxStack value: the
Library::remap will already have access to them (and always needs to, as
it has to fiddle with {Class,Field,Method}Nodes to actually move the
field).
Signed-off-by: Graham <gpe@openrs2.dev>
My rough plan for combining static scrambling and remapping is to split
Library::remap into three passes:
* Remove static methods, fields and initializers from the library,
storing them in a temporary location.
* Pass all classes through ClassNodeRemapper, as we do now.
* Add static methods, fields and initializers to their new classes,
remapping as we do so.
This ensures a ClassNode is never in a state where it has a mixture of
remapped and non-remapped fields, methods or instructions. This is
important to ensure no conflicts can occur when we use the refactored
names from the NameMap, rather than the auto-generated names.
It means TypedRemapper needs the ability to provide the instructions
that make up a field's initializer, such that Library::remap can move
these instructions to a different InsnList. The new getFieldInitializer
method and FieldInitializer type support this.
Signed-off-by: Graham <gpe@openrs2.dev>
I'm going to use it in multiple places, so I think it makes sense to
share it (at the expense of the asm module depending on the yaml
module).
Signed-off-by: Graham <gpe@openrs2.dev>
I thought it'd be nice to ensure we could represent any character in the
patterns. However, this isn't required (as the client only uses
alphabetical class, method and field names). Furthermore, the period
character is already unusable in class names due to the MemberRef string
parsing.
Signed-off-by: Graham <gpe@openrs2.dev>
<init> methods do not override each other. This caused us to incorrectly
calculate visibility in some cases in the VisibilityTransformer.
Signed-off-by: Graham <gpe@openrs2.dev>
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>
The Resource::compress method already holds entire files in memory at
once, as does the client-side loader. We might as well do the same on
the server-side.
Signed-off-by: Graham <gpe@openrs2.dev>
This will provide a few benefits:
- Some of the implementations can now be turned into objects, reducing
memory allocation.
- A single Resource.compressLibrary() method will be able to take a
LibraryWriter, reducing duplication.
Signed-off-by: Graham <gpe@openrs2.dev>
Java 11's Pack200 implementation complains if stack map frames are present, and
passes the classes through unmodified. I'm not sure why.
Stack map frames are only required in Java 7, so for 6 and below a reasonable
workaround is to not emit them.
A nice side effect of this change is that the jar files created by the bundler
are be smaller. The pack200 files are too, and would be even if the classes
were not passed through unmodified.
I'm ignoring the deobfuscator mapping files for now, but when the
deobfuscator is finished then I'll add them to the repository and keep
them up to date.
Signed-off-by: Graham <gpe@openrs2.dev>
The next commit will make MemberRef comparable, with the owner/name
being used for sorting before the descriptor. This makes the output of
the fields consistent with the sort order.
Signed-off-by: Graham <gpe@openrs2.dev>
I think relying on just the isBodyEmpty() check is more correct too, as
the end label of a try/catch is exclusive. Furthermore, we don't want to
delete try/catch nodes where the middle of the body is not dead (even if
the start and end are dead).
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>