Uso da ferramenta antiofuscação Threadtear

Durante o processo de desenvolvimento, encontramos algumas bibliotecas de terceiros que não são de código aberto. Às vezes, precisamos nos referir a alguns dos códigos e precisamos descompilá-los para visualizá-los. Às vezes também é encontrado que o código foi ofuscado. Este artigo apresenta principalmente como usar o Threadtear para desofuscar o pacote jar ofuscado.

Endereço Threadtear Git: https://github.com/GraxCode/threadtear

compilar jar executável

Existem duas maneiras:
1. Baixe diretamente a versão mais recente lançada pelo Github. (Baixei a última versão 3.0.1 e descobri que não roda normalmente e tem anormalidades)
2. Baixe o código do projeto Git e importe o projeto com o Android Studio. E execute os dois comandos a seguir e, em seguida, um arquivo jar executável será obtido nas compilações/libs do módulo gui: threadtear-gui-3.0.0-all.jar.

gradle build
gradle fatJar

uso de ferramentas

Execute o seguinte comando no diretório do arquivo jar executável recém-gerado (você também pode copiar o arquivo jar recém-gerado para um novo diretório) para abrir a ferramenta Threadtear:

java -noverify -jar threadtear-gui-3.0.0-all.jar

A interface da ferramenta é mostrada na figura abaixo:
insira a descrição da imagem aqui
Há uma configuração de aparência no menu de ajuda para definir o estilo da interface, principalmente para definir o tamanho do texto, o tamanho padrão é um pouco pequeno. . .
Em seguida, primeiro definimos as tarefas a serem executadas, clique no botão Adicionar, conforme mostrado na figura abaixo:
insira a descrição da imagem aqui
A seguir, adicionaremos as tarefas mostradas na figura abaixo à lista de executáveis ​​em ordem:
insira a descrição da imagem aqui
Em seguida, precisaremos descompilar e desofuscar o jar diretamente Arraste-o para a área da lista de classes à direita.

Aqui não encontrei uma combinação de lista de execução que restaure completamente todas as variáveis ​​ofuscadas de cada arquivo para seus nomes originais.A tarefa de execução porta a porta é apenas analisar cada nome de classe. O nome da variável ainda está em estudo, atualize a tempo se houver algum progresso, desculpe~

Execução personalizada

insira a descrição da imagem aqui

Conforme mostrado na figura acima, depois de baixar o código-fonte do projeto, crie um novo diretório personalizado no módulo principal, crie uma Execução personalizada e adicione a Execução personalizada ao ExecutionLink. Em seguida, reembalar. Dessa forma, podemos ver a Execução personalizada que acabamos de criar na ExecutionList do jar executável.

public class MyExecution extends Execution implements IConstantReferenceHandler {
    
    

    public MyExecution() {
    
    
        super(ExecutionCategory.GENERIC, "My execution", "Performs stack analysis and replaces code.");
    }

    @Override
    public boolean execute(Map<String, Clazz> classes, boolean verbose) {
    
    
        classes.values().stream().map(c -> c.node).forEach(this::analyzeAndRewrite);
        return true;
    }

    public void analyzeAndRewrite(ClassNode cn) {
    
    
        cn.methods.forEach(m -> {
    
    
            // this analyzer keeps known stack values, e.g. can be useful for jump prediction
            Analyzer<ConstantValue> a = new Analyzer<ConstantValue>(new ConstantTracker(this,
                    Access.isStatic(m.access), m.maxLocals, m.desc, new Object[0]));

            try {
    
    
                a.analyze(cn.name, m);
            } catch (AnalyzerException e) {
    
    
                logger.error("Failed stack analysis in " + cn.name + "." + m.name + ":" + e.getMessage());
                return;
            }

            Frame<ConstantValue>[] frames = a.getFrames();
            InsnList rewrittenCode = new InsnList();
            Map<LabelNode, LabelNode> labels = Instructions.cloneLabels(m.instructions);

            // rewrite method instructions
            for (int i = 0; i < m.instructions.size(); i++) {
    
    

                AbstractInsnNode ain = m.instructions.get(i);
                Frame<ConstantValue> frame = frames[i];
                // replace / modify instructions, etc...

                if (frame.getStackSize() > 0) {
    
    
                    ConstantValue top = frame.getStack(frame.getStackSize() - 1);

                    if (top.isKnown() && top.isInteger()) {
    
    
                        int knownTopStackValue = top.getAsInteger();
                        // use the known stack to remove jumps, simplify code, etc...
                        // if(...) { rewrittenCode.add(...); }
                        continue;
                    }
                }

                rewrittenCode.add(ain.clone(labels));
            }

            // update instructions and fix try catch blocks, local variables, etc...
            Instructions.updateInstructions(m, labels, rewrittenCode);
        });
    }

    /**
     * Use this method to predict stack values if fields are loaded
     */
    @Override
    public Object getFieldValueOrNull(BasicValue v, String owner, String name, String desc) {
    
    
        return null;
    }

    /**
     * Use this method to predict stack values if methods are invoked on known objects
     */
    @Override
    public Object getMethodReturnOrNull(BasicValue v, String owner, String name, String desc, List<?
            extends ConstantValue> values) {
    
    

        if (name.equals("toCharArray") && owner.equals("java/lang/String")) {
    
    

            if (!values.get(0).isKnown()) {
    
    
                // invocation target is not known, we can't compute the return
                return null;
            }

            return ((String) values.get(0).getValue()).toCharArray();
        }

        return null;
    }
}

insira a descrição da imagem aqui

Acho que você gosta

Origin blog.csdn.net/u012230055/article/details/128894612
Recomendado
Clasificación