667 has an initializer like `a = b = new X()`. This broke the previous
version of the unscrambler, as it treated it as two separate
initializers: `a = b = new X()` and `b = new X()`. When the fields were
moved, the overlapping instructions were removed twice from the original
<clinit> method, making its size negative.
Even if this were fixed, it is still not safe to move the initializers,
as `new X()` would end up being executed twice, not once.
This commit fixes the problem by treating any simple initializer that
overlaps with any other simple initializer as a complex initializer.
Signed-off-by: Graham <gpe@openrs2.org>
This commit makes the following improvements:
- Converts the list of instructions in the entry and exit block to a
set, which makes checking for containment more efficient.
- Removes redundant excluded field filtering, which is already handled
by the unscramble() method.
- Treats fields written with PUTSTATIC outside the entry or exit block
as complex, instead of just fields read with GETSTATIC.
- Treats fields with multiple simple initializers as complex.
- Treats fields where we fail to extract a simple initializer as
complex. This fixes a bug where we accidentally thought those fields
had no initializer.
Signed-off-by: Graham <gpe@openrs2.org>
This is a slightly nicer solution than running a combined transformer
until it reaches a fixed point: we know we'd only need two passes,
rather than an arbitrary number of passes.
The 667 client uses various exception types beyond RuntimeException in
ZKM exception obfuscation handlers, including Throwable, Exception,
EOFException and IOException. This separation also allows us to remove
the type constraint for ZKM handlers.
Signed-off-by: Graham <gpe@openrs2.org>
The build 667 client has some ZKM exception handlers inside Jagex's
exeption tracing handlers. In a single pass, the regex is only capable
of matching the former and not the latter. The ZKM exception handlers
were removed, confusingly leaving Jagex exception handlers that do match
the CATCH_MATCHER regex.
Signed-off-by: Graham <gpe@openrs2.org>
This fixes a bug when deobfuscating the build 225 client, which has code
that looks like a flow obstructor initializer, but it reads an argument
rather than a static variable.
Signed-off-by: Graham <gpe@openrs2.org>
There are two main reasons for this change: by default, logback uses
stdout (!) and not stderr. This caused problems in programs like
packclass/unpackclass, where the packclass or JAR files were mixed in
with Netty's debug logging.
Secondly, the debug logging from lots of third-party libraries was
annoying (as it made it difficult to pick out OpenRS2-specific log
messages), so I've disabled lots of it.
Signed-off-by: Graham <gpe@openrs2.org>
The previous implementation didn't attempt to walk the call graph, so it
wouldn't remove all unused methods.
Closes#127.
Signed-off-by: Graham <gpe@openrs2.org>
I'm going to try to minimise use of this (as per
https://github.com/google/guice/wiki/Avoid-Injecting-Closable-Resources).
For example, I'm going to inject a pooling DataSource rather than
Connection objects, as per the advice at the end of the page. However,
HikariCP's DataSource implementation is itself Closeable.
Signed-off-by: Graham <gpe@openrs2.org>
I think it's actually fine to stick the jars in the nonfree/lib folder.
When we package up the entire OpenRS2 distribution, the fat jar is
placed in the lib folder, so using nonfree/lib is consistent with that.
Signed-off-by: Graham <gpe@openrs2.org>
This is in preparation for adding a new deob module which invokes the
bytecode deobfuscator, decompiler and AST deobfuscator in turn.
Signed-off-by: Graham <gpe@openrs2.org>