一步一步学习Allatori解密 (二)如何找到字符串加密方法

自己手工解密字符串很麻烦,要一个一个去执行,那么有没有方法可以用程序去解密呢?办法肯定是有的。接下来我们就一步一步去实现自动解密程序吧。

要实现自动解密,我们首先要先找到哪些方法是字符串解密方法。
在这里插入图片描述

分析一下这个加密方法,我们可以看到方法参数是String返回值是String,然后方法内部有些特殊的方法,比如charAt length还有^操作符等等这些特征。那我们就可以利用asm在字节码中找到这个加密方法。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

方法写完,我们测试一下,看看是否能找到加密方法
在这里插入图片描述

执行方法,在控制台输出了方法名称,今天先讲到这里,下次我们讲一下获取到方法,那么如何去解密字符串呢。
在这里插入图片描述

完整代码如下:

package org.example;

import org.apache.commons.io.IOUtils;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;


import java.io.IOException;
import java.util.jar.JarFile;

import static org.objectweb.asm.Opcodes.*;
import static org.objectweb.asm.Opcodes.INVOKESPECIAL;

public class FindAllatoriMethod {
    public static void main(String[] args) {
        JarFile inputJar = null;
        try {
            inputJar = new JarFile("D:\\work\\allatoriDecrypt\\obfuscator\\allatoriDecrypt.jar");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        JarFile finalInputJar = inputJar;
        inputJar.stream().forEach(entry -> {
            if (entry.isDirectory() || !entry.getName().endsWith(".class")) {
                return;
            }
            byte[] src = null;
            try {
                src = IOUtils.toByteArray(finalInputJar.getInputStream(entry));
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            ClassReader classReader = new ClassReader(src);
            ClassNode classNode = new ClassNode();
            classReader.accept(classNode, ClassReader.SKIP_DEBUG);

            for (MethodNode method : classNode.methods) {
                if(isAllatoriMethod(method)){
                    System.out.println(method.name);
                }
            }
        });
    }

    private static boolean isAllatoriMethod(MethodNode decryptorNode) {
        boolean isAllatori = true;
        isAllatori = isAllatori && containsInvokeVirtual(decryptorNode, "java/lang/String", "charAt", "(I)C");
        isAllatori = isAllatori && containsInvokeVirtual(decryptorNode, "java/lang/String", "length", "()I");
        isAllatori = isAllatori && containsInvokeSpecial(decryptorNode, "java/lang/String", "<init>", null);
        isAllatori = isAllatori && countOccurencesOf(decryptorNode, IXOR) > 2;
        isAllatori = isAllatori && countOccurencesOf(decryptorNode, NEWARRAY) > 0;
        return isAllatori;
    }

    public static boolean containsInvokeVirtual(MethodNode methodNode, String owner, String name, String desc) {
        for (AbstractInsnNode insn : methodNode.instructions) {
            if (isInvokeVirtual(insn, owner, name, desc)) {
                return true;
            }
        }
        return false;
    }

    public static boolean isInvokeVirtual(AbstractInsnNode insn, String owner, String name, String desc) {
        if (insn == null) {
            return false;
        }
        if (insn.getOpcode() != INVOKEVIRTUAL) {
            return false;
        }
        MethodInsnNode methodInsnNode = (MethodInsnNode) insn;
        return (owner == null || methodInsnNode.owner.equals(owner)) &&
                (name == null || methodInsnNode.name.equals(name)) &&
                (desc == null || methodInsnNode.desc.equals(desc));
    }

    public static boolean containsInvokeSpecial(MethodNode methodNode, String owner, String name, String desc) {
        for (AbstractInsnNode insn : methodNode.instructions) {
            if (isInvokeSpecial(insn, owner, name, desc)) {
                return true;
            }
        }
        return false;
    }

    public static boolean isInvokeSpecial(AbstractInsnNode insn, String owner, String name, String desc) {
        if (insn == null) {
            return false;
        }
        if (insn.getOpcode() != INVOKESPECIAL) {
            return false;
        }
        MethodInsnNode methodInsnNode = (MethodInsnNode) insn;
        return (owner == null || methodInsnNode.owner.equals(owner)) &&
                (name == null || methodInsnNode.name.equals(name)) &&
                (desc == null || methodInsnNode.desc.equals(desc));
    }

    public static int countOccurencesOf(MethodNode methodNode, int opcode) {
        int i = 0;
        for (AbstractInsnNode insnNode : methodNode.instructions) {
            if (insnNode.getOpcode() == opcode) {
                i++;
            }
        }
        return i;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值