Skip to content

Commit

Permalink
Fixes
Browse files Browse the repository at this point in the history
-ASM version set to 6.0, since javavm uses 6.0
-Obscure bug with MethodExecutor
  • Loading branch information
ThisTestUser committed Jul 25, 2020
1 parent efa6d95 commit 0017ae8
Show file tree
Hide file tree
Showing 8 changed files with 167 additions and 13 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<version>1.0.0</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<version.asm>7.1</version.asm>
<version.asm>6.0</version.asm>
</properties>
<build>
<sourceDirectory>src/main/java</sourceDirectory>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1166,7 +1166,9 @@ else if(obj instanceof JavaObject)
MethodInsnNode cast = (MethodInsnNode) now;
Type type = Type.getReturnType(cast.desc);
List<JavaValue> args = new ArrayList<>();
for (Type t1 : Type.getArgumentTypes(cast.desc)) {
List<Type> l = new ArrayList<>(Arrays.asList(Type.getArgumentTypes(cast.desc)));
Collections.reverse(l);
for (Type t1 : l) {
if (t1.getSort() == Type.LONG || t1.getSort() == Type.DOUBLE) {
if (!(stack.get(0) instanceof JavaTop)) {
throw new ExecutionException("Expected JavaTop");
Expand Down Expand Up @@ -1264,7 +1266,9 @@ else if(obj instanceof JavaObject)
MethodInsnNode cast = (MethodInsnNode) now;
Type type = Type.getReturnType(cast.desc);
List<JavaValue> args = new ArrayList<>();
for (Type t1 : Type.getArgumentTypes(cast.desc)) {
List<Type> l = new ArrayList<>(Arrays.asList(Type.getArgumentTypes(cast.desc)));
Collections.reverse(l);
for (Type t1 : l) {
if (t1.getSort() == Type.LONG || t1.getSort() == Type.DOUBLE) {
if (!(stack.get(0) instanceof JavaTop)) {
throw new ExecutionException("Expected JavaTop");
Expand Down Expand Up @@ -1443,7 +1447,9 @@ else if(obj instanceof JavaObject)
MethodInsnNode cast = (MethodInsnNode) now;
Type type = Type.getReturnType(cast.desc);
List<JavaValue> args = new ArrayList<>();
for (Type t1 : Type.getArgumentTypes(cast.desc)) {
List<Type> l = new ArrayList<>(Arrays.asList(Type.getArgumentTypes(cast.desc)));
Collections.reverse(l);
for (Type t1 : l) {
if (t1.getSort() == Type.LONG || t1.getSort() == Type.DOUBLE) {
if (!(stack.get(0) instanceof JavaTop)) {
throw new ExecutionException("Expected JavaTop");
Expand Down Expand Up @@ -1607,7 +1613,9 @@ else if(argumentTypes[i + 3].getSort() == Type.DOUBLE)
args.add(JavaValue.valueOf(arg));
}
List<JavaValue> newArgs = new ArrayList<>();
for (Type t1 : Type.getArgumentTypes(cast.desc)) {
List<Type> l = new ArrayList<>(Arrays.asList(Type.getArgumentTypes(cast.desc)));
Collections.reverse(l);
for (Type t1 : l) {
if (t1.getSort() == Type.LONG || t1.getSort() == Type.DOUBLE) {
if (!(stack.get(0) instanceof JavaTop)) {
throw new ExecutionException("Expected JavaTop");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,13 +104,14 @@ public boolean canCheckEquality(JavaValue first, JavaValue second, Context conte
{
MethodInsnNode m = (MethodInsnNode)ain;
String strCl = m.owner;
if(m.desc.equals("(Ljava/lang/String;)Ljava/lang/String;"))
if(m.desc.equals("(Ljava/lang/Object;)Ljava/lang/String;")
|| m.desc.equals("(Ljava/lang/String;)Ljava/lang/String;"))
{
Frame<SourceValue> f = frames[method.instructions.indexOf(m)];
if(f.getStack(f.getStackSize() - 1).insns.size() != 1)
continue;
AbstractInsnNode ldc = f.getStack(f.getStackSize() - 1).insns.iterator().next();
if(ldc.getOpcode() != Opcodes.LDC)
if(ldc.getOpcode() != Opcodes.LDC || !(((LdcInsnNode)ldc).cst instanceof String))
continue;
Context context = new Context(provider);
context.push(classNode.name, method.name, getDeobfuscator().getConstantPool(classNode).getSize());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ public boolean transform() throws Throwable {
if (results.size() == 1) {
InsnList replacement = new InsnList();
replacement.add(new InsnNode(POP2)); // remove existing args from stack
replacement.add(Utils.getNumberInsn(results.iterator().next()));
replacement.add(Utils.getIntInsn(results.iterator().next()));
replacements.put(ain, replacement);
folded.getAndIncrement();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public boolean transform() throws Throwable {
((MethodInsnNode) ain).name.equals("length") &&
ain.getPrevious() instanceof LdcInsnNode && ((LdcInsnNode) ain.getPrevious()).cst instanceof String) {
AbstractInsnNode previous = ain.getPrevious();
method.instructions.set(ain, Utils.getNumberInsn(((String)((LdcInsnNode)ain.getPrevious()).cst).length()));
method.instructions.set(ain, Utils.getIntInsn(((String)((LdcInsnNode)ain.getPrevious()).cst).length()));
method.instructions.remove(previous);
count.getAndIncrement();
}
Expand Down Expand Up @@ -81,7 +81,7 @@ else if(entry.getKey() == a2)
{
Integer resultValue;
if((resultValue = doMath(Utils.getIntValue(a1), Utils.getIntValue(a2), ain.getOpcode())) != null) {
AbstractInsnNode newValue = Utils.getNumberInsn(resultValue);
AbstractInsnNode newValue = Utils.getIntInsn(resultValue);
replace.put(ain, newValue);
method.instructions.set(ain, newValue);
method.instructions.remove(a1);
Expand Down Expand Up @@ -114,7 +114,7 @@ else if(entry.getKey() == a2)
if (ain.getOpcode() == Opcodes.INVOKESTATIC) {
Integer number = numberMethods.get(((MethodInsnNode)ain).owner + ((MethodInsnNode)ain).name + ((MethodInsnNode)ain).desc);
if (number != null) {
method.instructions.set(ain, Utils.getNumberInsn(number));
method.instructions.set(ain, Utils.getIntInsn(number));
count.getAndIncrement();
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
/*
* Copyright 2018 Sam Sun <[email protected]>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.javadeobfuscator.deobfuscator.transformers.special;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicInteger;

import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.InsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.VarInsnNode;

import com.javadeobfuscator.deobfuscator.config.*;
import com.javadeobfuscator.deobfuscator.exceptions.*;
import com.javadeobfuscator.deobfuscator.transformers.*;
import com.javadeobfuscator.deobfuscator.utils.TransformerHelper;
import com.javadeobfuscator.javavm.MethodExecution;
import com.javadeobfuscator.javavm.VirtualMachine;
import com.javadeobfuscator.javavm.mirrors.JavaClass;
import com.javadeobfuscator.javavm.utils.ArrayConversionHelper;
import com.javadeobfuscator.javavm.values.JavaWrapper;

public class BisGuardTransformer extends Transformer<TransformerConfig>
{
@Override
public boolean transform() throws WrongTransformerException
{
VirtualMachine vm = TransformerHelper.newVirtualMachine(this);
AtomicInteger count = new AtomicInteger();
System.out.println("[Special] [BisGuardTransformer] Starting");
ClassNode loader = classNodes().stream().filter(c -> c.name.equals("JavaPreloader")).findFirst().orElse(null);
MethodNode getCipher = loader == null ? null : loader.methods.stream().filter(m -> m.name.equals("getCipher")
&& m.desc.equals("([B)LJavaPreloader$Cipher;")).findFirst().orElse(null);
ClassNode cipher = classNodes().stream().filter(c -> c.name.equals("JavaPreloader$Cipher")).findFirst().orElse(null);
MethodNode decrypt = cipher == null ? null : cipher.methods.stream().filter(m -> m.name.equals("decrypt")
&& m.desc.equals("([B)V")).findFirst().orElse(null);
if(getCipher != null && decrypt != null)
{
MethodNode init = new MethodNode(Opcodes.ACC_PUBLIC, "<init>", "(I)V", null, null);
init.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0));
init.instructions.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false));
init.instructions.add(new InsnNode(Opcodes.RETURN));
loader.methods.add(init);
JavaWrapper instance = vm.newInstance(JavaClass.forName(vm, "JavaPreloader"), "(I)V", vm.newInt(0));
loader.methods.remove(init);
MethodExecution cipherInstance = vm.execute(loader, getCipher, instance, Collections.<JavaWrapper>singletonList(
vm.getNull()));
boolean contains = getDeobfuscator().getInputPassthrough().containsKey("JavaSerialNo.class");
byte[] decryptionKey = null;
if(contains)
{
byte[] data = getDeobfuscator().getInputPassthrough().get("JavaSerialNo.class");
JavaWrapper byteArr = ArrayConversionHelper.convertByteArray(vm, data);
vm.execute(cipher, decrypt, cipherInstance.getReturnValue(), Collections.<JavaWrapper>singletonList(byteArr));
byte[] b = ArrayConversionHelper.convertByteArray(byteArr.asArray());
getDeobfuscator().getInputPassthrough().remove("JavaSerialNo.class");
getDeobfuscator().loadInput("JavaSerialNo.class", b);
ClassNode cn = classNodes().stream().filter(c -> c.name.equals("JavaSerialNo")).findFirst().orElse(null);
MethodNode serialBytes = cn.methods.stream().filter(m -> m.name.equals("toSerialNoBytes")).findFirst().orElse(null);
MethodExecution execution = vm.execute(cn, serialBytes);
String res = vm.convertJavaObjectToString(execution.getReturnValue());
//Convert to decryption key
MethodNode hex2Bytes = loader.methods.stream().filter(m -> m.name.equals("hexToBytes")).findFirst().orElse(null);
MethodExecution execution2 = vm.execute(loader, hex2Bytes, instance, Collections.<JavaWrapper>singletonList(
vm.getString(res)));
cipherInstance = vm.execute(loader, getCipher, instance, Collections.<JavaWrapper>singletonList(
vm.getNull()));
decryptionKey = ArrayConversionHelper.convertByteArray(execution2.getReturnValue().asArray());
JavaWrapper byteArr1 = ArrayConversionHelper.convertByteArray(vm, decryptionKey);
vm.execute(cipher, decrypt, cipherInstance.getReturnValue(), Collections.<JavaWrapper>singletonList(byteArr1));
decryptionKey = ArrayConversionHelper.convertByteArray(byteArr1.asArray());
cipherInstance = vm.execute(loader, getCipher, instance, Collections.<JavaWrapper>singletonList(
ArrayConversionHelper.convertByteArray(vm, decryptionKey)));
}
Map<String, byte[]> decrypted = new HashMap<>();
for(Entry<String, byte[]> passthrough : getDeobfuscator().getInputPassthrough().entrySet())
if(passthrough.getKey().endsWith(".class"))
{
byte[] data = passthrough.getValue();
if(data[0] != -54 || data[1] != -2 || data[2] != -70 || data[3] != -66)
{
cipherInstance = vm.execute(loader, getCipher, instance, Collections.<JavaWrapper>singletonList(
decryptionKey == null ? vm.getNull() : ArrayConversionHelper.convertByteArray(vm, decryptionKey)));
JavaWrapper byteArr = ArrayConversionHelper.convertByteArray(vm, data);
vm.execute(cipher, decrypt, cipherInstance.getReturnValue(), Collections.<JavaWrapper>singletonList(byteArr));
byte[] b = ArrayConversionHelper.convertByteArray(byteArr.asArray());
decrypted.put(passthrough.getKey(), b);
count.getAndIncrement();
}
}
for(Entry<String, byte[]> entry : decrypted.entrySet())
{
getDeobfuscator().getInputPassthrough().remove(entry.getKey());
getDeobfuscator().loadInput(entry.getKey(), entry.getValue());
}
//Delete all class files related to encryption
classNodes().removeIf(c -> c.name.equals("JavaPreloader$1") || c.name.equals("JavaPreloader$2")
|| c.name.equals("JavaPreloader$3") || c.name.equals("JavaPreloader$Cipher")
|| c.name.equals("JavaPreloader$KlassLoader") || c.name.equals("JavaPreloader$Loader")
|| c.name.equals("JavaPreloader$Protected") || c.name.equals("JavaPreloader")
|| c.name.equals("JavaSerialNo") || c.name.equals("SerialNoClass")
|| c.name.equals("com/bisguard/utils/Authenticator"));
//Set Main-Class to Subordinate-Class
String realMain = null;
int index = -1;
String[] lines = new String(getDeobfuscator().getInputPassthrough().get("META-INF/MANIFEST.MF")).split("\n");
for(int i = 0; i < lines.length; i++)
{
String line = lines[i];
if(line.startsWith("Subordinate-Class: "))
realMain = line.replace("Subordinate-Class: ", "");
else if(line.startsWith("Main-Class: "))
index = i;
}
lines[index] = "Main-Class: " + realMain;
String res = "";
for(String line : lines)
res += line + "\n";
res = res.substring(0, res.length() - 2);
getDeobfuscator().getInputPassthrough().put("META-INF/MANIFEST.MF", res.getBytes());
}
System.out.println("[Special] [BisGuardTransformer] Decrypted " + count.get() + " classes");
System.out.println("[Special] [BisGuardTransformer] Done");
return count.get() > 0;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ else if(entry.getKey() == a2)
Integer resultValue;
if((resultValue = doMath(Utils.getIntValue(a1), Utils.getIntValue(a2), ain.getOpcode())) != null)
{
AbstractInsnNode newValue = Utils.getNumberInsn(resultValue);
AbstractInsnNode newValue = Utils.getIntInsn(resultValue);
replace.put(ain, newValue);
method.instructions.set(ain, newValue);
method.instructions.remove(a1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ public static InsnList cloneInsnList(InsnList original) {
return newInsnList;
}

public static AbstractInsnNode getNumberInsn(int number) {
public static AbstractInsnNode getIntInsn(int number) {
if (number >= -1 && number <= 5)
return new InsnNode(number + 3);
else if (number >= -128 && number <= 127)
Expand Down

0 comments on commit 0017ae8

Please sign in to comment.