Injector, deob, mixins

This commit is contained in:
Lucas
2019-06-08 09:33:50 +02:00
parent 276ff1995d
commit 49afdf7dc7
599 changed files with 84012 additions and 1821 deletions

View File

@@ -0,0 +1,44 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.asm;
import java.io.IOException;
import java.io.InputStream;
import net.runelite.asm.visitors.ClassFileVisitor;
import org.objectweb.asm.ClassReader;
public class ClassUtil
{
public static ClassFile loadClass(InputStream in) throws IOException
{
ClassReader reader = new ClassReader(in);
ClassFileVisitor cv = new ClassFileVisitor();
reader.accept(cv, ClassReader.SKIP_FRAMES);
return cv.getClassFile();
}
}

View File

@@ -0,0 +1,81 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.asm.annotations;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Optional;
import net.runelite.asm.ClassFile;
import net.runelite.asm.ClassGroup;
import net.runelite.asm.ClassUtil;
import net.runelite.asm.Method;
import net.runelite.asm.Type;
import net.runelite.asm.attributes.Annotations;
import net.runelite.asm.attributes.annotation.Annotation;
import net.runelite.asm.attributes.annotation.Element;
import net.runelite.deob.util.JarUtil;
import org.junit.Assert;
import org.junit.Test;
public class AnnotationTest
{
@Test
public void testAnnotation() throws IOException
{
InputStream in = this.getClass().getClassLoader().getResourceAsStream("net/runelite/asm/annotations/TestClass.class");
Assert.assertNotNull(in);
ClassGroup group = new ClassGroup();
ClassFile cf = ClassUtil.loadClass(in);
group.addClass(cf);
byte[] out = JarUtil.writeClass(group, cf);
// parse it again
cf = ClassUtil.loadClass(new ByteArrayInputStream(out));
Method method = cf.getMethods().get(1);
Assert.assertEquals("method1", method.getName());
Annotations annotations = method.getAnnotations();
Assert.assertNotNull(annotations);
Optional<Annotation> annotation = annotations.getAnnotations().stream().filter(a -> a.getType().equals(new Type("Lnet/runelite/asm/annotations/MyAnnotation;"))).findFirst();
Assert.assertTrue(annotation.isPresent());
Annotation an = annotation.get();
List<Element> elements = an.getElements();
Assert.assertEquals(1, elements.size());
Element element = elements.get(0);
Assert.assertEquals("value", element.getName());
Assert.assertEquals("method1", element.getValue());
}
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.asm.annotations;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation
{
String value();
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.asm.annotations;
public class TestClass
{
@MyAnnotation("field1")
public int field1;
@MyAnnotation("method1")
public void method1() { }
}

View File

@@ -0,0 +1,117 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.asm.attributes.code.instructions;
import static net.runelite.asm.Type.INT;
import net.runelite.asm.attributes.code.Instruction;
import net.runelite.asm.attributes.code.InstructionType;
import net.runelite.asm.attributes.code.Instructions;
import net.runelite.asm.execution.Frame;
import net.runelite.asm.execution.InstructionContext;
import net.runelite.asm.execution.Stack;
import net.runelite.asm.execution.StackContext;
import net.runelite.asm.execution.Value;
import net.runelite.asm.execution.VariableContext;
import net.runelite.asm.execution.Variables;
import net.runelite.deob.deobfuscators.mapping.ParallelExecutorMapping;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class IfEqTest
{
@Test
public void testIsSame()
{
Instructions ins = mock(Instructions.class);
Frame originalIfEqFrame = mock(Frame.class);
Stack stack = new Stack(42);
Variables variables = new Variables(42);
when(originalIfEqFrame.getStack()).thenReturn(stack);
when(originalIfEqFrame.getVariables()).thenReturn(variables);
variables.set(9, new VariableContext(INT));
Instruction i = new LDC(ins, 0);
InstructionContext ctx = new InstructionContext(i, originalIfEqFrame);
// ifeq 0
IfEq ifeq = new IfEq(ins, InstructionType.IFEQ);
InstructionContext ifeqCtx = new InstructionContext(ifeq, originalIfEqFrame);
ifeqCtx.pop(new StackContext(ctx, INT, new Value(1)));
//
ins = mock(Instructions.class);
Frame originalIfIcmpNeFrame = mock(Frame.class);
stack = new Stack(42);
variables = new Variables(42);
when(originalIfIcmpNeFrame.getStack()).thenReturn(stack);
when(originalIfIcmpNeFrame.getVariables()).thenReturn(variables);
variables.set(5, new VariableContext(INT));
i = new LDC(ins, 1);
InstructionContext ctx1 = new InstructionContext(i, originalIfIcmpNeFrame);
i = new ILoad(ins, 5);
InstructionContext ctx2 = new InstructionContext(i, originalIfIcmpNeFrame);
// ificmpne 1
IfICmpNe ificmpne = new IfICmpNe(ins, InstructionType.IF_ICMPNE);
InstructionContext ificmpneCtx = new InstructionContext(ificmpne, originalIfIcmpNeFrame);
ificmpneCtx.pop(
new StackContext(ctx1, INT, new Value(1)),
new StackContext(ctx2, INT, Value.UNKNOWN)
);
assertEquals(
ifeq.isSame(ifeqCtx, ificmpneCtx),
ificmpne.isSame(ificmpneCtx, ifeqCtx)
);
// check that both frames jump the same direction
Frame ifeqBranchFrame = mock(Frame.class);
ifeqCtx.branch(ifeqBranchFrame);
Frame ificmpneBranchFrame = mock(Frame.class);
ificmpneCtx.branch(ificmpneBranchFrame);
// initially originalIfEqFrame.other == originalIfIcmpNeFrame.other
when(originalIfEqFrame.getOther()).thenReturn(originalIfIcmpNeFrame);
when(originalIfIcmpNeFrame.getOther()).thenReturn(originalIfEqFrame);
ParallelExecutorMapping mapping = mock(ParallelExecutorMapping.class);
ifeq.map(mapping, ifeqCtx, ificmpneCtx);
// verify that ifeqBranchFrame.other = ificmpneBranchFrame
ArgumentCaptor<Frame> frameCapture = ArgumentCaptor.forClass(Frame.class);
verify(ifeqBranchFrame).setOther(frameCapture.capture());
assertEquals(ificmpneBranchFrame, frameCapture.getValue());
}
}

View File

@@ -0,0 +1,74 @@
/*
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.asm.attributes.code.instructions;
import static net.runelite.asm.Type.INT;
import net.runelite.asm.attributes.code.InstructionType;
import net.runelite.asm.attributes.code.Instructions;
import net.runelite.asm.execution.Frame;
import net.runelite.asm.execution.InstructionContext;
import net.runelite.asm.execution.Stack;
import net.runelite.asm.execution.StackContext;
import net.runelite.asm.execution.Value;
import net.runelite.asm.execution.Variables;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class IfICmpEqTest
{
@Test
public void testIsSame()
{
Instructions ins = mock(Instructions.class);
Frame frame = mock(Frame.class);
Stack stack = new Stack(42);
Variables variables = new Variables(42);
when(frame.getStack()).thenReturn(stack);
when(frame.getVariables()).thenReturn(variables);
IfICmpEq ifeq = new IfICmpEq(ins, InstructionType.IF_ICMPEQ);
InstructionContext ifeqCtx = new InstructionContext(ifeq, frame);
ifeqCtx.pop(new StackContext(getConstantCtx(ins, 1), INT, new Value(1)));
ifeqCtx.pop(new StackContext(getConstantCtx(ins, 1), INT, new Value(1)));
IfNe ifne = new IfNe(ins, InstructionType.IFNE);
InstructionContext ifneCtx = new InstructionContext(ifne, frame);
ifneCtx.pop(new StackContext(getConstantCtx(ins, 42), INT, new Value(42)));
assertTrue(ifeq.isSame(ifeqCtx, ifneCtx));
}
private InstructionContext getConstantCtx(Instructions ins, int constant)
{
LDC ldc = new LDC(ins, constant);
InstructionContext pushConstantCtx = mock(InstructionContext.class);
when(pushConstantCtx.getInstruction()).thenReturn(ldc);
return pushConstantCtx;
}
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.asm.attributes.code.instructions;
import net.runelite.asm.attributes.code.InstructionType;
import net.runelite.asm.attributes.code.Instructions;
import net.runelite.asm.execution.Frame;
import net.runelite.asm.execution.InstructionContext;
import net.runelite.asm.execution.Stack;
import net.runelite.asm.execution.Variables;
import org.junit.Assert;
import org.junit.Test;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
/**
*
* @author Adam
*/
public class LCmpTest
{
@Test
public void testIsSame()
{
LCmp cmp = new LCmp(mock(Instructions.class), InstructionType.LCMP);
LCmp cmp2 = new LCmp(mock(Instructions.class), InstructionType.LCMP);
Frame f1 = mock(Frame.class);
when(f1.getStack()).thenReturn(new Stack(42));
when(f1.getVariables()).thenReturn(new Variables(42));
Frame f2 = mock(Frame.class);
when(f2.getStack()).thenReturn(new Stack(42));
when(f2.getVariables()).thenReturn(new Variables(42));
InstructionContext ctx1 = new InstructionContext(cmp, f1);
InstructionContext ctx2 = new InstructionContext(cmp2, f2);
boolean result = cmp.isSame(ctx1, ctx2);
Assert.assertTrue(result);
}
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.asm.execution;
import java.io.File;
import net.runelite.asm.ClassGroup;
import net.runelite.deob.DeobTestProperties;
import net.runelite.deob.util.JarUtil;
import org.junit.Rule;
import org.junit.Test;
public class ExecutionTest
{
@Rule
public DeobTestProperties properties = new DeobTestProperties();
@Test
public void test() throws Exception
{
ClassGroup group1 = JarUtil.loadJar(new File(properties.getVanillaClient()));
Execution e = new Execution(group1);
e.populateInitialMethods();
e.run();
}
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.asm.execution;
import java.io.IOException;
import java.io.InputStream;
import net.runelite.asm.ClassFile;
import net.runelite.asm.ClassGroup;
import net.runelite.asm.ClassUtil;
import net.runelite.asm.Method;
import net.runelite.deob.deobfuscators.mapping.MappingExecutorUtil;
import net.runelite.deob.deobfuscators.mapping.ParallelExecutorMapping;
import org.junit.Assert;
import org.junit.Test;
public class ParallelMappingExecutorTest
{
@Test
public void testTableswitch() throws IOException
{
InputStream in = ParallelMappingExecutorTest.class.getResourceAsStream("tests/TableSwitch.class");
Assert.assertNotNull(in);
ClassGroup group = new ClassGroup();
ClassFile cf = ClassUtil.loadClass(in);
group.addClass(cf);
in = ParallelMappingExecutorTest.class.getResourceAsStream("tests/TableSwitch.class");
Assert.assertNotNull(in);
ClassGroup group2 = new ClassGroup();
ClassFile cf2 = ClassUtil.loadClass(in);
group2.addClass(cf2);
Method m1 = cf.findMethod("method");
Method m2 = cf2.findMethod("method");
ParallelExecutorMapping map = MappingExecutorUtil.map(m1, m2);
Assert.assertEquals(cf2.findField("field2"), map.get(cf.findField("field2")));
}
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.asm.execution;
import net.runelite.asm.ClassFile;
import net.runelite.asm.ClassGroup;
import net.runelite.asm.ClassUtil;
import net.runelite.asm.Method;
import net.runelite.deob.deobfuscators.mapping.MappingExecutorUtil;
import net.runelite.deob.deobfuscators.mapping.ParallelExecutorMapping;
import org.junit.Assert;
import org.junit.Test;
public class ParallellMappingExecutorTest
{
@Test
public void testStaticStep() throws Exception
{
ClassFile cf1 = ClassUtil.loadClass(getClass().getResourceAsStream("mapper/StaticStepTest.class"));
ClassFile cf2 = ClassUtil.loadClass(getClass().getResourceAsStream("mapper/StaticStepTest.class"));
ClassGroup group1 = new ClassGroup();
ClassGroup group2 = new ClassGroup();
group1.addClass(cf1);
group2.addClass(cf2);
group1.buildClassGraph();
group1.lookup();
group2.buildClassGraph();
group2.lookup();
Method m1 = cf1.findMethod("entry");
Method m2 = cf2.findMethod("entry");
Method map1 = cf1.findMethod("map"),
map2 = cf2.findMethod("map");
Assert.assertNotNull(map1);
Assert.assertNotNull(map2);
ParallelExecutorMapping map = MappingExecutorUtil.map(m1, m2);
Assert.assertEquals(map2, map.get(map1));
}
}

View File

@@ -0,0 +1,49 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.asm.execution.mapper;
public class StaticStepTest
{
static void func2()
{
}
static void func1()
{
func2();
}
void map()
{
}
static void entry()
{
func1();
func1();
new StaticStepTest().map();
}
}

View File

@@ -0,0 +1,49 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.asm.execution.tests;
public class TableSwitch
{
public static int field1;
public static int field2;
public static int field3;
public static int field4;
public static void method()
{
switch (field1)
{
case 0:
field2 = 2;
break;
case 1:
field3 = 3;
break;
case 2:
field4 = 4;
break;
}
}
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.asm.signature;
import net.runelite.asm.Type;
import org.junit.Assert;
import org.junit.Test;
public class SignatureTest
{
@Test
public void test()
{
Signature signature = new Signature("f(Ljava/lang/String;II[Lch;[ILce;IIB)V");
Type type = signature.getTypeOfArg(3);
Assert.assertTrue(type.isArray());
}
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.asm.visitors;
import java.io.File;
import net.runelite.asm.ClassGroup;
import net.runelite.deob.DeobTestProperties;
import net.runelite.deob.TemporyFolderLocation;
import net.runelite.deob.util.JarUtil;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
public class ClassFileVisitorTest
{
@Rule
public DeobTestProperties properties = new DeobTestProperties();
@Rule
public TemporaryFolder folder = TemporyFolderLocation.getTemporaryFolder();
@Test
public void test() throws Exception
{
ClassGroup group = JarUtil.loadJar(new File(properties.getVanillaClient()));
JarUtil.saveJar(group, folder.newFile());
}
}

View File

@@ -0,0 +1,91 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.deob;
import net.runelite.asm.ClassFile;
import net.runelite.asm.ClassGroup;
import net.runelite.asm.Field;
import net.runelite.asm.Method;
import net.runelite.asm.Type;
import net.runelite.asm.attributes.Code;
import net.runelite.asm.attributes.code.Instructions;
import net.runelite.asm.attributes.code.instructions.VReturn;
import net.runelite.asm.signature.Signature;
public class ClassGroupFactory
{
private static void addVoidMethod(ClassFile cf, String name)
{
Method method = new Method(cf, name, new Signature("()V"));
method.setStatic();
cf.addMethod(method);
Code code = new Code(method);
method.setCode(code);
Instructions ins = code.getInstructions();
ins.addInstruction(new VReturn(ins));
}
public static ClassGroup generateGroup()
{
ClassGroup group = new ClassGroup();
ClassFile cf = new ClassFile(group);
cf.setName("test");
cf.setSuperName("java/lang/Object");
group.addClass(cf);
Field field = new Field(cf, "field", Type.INT);
field.setStatic();
cf.addField(field);
Method method = new Method(cf, "func", new Signature("()V"));
method.setStatic();
cf.addMethod(method);
Code code = new Code(method);
method.setCode(code);
{
method = new Method(cf, "func2", new Signature("(III)V"));
method.setStatic();
cf.addMethod(method);
code = new Code(method);
method.setCode(code);
Instructions ins = code.getInstructions();
ins.addInstruction(new VReturn(ins));
}
addVoidMethod(cf, "void1");
addVoidMethod(cf, "void2");
addVoidMethod(cf, "void3");
addVoidMethod(cf, "void4");
return group;
}
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.deob;
import java.io.InputStream;
import java.util.Properties;
import org.junit.rules.ExternalResource;
public class DeobTestProperties extends ExternalResource
{
private String rsClient;
private int rsVersion;
private String vanillaClient;
@Override
protected void before() throws Throwable
{
Properties properties = new Properties();
InputStream resourceAsStream = getClass().getResourceAsStream("/deob-test.properties");
properties.load(resourceAsStream);
rsClient = (String) properties.get("rs.client");
rsVersion = Integer.parseInt((String) properties.get("rs.version"));
vanillaClient = (String) properties.get("vanilla.client");
}
public String getRsClient()
{
return rsClient;
}
public int getRsVersion()
{
return rsVersion;
}
public String getVanillaClient()
{
return vanillaClient;
}
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.deob;
import java.io.File;
import org.junit.rules.TemporaryFolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TemporyFolderLocation
{
private static final Logger logger = LoggerFactory.getLogger(TemporyFolderLocation.class);
static
{
File tmp = new File("d:/temp");
if (tmp.exists() || tmp.mkdir())
System.setProperty("java.io.tmpdir", "d:/temp");
}
public static TemporaryFolder getTemporaryFolder()
{
return new TemporaryFolder();
}
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.deob.clientver;
import java.io.File;
import java.io.IOException;
import net.runelite.deob.DeobTestProperties;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
public class ClientVersionTest
{
@Rule
public DeobTestProperties properties = new DeobTestProperties();
@Test
public void test() throws IOException
{
ClientVersion ver = new ClientVersion(new File(properties.getVanillaClient()));
Assert.assertEquals(properties.getRsVersion(), ver.getVersion());
}
}

View File

@@ -0,0 +1,83 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.deob.deobfuscators;
import java.util.Optional;
import net.runelite.asm.ClassGroup;
import net.runelite.asm.Type;
import net.runelite.asm.attributes.Code;
import net.runelite.asm.attributes.code.Instruction;
import net.runelite.asm.attributes.code.InstructionType;
import net.runelite.asm.attributes.code.Instructions;
import net.runelite.asm.attributes.code.instructions.AConstNull;
import net.runelite.asm.attributes.code.instructions.CheckCast;
import net.runelite.asm.attributes.code.instructions.IAdd;
import net.runelite.asm.attributes.code.instructions.LDC;
import net.runelite.asm.attributes.code.instructions.Return;
import net.runelite.deob.ClassGroupFactory;
import org.junit.Assert;
import org.junit.Test;
public class CastNullTest
{
@Test
public void testRun()
{
ClassGroup group = ClassGroupFactory.generateGroup();
Code code = group.findClass("test").findMethod("func").getCode();
Instructions ins = code.getInstructions();
code.setMaxStack(3);
CheckCast checkCast = new CheckCast(ins);
checkCast.setType(new Type("test"));
Instruction[] instructions =
{
new LDC(ins, 2),
new AConstNull(ins),
checkCast,
new LDC(ins, 2),
new IAdd(ins),
new Return(ins, InstructionType.IRETURN)
};
for (Instruction i : instructions)
{
ins.addInstruction(i);
}
Assert.assertEquals(6, ins.getInstructions().size());
CastNull lvt = new CastNull();
lvt.run(group);
Assert.assertEquals(5, ins.getInstructions().size());
Optional<Instruction> o = ins.getInstructions().stream().filter(i -> i instanceof CheckCast).findAny();
Assert.assertFalse(o.isPresent());
}
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.deob.deobfuscators;
import java.io.File;
import java.io.IOException;
import net.runelite.asm.ClassGroup;
import net.runelite.deob.DeobTestProperties;
import net.runelite.deob.TemporyFolderLocation;
import net.runelite.deob.util.JarUtil;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
public class EnumDeobfuscatorTest
{
@Rule
public DeobTestProperties properties = new DeobTestProperties();
@Rule
public TemporaryFolder folder = TemporyFolderLocation.getTemporaryFolder();
private ClassGroup group;
@Before
public void before() throws IOException
{
group = JarUtil.loadJar(new File(properties.getRsClient()));
}
@After
public void after() throws IOException
{
JarUtil.saveJar(group, folder.newFile());
}
@Test
@Ignore
public void testRun() throws Exception
{
new EnumDeobfuscator().run(group);
}
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.deob.deobfuscators;
import java.io.File;
import java.io.IOException;
import net.runelite.asm.ClassGroup;
import net.runelite.deob.DeobTestProperties;
import net.runelite.deob.TemporyFolderLocation;
import net.runelite.deob.util.JarUtil;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
public class FieldInlinerTest
{
@Rule
public DeobTestProperties properties = new DeobTestProperties();
@Rule
public TemporaryFolder folder = TemporyFolderLocation.getTemporaryFolder();
private ClassGroup group;
@Before
public void before() throws IOException
{
group = JarUtil.loadJar(new File(properties.getVanillaClient()));
}
@After
public void after() throws IOException
{
JarUtil.saveJar(group, folder.newFile());
}
@Test
public void testRun()
{
FieldInliner fi = new FieldInliner();
fi.run(group);
}
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.deob.deobfuscators;
import java.io.File;
import java.io.IOException;
import net.runelite.asm.ClassGroup;
import net.runelite.deob.DeobTestProperties;
import net.runelite.deob.TemporyFolderLocation;
import net.runelite.deob.util.JarUtil;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
public class IllegalStateExceptionsTest
{
@Rule
public DeobTestProperties properties = new DeobTestProperties();
@Rule
public TemporaryFolder folder = TemporyFolderLocation.getTemporaryFolder();
private ClassGroup group;
@Before
public void before() throws IOException
{
group = JarUtil.loadJar(new File(properties.getVanillaClient()));
}
@After
public void after() throws IOException
{
JarUtil.saveJar(group, folder.newFile());
}
@Test
public void testRun()
{
IllegalStateExceptions ise = new IllegalStateExceptions();
ise.run(group);
}
}

View File

@@ -0,0 +1,111 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.deob.deobfuscators;
import net.runelite.asm.ClassGroup;
import net.runelite.asm.attributes.Code;
import net.runelite.asm.attributes.code.Instruction;
import net.runelite.asm.attributes.code.Instructions;
import net.runelite.asm.attributes.code.instructions.AConstNull;
import net.runelite.asm.attributes.code.instructions.AStore;
import net.runelite.asm.attributes.code.instructions.IStore;
import net.runelite.asm.attributes.code.instructions.LDC;
import net.runelite.asm.attributes.code.instructions.LStore;
import net.runelite.asm.attributes.code.instructions.VReturn;
import net.runelite.deob.ClassGroupFactory;
import org.junit.Assert;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LvtTest
{
private static final Logger logger = LoggerFactory.getLogger(LvtTest.class);
@Test
public void testReuseIndex()
{
ClassGroup group = ClassGroupFactory.generateGroup();
Code code = group.findClass("test").findMethod("func").getCode();
Instructions ins = code.getInstructions();
Instruction body[] =
{
// var0 = null
new AConstNull(ins),
new AStore(ins, 0),
// var0 = 0
// this forces a reindex to varn
new LDC(ins, 0),
new IStore(ins, 0),
// var2 = null
new AConstNull(ins),
new AStore(ins, 2),
// var2 = 0
// this forces a reindex to varn+1
new LDC(ins, 0),
new IStore(ins, 2),
//var0 = 0L
new LDC(ins, 0L),
new LStore(ins, 0),
new VReturn(ins)
};
for (Instruction i : body)
{
ins.addInstruction(i);
}
Lvt lvt = new Lvt();
lvt.run(group);
AStore astore1 = (AStore) body[1];
IStore istore1 = (IStore) body[3];
AStore astore2 = (AStore) body[5];
IStore istore2 = (IStore) body[7];
LStore lstore1 = (LStore) body[9];
int astore1Idx = astore1.getVariableIndex();
int istore1Idx = istore1.getVariableIndex();
int astore2Idx = astore2.getVariableIndex();
int istore2Idx = istore2.getVariableIndex();
int lstore1Idx = lstore1.getVariableIndex();
logger.debug("{} -> {}", astore1, astore1.getVariableIndex());
logger.debug("{} -> {}", istore1, istore1.getVariableIndex());
logger.debug("{} -> {}", astore2, astore2.getVariableIndex());
logger.debug("{} -> {}", istore2, istore2.getVariableIndex());
logger.debug("{} -> {}", lstore1, lstore1.getVariableIndex());
Assert.assertNotEquals(astore1Idx, istore1Idx);
Assert.assertNotEquals(astore2Idx, istore2Idx);
// assert that the lstore doesn't overwrite an existing index
Assert.assertNotEquals(lstore1Idx + 1, astore1Idx);
Assert.assertNotEquals(lstore1Idx + 1, istore1Idx);
Assert.assertNotEquals(lstore1Idx + 1, astore2Idx);
Assert.assertNotEquals(lstore1Idx + 1, istore2Idx);
}
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.deob.deobfuscators;
import java.io.File;
import java.io.IOException;
import net.runelite.asm.ClassGroup;
import net.runelite.deob.DeobTestProperties;
import net.runelite.deob.TemporyFolderLocation;
import net.runelite.deob.util.JarUtil;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
public class OrderTest
{
@Rule
public DeobTestProperties properties = new DeobTestProperties();
@Rule
public TemporaryFolder folder = TemporyFolderLocation.getTemporaryFolder();
private ClassGroup group;
@Before
public void before() throws IOException
{
group = JarUtil.loadJar(new File(properties.getVanillaClient()));
}
@After
public void after() throws IOException
{
JarUtil.saveJar(group, folder.newFile());
}
@Test
@Ignore
public void testRun()
{
Order order = new Order();
order.run(group);
}
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.deob.deobfuscators;
import java.io.File;
import java.io.IOException;
import net.runelite.asm.ClassGroup;
import net.runelite.deob.DeobTestProperties;
import net.runelite.deob.TemporyFolderLocation;
import net.runelite.deob.util.JarUtil;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
public class PacketHandlerOrderTest
{
@Rule
public DeobTestProperties properties = new DeobTestProperties();
@Rule
public TemporaryFolder folder = TemporyFolderLocation.getTemporaryFolder();
private ClassGroup group;
@Before
public void before() throws IOException
{
group = JarUtil.loadJar(new File(properties.getRsClient()));
}
@After
public void after() throws IOException
{
JarUtil.saveJar(group, folder.newFile());
}
@Test
@Ignore
public void testRun() throws IOException
{
PacketHandlerOrder order = new PacketHandlerOrder();
order.run(group);
}
}

View File

@@ -0,0 +1,118 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.deob.deobfuscators;
import java.io.File;
import java.io.IOException;
import net.runelite.asm.ClassFile;
import net.runelite.asm.ClassGroup;
import net.runelite.asm.Field;
import net.runelite.asm.Method;
import net.runelite.asm.attributes.Code;
import net.runelite.asm.attributes.code.Instruction;
import net.runelite.asm.attributes.code.instruction.types.InvokeInstruction;
import net.runelite.deob.Deob;
import net.runelite.deob.DeobTestProperties;
import net.runelite.deob.TemporyFolderLocation;
import net.runelite.deob.util.JarUtil;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
public class RenameUniqueTest
{
@Rule
public DeobTestProperties properties = new DeobTestProperties();
@Rule
public TemporaryFolder folder = TemporyFolderLocation.getTemporaryFolder();
private ClassGroup group;
@Before
public void before() throws IOException
{
group = JarUtil.loadJar(new File(properties.getVanillaClient()));
}
@After
public void after() throws IOException
{
JarUtil.saveJar(group, folder.newFile());
}
@Test
public void testRun()
{
RenameUnique renameUnique = new RenameUnique();
renameUnique.run(group);
checkRenamed();
}
private void checkRenamed()
{
for (ClassFile cf : group.getClasses())
{
Assert.assertTrue(cf.getName().startsWith("class") || cf.getName().equals("client"));
for (Field f : cf.getFields())
{
// synthetic fields arent obfuscated
if (f.isSynthetic())
continue;
Assert.assertTrue(f.getName().startsWith("field"));
}
for (Method m : cf.getMethods())
{
Assert.assertTrue(m.getName().length() > 2);
checkCode(m.getCode());
}
}
}
private void checkCode(Code code)
{
if (code == null)
return;
for (Instruction i : code.getInstructions().getInstructions())
{
if (!(i instanceof InvokeInstruction))
continue;
InvokeInstruction ii = (InvokeInstruction) i;
Assert.assertTrue(ii.getMethod().getName().length() > Deob.OBFUSCATED_NAME_MAX_LEN
|| ii.getMethod().getClazz().getName().length() > Deob.OBFUSCATED_NAME_MAX_LEN);
}
}
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.deob.deobfuscators;
import java.io.File;
import java.io.IOException;
import net.runelite.asm.ClassGroup;
import net.runelite.deob.DeobTestProperties;
import net.runelite.deob.TemporyFolderLocation;
import net.runelite.deob.util.JarUtil;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
public class RuntimeExceptionsTest
{
@Rule
public DeobTestProperties properties = new DeobTestProperties();
@Rule
public TemporaryFolder folder = TemporyFolderLocation.getTemporaryFolder();
private ClassGroup group;
@Before
public void before() throws IOException
{
group = JarUtil.loadJar(new File(properties.getVanillaClient()));
}
@After
public void after() throws IOException
{
JarUtil.saveJar(group, folder.newFile());
}
@Test
public void testRun()
{
RuntimeExceptions re = new RuntimeExceptions();
re.run(group);
}
}

View File

@@ -0,0 +1,92 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.deob.deobfuscators;
import java.io.IOException;
import net.runelite.asm.ClassFile;
import net.runelite.asm.ClassGroup;
import net.runelite.asm.ClassUtil;
import net.runelite.asm.Method;
import net.runelite.asm.attributes.code.Label;
import net.runelite.deob.TemporyFolderLocation;
import net.runelite.deob.util.JarUtil;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
public class UnreachedCodeTest
{
@Rule
public TemporaryFolder folder = TemporyFolderLocation.getTemporaryFolder();
private ClassGroup group;
@Before
public void before() throws IOException
{
ClassFile cf = ClassUtil.loadClass(UnreachedCodeTest.class.getResourceAsStream("unreachedcode/UnreachableTest.class"));
Assert.assertNotNull(cf);
group = new ClassGroup();
group.addClass(cf);
}
@After
public void after() throws IOException
{
JarUtil.saveJar(group, folder.newFile());
}
@Test
public void testRun() throws IOException
{
UnreachedCode uc = new UnreachedCode();
uc.run(group);
ClassFile cf = group.getClasses().get(0);
Method method = cf.findMethod("entry");
Assert.assertFalse(method.getCode().getExceptions().getExceptions().isEmpty());
method = cf.findMethod("method1Unused");
Assert.assertNotNull(method);
Assert.assertFalse(method.getCode().getInstructions().getInstructions().stream().filter(i -> !(i instanceof Label)).findAny().isPresent());
Assert.assertTrue(method.getCode().getExceptions().getExceptions().isEmpty());
// Method is now invalid, remove so jar can be saved
cf.removeMethod(method);
// constructor now has no instructions
method = cf.findMethod("<init>");
Assert.assertNotNull(method);
Assert.assertFalse(method.getCode().getInstructions().getInstructions().stream().filter(i -> !(i instanceof Label)).findAny().isPresent());
// remove it too
cf.removeMethod(method);
}
}

View File

@@ -0,0 +1,91 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.deob.deobfuscators;
import java.io.IOException;
import java.io.InputStream;
import net.runelite.asm.ClassFile;
import net.runelite.asm.ClassGroup;
import net.runelite.asm.ClassUtil;
import net.runelite.deob.DeobTestProperties;
import net.runelite.deob.TemporyFolderLocation;
import net.runelite.deob.util.JarUtil;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
public class UnusedClassTest
{
@Rule
public DeobTestProperties properties = new DeobTestProperties();
@Rule
public TemporaryFolder folder = TemporyFolderLocation.getTemporaryFolder();
private ClassGroup group;
@Before
public void before() throws IOException
{
group = new ClassGroup();
load("EmptyInterface.class");
load("ClassA.class");
ClassFile emptyClass = load("EmptyClass.class");
emptyClass.removeMethod(emptyClass.findMethod("<init>"));
}
private ClassFile load(String name) throws IOException
{
InputStream in = UnusedClassTest.class.getResourceAsStream("unusedclass/" + name);
Assert.assertNotNull(in);
ClassFile cf = ClassUtil.loadClass(in);
group.addClass(cf);
return cf;
}
@After
public void after() throws IOException
{
JarUtil.saveJar(group, folder.newFile());
}
@Test
public void testRun()
{
UnusedClass uc = new UnusedClass();
uc.run(group);
Assert.assertNotNull(group.findClass("net/runelite/deob/deobfuscators/unusedclass/ClassA"));
Assert.assertNull(group.findClass("net/runelite/deob/deobfuscators/unusedclass/EmptyClass"));
Assert.assertNotNull(group.findClass("net/runelite/deob/deobfuscators/unusedclass/EmptyInterface"));
}
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.deob.deobfuscators;
import java.io.File;
import java.io.IOException;
import net.runelite.asm.ClassGroup;
import net.runelite.deob.DeobTestProperties;
import net.runelite.deob.TemporyFolderLocation;
import net.runelite.deob.util.JarUtil;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
public class UnusedFieldsTest
{
@Rule
public DeobTestProperties properties = new DeobTestProperties();
@Rule
public TemporaryFolder folder = TemporyFolderLocation.getTemporaryFolder();
private ClassGroup group;
@Before
public void before() throws IOException
{
group = JarUtil.loadJar(new File(properties.getVanillaClient()));
}
@After
public void after() throws IOException
{
JarUtil.saveJar(group, folder.newFile());
}
@Test
public void testRun()
{
UnusedFields uf = new UnusedFields();
uf.run(group);
}
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.deob.deobfuscators;
import java.io.File;
import java.io.IOException;
import net.runelite.asm.ClassGroup;
import net.runelite.deob.DeobTestProperties;
import net.runelite.deob.TemporyFolderLocation;
import net.runelite.deob.util.JarUtil;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
public class UnusedMethodsTest
{
@Rule
public DeobTestProperties properties = new DeobTestProperties();
@Rule
public TemporaryFolder folder = TemporyFolderLocation.getTemporaryFolder();
private ClassGroup group;
@Before
public void before() throws IOException
{
group = JarUtil.loadJar(new File(properties.getVanillaClient()));
}
@After
public void after() throws IOException
{
JarUtil.saveJar(group, folder.newFile());
}
@Test
public void testRun()
{
UnusedMethods um = new UnusedMethods();
um.run(group);
}
}

View File

@@ -0,0 +1,95 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.deob.deobfuscators;
import java.io.File;
import java.io.IOException;
import net.runelite.asm.ClassGroup;
import net.runelite.deob.DeobTestProperties;
import net.runelite.deob.TemporyFolderLocation;
import net.runelite.deob.util.JarUtil;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
public class UnusedParametersTest
{
@Rule
public DeobTestProperties properties = new DeobTestProperties();
@Rule
public TemporaryFolder folder = TemporyFolderLocation.getTemporaryFolder();
private ClassGroup group;
@Before
public void before() throws IOException
{
group = JarUtil.loadJar(new File(properties.getVanillaClient()));
}
@After
public void after() throws IOException
{
JarUtil.saveJar(group, folder.newFile());
}
@Test
public void testRun()
{
RenameUnique r = new RenameUnique();
r.run(group);
r = null;
System.gc();
RuntimeExceptions re = new RuntimeExceptions();
re.run(group);
re = null;
System.gc();
UnreachedCode uc = new UnreachedCode();
uc.run(group);
uc = null;
System.gc();
UnusedMethods um = new UnusedMethods();
um.run(group);
um = null;
System.gc();
IllegalStateExceptions ise = new IllegalStateExceptions();
ise.run(group);
ise = null;
System.gc();
UnusedParameters cp = new UnusedParameters();
cp.run(group);
cp = null;
System.gc();
}
}

View File

@@ -0,0 +1,177 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.deob.deobfuscators.arithmetic;
import net.runelite.asm.ClassGroup;
import net.runelite.asm.Type;
import net.runelite.asm.attributes.Code;
import net.runelite.asm.attributes.code.Instruction;
import net.runelite.asm.attributes.code.Instructions;
import net.runelite.asm.attributes.code.instructions.AConstNull;
import net.runelite.asm.attributes.code.instructions.Dup;
import net.runelite.asm.attributes.code.instructions.Dup_X1;
import net.runelite.asm.attributes.code.instructions.GetField;
import net.runelite.asm.attributes.code.instructions.IAdd;
import net.runelite.asm.attributes.code.instructions.ILoad;
import net.runelite.asm.attributes.code.instructions.IMul;
import net.runelite.asm.attributes.code.instructions.IStore;
import net.runelite.asm.attributes.code.instructions.LDC;
import net.runelite.asm.attributes.code.instructions.Pop2;
import net.runelite.asm.attributes.code.instructions.VReturn;
import net.runelite.asm.execution.Execution;
import net.runelite.asm.pool.Class;
import net.runelite.asm.pool.Field;
import net.runelite.deob.ClassGroupFactory;
import net.runelite.deob.Deobfuscator;
import org.junit.Assert;
import org.junit.Test;
public class DupDeobfuscatorTest
{
@Test
public void test()
{
ClassGroup group = ClassGroupFactory.generateGroup();
Code code = group.findClass("test").findMethod("func").getCode();
Instructions ins = code.getInstructions();
code.setMaxStack(5);
Instruction[] prepareVariables =
{
new LDC(ins, 1),
new IStore(ins, 0)
};
for (Instruction i : prepareVariables)
{
ins.addInstruction(i);
}
LDC constant1 = new LDC(ins, 1129258489),
constant2 = new LDC(ins, -1692330935),
constant3 = new LDC(ins, 1641298955),
constant4 = new LDC(ins, 1043501435);
Instruction body[] =
{
new AConstNull(ins), // this
new AConstNull(ins), // this
new ILoad(ins, 0),
constant1,
new IMul(ins),
new Dup_X1(ins),
constant2,
new IMul(ins),
new Pop2(ins), // putfield
constant3,
new IMul(ins),
constant4,
new IMul(ins),
new Pop2(ins), // putfield
new VReturn(ins)
};
for (Instruction i : body)
{
ins.addInstruction(i);
}
Execution e = new Execution(group);
e.populateInitialMethods();
e.run();
assert constant1.getConstantAsInt() * constant2.getConstantAsInt() == 1;
assert constant3.getConstantAsInt() * constant4.getConstantAsInt() * constant1.getConstantAsInt() == 1;
Deobfuscator d = new DupDeobfuscator();
d.run(group);
// assert the dup_x1 was removed
long dupCount = ins.getInstructions().stream()
.filter(i -> i instanceof Dup_X1)
.count();
Assert.assertEquals(0, dupCount);
}
//035 aload_0 // this
//036 dup // this this
//037 getfield class153/field2097 I // this I
//038 ldc 830083863
//039 imul // this I
//040 ldc 830083863
//041 iadd // this I
//042 dup_x1 // I this I
@Test
public void test2()
{
ClassGroup group = ClassGroupFactory.generateGroup();
Code code = group.findClass("test").findMethod("func").getCode();
Instructions ins = code.getInstructions();
code.setMaxStack(3);
Instruction body[] =
{
new AConstNull(ins), // this
new Dup(ins), // this this
new GetField(ins, new Field(new Class("test"), "field", Type.INT)),
new LDC(ins, 830083863), // this this I I
new IMul(ins), // this this I
new LDC(ins, 830083863),
new IAdd(ins),
new Dup_X1(ins),
new LDC(ins, 636900519),
new IMul(ins), // pops dup
new VReturn(ins)
};
for (Instruction i : body)
{
ins.addInstruction(i);
}
Execution e = new Execution(group);
e.populateInitialMethods();
e.run();
Deobfuscator d = new DupDeobfuscator();
d.run(group);
// assert the dup wasn't duplicated
long dupCount = ins.getInstructions().stream()
.filter(i -> i instanceof Dup)
.count();
Assert.assertEquals(1, dupCount);
// assert the dup_x1 was removed
dupCount = ins.getInstructions().stream()
.filter(i -> i instanceof Dup_X1)
.count();
Assert.assertEquals(0, dupCount);
}
}

View File

@@ -0,0 +1,87 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.deob.deobfuscators.arithmetic;
import java.io.File;
import java.io.IOException;
import net.runelite.asm.ClassGroup;
import net.runelite.deob.DeobTestProperties;
import net.runelite.deob.TemporyFolderLocation;
import net.runelite.deob.util.JarUtil;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
public class ModArithTest
{
@Rule
public DeobTestProperties properties = new DeobTestProperties();
@Rule
public TemporaryFolder folder = TemporyFolderLocation.getTemporaryFolder();
private ClassGroup group;
@Before
public void before() throws IOException
{
group = JarUtil.loadJar(new File(properties.getVanillaClient()));
}
@After
public void after() throws IOException
{
JarUtil.saveJar(group, folder.newFile());
}
@Test
@Ignore
public void testRun()
{
ModArith mod = new ModArith();
mod.run(group);
int last = -1, cur;
while ((cur = mod.runOnce()) > 0)
{
new MultiplicationDeobfuscator().run(group);
new MultiplyOneDeobfuscator(true).run(group);
new MultiplyZeroDeobfuscator().run(group);
if (last == cur)
break;
last = cur;
}
mod.annotateEncryption();
}
}

View File

@@ -0,0 +1,919 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.deob.deobfuscators.arithmetic;
import net.runelite.asm.ClassGroup;
import net.runelite.asm.attributes.Code;
import net.runelite.asm.attributes.code.Instruction;
import net.runelite.asm.attributes.code.Instructions;
import net.runelite.asm.attributes.code.Label;
import net.runelite.asm.attributes.code.instructions.AConstNull;
import net.runelite.asm.attributes.code.instructions.Dup2_X1;
import net.runelite.asm.attributes.code.instructions.Dup_X1;
import net.runelite.asm.attributes.code.instructions.Goto;
import net.runelite.asm.attributes.code.instructions.IAdd;
import net.runelite.asm.attributes.code.instructions.ILoad;
import net.runelite.asm.attributes.code.instructions.IMul;
import net.runelite.asm.attributes.code.instructions.IStore;
import net.runelite.asm.attributes.code.instructions.IfEq;
import net.runelite.asm.attributes.code.instructions.InvokeStatic;
import net.runelite.asm.attributes.code.instructions.LDC;
import net.runelite.asm.attributes.code.instructions.LLoad;
import net.runelite.asm.attributes.code.instructions.LMul;
import net.runelite.asm.attributes.code.instructions.LStore;
import net.runelite.asm.attributes.code.instructions.Pop;
import net.runelite.asm.attributes.code.instructions.Pop2;
import net.runelite.asm.attributes.code.instructions.SiPush;
import net.runelite.asm.attributes.code.instructions.Swap;
import net.runelite.asm.attributes.code.instructions.VReturn;
import net.runelite.asm.execution.Execution;
import net.runelite.deob.ClassGroupFactory;
import net.runelite.deob.Deobfuscator;
import org.junit.Assert;
import org.junit.Test;
public class MultiplicationDeobfuscatorTest
{
// aload 2
// ldc_w 1587543155
// iload 4
// imul
// dup_x1
// ldc_w -2130376517
// imul
// putfield class2/field279 I
// ldc_w -67313687
// imul
// putstatic class29/field949 I
@Test
public void test1()
{
ClassGroup group = ClassGroupFactory.generateGroup();
Code code = group.findClass("test").findMethod("func").getCode();
Instructions ins = code.getInstructions();
code.setMaxStack(5);
// vars[0] = 3
Instruction[] prepareVariables =
{
new LDC(ins, 3),
new IStore(ins, 0)
};
for (Instruction i : prepareVariables)
{
ins.addInstruction(i);
}
LDC constant1 = new LDC(ins, 1587543155),
constant2 = new LDC(ins, -2130376517),
constant3 = new LDC(ins, -67313687);
Instruction body[] =
{
new LDC(ins, 0), // for dup_x1 to place before this
constant1,
new ILoad(ins, 0),
new IMul(ins),
new Dup_X1(ins),
constant2,
new IMul(ins),
new Pop(ins),
new Pop(ins),
constant3,
new IMul(ins),
new Pop(ins),
new VReturn(ins)
};
for (Instruction i : body)
{
ins.addInstruction(i);
}
// check execution runs ok
Execution e = new Execution(group);
e.populateInitialMethods();
e.run();
assert constant1.getConstantAsInt() * constant2.getConstantAsInt() == 1;
assert constant1.getConstantAsInt() * constant3.getConstantAsInt() == -1_095_175_765;
Deobfuscator d = new MultiplicationDeobfuscator();
d.run(group);
Assert.assertEquals(1, constant1.getConstantAsInt());
Assert.assertEquals(1, constant2.getConstantAsInt());
Assert.assertEquals(-1_095_175_765, constant3.getConstantAsInt());
}
// aload_0
// dup
// getfield class118/field2201 I
// ldc_w -2079217519
// imul
// ldc -2079217519
// iadd
// dup_x1
// ldc_w 561453169
// imul
// putfield class118/field2201 I
// ldc 561453169
// imul
@Test
public void test2()
{
ClassGroup group = ClassGroupFactory.generateGroup();
Code code = group.findClass("test").findMethod("func").getCode();
Instructions ins = code.getInstructions();
code.setMaxStack(4);
// vars[0] = 3
Instruction[] prepareVariables =
{
new LDC(ins, 3),
new IStore(ins, 0)
};
for (Instruction i : prepareVariables)
{
ins.addInstruction(i);
}
LDC constant1 = new LDC(ins, -2079217519),
constant2 = new LDC(ins, -2079217519),
constant3 = new LDC(ins, 561453169),
constant4 = new LDC(ins, 561453169);
Instruction body[] =
{
new LDC(ins, 0), // for dup_x1 to place before this
new ILoad(ins, 0),
constant1,
new IMul(ins),
constant2,
new IAdd(ins),
new Dup_X1(ins), // result, 0, result
constant3,
new IMul(ins),
new Pop(ins),
new Pop(ins),
constant4,
new IMul(ins),
new VReturn(ins)
};
for (Instruction i : body)
{
ins.addInstruction(i);
}
Execution e = new Execution(group);
e.populateInitialMethods();
e.run();
assert constant1.getConstantAsInt() * constant3.getConstantAsInt() == 1;
assert constant2.getConstantAsInt() * constant4.getConstantAsInt() == 1;
Deobfuscator d = new MultiplicationDeobfuscator();
d.run(group);
Assert.assertEquals(1, constant1.getConstantAsInt());
Assert.assertEquals(1, constant2.getConstantAsInt());
Assert.assertEquals(1, constant3.getConstantAsInt());
Assert.assertEquals(1, constant4.getConstantAsInt());
}
@Test
public void test3()
{
ClassGroup group = ClassGroupFactory.generateGroup();
Code code = group.findClass("test").findMethod("func").getCode();
Instructions ins = code.getInstructions();
code.setMaxStack(2);
Instruction[] prepareVariables =
{
new LDC(ins, 3),
new IStore(ins, 0),
};
for (Instruction i : prepareVariables)
{
ins.addInstruction(i);
}
LDC constant1 = new LDC(ins, 1381104939),
constant2 = new LDC(ins, 1381104939),
constant3 = new LDC(ins, 981643079),
constant4 = new LDC(ins, 1807370871),
constant5 = new LDC(ins, 981643079);
Label label1 = new Label(ins);
Instruction body[] =
{
constant4,
constant1,
new ILoad(ins, 0),
new IMul(ins),
new LDC(ins, 0),
new IfEq(ins, label1),
constant2,
new IMul(ins),
label1,
constant3,
new IMul(ins),
new IMul(ins), // constant4
constant5,
new IMul(ins),
new Pop(ins),
new VReturn(ins)
};
for (Instruction i : body)
{
ins.addInstruction(i);
}
Execution e = new Execution(group);
e.populateInitialMethods();
e.run();
assert constant4.getConstantAsInt() * constant5.getConstantAsInt() == 1;
// {
// Collection<InstructionContext> ctxs = e.getInstructonContexts(body[3]);
// assert ctxs.size() == 1;
//
// InstructionContext ictx = ctxs.iterator().next();
// boolean onlyPath = MultiplicationDeobfuscator.isOnlyPath(e, ictx);
// Assert.assertFalse(onlyPath);
// }
Deobfuscator d = new MultiplicationDeobfuscator();
d.run(group);
Assert.assertEquals(1381104939, constant1.getConstantAsInt());
Assert.assertEquals(1381104939, constant2.getConstantAsInt());
Assert.assertEquals(1, constant3.getConstantAsInt());
Assert.assertEquals(1, constant4.getConstantAsInt());
Assert.assertEquals(981643079, constant5.getConstantAsInt()); // assumes result is moved to the end here.
}
@Test
public void test4()
{
ClassGroup group = ClassGroupFactory.generateGroup();
Code code = group.findClass("test").findMethod("func").getCode();
Instructions ins = code.getInstructions();
code.setMaxStack(2);
Instruction[] prepareVariables =
{
new LDC(ins, 3),
new IStore(ins, 0),
};
for (Instruction i : prepareVariables)
{
ins.addInstruction(i);
}
LDC constant1 = new LDC(ins, 1807370871);
LDC constant2 = new LDC(ins, 981643079);
Label label1 = new Label(ins);
Instruction body[] =
{
new ILoad(ins, 0),
new LDC(ins, 2),
new IMul(ins),
new LDC(ins, 0),
new IfEq(ins, label1),
new Pop(ins),
new LDC(ins, 3),
label1,
constant1,
new IMul(ins),
constant2,
new IMul(ins),
new VReturn(ins)
};
for (Instruction i : body)
{
ins.addInstruction(i);
}
Execution e = new Execution(group);
e.populateInitialMethods();
e.run();
assert constant1.getConstantAsInt() * constant2.getConstantAsInt() == 1;
Deobfuscator d = new MultiplicationDeobfuscator();
d.run(group);
Assert.assertEquals(1, constant1.getConstantAsInt());
Assert.assertEquals(1, constant2.getConstantAsInt());
}
@Test
public void test5()
{
ClassGroup group = ClassGroupFactory.generateGroup();
Code code = group.findClass("test").findMethod("func").getCode();
Instructions ins = code.getInstructions();
code.setMaxStack(2);
Instruction[] prepareVariables =
{
new LDC(ins, 3),
new IStore(ins, 0),
new LDC(ins, 2),
new IStore(ins, 1)
};
for (Instruction i : prepareVariables)
{
ins.addInstruction(i);
}
LDC constant1 = new LDC(ins, -2079217519),
constant2 = new LDC(ins, -2079217519),
constant3 = new LDC(ins, 561453169);
Instruction body[] =
{
new ILoad(ins, 0),
constant1,
new IMul(ins),
new IStore(ins, 2),
new ILoad(ins, 2),
new ILoad(ins, 1),
constant2,
new IMul(ins),
new IAdd(ins),
constant3,
new IMul(ins),
new VReturn(ins)
};
for (Instruction i : body)
{
ins.addInstruction(i);
}
Execution e = new Execution(group);
e.populateInitialMethods();
e.run();
assert constant1.getConstantAsInt() * constant3.getConstantAsInt() == 1;
Deobfuscator d = new MultiplicationDeobfuscator();
d.run(group);
Assert.assertEquals(1, constant1.getConstantAsInt());
Assert.assertEquals(1, constant2.getConstantAsInt());
Assert.assertEquals(1, constant3.getConstantAsInt());
}
@Test
public void test6()
{
ClassGroup group = ClassGroupFactory.generateGroup();
Code code = group.findClass("test").findMethod("func").getCode();
Instructions ins = code.getInstructions();
code.setMaxStack(2);
Instruction[] prepareVariables =
{
new LDC(ins, 3),
new IStore(ins, 0),
new LDC(ins, 2),
new IStore(ins, 1)
};
for (Instruction i : prepareVariables)
{
ins.addInstruction(i);
}
LDC constant1 = new LDC(ins, 575391417);
LDC constant2 = new LDC(ins, -497786999);
Instruction body[] =
{
new ILoad(ins, 0),
new ILoad(ins, 1),
new Dup_X1(ins),
new Pop(ins),
new Pop(ins),
constant1,
new IMul(ins),
constant2,
new IMul(ins),
new Pop(ins),
new VReturn(ins)
};
for (Instruction i : body)
{
ins.addInstruction(i);
}
Execution e = new Execution(group);
e.populateInitialMethods();
e.run();
assert constant1.getConstantAsInt() * constant2.getConstantAsInt() == 1;
Deobfuscator d = new MultiplicationDeobfuscator();
d.run(group);
Assert.assertEquals(1, constant1.getConstantAsInt());
Assert.assertEquals(1, constant2.getConstantAsInt());
}
@Test
public void test7()
{
ClassGroup group = ClassGroupFactory.generateGroup();
Code code = group.findClass("test").findMethod("func").getCode();
Instructions ins = code.getInstructions();
code.setMaxStack(2);
Instruction[] prepareVariables =
{
new LDC(ins, 3),
new IStore(ins, 0),
new LDC(ins, 2),
new IStore(ins, 1)
};
for (Instruction i : prepareVariables)
{
ins.addInstruction(i);
}
LDC constant1 = new LDC(ins, 2131037801),
constant2 = new LDC(ins, -1306959399),
constant3 = new LDC(ins, -1);
Instruction body[] =
{
constant3,
constant1,
new IMul(ins),
constant2,
new IMul(ins),
new Pop(ins),
new VReturn(ins)
};
for (Instruction i : body)
{
ins.addInstruction(i);
}
Execution e = new Execution(group);
e.populateInitialMethods();
e.run();
assert constant1.getConstantAsInt() * constant2.getConstantAsInt() == 1;
Deobfuscator d = new MultiplicationDeobfuscator();
d.run(group);
Assert.assertEquals(1, constant1.getConstantAsInt());
Assert.assertEquals(-1, constant2.getConstantAsInt());
Assert.assertEquals(1, constant3.getConstantAsInt());
}
@Test
public void test8()
{
ClassGroup group = ClassGroupFactory.generateGroup();
Code code = group.findClass("test").findMethod("func").getCode();
Instructions ins = code.getInstructions();
code.setMaxStack(2);
Instruction[] prepareVariables =
{
new LDC(ins, 3),
new IStore(ins, 0)
};
for (Instruction i : prepareVariables)
{
ins.addInstruction(i);
}
LDC constant1 = new LDC(ins, -1616202347);
LDC constant2 = new LDC(ins, 2747837);
Label label1 = new Label(ins),
label2 = new Label(ins),
label3 = new Label(ins);
Instruction body[] =
{
constant1,
constant2,
new IMul(ins),
new ILoad(ins, 0),
new LDC(ins, 42),
new IfEq(ins, label1),
new Goto(ins, label2),
label1,
new LDC(ins, -1),
new Goto(ins, label3),
label2,
new LDC(ins, 0),
new Goto(ins, label3),
label3,
new InvokeStatic(ins, group.findClass("test").findMethod("func2").getPoolMethod()),
new VReturn(ins)
};
for (Instruction i : body)
{
ins.addInstruction(i);
}
Execution e = new Execution(group);
e.populateInitialMethods();
e.run();
assert constant1.getConstantAsInt() * constant2.getConstantAsInt() == 1;
Deobfuscator d = new MultiplicationDeobfuscator();
d.run(group);
Assert.assertEquals(1, constant1.getConstantAsInt());
Assert.assertEquals(1, constant2.getConstantAsInt());
}
// aload 0
// aload 0
// aload 1
// invokevirtual class226/method4078()J
// ldc2_w -81013729583719545
// lmul
// dup2_x1
// ldc2_w -6236978337732675017
// lmul
// putfield class227/field3204 J
// ldc2_w -6236978337732675017
// lmul
// putfield class227/field3196 J
@Test
public void test9()
{
ClassGroup group = ClassGroupFactory.generateGroup();
Code code = group.findClass("test").findMethod("func").getCode();
Instructions ins = code.getInstructions();
code.setMaxStack(3);
Instruction[] prepareVariables =
{
new LDC(ins, 1L),
new LStore(ins, 0)
};
for (Instruction i : prepareVariables)
{
ins.addInstruction(i);
}
LDC constant1 = new LDC(ins, -81013729583719545L),
constant2 = new LDC(ins, -6236978337732675017L),
constant3 = new LDC(ins, -6236978337732675017L);
Instruction body[] =
{
new LDC(ins, 0),
new LLoad(ins, 0),
constant1,
new LMul(ins),
new Dup2_X1(ins), // lmul, 0, lmul
constant2,
new LMul(ins),
new Pop(ins),
new Pop(ins),
constant3,
new LMul(ins),
new Pop(ins),
new VReturn(ins)
};
for (Instruction i : body)
{
ins.addInstruction(i);
}
Execution e = new Execution(group);
e.populateInitialMethods();
e.run();
assert constant1.getConstantAsLong() * constant2.getConstantAsLong() == 1L;
Deobfuscator d = new MultiplicationDeobfuscator();
d.run(group);
Assert.assertEquals(1L, constant1.getConstantAsLong());
Assert.assertEquals(1L, constant2.getConstantAsLong());
Assert.assertEquals(1L, constant3.getConstantAsLong());
}
@Test
public void test10()
{
ClassGroup group = ClassGroupFactory.generateGroup();
Code code = group.findClass("test").findMethod("func").getCode();
Instructions ins = code.getInstructions();
code.setMaxStack(5);
// vars[0] = 3
Instruction[] prepareVariables =
{
new LDC(ins, 3),
new IStore(ins, 0)
};
for (Instruction i : prepareVariables)
{
ins.addInstruction(i);
}
LDC constant1 = new LDC(ins, -1729723287);
LDC constant2 = new LDC(ins, -143176743);
Instruction body[] =
{
new ILoad(ins, 0),
constant1,
new IMul(ins),
constant2,
new IMul(ins),
new VReturn(ins)
};
for (Instruction i : body)
{
ins.addInstruction(i);
}
// check execution runs ok
Execution e = new Execution(group);
e.populateInitialMethods();
e.run();
assert constant1.getConstantAsInt() * constant2.getConstantAsInt() == 1;
Deobfuscator d = new MultiplicationDeobfuscator();
d.run(group);
Assert.assertEquals(1, constant1.getConstantAsInt());
Assert.assertEquals(1, constant2.getConstantAsInt());
}
//020 aload_0
//021 aload_0
//022 iload_1
//023 ldc 1129258489
//024 imul
//025 dup_x1
//026 ldc -1692330935
//027 imul
//028 putfield class81/field1351 I
//029 ldc 1641298955
//030 imul // this pops other side of dup_x1
//031 ldc 1043501435
//032 imul
//033 putfield class81/field1326 I
@Test
public void test11()
{
ClassGroup group = ClassGroupFactory.generateGroup();
Code code = group.findClass("test").findMethod("func").getCode();
Instructions ins = code.getInstructions();
code.setMaxStack(5);
Instruction[] prepareVariables =
{
new LDC(ins, 1),
new IStore(ins, 0)
};
for (Instruction i : prepareVariables)
{
ins.addInstruction(i);
}
LDC constant1 = new LDC(ins, 1129258489),
constant2 = new LDC(ins, -1692330935),
constant3 = new LDC(ins, 1641298955),
constant4 = new LDC(ins, 1043501435);
Instruction body[] =
{
new AConstNull(ins), // this
new AConstNull(ins), // this
new ILoad(ins, 0),
constant1,
new IMul(ins),
new Dup_X1(ins),
constant2,
new IMul(ins),
new Pop2(ins), // putfield
constant3,
new IMul(ins),
constant4,
new IMul(ins),
new Pop2(ins), // putfield
new VReturn(ins)
};
for (Instruction i : body)
{
ins.addInstruction(i);
}
Execution e = new Execution(group);
e.populateInitialMethods();
e.run();
assert constant1.getConstantAsInt() * constant2.getConstantAsInt() == 1;
assert constant3.getConstantAsInt() * constant4.getConstantAsInt() * constant1.getConstantAsInt() == 1;
;
Deobfuscator d = new MultiplicationDeobfuscator();
d.run(group);
Assert.assertEquals(1, constant1.getConstantAsInt());
Assert.assertEquals(1, constant2.getConstantAsInt());
Assert.assertEquals(1, constant3.getConstantAsInt());
Assert.assertEquals(1, constant4.getConstantAsInt());
}
//020 aload_0
//021 aload_0
//022 iload_1
//023 ldc 1129258489
//024 imul // this, this, mul
//025 swap // this, mul s, this
//026 iload_1
//027 iconst_1
//028 imul // this, mul s, this, mul
//029 iconst_1
//030 imul
//031 putfield class81/field1351 I // this, mul
//032 iconst_1
//033 imul
//034 ldc -1692330935
//035 imul
//036 putfield class81/field1326 I
@Test
public void test12()
{
ClassGroup group = ClassGroupFactory.generateGroup();
Code code = group.findClass("test").findMethod("func").getCode();
Instructions ins = code.getInstructions();
code.setMaxStack(5);
Instruction[] prepareVariables =
{
new LDC(ins, 1),
new IStore(ins, 0)
};
for (Instruction i : prepareVariables)
{
ins.addInstruction(i);
}
LDC constant1 = new LDC(ins, 1129258489);
LDC constant2 = new LDC(ins, -1692330935);
Instruction body[] =
{
new AConstNull(ins), // this
new AConstNull(ins), // this
new ILoad(ins, 0),
constant1,
new IMul(ins),
new Swap(ins), // null, mul, null
new ILoad(ins, 0),
new Pop2(ins), // putfield
constant2,
new IMul(ins),
new Pop2(ins), // putfield
new VReturn(ins)
};
for (Instruction i : body)
{
ins.addInstruction(i);
}
Execution e = new Execution(group);
e.populateInitialMethods();
e.run();
assert constant1.getConstantAsInt() * constant2.getConstantAsInt() == 1;
Deobfuscator d = new MultiplicationDeobfuscator();
d.run(group);
Assert.assertEquals(1, constant1.getConstantAsInt());
Assert.assertEquals(1, constant2.getConstantAsInt());
}
//sipush 512
//ldc -688421113
//imul
//ldc -585812297
//imul
//putstatic class134/field2009 I
@Test
public void test13()
{
ClassGroup group = ClassGroupFactory.generateGroup();
Code code = group.findClass("test").findMethod("func").getCode();
Instructions ins = code.getInstructions();
code.setMaxStack(2);
LDC constant1 = new LDC(ins, -688421113);
LDC constant2 = new LDC(ins, -585812297);
Instruction body[] =
{
new SiPush(ins, (short) 512),
constant1,
new IMul(ins),
constant2,
new IMul(ins),
new VReturn(ins)
};
for (Instruction i : body)
{
ins.addInstruction(i);
}
Execution e = new Execution(group);
e.populateInitialMethods();
e.run();
assert constant1.getConstantAsInt() * constant2.getConstantAsInt() == 1;
Deobfuscator d = new MultiplicationDeobfuscator();
d.run(group);
Assert.assertEquals(1, constant1.getConstantAsInt());
Assert.assertEquals(1, constant2.getConstantAsInt());
}
}

View File

@@ -0,0 +1,253 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.deob.deobfuscators.arithmetic;
import net.runelite.asm.ClassGroup;
import net.runelite.asm.attributes.Code;
import net.runelite.asm.attributes.code.Instruction;
import net.runelite.asm.attributes.code.Instructions;
import net.runelite.asm.attributes.code.Label;
import net.runelite.asm.attributes.code.instructions.Goto;
import net.runelite.asm.attributes.code.instructions.IDiv;
import net.runelite.asm.attributes.code.instructions.ILoad;
import net.runelite.asm.attributes.code.instructions.IMul;
import net.runelite.asm.attributes.code.instructions.IStore;
import net.runelite.asm.attributes.code.instructions.IfEq;
import net.runelite.asm.attributes.code.instructions.IfICmpEq;
import net.runelite.asm.attributes.code.instructions.LDC;
import net.runelite.asm.attributes.code.instructions.SiPush;
import net.runelite.asm.attributes.code.instructions.VReturn;
import net.runelite.asm.execution.Execution;
import net.runelite.deob.ClassGroupFactory;
import net.runelite.deob.Deobfuscator;
import org.junit.Assert;
import org.junit.Test;
public class MultiplyOneDeobfuscatorTest
{
@Test
public void testDir()
{
ClassGroup group = ClassGroupFactory.generateGroup();
Code code = group.findClass("test").findMethod("func").getCode();
Instructions ins = code.getInstructions();
code.setMaxStack(2);
// vars[0] = 3
Instruction[] prepareVariables = {
new LDC(ins, 3),
new IStore(ins, 0)
};
for (Instruction i : prepareVariables)
ins.addInstruction(i);
Label label = new Label(ins),
label2 = new Label(ins);
LDC one = new LDC(ins, 1);
Instruction body[] = {
new SiPush(ins, (short) 256),
new ILoad(ins, 0),
new IfEq(ins, label),
new LDC(ins, 2),
new Goto(ins, label2),
label,
one,
label2,
new IMul(ins),
new VReturn(ins)
};
for (Instruction i : body)
ins.addInstruction(i);
// check execution runs ok
Execution e = new Execution(group);
e.populateInitialMethods();
e.run();
Deobfuscator d = new MultiplyOneDeobfuscator(false);
d.run(group);
Assert.assertTrue(one.getInstructions() != null);
}
@Test
public void test()
{
ClassGroup group = ClassGroupFactory.generateGroup();
Code code = group.findClass("test").findMethod("func").getCode();
Instructions ins = code.getInstructions();
code.setMaxStack(2);
// vars[0] = 3
Instruction[] prepareVariables = {
new LDC(ins, 3),
new IStore(ins, 0)
};
for (Instruction i : prepareVariables)
ins.addInstruction(i);
Label label = new Label(ins),
label2 = new Label(ins);
LDC one = new LDC(ins, 1);
IMul mul = new IMul(ins);
Instruction body[] = {
new SiPush(ins, (short) 256),
new ILoad(ins, 0),
new IfEq(ins, label),
label,
one,
label2,
mul,
new VReturn(ins)
};
for (Instruction i : body)
ins.addInstruction(i);
// check execution runs ok
Execution e = new Execution(group);
e.populateInitialMethods();
e.run();
Deobfuscator d = new MultiplyOneDeobfuscator(false);
d.run(group);
Assert.assertTrue(one.getInstructions() == null);
Assert.assertTrue(mul.getInstructions() == null);
}
// iconst_1
// iconst_m1
// iload 5
// if_icmpeq LABEL0x56d1
// iload 5
// iconst_1
// if_icmpne LABEL0x56e8
// goto LABEL0x56d1
//LABEL0x56d1:
// getstatic class139/field2130 I
// ldc_w -1440517609
// imul
// goto LABEL0x5708
//LABEL0x56e8:
// getstatic class139/field2130 I
// ldc_w -1440517609
// imul
// getstatic client/field377 I
// iadd
// iconst_2
// idiv
//LABEL0x5708:
// imul
// putstatic client/field377 I
//
// client.field377 = 1 * (-1 != var5 && var5 != 1?(class139.field2130 + client.field377) / 2:class139.field2130);
@Test
public void test2()
{
ClassGroup group = ClassGroupFactory.generateGroup();
Code code = group.findClass("test").findMethod("func").getCode();
Instructions ins = code.getInstructions();
code.setMaxStack(2);
// vars[0] = 3
Instruction[] prepareVariables = {
new LDC(ins, 3),
new IStore(ins, 0),
new LDC(ins, 2),
new IStore(ins, 1)
};
for (Instruction i : prepareVariables)
ins.addInstruction(i);
Label label = new Label(ins),
label2 = new Label(ins),
label3 = new Label(ins);
LDC one = new LDC(ins, 1);
IMul mul = new IMul(ins);
Instruction body[] = {
one,
new LDC(ins, -1),
new ILoad(ins, 0),
new IfICmpEq(ins, label),
new Goto(ins, label2),
label,
new ILoad(ins, 1),
new LDC(ins, -1440517609),
new IDiv(ins),
new Goto(ins, label3),
label2,
new ILoad(ins, 1),
new LDC(ins, -1440517609),
new IDiv(ins),
label3,
mul,
new VReturn(ins)
};
for (Instruction i : body)
ins.addInstruction(i);
// check execution runs ok
Execution e = new Execution(group);
e.populateInitialMethods();
e.run();
Deobfuscator d = new MultiplyOneDeobfuscator(false);
d.run(group);
Assert.assertTrue(one.getInstructions() == null);
Assert.assertTrue(mul.getInstructions() == null);
}
}

View File

@@ -0,0 +1,70 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.deob.deobfuscators.arithmetic;
import java.io.File;
import java.io.IOException;
import net.runelite.asm.ClassGroup;
import net.runelite.deob.DeobTestProperties;
import net.runelite.deob.TemporyFolderLocation;
import net.runelite.deob.util.JarUtil;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
public class MultiplyZeroDeobfuscatorTest
{
@Rule
public DeobTestProperties properties = new DeobTestProperties();
@Rule
public TemporaryFolder folder = TemporyFolderLocation.getTemporaryFolder();
private ClassGroup group;
@Before
public void before() throws IOException
{
group = JarUtil.loadJar(new File(properties.getVanillaClient()));
}
@After
public void after() throws IOException
{
JarUtil.saveJar(group, folder.newFile());
}
@Test
@Ignore
public void testRun()
{
MultiplyZeroDeobfuscator m = new MultiplyZeroDeobfuscator();
m.run(group);
}
}

View File

@@ -0,0 +1,173 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.deob.deobfuscators.arithmetic;
import java.io.IOException;
import java.io.InputStream;
import net.runelite.asm.ClassFile;
import net.runelite.asm.ClassGroup;
import net.runelite.asm.ClassUtil;
import net.runelite.asm.Method;
import net.runelite.asm.attributes.Code;
import net.runelite.asm.attributes.code.Instruction;
import net.runelite.asm.attributes.code.Instructions;
import net.runelite.asm.attributes.code.instructions.LDC;
import net.runelite.deob.Deobfuscator;
import org.junit.Assert;
import static org.junit.Assert.assertFalse;
import org.junit.Test;
class TestClass
{
private static int dummy(Object... args)
{
return 0;
}
private int field1051 = -1611704481;
private int field2701;
private int field2138, field2130;
public void test()
{
TestClass tc = new TestClass(); // to trick executor to call the constructor
int var = 42;
if (-1 != this.field1051 * 1928543073)
{
dummy(this.field1051 * 1928543073);
this.field1051 = dummy() * 1611704481;
}
if (field2701 * 1550405721 > 30000)
{
field2701 += -1868498967 * var;
}
field2138 = tc.dummy() * 1510226873;
field2130 = 572701809 * tc.field2138;
if (-1722291303 * field2130 >= var)
{
var = field2130 * -1722291303;
}
}
}
class TestClass2
{
int field2863;
int array[];
public void test()
{
TestClass2 tc = new TestClass2();
field2863 = -1446933277;
array[378529589 * tc.field2863] = 1;
int var = 32;
tc.field2863 = var * 1446933277;
array[378529589 * tc.field2863] = 1;
}
}
public class SimpleModArithTest
{
static boolean isBig(int val)
{
if ((val & 0x80000000) != 0)
{
val = ~val + 1;
}
return (val & 0x7ff00000) != 0;
}
private void checkConstants(ClassFile cf)
{
for (Method m : cf.getMethods())
{
Code code = m.getCode();
Instructions instructions = code.getInstructions();
for (Instruction i : instructions.getInstructions())
{
if (i instanceof LDC)
{
LDC ldc = (LDC) i;
Integer value = (Integer) ldc.getConstantAsInt();
assertFalse(isBig(value));
}
}
}
}
@Test
public void test() throws IOException
{
InputStream in = this.getClass().getClassLoader().getResourceAsStream("net/runelite/deob/deobfuscators/arithmetic/TestClass.class");
Assert.assertNotNull(in);
ClassGroup group = new ClassGroup();
ClassFile cf = ClassUtil.loadClass(in);
group.addClass(cf);
ModArith d1 = new ModArith();
d1.run(group);
d1.runOnce();
Deobfuscator d2 = new MultiplicationDeobfuscator();
d2.run(group);
this.checkConstants(cf);
}
@Test
public void test2() throws IOException
{
InputStream in = this.getClass().getClassLoader().getResourceAsStream("net/runelite/deob/deobfuscators/arithmetic/TestClass2.class");
Assert.assertNotNull(in);
ClassGroup group = new ClassGroup();
ClassFile cf = ClassUtil.loadClass(in);
group.addClass(cf);
ModArith d1 = new ModArith();
d1.run(group);
d1.runOnce();
Deobfuscator d2 = new MultiplicationDeobfuscator();
d2.run(group);
Encryption e = d1.getEncryption();
Pair pair = e.getField(cf.findField("field2863").getPoolField());
Assert.assertEquals(378529589, (int) pair.getter);
}
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.deob.deobfuscators.cfg;
import java.io.File;
import java.io.IOException;
import net.runelite.asm.ClassGroup;
import net.runelite.deob.DeobTestProperties;
import net.runelite.deob.TemporyFolderLocation;
import net.runelite.deob.util.JarUtil;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
public class ControlFlowDeobfuscatorTest
{
@Rule
public DeobTestProperties properties = new DeobTestProperties();
@Rule
public TemporaryFolder folder = TemporyFolderLocation.getTemporaryFolder();
private ClassGroup group;
@Before
public void before() throws IOException
{
group = JarUtil.loadJar(new File(properties.getVanillaClient()));
}
@After
public void after() throws IOException
{
JarUtil.saveJar(group, folder.newFile());
}
@Test
@Ignore
public void testRun() throws Exception
{
new ControlFlowDeobfuscator().run(group);
}
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.deob.deobfuscators.constparam;
import java.io.File;
import java.io.IOException;
import net.runelite.asm.ClassGroup;
import net.runelite.deob.DeobTestProperties;
import net.runelite.deob.TemporyFolderLocation;
import net.runelite.deob.util.JarUtil;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
public class ConstantParameterTest
{
@Rule
public DeobTestProperties properties = new DeobTestProperties();
@Rule
public TemporaryFolder folder = TemporyFolderLocation.getTemporaryFolder();
private ClassGroup group;
@Before
public void before() throws IOException
{
group = JarUtil.loadJar(new File(properties.getVanillaClient()));
}
@After
public void after() throws IOException
{
JarUtil.saveJar(group, folder.newFile());
}
@Test
@Ignore
public void testRun()
{
ConstantParameter cp = new ConstantParameter();
cp.run(group);
}
}

View File

@@ -0,0 +1,391 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.deob.deobfuscators.exprargorder;
import java.io.File;
import java.util.List;
import net.runelite.asm.ClassGroup;
import net.runelite.asm.attributes.Code;
import net.runelite.asm.attributes.code.Instruction;
import static net.runelite.asm.attributes.code.InstructionType.IADD;
import static net.runelite.asm.attributes.code.InstructionType.IAND;
import static net.runelite.asm.attributes.code.InstructionType.IF_ICMPEQ;
import static net.runelite.asm.attributes.code.InstructionType.ILOAD;
import static net.runelite.asm.attributes.code.InstructionType.LDC;
import static net.runelite.asm.attributes.code.InstructionType.SIPUSH;
import net.runelite.asm.attributes.code.Instructions;
import net.runelite.asm.attributes.code.Label;
import net.runelite.asm.attributes.code.instructions.IAdd;
import net.runelite.asm.attributes.code.instructions.IAnd;
import net.runelite.asm.attributes.code.instructions.ILoad;
import net.runelite.asm.attributes.code.instructions.IMul;
import net.runelite.asm.attributes.code.instructions.IStore;
import net.runelite.asm.attributes.code.instructions.IfICmpEq;
import net.runelite.asm.attributes.code.instructions.LDC;
import net.runelite.asm.attributes.code.instructions.Pop;
import net.runelite.asm.attributes.code.instructions.SiPush;
import net.runelite.asm.attributes.code.instructions.VReturn;
import net.runelite.deob.ClassGroupFactory;
import net.runelite.deob.util.JarUtil;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
public class ExprArgOrderTest
{
@Test
public void test()
{
ClassGroup group = ClassGroupFactory.generateGroup();
Code code = group.findClass("test").findMethod("func").getCode();
Instructions ins = code.getInstructions();
code.setMaxStack(2);
// vars[0] = 3
Instruction[] prepareVariables =
{
new LDC(ins, 3),
new IStore(ins, 0)
};
for (Instruction i : prepareVariables)
{
ins.addInstruction(i);
}
Instruction body[] =
{
// 3 + var0 -> var0 + 3
new LDC(ins, 3), // 2
new ILoad(ins, 0),
new IAdd(ins),
new Pop(ins),
new VReturn(ins)
};
for (Instruction i : body)
{
ins.addInstruction(i);
}
ExprArgOrder exprArgOrder = new ExprArgOrder();
exprArgOrder.run(group);
List<Instruction> instructions = ins.getInstructions();
assertEquals(ILOAD, instructions.get(2).getType());
assertEquals(LDC, instructions.get(3).getType());
assertEquals(IADD, instructions.get(4).getType());
}
@Test
public void test2()
{
ClassGroup group = ClassGroupFactory.generateGroup();
Code code = group.findClass("test").findMethod("func").getCode();
Instructions ins = code.getInstructions();
code.setMaxStack(2);
// vars[0] = 3
Instruction[] prepareVariables =
{
new LDC(ins, 3),
new IStore(ins, 0)
};
for (Instruction i : prepareVariables)
{
ins.addInstruction(i);
}
Instruction body[] =
{
// var0 + 3 -> var0 + 3
new ILoad(ins, 0), // 2
new LDC(ins, 3),
new IAdd(ins),
new Pop(ins),
// (3 + var0) + 512 -> (var0 + 3) + 512
new LDC(ins, 3), // 6
new ILoad(ins, 0),
new IAdd(ins),
new SiPush(ins, (short) 512),
new IAdd(ins),
new Pop(ins),
new VReturn(ins)
};
for (Instruction i : body)
{
ins.addInstruction(i);
}
ExprArgOrder exprArgOrder = new ExprArgOrder();
exprArgOrder.run(group);
List<Instruction> instructions = ins.getInstructions();
// ensure this stays the same
assertEquals(ILOAD, instructions.get(2).getType());
assertEquals(LDC, instructions.get(3).getType());
assertEquals(IADD, instructions.get(4).getType());
//
assertEquals(ILOAD, instructions.get(6).getType());
assertEquals(SIPUSH, instructions.get(7).getType());
assertEquals(IADD, instructions.get(8).getType());
assertEquals(LDC, instructions.get(9).getType());
assertEquals(IADD, instructions.get(10).getType());
}
@Test
public void test3()
{
ClassGroup group = ClassGroupFactory.generateGroup();
Code code = group.findClass("test").findMethod("func").getCode();
Instructions ins = code.getInstructions();
code.setMaxStack(2);
// vars[0] = 3
Instruction[] prepareVariables =
{
new LDC(ins, 3),
new IStore(ins, 0)
};
for (Instruction i : prepareVariables)
{
ins.addInstruction(i);
}
Instruction body[] =
{
// 512 + (3 + var1) -> var1 + 3 + 512
new LDC(ins, 512),
new LDC(ins, 3),
new ILoad(ins, 0),
new IAdd(ins),
new IAdd(ins),
new Pop(ins),
new VReturn(ins)
};
for (Instruction i : body)
{
ins.addInstruction(i);
}
ExprArgOrder exprArgOrder = new ExprArgOrder();
exprArgOrder.run(group);
List<Instruction> instructions = ins.getInstructions();
// 2: iload
// 3: iconst 3
// 4: iadd
// 5: ldc
// 6: add
assertEquals(IADD, instructions.get(4).getType());
assertEquals(IADD, instructions.get(6).getType());
}
@Test
public void test4()
{
ClassGroup group = ClassGroupFactory.generateGroup();
Code code = group.findClass("test").findMethod("func").getCode();
Instructions ins = code.getInstructions();
code.setMaxStack(2);
// vars[0] = 3
Instruction[] prepareVariables =
{
new LDC(ins, 3),
new IStore(ins, 0)
};
for (Instruction i : prepareVariables)
{
ins.addInstruction(i);
}
Instruction body[] =
{
new SiPush(ins, (short) 600),
new ILoad(ins, 0),
new LDC(ins, 3),
new IMul(ins),
new IAdd(ins),
new Pop(ins),
new ILoad(ins, 0),
new LDC(ins, 3),
new IMul(ins),
new SiPush(ins, (short) 600),
new IAdd(ins),
new Pop(ins),
new VReturn(ins)
};
for (Instruction i : body)
{
ins.addInstruction(i);
}
ExprArgOrder exprArgOrder = new ExprArgOrder();
exprArgOrder.run(group);
List<Instruction> instructions = ins.getInstructions();
for (int i = 2; i <= 7; ++i)
{
assertEquals(instructions.get(i).getType(), instructions.get(i + 6).getType());
}
}
@Test
public void test5()
{
ClassGroup group = ClassGroupFactory.generateGroup();
Code code = group.findClass("test").findMethod("func").getCode();
Instructions ins = code.getInstructions();
code.setMaxStack(2);
// vars[0] = 3
Instruction[] prepareVariables =
{
new LDC(ins, 3),
new IStore(ins, 0)
};
for (Instruction i : prepareVariables)
{
ins.addInstruction(i);
}
Label label = new Label(ins);
Instruction body[] =
{
// if (0 == 3 + var0) -> if (var0 + 3 == 0)
new LDC(ins, 0),
new LDC(ins, 3),
new ILoad(ins, 0),
new IAdd(ins),
new IfICmpEq(ins, label),
label,
new VReturn(ins)
};
for (Instruction i : body)
{
ins.addInstruction(i);
}
ExprArgOrder exprArgOrder = new ExprArgOrder();
exprArgOrder.run(group);
List<Instruction> instructions = ins.getInstructions();
// ldc iload add -> iload ldc iadd
assertEquals(ILOAD, instructions.get(2).getType());
assertEquals(LDC, instructions.get(3).getType());
assertEquals(IADD, instructions.get(4).getType());
// idc moves from 2 to 5
assertEquals(LDC, instructions.get(5).getType());
assertEquals(IF_ICMPEQ, instructions.get(6).getType());
}
@Test
public void test6()
{
ClassGroup group = ClassGroupFactory.generateGroup();
Code code = group.findClass("test").findMethod("func").getCode();
Instructions ins = code.getInstructions();
code.setMaxStack(2);
// vars[0] = 3
Instruction[] prepareVariables =
{
new LDC(ins, 3),
new IStore(ins, 0)
};
for (Instruction i : prepareVariables)
{
ins.addInstruction(i);
}
Label label = new Label(ins);
/*
iconst_0
ldc 8388608
iload_3
iadd
ldc -16777216
iand
if_icmpeq LABEL0x49
*/
Instruction body[] =
{
new LDC(ins, 0),
new LDC(ins, 8388608),
new ILoad(ins, 0),
new IAdd(ins),
new LDC(ins, -16777216),
new IAnd(ins),
new IfICmpEq(ins, label), // 8
label,
new VReturn(ins)
};
for (Instruction i : body)
{
ins.addInstruction(i);
}
ExprArgOrder exprArgOrder = new ExprArgOrder();
exprArgOrder.run(group);
List<Instruction> instructions = ins.getInstructions();
assertEquals(ILOAD, instructions.get(2).getType());
assertEquals(LDC, instructions.get(3).getType());
assertEquals(IADD, instructions.get(4).getType());
assertEquals(LDC, instructions.get(5).getType());
assertEquals(IAND, instructions.get(6).getType());
assertEquals(LDC, instructions.get(7).getType());
assertEquals(IF_ICMPEQ, instructions.get(8).getType());
}
}

View File

@@ -0,0 +1,315 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.deob.deobfuscators.mapping;
import java.io.File;
import java.io.IOException;
import java.time.Instant;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import net.runelite.asm.ClassFile;
import net.runelite.asm.ClassGroup;
import net.runelite.asm.Field;
import net.runelite.asm.Method;
import net.runelite.asm.Type;
import net.runelite.asm.signature.Signature;
import net.runelite.deob.DeobAnnotations;
import net.runelite.deob.DeobTestProperties;
import net.runelite.deob.util.JarUtil;
import org.junit.Rule;
import org.junit.Test;
public class MappingDumper
{
@Rule
public DeobTestProperties properties = new DeobTestProperties();
@Test
public void dump() throws IOException
{
ClassGroup group = JarUtil.loadJar(new File(properties.getRsClient()));
final String GAP = "%-40s";
int classes = 0, methods = 0, fields = 0;
StringBuilder mBuilder = new StringBuilder();
StringBuilder sBuilder = new StringBuilder();
StringBuilder tmp;
for (ClassFile cf : group.getClasses())
{
String implName = DeobAnnotations.getImplements(cf);
String className = DeobAnnotations.getObfuscatedName(cf.getAnnotations());
if (implName != null)
{
mBuilder.append("\n").append(implName).append(" -> ").append(className).append("\n");
++classes;
}
for (Field f : cf.getFields())
{
String exportName = DeobAnnotations.getExportedName(f.getAnnotations());
if (exportName == null)
{
continue;
}
++fields;
String fieldName = DeobAnnotations.getObfuscatedName(f.getAnnotations());
Type type = f.getType();
Number getter = DeobAnnotations.getObfuscatedGetter(f);
String fieldType = typeToString(type);
if (f.isStatic())
{
tmp = sBuilder;
}
else
{
tmp = mBuilder;
}
tmp.append("\t").append(String.format(GAP, fieldType)).append(String.format(GAP, exportName))
.append(className).append(".").append(fieldName);
if (getter != null)
{
tmp.append(" * ").append(getter).append("\n");
}
else
{
tmp.append("\n");
}
}
for (Method m : cf.getMethods())
{
String exportName = DeobAnnotations.getExportedName(m.getAnnotations());
if (exportName == null)
{
continue;
}
methods++;
String methodName = DeobAnnotations.getObfuscatedName(m.getAnnotations());
Signature signature = DeobAnnotations.getObfuscatedSignature(m);
String garbageValue = DeobAnnotations.getObfuscatedValue(m);
if (signature == null)
{
signature = m.getDescriptor();
}
String returnType = typeToString(m.getDescriptor().getReturnValue());
String[] paramTypes = new String[signature.size()];
for (int i = 0; i < paramTypes.length; i++)
{
paramTypes[i] = typeToString(signature.getTypeOfArg(i));
}
if (m.isStatic())
{
tmp = sBuilder;
}
else
{
tmp = mBuilder;
}
tmp.append("\t").append(String.format(GAP, returnType)).append(String.format(GAP, exportName))
.append(className).append(".").append(methodName);
tmp.append("(");
for (int i = 0; i < paramTypes.length; i++)
{
tmp.append(paramTypes[i]);
if (i == paramTypes.length - 1)
{
if (garbageValue != null)
{
tmp.append(" = ").append(garbageValue);
}
}
else
{
tmp.append(", ");
}
}
tmp.append(")\n");
}
}
System.out.println("RuneLite http://github.com/runelite");
System.out.println("Run " + Instant.now());
System.out.println("Classes: " + classes + ", methods: " + methods + ", fields: " + fields);
System.out.println("Gamepack " + properties.getRsVersion());
System.out.println(mBuilder.toString());
System.out.println("Static ->");
System.out.println(sBuilder.toString());
}
@Test
public void dumpJson() throws IOException
{
ClassGroup group = JarUtil.loadJar(new File(properties.getRsClient()));
Gson gson = new GsonBuilder().setPrettyPrinting().create();
JsonObject jObject = new JsonObject();
JsonArray jFields = new JsonArray();
JsonArray jMethods = new JsonArray();
for (ClassFile cf : group.getClasses())
{
String implName = DeobAnnotations.getImplements(cf);
String className = DeobAnnotations.getObfuscatedName(cf.getAnnotations());
for (Field f : cf.getFields())
{
String exportName = DeobAnnotations.getExportedName(f.getAnnotations());
if (exportName == null)
{
continue;
}
String fieldName = DeobAnnotations.getObfuscatedName(f.getAnnotations());
Type obfType = DeobAnnotations.getObfuscatedType(f);
Number getter = DeobAnnotations.getObfuscatedGetter(f);
JsonObject jField = new JsonObject();
jField.addProperty("name", exportName);
jField.addProperty("owner", f.isStatic() ? "" : implName);
jField.addProperty("class", className);
jField.addProperty("field", fieldName);
jField.addProperty("obfSignature", (obfType != null ? obfType.toString() : ""));
jField.addProperty("signature", f.getType().toString());
jField.addProperty("multiplier", (getter != null ? getter : 0));
jField.addProperty("static", f.isStatic());
jFields.add(jField);
}
for (Method m : cf.getMethods())
{
String exportName = DeobAnnotations.getExportedName(m.getAnnotations());
if (exportName == null)
{
continue;
}
String methodName = DeobAnnotations.getObfuscatedName(m.getAnnotations());
Signature obfSignature = DeobAnnotations.getObfuscatedSignature(m);
String predicate = DeobAnnotations.getObfuscatedValue(m);
JsonObject jMethod = new JsonObject();
jMethod.addProperty("name", exportName);
jMethod.addProperty("owner", m.isStatic() ? "" : implName);
jMethod.addProperty("class", className);
jMethod.addProperty("field", methodName);
jMethod.addProperty("obfSignature", (obfSignature != null ? obfSignature.toString() : ""));
jMethod.addProperty("signature", m.getDescriptor().toString());
jMethod.addProperty("predicate", (predicate != null ? predicate : ""));
jMethod.addProperty("static", m.isStatic());
jMethods.add(jMethod);
}
}
jObject.addProperty("runelite", "http://github.com/runelite");
jObject.addProperty("run", Instant.now().toString());
jObject.addProperty("gamepack", properties.getRsVersion());
jObject.add("fields", jFields);
jObject.add("methods", jMethods);
System.out.println(gson.toJson(jObject));
}
private static String typeToString(Type type)
{
String subType;
switch (type.toString())
{
case "B":
subType = byte.class.getCanonicalName();
break;
case "C":
subType = char.class.getCanonicalName();
break;
case "I":
subType = int.class.getCanonicalName();
break;
case "S":
subType = short.class.getCanonicalName();
break;
case "Z":
subType = boolean.class.getCanonicalName();
break;
case "D":
subType = double.class.getCanonicalName();
break;
case "F":
subType = float.class.getCanonicalName();
break;
case "J":
subType = long.class.getCanonicalName();
break;
case "V":
subType = void.class.getCanonicalName();
break;
default:
subType = type.getInternalName();
break;
}
if (type.isArray())
{
for (int i = 0; i < type.getDimensions(); ++i)
{
subType += "[]";
}
}
return subType;
}
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.deob.deobfuscators.menuaction;
import java.io.File;
import java.io.IOException;
import net.runelite.asm.ClassGroup;
import net.runelite.deob.DeobTestProperties;
import net.runelite.deob.TemporyFolderLocation;
import net.runelite.deob.util.JarUtil;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.Rule;
import org.junit.rules.TemporaryFolder;
public class MenuActionDeobfuscatorTest
{
@Rule
public DeobTestProperties properties = new DeobTestProperties();
@Rule
public TemporaryFolder folder = TemporyFolderLocation.getTemporaryFolder();
private ClassGroup group;
@Before
public void before() throws IOException
{
group = JarUtil.loadJar(new File(properties.getRsClient()));
}
@After
public void after() throws IOException
{
JarUtil.saveJar(group, folder.newFile());
}
@Test
@Ignore
public void testRun()
{
new MenuActionDeobfuscator().run(group);
}
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.deob.deobfuscators.packethandler;
import java.io.File;
import java.io.IOException;
import net.runelite.asm.ClassGroup;
import net.runelite.deob.DeobTestProperties;
import net.runelite.deob.TemporyFolderLocation;
import net.runelite.deob.util.JarUtil;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
public class PacketTypeFinderTest
{
@Rule
public DeobTestProperties properties = new DeobTestProperties();
@Rule
public TemporaryFolder folder = TemporyFolderLocation.getTemporaryFolder();
private ClassGroup group;
@Before
public void before() throws IOException
{
group = JarUtil.loadJar(new File(properties.getRsClient()));
}
@Test
@Ignore
public void testRun() throws IOException
{
PacketTypeFinder bf = new PacketTypeFinder(group);
bf.find();
}
}

View File

@@ -0,0 +1,72 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.deob.deobfuscators.packetwrite;
import java.io.File;
import java.io.IOException;
import net.runelite.asm.ClassGroup;
import net.runelite.deob.DeobTestProperties;
import net.runelite.deob.TemporyFolderLocation;
import net.runelite.deob.util.JarUtil;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.Rule;
import org.junit.rules.TemporaryFolder;
public class PacketWriteDeobfuscatorTest
{
@Rule
public DeobTestProperties properties = new DeobTestProperties();
@Rule
public TemporaryFolder folder = TemporyFolderLocation.getTemporaryFolder();
private ClassGroup group;
@Before
public void before() throws IOException
{
group = JarUtil.loadJar(new File(properties.getRsClient()));
group.removeClass(group.findClass("net/runelite/rs/Reflection"));
}
@After
public void after() throws IOException
{
JarUtil.saveJar(group, folder.newFile());
}
@Test
@Ignore
public void testRun() throws IOException
{
PacketWriteDeobfuscator pw = new PacketWriteDeobfuscator();
pw.run(group);
}
}

View File

@@ -0,0 +1,75 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.deob.deobfuscators.transformers;
import java.io.File;
import java.io.IOException;
import net.runelite.asm.ClassGroup;
import net.runelite.deob.TemporyFolderLocation;
import net.runelite.deob.util.JarUtil;
import org.junit.After;
import org.junit.Test;
import org.junit.Before;
import org.junit.Rule;
import org.junit.rules.TemporaryFolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ClientErrorTransformerTest
{
private static final Logger logger = LoggerFactory.getLogger(ClientErrorTransformerTest.class);
private static final File GAMEPACK = new File("C:\\Users\\Adam\\.m2\\repository\\net\\runelite\\rs\\rs-client\\127.2-SNAPSHOT\\rs-client-127.2-SNAPSHOT.jar");
@Rule
public TemporaryFolder folder = TemporyFolderLocation.getTemporaryFolder();
private ClassGroup group;
@Before
public void before() throws IOException
{
group = JarUtil.loadJar(GAMEPACK);
}
@After
public void after() throws IOException
{
File out = folder.newFile();
JarUtil.saveJar(group, out);
logger.info("Wrote to {}", out);
}
//@Test
public void testRun()
{
ClientErrorTransformer e = new ClientErrorTransformer();
e.transform(group);
}
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.deob.deobfuscators.transformers.buffer;
import java.io.File;
import java.io.IOException;
import net.runelite.asm.ClassGroup;
import net.runelite.deob.DeobTestProperties;
import net.runelite.deob.TemporyFolderLocation;
import net.runelite.deob.util.JarUtil;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
public class BufferFinderTest
{
@Rule
public DeobTestProperties properties = new DeobTestProperties();
@Rule
public TemporaryFolder folder = TemporyFolderLocation.getTemporaryFolder();
private ClassGroup group;
@Before
public void before() throws IOException
{
group = JarUtil.loadJar(new File(properties.getRsClient()));
}
@Test
@Ignore
public void testRun() throws IOException
{
BufferFinder bf = new BufferFinder(group);
bf.find();
}
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.deob.deobfuscators.transformers.buffer;
import org.junit.Test;
import static org.junit.Assert.*;
/**
*
* @author Adam
*/
public class RuneliteBufferTest
{
@Test
public void testRuneliteFinishPacket()
{
RuneliteBuffer buffer = new RuneliteBuffer();
byte[] b = new byte[7];
buffer.setPayload(b);
buffer.runeliteWriteByte((byte) 0);
buffer.runeliteInitPacket();
buffer.runeliteWriteInt(42);
assertEquals(0, b[2]); // non finished lenghts are 0 initialized
buffer.runeliteFinishPacket();
assertEquals(7, b.length);
assertEquals(0, b[0]);
assertEquals(0, b[1]);
assertEquals(4, b[2]);
assertEquals(0, b[3]);
assertEquals(0, b[4]);
assertEquals(0, b[5]);
assertEquals(42, b[6]);
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.deob.deobfuscators.unreachedcode;
public class UnreachableTest
{
public UnreachableTest()
{
}
public void entry()
{
try
{
System.out.println("used");
}
catch (Exception ex)
{
System.out.println("should be hit");
}
}
public void method1Unused()
{
try
{
System.out.println("unused");
}
catch (Exception ex)
{
System.out.println("oh no, an exception");
}
}
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.deob.deobfuscators.unusedclass;
public class ClassA implements EmptyInterface
{
public void run()
{
System.out.append("code!");
}
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.deob.deobfuscators.unusedclass;
public class EmptyClass
{
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.deob.deobfuscators.unusedclass;
public interface EmptyInterface
{
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.deob.injection;
import java.util.HashMap;
import java.util.Map;
import net.runelite.asm.ClassFile;
import net.runelite.asm.ClassGroup;
import net.runelite.deob.util.JarUtil;
public class TestingClassLoader extends ClassLoader
{
private ClassGroup group;
private Map<String, Class<?>> classes = new HashMap<>();
public TestingClassLoader(ClassGroup group)
{
this.group = group;
}
@Override
public Class<?> findClass(String name) throws ClassNotFoundException
{
ClassFile cf = group.findClass(name);
if (cf == null)
{
return super.findClass(name);
}
Class<?> c = classes.get(name);
if (c != null)
{
return c;
}
byte[] clazz = JarUtil.writeClass(group, cf);
return defineClass(name, clazz);
}
private Class<?> defineClass(String name, byte[] b)
{
Class<?> c = super.defineClass(name.replace('/', '.'), b, 0, b.length);
classes.put(name, c);
return c;
}
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.deob.updater;
import java.io.File;
import java.io.IOException;
import net.runelite.asm.ClassGroup;
import net.runelite.asm.Type;
import net.runelite.deob.util.JarUtil;
import org.junit.After;
import org.junit.Before;
public class AnnotationCopierTest
{
private static final Type EXPORT = new Type("Lnet/runelite/mapping/Export;");
private static final Type IMPLEMENTS = new Type("Lnet/runelite/mapping/Implements;");
private static final Type REPLACE = new Type("Lnet/runelite/mapping/Replace;");
private static final String JAR1 = "C:\\Users\\Adam\\.m2\\repository\\net\\runelite\\rs\\rs-client\\116.2-SNAPSHOT\\in.jar",
JAR2 = "d:/rs/07/gamepack_116_deobfuscated.jar",
OUT = "d:/rs/07/adamout.jar";
private ClassGroup group1, group2;
@Before
public void before() throws IOException
{
group1 = JarUtil.loadJar(new File(JAR1));
group2 = JarUtil.loadJar(new File(JAR2));
}
@After
public void after() throws IOException
{
JarUtil.saveJar(group2, new File(OUT));
}
//@Test
public void testCopy()
{
AnnotationCopier ac = new AnnotationCopier(group1, group2, EXPORT, IMPLEMENTS, REPLACE);
ac.copy();
}
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.deob.updater;
import java.io.File;
import java.io.IOException;
import net.runelite.asm.ClassGroup;
import net.runelite.deob.util.JarUtil;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class AnnotationRenamerTest
{
private static final String JAR = "C:\\Users\\Adam\\.m2\\repository\\net\\runelite\\rs\\rs-client\\120.2-SNAPSHOT\\rs-client-120.2-SNAPSHOT.jar",
OUT = "d:/rs/07/adamout.jar";
private ClassGroup group;
@Before
public void before() throws IOException
{
group = JarUtil.loadJar(new File(JAR));
}
@After
public void after() throws IOException
{
JarUtil.saveJar(group, new File(OUT));
}
//@Test
public void testRename()
{
AnnotationRenamer ar = new AnnotationRenamer(group);
ar.run();
}
}

View File

@@ -0,0 +1,221 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.deob.updater;
import java.io.File;
import java.io.IOException;
import java.util.Map;
import net.runelite.asm.ClassFile;
import net.runelite.asm.ClassGroup;
import net.runelite.asm.Field;
import net.runelite.asm.Method;
import net.runelite.deob.DeobAnnotations;
import net.runelite.deob.DeobTestProperties;
import net.runelite.deob.deobfuscators.mapping.AnnotationIntegrityChecker;
import net.runelite.deob.deobfuscators.mapping.AnnotationMapper;
import net.runelite.deob.deobfuscators.mapping.Mapper;
import net.runelite.deob.deobfuscators.mapping.ParallelExecutorMapping;
import net.runelite.deob.util.JarUtil;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class UpdateMappingsTest
{
private static final Logger logger = LoggerFactory.getLogger(UpdateMappingsTest.class);
private static final String JAR = "d:/rs/07/gamepack_139_deobfuscated.jar",
OUT = "d:/rs/07/adamout.jar";
@Rule
public DeobTestProperties properties = new DeobTestProperties();
@Test
@Ignore
public void testManual() throws IOException
{
File client = new File(properties.getRsClient());
ClassGroup group1 = JarUtil.loadJar(client);
ClassGroup group2 = JarUtil.loadJar(new File(JAR));
map(group1, group2);
JarUtil.saveJar(group2, new File(OUT));
}
@Test
public void testRun() throws IOException
{
File client = new File(properties.getRsClient());
ClassGroup group1 = JarUtil.loadJar(client);
ClassGroup group2 = JarUtil.loadJar(client);
// Remove existing annotations
unannotate(group2);
// Map the client against itself
map(group1, group2);
check(group1, group2);
}
private void unannotate(ClassGroup group)
{
for (ClassFile cf : group.getClasses())
{
cf.getAnnotations().clearAnnotations();
for (Field f : cf.getFields())
{
f.getAnnotations().clearAnnotations();
}
for (Method m : cf.getMethods())
{
m.getAnnotations().clearAnnotations();
}
}
}
private void check(ClassGroup group1, ClassGroup group2)
{
for (ClassFile cf : group1.getClasses())
{
ClassFile other = group2.findClass(cf.getName());
String implname = DeobAnnotations.getImplements(cf);
String otherimplname = DeobAnnotations.getImplements(other);
Assert.assertEquals(implname, otherimplname);
for (Field f : cf.getFields())
{
Field otherf = other.findField(f.getName(), f.getType());
assert otherf != null : "unable to find " + f;
String name = DeobAnnotations.getExportedName(f.getAnnotations());
String otherName = DeobAnnotations.getExportedName(otherf.getAnnotations());
Assert.assertEquals(name + " <-> " + otherName, name, otherName);
}
for (Method m : cf.getMethods())
{
Method otherm = other.findMethod(m.getName(), m.getDescriptor());
assert otherm != null : "unable to find " + m;
String name = DeobAnnotations.getExportedName(m.getAnnotations());
String otherName = DeobAnnotations.getExportedName(otherm.getAnnotations());
Assert.assertEquals(name + " <-> " + otherName, name, otherName);
}
}
}
private void map(ClassGroup group1, ClassGroup group2)
{
logger.info("Mapping group1 ({}) vs group2 ({})", desc(group1), desc(group2));
Mapper mapper = new Mapper(group1, group2);
mapper.run();
ParallelExecutorMapping mapping = mapper.getMapping();
summary(mapping, group1);
AnnotationMapper amapper = new AnnotationMapper(group1, group2, mapping);
amapper.run();
AnnotationIntegrityChecker aic = new AnnotationIntegrityChecker(group1, group2, mapping);
aic.run();
if (aic.getErrors() > 0)
{
Assert.fail("Errors in annotation integrity checker");
}
AnnotationRenamer an = new AnnotationRenamer(group2);
an.run();
}
private static String desc(ClassGroup cg)
{
int methods = 0, fields = 0, classes = 0;
for (ClassFile cf : cg.getClasses())
{
++classes;
methods += cf.getMethods().size();
fields += cf.getFields().size();
}
int total = methods + fields + classes;
return "total: " + total + ", " + methods + " methods, " + fields + " fields, " + classes + " classes";
}
public static void summary(ParallelExecutorMapping finalm, ClassGroup in)
{
int fields = 0, staticMethod = 0, method = 0, total = 0, classes = 0;
for (Map.Entry<Object, Object> e : finalm.getMap().entrySet())
{
Object o = e.getKey();
if (o instanceof Field)
{
++fields;
Field f = (Field) o;
assert f.getClassFile().getGroup() == in;
}
else if (o instanceof Method)
{
Method m = (Method) o;
assert m.getClassFile().getGroup() == in;
if (m.isStatic())
{
++staticMethod;
}
else
{
++method;
}
}
else if (o instanceof ClassFile)
{
++classes;
}
++total;
}
logger.info("Total mapped: {}. {} fields, {} static methods, {} member methods, {} classes",
total, fields, staticMethod, method, classes);
}
}

View File

@@ -0,0 +1,331 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.osb;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Map;
import net.runelite.asm.ClassFile;
import net.runelite.asm.ClassGroup;
import net.runelite.asm.Field;
import net.runelite.asm.Method;
import net.runelite.asm.Type;
import net.runelite.asm.attributes.Annotations;
import net.runelite.asm.attributes.annotation.Annotation;
import net.runelite.asm.attributes.annotation.Element;
import net.runelite.asm.signature.Signature;
import net.runelite.deob.util.JarUtil;
import net.runelite.osb.inject.ClassHook;
import net.runelite.osb.inject.FieldHook;
import net.runelite.osb.inject.MethodHook;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
public class HookImporter
{
private static final File IN = new File("C:\\Users\\Adam\\.m2\\repository\\net\\runelite\\rs\\rs-client\\114.2-SNAPSHOT\\rs-client-114.2-SNAPSHOT.jar");
private static final File OUT = new File("c:\\rs\\adamout.jar");
private static final Type OBFUSCATED_NAME = new Type("Lnet/runelite/mapping/ObfuscatedName;");
private static final Type IMPLEMENTS = new Type("Lnet/runelite/mapping/Implements;");
private static final Type EXPORT = new Type("Lnet/runelite/mapping/Export;");
private static final Type OBFUSCATED_SIGNATURE = new Type("Lnet/runelite/mapping/ObfuscatedSignature;");
private Map<String, ClassHook> hooks;
private ClassGroup group;
@Before
public void before() throws IOException
{
InputStream is = HookImporter.class.getResourceAsStream("osbmappings-114.json");
Assert.assertNotNull(is);
Gson gson = new Gson();
java.lang.reflect.Type type = new TypeToken<Map<String, ClassHook>>()
{
}.getType();
hooks = gson.fromJson(new InputStreamReader(is), type);
group = JarUtil.loadJar(IN);
}
@After
public void after() throws IOException
{
JarUtil.saveJar(group, OUT);
}
@Test
@Ignore
public void importHooks()
{
int classes = 0, fields = 0, methods = 0, callbacks = 0;
for (String deobfuscatedClassName : hooks.keySet())
{
ClassHook ch = hooks.get(deobfuscatedClassName);
ClassFile cf = this.findClassWithObfuscatedName(ch.getClazz());
assert cf != null;
String implementsName = getAnnotation(cf.getAnnotations(), IMPLEMENTS);
if (implementsName.isEmpty())
{
cf.getAnnotations().addAnnotation(IMPLEMENTS, "value", deobfuscatedClassName);
++classes;
}
for (String deobfuscatedFieldName : ch.getFields().keySet())
{
FieldHook fh = ch.getFields().get(deobfuscatedFieldName);
String[] s = fh.getField().split("\\.");
Field f;
if (s.length == 2)
{
ClassFile cf2 = this.findClassWithObfuscatedName(s[0]);
assert cf2 != null;
f = this.findFieldWithObfuscatedName(cf2, s[1]);
}
else if (s.length == 1)
{
f = this.findFieldWithObfuscatedName(cf, fh.getField());
}
else
{
throw new RuntimeException();
}
assert f != null;
String exportedName = getAnnotation(f.getAnnotations(), EXPORT);
if (exportedName.isEmpty())
{
f.getAnnotations().addAnnotation(EXPORT, "value", deobfuscatedFieldName);
++fields;
}
}
for (String deobfuscatedMethodName : ch.getMethods().keySet())
{
MethodHook mh = ch.getMethods().get(deobfuscatedMethodName);
String[] s = mh.getMethod().split("\\.");
Method m;
if (s.length == 2)
{
ClassFile cf2 = this.findClassWithObfuscatedName(s[0]);
assert cf2 != null;
m = this.findMethodWithObfuscatedName(cf2, s[1], mh.getClientDesc());
}
else if (s.length == 1)
{
m = this.findMethodWithObfuscatedName(cf, mh.getMethod(), mh.getClientDesc());
}
else
{
throw new RuntimeException();
}
assert m != null;
String exportedName = getAnnotation(m.getAnnotations(), EXPORT);
if (exportedName.isEmpty())
{
m.getAnnotations().addAnnotation(EXPORT, "value", deobfuscatedMethodName);
++methods;
}
}
for (String deobfuscatedMethodName : ch.getCallbacks().keySet())
{
MethodHook mh = ch.getCallbacks().get(deobfuscatedMethodName);
String[] s = mh.getMethod().split("\\.");
Method m;
if (s.length == 2)
{
ClassFile cf2 = this.findClassWithObfuscatedName(s[0]);
assert cf2 != null;
m = this.findMethodWithObfuscatedName(cf2, s[1], mh.getClientDesc());
}
else if (s.length == 1)
{
m = this.findMethodWithObfuscatedName(cf, mh.getMethod(), mh.getClientDesc());
}
else
{
throw new RuntimeException();
}
assert m != null;
String exportedName = getAnnotation(m.getAnnotations(), EXPORT);
if (exportedName.isEmpty())
{
m.getAnnotations().addAnnotation(EXPORT, "value", deobfuscatedMethodName);
++callbacks;
}
}
}
System.out.println("Imported " + classes + " classes, " + fields + " fields, " + methods + " methods, " + callbacks + " callbacks");
}
private ClassFile findClassWithObfuscatedName(String name)
{
for (ClassFile c : group.getClasses())
{
if (c.getName().equals(name))
{
return c;
}
Annotations an = c.getAnnotations();
if (getAnnotation(an, OBFUSCATED_NAME).equals(name))
{
return c;
}
}
return null;
}
private Field findFieldWithObfuscatedName(ClassFile c, String name)
{
for (Field f : c.getFields())
{
Annotations an = f.getAnnotations();
if (getAnnotation(an, OBFUSCATED_NAME).equals(name))
{
return f;
}
}
return null;
}
private Method findMethodWithObfuscatedName(ClassFile c, String name, String signature)
{
Signature sig = new Signature(signature);
for (Method m : c.getMethods())
{
Annotations an = m.getAnnotations();
if (getAnnotation(an, OBFUSCATED_NAME).equals(name))
{
Signature methodSig = getObfuscatedMethodSignature(m);
if (methodSig.equals(sig))
{
return m;
}
else
{
methodSig.equals(sig);
getObfuscatedMethodSignature(m);
}
}
}
return null;
}
private String getAnnotation(Annotations an, Type type)
{
if (an == null)
{
return "";
}
for (Annotation a : an.getAnnotations())
{
if (a.getType().equals(type))
{
for (Element e : a.getElements())
{
String str = (String) e.getValue();
return str;
}
}
}
return "";
}
private Signature getObfuscatedMethodSignature(Method method)
{
String sig = getAnnotation(method.getAnnotations(), OBFUSCATED_SIGNATURE);
if (sig.isEmpty() == false)
{
return toObSignature(new Signature(sig)); // if it is annoted, use that
}
else
{
return toObSignature(method.getDescriptor());
}
}
private Type toObType(Type t)
{
if (t.isPrimitive())
{
return t;
}
if (!t.getInternalName().startsWith("class") && !t.getInternalName().equals("client"))
{
return t;
}
ClassFile cf = group.findClass(t.getInternalName());
assert cf != null;
Annotations an = cf.getAnnotations();
String obfuscatedName = an.find(OBFUSCATED_NAME).getElement().getString();
return Type.getType("L" + obfuscatedName + ";", t.getDimensions());
}
private Signature toObSignature(Signature s)
{
Signature.Builder builder = new Signature.Builder()
.setReturnType(toObType(s.getReturnValue()));
for (Type t : s.getArguments())
{
builder.addArgument(toObType(t));
}
return builder.build();
}
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.osb.inject;
import com.google.gson.annotations.SerializedName;
import java.util.HashMap;
import java.util.Map;
public class ClassHook
{
@SerializedName("class")
private String clazz;
private Map<String, FieldHook> fields = new HashMap<>();
private Map<String, MethodHook> methods = new HashMap<>();
private Map<String, MethodHook> callbacks = new HashMap<>();
public String getClazz()
{
return clazz;
}
public Map<String, FieldHook> getFields()
{
return fields;
}
public Map<String, MethodHook> getMethods()
{
return methods;
}
public Map<String, MethodHook> getCallbacks()
{
return callbacks;
}
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.osb.inject;
public class FieldHook
{
private String field; // obfuscated name
private Number multiplier;
public String getField()
{
return field;
}
public Number getMultiplier()
{
return multiplier;
}
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.osb.inject;
public class MethodHook
{
private String method; // ob method name
private String desc; // deob desc
private String clientDesc; // ob desc
public String getMethod()
{
return method;
}
public String getDesc()
{
return desc;
}
public String getClientDesc()
{
return clientDesc;
}
}

View File

@@ -0,0 +1,129 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.runeloader;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
import net.runelite.runeloader.inject.GetterInjectInstruction;
import net.runelite.runeloader.inject.InjectionModscript;
import net.runelite.mapping.Export;
import net.runelite.mapping.ObfuscatedName;
import net.runelite.runeloader.inject.Injection;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
public class CheckExports
{
private static final File CLIENT = new File("/Users/adam/w/rs/07/rs-client-1.0-SNAPSHOT.jar");
private final List<Class> classes = new ArrayList<>();
@Before
public void before() throws MalformedURLException, ClassNotFoundException
{
ClassLoader loader = new URLClassLoader(new URL[] { CLIENT.toURL() });
Class c = loader.loadClass("net.runelite.rs.client.client");
classes.add(c);
for (int i = 0; i < 230; ++i)
{
try
{
c = loader.loadClass("net.runelite.rs.client.class" + i);
classes.add(c);
}
catch (ClassNotFoundException ex)
{
}
}
}
private Class<?> findClassWithObfuscatedName(String name)
{
for (Class c : classes)
{
if (c.getName().equals("net.runelite.rs.client.client") && name.equals("client"))
return c;
ObfuscatedName oc = (ObfuscatedName) c.getDeclaredAnnotation(ObfuscatedName.class);
if (oc == null)
continue;
if (oc.value().equals(name))
return c;
}
return null;
}
private Field findFieldWithObfuscatedName(Class c, String name)
{
for (Field f : c.getDeclaredFields())
{
ObfuscatedName oc = (ObfuscatedName) f.getDeclaredAnnotation(ObfuscatedName.class);
if (oc == null)
continue;
if (oc.value().equals(name))
return f;
}
return null;
}
private boolean isExported(Field f)
{
Export export = (Export) f.getDeclaredAnnotation(Export.class);
return export != null;
}
@Test
@Ignore
public void checkMappings() throws IOException
{
InjectionModscript mod = Injection.load(MappingImporter.class.getResourceAsStream(MappingImporter.RL_INJECTION));
for (int i = 0; i < mod.getGetterInjects().size(); ++i)
{
GetterInjectInstruction gii = (GetterInjectInstruction) mod.getGetterInjects().get(i);
Class c = this.findClassWithObfuscatedName(gii.getGetterClassName());
Assert.assertNotNull(c);
Field f = this.findFieldWithObfuscatedName(c, gii.getGetterFieldName());
Assert.assertNotNull(f);
Assert.assertTrue(this.isExported(f));
}
}
}

View File

@@ -0,0 +1,150 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.runeloader;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
import net.runelite.runeloader.inject.GetterInjectInstruction;
import net.runelite.runeloader.inject.InjectionModscript;
import net.runelite.mapping.Export;
import net.runelite.mapping.ObfuscatedGetter;
import net.runelite.mapping.ObfuscatedName;
import net.runelite.runeloader.inject.Injection;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
public class CheckMappings
{
private static final File CLIENT = new File("d:/rs/07/adamout.jar");
private final List<Class> classes = new ArrayList<>();
@Before
public void before() throws MalformedURLException, ClassNotFoundException
{
ClassLoader loader = new URLClassLoader(new URL[] { CLIENT.toURL() });
Class c = loader.loadClass("client");
classes.add(c);
for (int i = 0; i < 230; ++i)
{
try
{
c = loader.loadClass("class" + i);
classes.add(c);
}
catch (ClassNotFoundException ex)
{
}
}
}
private Class<?> findClassWithObfuscatedName(String name)
{
for (Class c : classes)
{
if (c.getName().equals("net.runelite.rs.client.client") && name.equals("client"))
return c;
ObfuscatedName oc = (ObfuscatedName) c.getDeclaredAnnotation(ObfuscatedName.class);
if (oc == null)
continue;
if (oc.value().equals(name))
return c;
}
return null;
}
private Field findFieldWithObfuscatedName(Class c, String name)
{
for (Field f : c.getDeclaredFields())
{
ObfuscatedName oc = (ObfuscatedName) f.getDeclaredAnnotation(ObfuscatedName.class);
if (oc == null)
continue;
if (oc.value().equals(name))
return f;
}
return null;
}
private Integer getIntegerMultiplier(Field f)
{
ObfuscatedGetter getter = (ObfuscatedGetter) f.getDeclaredAnnotation(ObfuscatedGetter.class);
if (getter == null)
return null;
return getter.intValue() == 0 ? null : getter.intValue();
}
private String getExportedName(Field f)
{
Export e = (Export) f.getDeclaredAnnotation(Export.class);
if (e == null)
return null;
return e.value();
}
@Test
@Ignore
public void checkMappings() throws IOException
{
InjectionModscript mod = Injection.load(MappingImporter.class.getResourceAsStream(MappingImporter.RL_INJECTION));
for (int i = 0; i < mod.getGetterInjects().size(); ++i)
{
GetterInjectInstruction gii = (GetterInjectInstruction) mod.getGetterInjects().get(i);
Class c = this.findClassWithObfuscatedName(gii.getGetterClassName());
Assert.assertNotNull(c);
Field f = this.findFieldWithObfuscatedName(c, gii.getGetterFieldName());
Assert.assertNotNull(f);
String exportedName = this.getExportedName(f);
String attrName = gii.getGetterName();
attrName = Utils.toExportedName(attrName);
Integer mul = gii.getMultiplier(),
myMul = this.getIntegerMultiplier(f);
// XXX Check @Export etc names
//Assert.assertEquals(exportedName, attrName);
Assert.assertEquals(myMul, mul);
}
}
}

View File

@@ -0,0 +1,210 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.runeloader;
import java.io.File;
import java.io.IOException;
import net.runelite.asm.ClassFile;
import net.runelite.asm.ClassGroup;
import net.runelite.asm.Field;
import net.runelite.asm.Type;
import net.runelite.asm.attributes.Annotations;
import net.runelite.asm.attributes.annotation.Annotation;
import net.runelite.asm.attributes.annotation.Element;
import net.runelite.runeloader.inject.AddInterfaceInstruction;
import net.runelite.runeloader.inject.GetterInjectInstruction;
import net.runelite.runeloader.inject.InjectionModscript;
import net.runelite.deob.util.JarUtil;
import net.runelite.runeloader.inject.Injection;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MappingImporter
{
private static final Logger logger = LoggerFactory.getLogger(MappingImporter.class);
private static final File IN = new File("d:/rs/07/adamin.jar");
private static final File OUT = new File("d:/rs/07/adamout.jar");
public static final String RL_INJECTION = "injection_130.json";
private static final Type OBFUSCATED_NAME = new Type("Lnet/runelite/mapping/ObfuscatedName;");
private static final Type EXPORT = new Type("Lnet/runelite/mapping/Export;");
private static final Type IMPLEMENTS = new Type("Lnet/runelite/mapping/Implements;");
private ClassGroup group;
@Before
public void before() throws IOException
{
group = JarUtil.loadJar(IN);
}
@After
public void after() throws IOException
{
JarUtil.saveJar(group, OUT);
}
private boolean hasObfuscatedName(Annotations an, String name)
{
if (an == null)
{
return false;
}
for (Annotation a : an.getAnnotations())
{
if (a.getType().equals(OBFUSCATED_NAME))
{
for (Element e : a.getElements())
{
String str = (String) e.getValue();
if (str.equals(name))
{
return true;
}
}
}
}
return false;
}
private ClassFile findClassWithObfuscatedName(String name)
{
for (ClassFile c : group.getClasses())
{
if (c.getName().equals(name))
{
return c;
}
Annotations an = c.getAnnotations();
if (this.hasObfuscatedName(an, name))
{
return c;
}
}
return null;
}
private Field findFieldWithObfuscatedName(ClassFile c, String name)
{
for (Field f : c.getFields())
{
Annotations an = f.getAnnotations();
if (this.hasObfuscatedName(an, name))
{
return f;
}
}
return null;
}
@Test
@Ignore
public void makeMappings() throws IOException
{
InjectionModscript mod = Injection.load(MappingImporter.class.getResourceAsStream(RL_INJECTION));
int fields = 0, classes = 0;
for (int i = 0; i < mod.getGetterInjects().size(); ++i)
{
GetterInjectInstruction gii = (GetterInjectInstruction) mod.getGetterInjects().get(i);
ClassFile cf = this.findClassWithObfuscatedName(gii.getGetterClassName());
Assert.assertNotNull(cf);
Field f = this.findFieldWithObfuscatedName(cf, gii.getGetterFieldName());
if (f == null)
{
// some of their fields they inject getters for they also inject,
// so they don't all exist
continue;
}
String attrName = gii.getGetterName();
attrName = Utils.toExportedName(attrName);
Annotations an = f.getAnnotations();
Annotation a = an.find(EXPORT);
if (a != null)
{
String exportedName = a.getElement().getString();
if (!attrName.equals(exportedName))
{
logger.info("Exported field " + f + " with mismatched name. Theirs: " + attrName + ", mine: " + exportedName);
}
}
else
{
an.addAnnotation(EXPORT, "value", attrName);
logger.info("Exporting field " + f + " with name " + attrName);
++fields;
}
}
for (AddInterfaceInstruction aii : mod.getAddInterfaceInjects())
{
ClassFile cf = this.findClassWithObfuscatedName(aii.getClientClass());
Assert.assertNotNull(cf);
String iface = aii.getInterfaceClass();
iface = iface.replace("com/runeloader/api/bridge/os/accessor/", "");
Annotations an = cf.getAnnotations();
Annotation a = an.find(IMPLEMENTS);
if (a != null)
{
String implementsName = a.getElement().getString();
if (!iface.equals(implementsName))
{
logger.info("Implements class " + cf + " with mismatched name. Theirs: " + iface + ", mine: " + implementsName);
}
}
else
{
an.addAnnotation(IMPLEMENTS, "value", iface);
logger.info("Exporting class " + cf.getName() + " with name " + iface);
++classes;
}
}
logger.info("Added {} fields, {} classes", fields, classes);
}
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.runeloader;
public class Utils
{
public static String toExportedName(String attrName)
{
if (attrName.startsWith("get"))
{
attrName = attrName.substring(3);
attrName = Character.toLowerCase(attrName.charAt(0)) + attrName.substring(1);
}
if (attrName.equalsIgnoreCase("fps"))
attrName = "FPS";
return attrName;
}
}

View File

@@ -0,0 +1,17 @@
package net.runelite.runeloader.inject;
public class AddFieldInstruction
{
public String owner;
public String name;
public String desc;
public int access;
public AddFieldInstruction(String var1, String var2, String var3, int var4)
{
this.owner = var1;
this.name = var2;
this.desc = var3;
this.access = var4;
}
}

View File

@@ -0,0 +1,23 @@
package net.runelite.runeloader.inject;
public class AddInterfaceInstruction
{
private final String clientClass;
private final String interfaceClass;
public AddInterfaceInstruction(String var1, String var2)
{
this.clientClass = var1;
this.interfaceClass = var2;
}
public String getClientClass()
{
return this.clientClass;
}
public String getInterfaceClass()
{
return this.interfaceClass;
}
}

View File

@@ -0,0 +1,25 @@
package net.runelite.runeloader.inject;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
public class AddMethodInstruction
{
private final String clientClass;
private final String methodName;
private final String methodDesc;
private final AbstractInsnNode[] instructions;
public AddMethodInstruction(String var1, String var2, String var3, AbstractInsnNode[] var4)
{
this.clientClass = var1;
this.methodName = var2;
this.methodDesc = var3;
this.instructions = var4;
}
public boolean valid(ClassNode var1)
{
return var1.name.equalsIgnoreCase(this.clientClass);
}
}

View File

@@ -0,0 +1,64 @@
package net.runelite.runeloader.inject;
public class GetterInjectInstruction
{
private final String className;
private final String getterMethodDesc;
private final String getterName;
private final String getterClassName;
private final String getterFieldName;
private final Integer multiplier;
private final boolean staticField;
public GetterInjectInstruction(String var1, String var2, String var3, String var4, String var5, Integer var6, boolean var7)
{
this.className = var1;
this.getterMethodDesc = "()" + var3;
this.getterName = var2;
this.getterClassName = var4;
this.getterFieldName = var5;
this.multiplier = var6;
this.staticField = var7;
}
@Override
public String toString()
{
return "GetterInjectInstruction{" + "className=" + className + ", getterMethodDesc=" + getterMethodDesc + ", getterName=" + getterName + ", getterClassName=" + getterClassName + ", getterFieldName=" + getterFieldName + ", multiplier=" + multiplier + ", staticField=" + staticField + '}';
}
public String getClassName()
{
return this.className;
}
public String getGetterMethodDesc()
{
return this.getterMethodDesc;
}
public String getGetterName()
{
return this.getterName;
}
public String getGetterClassName()
{
return this.getterClassName;
}
public String getGetterFieldName()
{
return this.getterFieldName;
}
public Integer getMultiplier()
{
return this.multiplier;
}
public boolean isStaticField()
{
return this.staticField;
}
}

View File

@@ -0,0 +1,19 @@
package net.runelite.runeloader.inject;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.objectweb.asm.tree.AbstractInsnNode;
public class Injection
{
private static final Gson decoder = (new GsonBuilder()).registerTypeAdapter(AbstractInsnNode.class, new InstructionDeserializer()).create();
public InjectionModscript resource;
public static InjectionModscript load(InputStream in)
{
return decoder.fromJson(new InputStreamReader(in), Injection.class).resource;
}
}

View File

@@ -0,0 +1,62 @@
package net.runelite.runeloader.inject;
import java.util.LinkedList;
import java.util.List;
public class InjectionModscript
{
private int revision;
private List<GetterInjectInstruction> getterInjects = new LinkedList<>();
private List superChangeInjects = new LinkedList();
private List<AddInterfaceInstruction> addInterfaceInjects = new LinkedList<>();
private List methodMods = new LinkedList();
private List addMethods = new LinkedList();
private List instructionReplacements = new LinkedList();
private List newMethodMods = new LinkedList();
private List newFields = new LinkedList();
public int getRevision()
{
return revision;
}
public List<GetterInjectInstruction> getGetterInjects()
{
return this.getterInjects;
}
public List getSuperChangeInjects()
{
return this.superChangeInjects;
}
public List<AddInterfaceInstruction> getAddInterfaceInjects()
{
return this.addInterfaceInjects;
}
public List getMethodMods()
{
return this.methodMods;
}
public List getAddMethods()
{
return this.addMethods;
}
public List getNewMethodMods()
{
return this.newMethodMods;
}
public List getInstructionReplacements()
{
return this.instructionReplacements;
}
public List getNewFields()
{
return this.newFields;
}
}

View File

@@ -0,0 +1,82 @@
package net.runelite.runeloader.inject;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import java.lang.reflect.Type;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.FieldInsnNode;
import org.objectweb.asm.tree.InsnNode;
import org.objectweb.asm.tree.IntInsnNode;
import org.objectweb.asm.tree.LdcInsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.TypeInsnNode;
import org.objectweb.asm.tree.VarInsnNode;
public class InstructionDeserializer implements JsonDeserializer
{
@Override
public AbstractInsnNode deserialize(JsonElement var1, Type var2, JsonDeserializationContext var3)
{
JsonObject var4 = (JsonObject) var1;
int var5 = var4.get("opcode").getAsInt();
if (var5 != 21 && var5 != 25 && var5 != 58 && var5 != 54 && var5 != 22 && var5 != 55)
{
String var7;
String var8;
String var10;
if (var5 != 184 && var5 != 182 && var5 != 183)
{
if (var5 == 18)
{
try
{
return new LdcInsnNode(Integer.valueOf(var4.get("cst").getAsInt()));
}
catch (Exception var9)
{
return new LdcInsnNode(var4.get("cst").getAsString());
}
}
else if (var5 != 187 && var5 != 189)
{
if (var5 != 16 && var5 != 17)
{
if (var5 != 179 && var5 != 178 && var5 != 180 && var5 != 181)
{
return new InsnNode(var5);
}
else
{
var10 = var4.get("owner").getAsString();
var7 = var4.get("name").getAsString();
var8 = var4.get("desc").getAsString();
return new FieldInsnNode(var5, var10, var7, var8);
}
}
else
{
return new IntInsnNode(var5, var4.get("operand").getAsInt());
}
}
else
{
return new TypeInsnNode(var5, var4.get("desc").getAsString());
}
}
else
{
var10 = var4.get("owner").getAsString();
var7 = var4.get("name").getAsString();
var8 = var4.get("desc").getAsString();
return new MethodInsnNode(var5, var10, var7, var8);
}
}
else
{
int var6 = var4.get("var").getAsInt();
return new VarInsnNode(var5, var6);
}
}
}

View File

@@ -0,0 +1,64 @@
package net.runelite.runeloader.inject;
import java.util.Iterator;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.MethodNode;
public class MethodModInstruction {
private final int startIndex;
private final AbstractInsnNode[] nodes;
public final String owner;
public final String method;
public final String desc;
public MethodModInstruction(int var1, AbstractInsnNode[] var2, String var3, String var4, String var5) {
this.startIndex = var1;
this.nodes = var2;
this.owner = var3;
this.method = var4;
this.desc = var5;
}
public boolean valid(ClassNode var1) {
return var1.name.equalsIgnoreCase(this.owner);
}
public void inject(ClassNode var1) {
Iterator var3 = var1.methods.iterator();
while(true) {
MethodNode var2;
do {
do {
if(!var3.hasNext()) {
return;
}
var2 = (MethodNode)var3.next();
} while(!var2.name.equalsIgnoreCase(this.method));
} while(!var2.desc.equalsIgnoreCase(this.desc));
InsnList var4 = var2.instructions;
try {
AbstractInsnNode var5 = var4.get(this.startIndex);
AbstractInsnNode var6 = null;
for(int var7 = 0; var7 < this.nodes.length; ++var7) {
if(var6 == null) {
var4.insertBefore(var5, this.nodes[var7]);
} else {
var4.insert(var6, this.nodes[var7]);
}
var6 = this.nodes[var7];
}
} catch (Exception var8) {
System.err.println("Failed on " + this.startIndex + " @ " + this.owner + "." + this.method + " " + this.desc);
var8.printStackTrace();
}
}
}
}

View File

@@ -0,0 +1,19 @@
package net.runelite.runeloader.inject;
import org.objectweb.asm.tree.AbstractInsnNode;
public class ReplaceNodeInstruction {
public final String owner;
public final String method;
public final String desc;
public final int index;
public final AbstractInsnNode replaceWith;
public ReplaceNodeInstruction(String var1, String var2, String var3, int var4, AbstractInsnNode var5) {
this.owner = var1;
this.method = var2;
this.desc = var3;
this.index = var4;
this.replaceWith = var5;
}
}

View File

@@ -0,0 +1,35 @@
package net.runelite.runeloader.inject;
import org.objectweb.asm.tree.ClassNode;
public class SuperChangeInstruction
{
private final String clientName;
private final String superName;
public SuperChangeInstruction(String var1, String var2)
{
this.clientName = var1;
this.superName = var2;
}
public String getClientName()
{
return this.clientName;
}
public String getSuperName()
{
return this.superName;
}
public boolean valid(ClassNode var1)
{
return var1.name.equalsIgnoreCase(this.clientName);
}
public void inject(ClassNode var1)
{
var1.superName = this.superName;
}
}

View File

@@ -0,0 +1,18 @@
package net.runelite.runeloader.inject;
import org.objectweb.asm.Label;
public class TableJumpInstruction$TableJump
{
public Label label;
public final int instructionIndex;
public final int labelArrayIndex;
public final int opcode;
public TableJumpInstruction$TableJump(int var1, int var2, int var3)
{
this.instructionIndex = var1;
this.opcode = var3;
this.labelArrayIndex = var2;
}
}

View File

@@ -0,0 +1,32 @@
package net.runelite.runeloader.inject;
import java.util.Iterator;
import org.objectweb.asm.Label;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.JumpInsnNode;
import org.objectweb.asm.tree.LabelNode;
import org.objectweb.asm.tree.MethodNode;
public class TableJumpInstruction
{
private final TableJumpInstruction$TableJump[] tableJumps;
private final int[] labels;
private final int start;
private final AbstractInsnNode[] instructions;
private final String owner;
private final String name;
private final String desc;
public TableJumpInstruction(TableJumpInstruction$TableJump[] var1, AbstractInsnNode[] var2, int[] var3, int var4, String var5, String var6, String var7)
{
this.tableJumps = var1;
this.instructions = var2;
this.labels = var3;
this.owner = var5;
this.name = var6;
this.desc = var7;
this.start = var4;
}
}

View File

@@ -0,0 +1,14 @@
package net.runelite.runesuite;
import com.google.gson.annotations.SerializedName;
import java.util.List;
public class HookClass
{
@SerializedName("class")
String clazz;
String name;
int access;
List<HookField> fields;
List<HookMethod> methods;
}

View File

@@ -0,0 +1,15 @@
package net.runelite.runesuite;
public class HookField
{
String field;
String owner;
String name;
int access;
@Override
public String toString()
{
return "HookField{" + "field=" + field + ", owner=" + owner + ", name=" + name + '}';
}
}

View File

@@ -0,0 +1,280 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.runesuite;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
import net.runelite.asm.ClassFile;
import net.runelite.asm.ClassGroup;
import net.runelite.asm.Field;
import net.runelite.asm.Method;
import net.runelite.asm.Type;
import net.runelite.asm.attributes.Annotations;
import net.runelite.asm.attributes.annotation.Annotation;
import net.runelite.asm.attributes.annotation.Element;
import net.runelite.asm.signature.Signature;
import net.runelite.asm.signature.util.VirtualMethods;
import static net.runelite.deob.DeobAnnotations.EXPORT;
import static net.runelite.deob.DeobAnnotations.IMPLEMENTS;
import static net.runelite.deob.DeobAnnotations.OBFUSCATED_NAME;
import static net.runelite.deob.DeobAnnotations.OBFUSCATED_SIGNATURE;
import net.runelite.deob.DeobTestProperties;
import net.runelite.deob.TemporyFolderLocation;
import net.runelite.deob.deobfuscators.Renamer;
import net.runelite.deob.util.JarUtil;
import net.runelite.deob.util.NameMappings;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HookImporter
{
private static final Logger logger = LoggerFactory.getLogger(HookImporter.class);
@Rule
public DeobTestProperties properties = new DeobTestProperties();
@Rule
public TemporaryFolder folder = TemporyFolderLocation.getTemporaryFolder();
private List<HookClass> hooks;
private ClassGroup group;
@Before
public void before() throws IOException
{
group = JarUtil.loadJar(new File(properties.getRsClient()));
InputStream is = getClass().getResourceAsStream("hooks.json");
Gson gson = new Gson();
java.lang.reflect.Type type = new TypeToken<List<HookClass>>()
{
}.getType();
hooks = gson.fromJson(new InputStreamReader(is), type);
}
@After
public void after() throws IOException
{
File out = new File("C:/Users/Lucas/Desktop/client.jar");
JarUtil.saveJar(group, out);
logger.info("Wrote to {}", out);
}
@Test
public void importHooks()
{
int classes = 0, fields = 0, methods = 0, access = 0;
NameMappings mappings = new NameMappings();
for (HookClass hc : hooks)
{
ClassFile cf = findClassWithObfuscatedName(hc.name);
assert cf != null;
if (cf.getAccess() != hc.access)
{
cf.setAccess(hc.access);
++access;
}
String implementsName = getAnnotation(cf.getAnnotations(), IMPLEMENTS);
if (implementsName.isEmpty())
{
String deobfuscatedClassName = hc.clazz;
cf.getAnnotations().addAnnotation(IMPLEMENTS, "value", deobfuscatedClassName);
mappings.map(cf.getPoolClass(), deobfuscatedClassName);
++classes;
}
for (HookField fh : hc.fields)
{
ClassFile cf2 = findClassWithObfuscatedName(fh.owner);
assert cf2 != null;
Field f = findFieldWithObfuscatedName(cf2, fh.name);
if (f == null)
{
continue;
}
if (f.getAccessFlags() != fh.access)
{
f.setAccessFlags(fh.access);
++access;
}
String exportedName = getAnnotation(f.getAnnotations(), EXPORT);
if (exportedName.isEmpty())
{
String deobfuscatedFieldName = fh.field;
Field other = cf2.findField(deobfuscatedFieldName);
if (other != null)
{
logger.warn("Name collision for field {}", deobfuscatedFieldName);
continue;
}
f.getAnnotations().addAnnotation(EXPORT, "value", deobfuscatedFieldName);
mappings.map(f.getPoolField(), deobfuscatedFieldName);
++fields;
}
}
outer:
for (HookMethod hm : hc.methods)
{
ClassFile cf2 = findClassWithObfuscatedName(hm.owner);
assert cf2 != null;
Method m = findMethodWithObfuscatedName(cf2, hm.name, hm.descriptor);
if (m == null)
{
logger.warn(hm.toString() + " is missing");
continue;
}
if (m.getAccessFlags() != hm.access)
{
m.setAccessFlags(hm.access);
++access;
}
// maybe only the base class method is exported
List<Method> virtualMethods = VirtualMethods.getVirtualMethods(m);
for (Method method : virtualMethods)
{
String exportedName = getAnnotation(method.getAnnotations(), EXPORT);
if (!exportedName.isEmpty())
{
continue outer;
}
}
String deobfuscatedMethodName = hm.method;
m.getAnnotations().addAnnotation(EXPORT, "value", deobfuscatedMethodName);
mappings.map(m.getPoolMethod(), deobfuscatedMethodName);
++methods;
}
}
Renamer renamer = new Renamer(mappings);
renamer.run(group);
logger.info("Imported {} classes, {} fields, {} methods, {} access levels", classes, fields, methods, access);
}
private ClassFile findClassWithObfuscatedName(String name)
{
for (ClassFile c : group.getClasses())
{
if (c.getName().equals(name))
{
return c;
}
Annotations an = c.getAnnotations();
if (getAnnotation(an, OBFUSCATED_NAME).equals(name))
{
return c;
}
}
return null;
}
private Field findFieldWithObfuscatedName(ClassFile c, String name)
{
for (Field f : c.getFields())
{
Annotations an = f.getAnnotations();
if (getAnnotation(an, OBFUSCATED_NAME).equals(name))
{
return f;
}
}
return null;
}
private Method findMethodWithObfuscatedName(ClassFile c, String name, String signature)
{
Signature sig = new Signature(signature);
for (Method m : c.getMethods())
{
Annotations an = m.getAnnotations();
if (m.getName().equals(name) || getAnnotation(an, OBFUSCATED_NAME).equals(name))
{
Signature methodSig = getObfuscatedMethodSignature(m);
if (methodSig.equals(sig))
{
return m;
}
}
}
return null;
}
private String getAnnotation(Annotations an, Type type)
{
Annotation a = an.find(type);
if (a != null)
{
for (Element e : a.getElements())
{
String str = (String) e.getValue();
return str;
}
}
return "";
}
private Signature getObfuscatedMethodSignature(Method method)
{
String sig = getAnnotation(method.getAnnotations(), OBFUSCATED_SIGNATURE);
if (sig.isEmpty() == false)
{
return new Signature(sig); // if it is annotated, use that
}
else
{
return method.getDescriptor();
}
}
}

View File

@@ -0,0 +1,19 @@
package net.runelite.runesuite;
public class HookMethod
{
String method;
String owner;
String name;
int access;
String[] parameters;
String descriptor;
@Override
public String toString()
{
return method +
owner +
name;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,3 @@
rs.client=C:/Users/Lucas/Desktop/gamepack180_deob.jar
rs.version=180
vanilla.client=${net.runelite.rs:vanilla:jar}