package net.contra.obfuscator.trans.deob;
import com.sun.org.apache.bcel.internal.classfile.Method;
import com.sun.org.apache.bcel.internal.generic.*;
import net.contra.obfuscator.Application;
import net.contra.obfuscator.ITransformer;
import net.contra.obfuscator.Settings;
import net.contra.obfuscator.util.bcel.BCELMethods;
import net.contra.obfuscator.util.bcel.JarLoader;
import net.contra.obfuscator.util.misc.LogHandler;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
public class JShrinkDeobfuscator implements ITransformer {
private final LogHandler Logger = new LogHandler("AllatoriDeobfuscator");
private String Location = "";
private JarLoader LoadedJar;
public JShrinkDeobfuscator(String loc) {
Location = loc;
}
public void load() {
LoadedJar = new JarLoader(Location);
}
private ClassGen getShrinkClassGen(JarLoader jr) {
for (ClassGen cg : jr.ClassEntries.values()) {
if (cg.getMethods().length == 3 && cg.getMethods()[1].isStatic()
&& cg.getMethods()[1].isFinal()
&& cg.getMethods()[1].isPublic()
&& cg.getMethods()[1].isSynchronized()
&& cg.getMethods()[1].getReturnType().toString().equals("java.lang.String")) {
return cg;
}
}
return null;
}
public void transform() {
ClassGen shrinkClass = getShrinkClassGen(LoadedJar);
if (shrinkClass == null) {
Logger.error("Could not locate JShrink loader class.");
Logger.error("This is not obfuscated with JShrink.");
Application.close();
} else {
Logger.debug("JShrink Class: " + shrinkClass.getClassName());
}
for (ClassGen cg : LoadedJar.ClassEntries.values()) {
for (Method method : cg.getMethods()) {
MethodGen mg = new MethodGen(method, cg.getClassName(), cg.getConstantPool());
InstructionList list = mg.getInstructionList();
if (list == null) continue;
Logger.debug("Stripping JShrink Calls -> Class: " + cg.getClassName() + " Method: " + method.getName());
InstructionHandle[] handles = list.getInstructionHandles();
for (InstructionHandle handle : handles) {
if (handle.getNext() == null) continue;
if (BCELMethods.isInteger(handle.getInstruction())
&& handle.getNext().getInstruction() instanceof INVOKESTATIC) {
assert shrinkClass != null;
if (!BCELMethods.getInvokeClassName(handle.getNext().getInstruction(), cg.getConstantPool()).equals(shrinkClass.getClassName()))
continue;
int storeidx = BCELMethods.getIntegerValue(handle.getInstruction());
StoreHandler store = new StoreHandler(LoadedJar);
String orig = store.getString(storeidx);
int stridx = cg.getConstantPool().addString(orig);
handle.getNext().setInstruction(new NOP()); //Remove invoke to shrink class
handle.setInstruction(new LDC(stridx)); //Replace old str with our new one
logger.debug(storeidx + " -> " + orig);
}
}
list.setPositions();
mg.setInstructionList(list);
mg.setMaxLocals();
mg.setMaxStack();
cg.replaceMethod(method, mg.getMethod());
}
}
}
public void save() {
String loc = Location.replace(".jar", Settings.FILE_TAG + ".jar");
LoadedJar.saveJar(loc);
}
}
class StoreHandler {
static byte[] WSVZ;
static String[] append = new String[256];
static int[] close = new int[256];
public StoreHandler(JarLoader loader) {
try {
InputStream localInputStream = new ByteArrayInputStream(loader.NonClassEntries.get("I/I.gif"));
int i = localInputStream.read() << 16 | localInputStream.read() << 8 | localInputStream.read();
WSVZ = new byte[i];
int j = 0;
int k = (byte) i;
byte[] arrayOfByte = WSVZ;
while (i != 0) {
int m = localInputStream.read(arrayOfByte, j, i);
if (m == -1) {
break;
}
i -= m;
m += j;
while (j < m) {
int int2 = j;
arrayOfByte[int2] = (byte) (arrayOfByte[int2] ^ k);
j++;
}
}
localInputStream.reset();
localInputStream.close();
} catch (Exception ignored) {
}
}
public String getString(int paramInt) {
int i = paramInt & 0xFF;
if (close[i] != paramInt) {
close[i] = paramInt;
if (paramInt < 0) {
paramInt &= 65535;
}
String str = new String(WSVZ, paramInt, WSVZ[(paramInt - 1)] & 0xFF).intern();
append[i] = str;
}
return append[i];
}
}