Search in sources :

Example 26 with ControlFlowGraph

use of org.mapleir.ir.cfg.ControlFlowGraph in project maple-ir by LLVM-but-worse.

the class ExceptionFixerPass method accept.

@Override
public PassResult accept(PassContext cxt) {
    final AtomicInteger counter = new AtomicInteger();
    for (ControlFlowGraph value : cxt.getAnalysis().getIRCache().values()) {
        for (ExceptionRange<BasicBlock> range : value.getRanges()) {
            if (range.getTypes().size() <= 1)
                continue;
            ClassNode superType = null;
            for (Type type : range.getTypes()) {
                ClassNode classNode = cxt.getAnalysis().getApplication().findClassNode(type.getClassName());
                if (classNode == null) {
                    try {
                        classNode = ClassHelper.create(type.getClassName());
                    } catch (IOException e) {
                        continue;
                    }
                }
                if (superType == null) {
                    superType = classNode;
                } else {
                    superType = cxt.getAnalysis().getApplication().getClassTree().getCommonSuperType(superType.getName(), classNode.getName());
                }
            }
            final Set<Type> types = new HashSet<>(Collections.singleton(superType == null ? TypeUtils.OBJECT_TYPE : Type.getObjectType(superType.getName())));
            range.setTypes(types);
            counter.incrementAndGet();
        }
    }
    logger.info("[*] Successfully fixed" + counter.get() + " exception ranges!");
    return PassResult.with(cxt, this).finished().make();
}
Also used : ClassNode(org.mapleir.asm.ClassNode) Type(org.objectweb.asm.Type) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ControlFlowGraph(org.mapleir.ir.cfg.ControlFlowGraph) BasicBlock(org.mapleir.ir.cfg.BasicBlock) IOException(java.io.IOException)

Example 27 with ControlFlowGraph

use of org.mapleir.ir.cfg.ControlFlowGraph in project maple-ir by LLVM-but-worse.

the class FieldRSADecryptionPass method accept.

@Override
public PassResult accept(PassContext pcxt) {
    this.cxt = pcxt.getAnalysis();
    for (MethodNode m : cxt.getIRCache().getActiveMethods()) {
        ControlFlowGraph cfg = cxt.getIRCache().getFor(m);
        for (BasicBlock b : cfg.vertices()) {
            for (Stmt stmt : b) {
                for (Expr c : stmt.enumerateOnlyChildren()) {
                    if (c.getOpcode() == ARITHMETIC) {
                        ArithmeticExpr arith = (ArithmeticExpr) c;
                        if (arith.getOperator() == Operator.MUL) {
                            Expr l = arith.getLeft();
                            Expr r = arith.getRight();
                            if (r.getOpcode() == CONST_LOAD && l.getOpcode() == FIELD_LOAD) {
                                FieldLoadExpr fle = (FieldLoadExpr) l;
                                ConstantExpr constt = (ConstantExpr) r;
                                Number n = (Number) constt.getConstant();
                                boolean isLong = (n instanceof Long);
                                if (__eq(n, 1, isLong) || __eq(n, 0, isLong)) {
                                    continue;
                                }
                                if (n instanceof Integer || n instanceof Long) {
                                    cdecs.getNonNull(key(fle)).add(n);
                                }
                            }
                        }
                    }
                }
                if (stmt.getOpcode() == FIELD_STORE) {
                    FieldStoreStmt fss = (FieldStoreStmt) stmt;
                    Expr val = fss.getValueExpression();
                    if (bcheck1(val)) {
                        if (val.getOpcode() == CONST_LOAD) {
                            ConstantExpr c = (ConstantExpr) val;
                            if (c.getConstant() instanceof Integer || c.getConstant() instanceof Long) {
                                Number n = (Number) c.getConstant();
                                if (large(n, c.getConstant() instanceof Long)) {
                                    cencs.getNonNull(key(fss)).add(n);
                                }
                            }
                        }
                        continue;
                    }
                    ArithmeticExpr ar = (ArithmeticExpr) val;
                    if (ar.getRight().getOpcode() == CONST_LOAD) {
                        ConstantExpr c = (ConstantExpr) ar.getRight();
                        Number n = (Number) c.getConstant();
                        boolean isLong = c.getConstant() instanceof Long;
                        if (__eq(n, 1, isLong) || __eq(n, 0, isLong)) {
                            continue;
                        }
                        if (ar.getOperator() == Operator.ADD) {
                            if (!large(n, isLong)) {
                                continue;
                            }
                        }
                        cencs.getNonNull(key(fss)).add(n);
                    }
                }
            }
            for (Stmt stmt : b) {
                if (stmt.getOpcode() == FIELD_STORE) {
                    if (key((FieldStoreStmt) stmt).equals("co.k I")) {
                    // System.out.println("HERE1: " + stmt);
                    // 
                    // System.out.println(cfg);
                    }
                    handleFss((FieldStoreStmt) stmt);
                }
                for (Expr e : stmt.enumerateOnlyChildren()) {
                    if (e.getOpcode() == FIELD_LOAD) {
                        if (key((FieldLoadExpr) e).equals("co.k I")) {
                        // System.out.println("HERE2: " + stmt);
                        }
                        handleFle(stmt, (FieldLoadExpr) e);
                    }
                }
            }
        }
    }
    Set<String> keys = new HashSet<>();
    keys.addAll(cencs.keySet());
    keys.addAll(cdecs.keySet());
    for (String k : keys) {
        boolean _longint = k.endsWith("J");
        Set<Number> encs = cencs.getNonNull(k);
        Set<Number> decs = cdecs.getNonNull(k);
        try {
            Number[] pair = get_pair(encs, decs, constants.getNonNull(k), _longint);
            if (pair.length != 2) {
                Set<Number> extended = new HashSet<>(constants.getNonNull(k));
                extended.addAll(dangerConstants.getNonNull(k));
                pair = get_pair(encs, decs, extended, _longint);
            }
            if (pair.length != 2) {
            // System.out.println("No pair for: " + k);
            // System.out.println("Constants: " + constants.getNonNull(k));
            // System.out.println("Dconsts  : " + dangerConstants.getNonNull(k));
            // System.out.println("Encs     : " + encs);
            // System.out.println("Decs     : " + decs);
            } else {
                pairs.put(k, pair);
            // System.out.println("for: " + k + ": " + Arrays.toString(pair));
            }
        } catch (IllegalStateException e) {
            System.err.println();
            System.err.println("Constants: " + constants.getNonNull(k));
            System.out.println("Dconsts  : " + dangerConstants.getNonNull(k));
            System.err.println("Encs     : " + encs);
            System.err.println("Decs     : " + decs);
            System.err.println("key: " + k);
            throw e;
        }
    }
    System.out.printf("  identified %n field encoder/decoder pairs.%n", pairs.size());
    transform(cxt);
    return PassResult.with(pcxt, this).finished().make();
}
Also used : FieldStoreStmt(org.mapleir.ir.code.stmt.FieldStoreStmt) FieldLoadExpr(org.mapleir.ir.code.expr.FieldLoadExpr) BasicBlock(org.mapleir.ir.cfg.BasicBlock) ConstantExpr(org.mapleir.ir.code.expr.ConstantExpr) FieldStoreStmt(org.mapleir.ir.code.stmt.FieldStoreStmt) Stmt(org.mapleir.ir.code.Stmt) BigInteger(java.math.BigInteger) MethodNode(org.mapleir.asm.MethodNode) ArithmeticExpr(org.mapleir.ir.code.expr.ArithmeticExpr) Expr(org.mapleir.ir.code.Expr) ConstantExpr(org.mapleir.ir.code.expr.ConstantExpr) FieldLoadExpr(org.mapleir.ir.code.expr.FieldLoadExpr) ArithmeticExpr(org.mapleir.ir.code.expr.ArithmeticExpr) ControlFlowGraph(org.mapleir.ir.cfg.ControlFlowGraph)

Example 28 with ControlFlowGraph

use of org.mapleir.ir.cfg.ControlFlowGraph in project maple-ir by LLVM-but-worse.

the class FieldRSADecryptionPass method transform.

private void transform(AnalysisContext cxt) {
    for (ClassNode cn : cxt.getApplication().iterate()) {
        for (MethodNode m : cn.getMethods()) {
            ControlFlowGraph cfg = cxt.getIRCache().getFor(m);
            for (BasicBlock b : cfg.vertices()) {
                for (Stmt stmt : b) {
                    // String fsKey = "";
                    if (stmt.getOpcode() == Opcode.FIELD_STORE) {
                        FieldStoreStmt fs = (FieldStoreStmt) stmt;
                        // [enc, dec]
                        Number[] p = pairs.get(key(fs));
                        if (p != null) {
                            Expr e = fs.getValueExpression();
                            e.unlink();
                            ArithmeticExpr ae = new ArithmeticExpr(new ConstantExpr(p[1], ConstantExpr.computeType(p[1])), e, Operator.MUL);
                            fs.setValueExpression(ae);
                        // fsKey = key(fs);
                        }
                    }
                    for (Expr e : stmt.enumerateOnlyChildren()) {
                        if (e.getOpcode() == FIELD_LOAD) {
                            CodeUnit par = e.getParent();
                            FieldLoadExpr fl = (FieldLoadExpr) e;
                            // [enc, dec]
                            Number[] p = pairs.get(key(fl));
                            if (p == null) {
                                continue;
                            }
                            if (par.getOpcode() == ARITHMETIC) {
                                ArithmeticExpr ae = (ArithmeticExpr) par;
                                if (ae.getRight().getOpcode() == CONST_LOAD) {
                                    ConstantExpr ce = (ConstantExpr) ae.getRight();
                                    Number cst = (Number) ce.getConstant();
                                    Number res = __mul(cst, p[0], p[0].getClass().equals(Long.class));
                                    // if(!__eq(res, 1, p[0].getClass().equals(Long.class))) {
                                    // System.out.println(cst + " -> " + res);
                                    // System.out.println("  expr: " + fl.getRootParent());
                                    // }
                                    par.writeAt(new ConstantExpr(res, ConstantExpr.computeType(res)), par.indexOf(ce));
                                    continue;
                                }
                            }
                            ArithmeticExpr ae = new ArithmeticExpr(new ConstantExpr(p[0], ConstantExpr.computeType(p[0])), fl.copy(), Operator.MUL);
                            par.writeAt(ae, par.indexOf(fl));
                        }
                    }
                }
            }
        }
    }
// for(ClassNode cn : cxt.getClassTree().getClasses().values()) {
// for(MethodNode m : cn.getMethods()) {
// ControlFlowGraph cfg = cxt.getCFGS().getIR(m);
// 
// for(BasicBlock b : cfg.vertices()) {
// for(Stmt stmt : b) {
// for(Expr e : stmt.enumerateOnlyChildren()) {
// if(e.getOpcode() == Opcode.ARITHMETIC) {
// ArithmeticExpr ae = (ArithmeticExpr) e;
// if(ae.getRight().getOpcode() == Opcode.CONST_LOAD) {
// ConstantExpr c = (ConstantExpr) ae.getRight();
// Object o = c.getConstant();
// 
// if(o instanceof Long || o instanceof Integer) {
// Number n = (Number) o;
// if(__eq(n, 1, ae.getType().equals(DescType.LONG_TYPE))) {
// Expr l = ae.getLeft();
// l.unlink();
// 
// CodeUnit aePar = ae.getParent();
// aePar.writeAt(l, aePar.indexOf(ae));
// } else if(__eq(n, 0, ae.getType().equals(DescType.LONG_TYPE))) {
// c.unlink();
// 
// CodeUnit aePar = ae.getParent();
// aePar.writeAt(c, aePar.indexOf(ae));
// }
// }
// }
// }
// }
// }
// }
// }
// }
}
Also used : FieldStoreStmt(org.mapleir.ir.code.stmt.FieldStoreStmt) ClassNode(org.mapleir.asm.ClassNode) FieldLoadExpr(org.mapleir.ir.code.expr.FieldLoadExpr) BasicBlock(org.mapleir.ir.cfg.BasicBlock) ConstantExpr(org.mapleir.ir.code.expr.ConstantExpr) FieldStoreStmt(org.mapleir.ir.code.stmt.FieldStoreStmt) Stmt(org.mapleir.ir.code.Stmt) CodeUnit(org.mapleir.ir.code.CodeUnit) MethodNode(org.mapleir.asm.MethodNode) ArithmeticExpr(org.mapleir.ir.code.expr.ArithmeticExpr) Expr(org.mapleir.ir.code.Expr) ConstantExpr(org.mapleir.ir.code.expr.ConstantExpr) FieldLoadExpr(org.mapleir.ir.code.expr.FieldLoadExpr) ArithmeticExpr(org.mapleir.ir.code.expr.ArithmeticExpr) ControlFlowGraph(org.mapleir.ir.cfg.ControlFlowGraph)

Example 29 with ControlFlowGraph

use of org.mapleir.ir.cfg.ControlFlowGraph in project maple-ir by LLVM-but-worse.

the class ClassRenamerPass method accept.

/*private String getClassName(String name) {
		int i = name.lastIndexOf('/');
		if(i == -1) {
			return name;
		} else {
			return name.substring(i + 1, name.length());
		}
	}*/
@Override
public PassResult accept(PassContext pcxt) {
    AnalysisContext cxt = pcxt.getAnalysis();
    ApplicationClassSource source = cxt.getApplication();
    Collection<ClassNode> classes = CollectionUtils.collate(source.iterator());
    // int min = RenamingUtil.computeMinimum(classes.size());
    int n = RenamingUtil.numeric("aaa");
    int step = 27;
    for (ClassNode cn : classes) {
        String className = RenamingUtil.getClassName(cn.getName());
        if (!heuristic.shouldRename(className, cn.node.access)) {
            System.out.println("Heuristic bypass " + cn.getName());
        }
        String newName = heuristic.shouldRename(className, cn.node.access) ? RenamingUtil.createName(n) : className;
        String s = RenamingUtil.getPackage(cn.getName()) + newName;
        n += step;
        remapping.put(cn.getName(), s);
        // System.out.println(cn.getName() + " -> " + s);
        cn.node.name = s;
    }
    for (ClassNode cn : classes) {
        cn.node.superName = remapping.getOrDefault(cn.node.superName, cn.node.superName);
        {
            List<String> ifaces = new ArrayList<>();
            for (int i = 0; i < cn.node.interfaces.size(); i++) {
                String s = cn.node.interfaces.get(i);
                ifaces.add(remapping.getOrDefault(s, s));
            }
            cn.node.interfaces = ifaces;
        }
        unsupported(cn.node.signature);
        // unsupported(cn.sourceFile);
        // unsupported(cn.sourceDebug);
        cn.node.outerClass = remapping.getOrDefault(cn.node.outerClass, cn.node.outerClass);
        // unsupported(cn.outerMethod);
        // unsupported(cn.outerMethodDesc);
        unsupported(cn.node.visibleAnnotations);
        unsupported(cn.node.invisibleAnnotations);
        unsupported(cn.node.visibleTypeAnnotations);
        unsupported(cn.node.invisibleTypeAnnotations);
        unsupported(cn.node.attrs);
        unsupported(cn.node.innerClasses);
        for (FieldNode f : cn.getFields()) {
            unsupported(cn.node.signature);
            {
                Type type = Type.getType(f.node.desc);
                String newType = resolveType(type, remapping);
                if (newType != null) {
                    f.node.desc = newType;
                }
            }
            unsupported(f.node.visibleAnnotations);
            unsupported(f.node.invisibleAnnotations);
            unsupported(f.node.visibleTypeAnnotations);
            unsupported(f.node.invisibleTypeAnnotations);
            unsupported(f.node.attrs);
        }
        for (MethodNode m : cn.getMethods()) {
            m.node.desc = resolveMethod(m.node.desc, remapping);
            unsupported(m.node.signature);
            {
                List<String> exceptions = new ArrayList<>();
                for (int i = 0; i < m.node.exceptions.size(); i++) {
                    String s = m.node.exceptions.get(i);
                    exceptions.add(remapping.getOrDefault(s, s));
                }
                m.node.exceptions = exceptions;
            }
            unsupported(m.node.parameters);
            unsupported(m.node.visibleAnnotations);
            unsupported(m.node.invisibleAnnotations);
            unsupported(m.node.visibleTypeAnnotations);
            unsupported(m.node.invisibleTypeAnnotations);
            unsupported(m.node.attrs);
            unsupported(m.node.annotationDefault);
            unsupported(m.node.visibleParameterAnnotations);
            unsupported(m.node.invisibleParameterAnnotations);
            for (TryCatchBlockNode tcbn : m.node.tryCatchBlocks) {
                tcbn.type = remapping.getOrDefault(tcbn.type, tcbn.type);
            }
            ControlFlowGraph cfg = cxt.getIRCache().getFor(m);
            for (ExceptionRange<BasicBlock> er : cfg.getRanges()) {
                Set<Type> newTypeSet = new HashSet<>();
                for (Type t : er.getTypes()) {
                    // FIXME:
                    String s = t.getInternalName();
                    if (remapping.containsKey(s)) {
                        newTypeSet.add(Type.getType("L" + remapping.get(s) + ";"));
                    } else {
                        newTypeSet.add(t);
                    }
                }
                er.setTypes(newTypeSet);
            }
            if (m.node.localVariables != null) {
                m.node.localVariables.clear();
                for (LocalVariableNode lvn : m.node.localVariables) {
                    String newDesc = resolveType(Type.getType(lvn.desc), remapping);
                    if (newDesc != null) {
                        lvn.desc = newDesc;
                    }
                    unsupported(lvn.signature);
                }
            }
            unsupported(m.node.visibleLocalVariableAnnotations);
            unsupported(m.node.invisibleLocalVariableAnnotations);
            for (BasicBlock b : cfg.vertices()) {
                for (Stmt stmt : b) {
                    if (stmt.getOpcode() == Opcode.FIELD_STORE) {
                        FieldStoreStmt fs = (FieldStoreStmt) stmt;
                        String owner = fs.getOwner();
                        fs.setOwner(remapping.getOrDefault(owner, owner));
                        {
                            Type type = Type.getType(fs.getDesc());
                            String newType = resolveType(type, remapping);
                            if (newType != null) {
                                fs.setDesc(newType);
                            }
                        }
                    } else if (stmt.getOpcode() == Opcode.RETURN) {
                        ReturnStmt ret = (ReturnStmt) stmt;
                        String newType = resolveType(ret.getType(), remapping);
                        if (newType != null) {
                            ret.setType(Type.getType(newType));
                        }
                    } else if (stmt instanceof AbstractCopyStmt) {
                        AbstractCopyStmt copy = (AbstractCopyStmt) stmt;
                        VarExpr v = copy.getVariable();
                        String newType = resolveType(v.getType(), remapping);
                        if (newType != null) {
                            v.setType(Type.getType(newType));
                        }
                    }
                    for (Expr e : stmt.enumerateOnlyChildren()) {
                        if (e.getOpcode() == Opcode.CAST) {
                            CastExpr cast = (CastExpr) e;
                            String newType = resolveType(cast.getType(), remapping);
                            if (newType != null) {
                                cast.setType(Type.getType(newType));
                            }
                        } else if (e.getOpcode() == Opcode.CATCH) {
                            CaughtExceptionExpr caught = (CaughtExceptionExpr) e;
                            String newType = resolveType(caught.getType(), remapping);
                            if (newType != null) {
                                caught.setType(Type.getType(newType));
                            }
                        } else if (e.getOpcode() == Opcode.INVOKE) {
                            InvocationExpr invoke = (InvocationExpr) e;
                            if (invoke.isDynamic())
                                throw new UnsupportedOperationException();
                            invoke.setOwner(remapping.getOrDefault(invoke.getOwner(), invoke.getOwner()));
                            invoke.setDesc(resolveMethod(invoke.getDesc(), remapping));
                        } else if (e.getOpcode() == Opcode.FIELD_LOAD) {
                            FieldLoadExpr fl = (FieldLoadExpr) e;
                            fl.setOwner(remapping.getOrDefault(fl.getOwner(), fl.getOwner()));
                            String newType = resolveType(fl.getType(), remapping);
                            if (newType != null) {
                                fl.setDesc(newType);
                            }
                        } else if (e.getOpcode() == Opcode.INIT_OBJ) {
                            InitialisedObjectExpr init = (InitialisedObjectExpr) e;
                            init.setOwner(remapping.getOrDefault(init.getOwner(), init.getOwner()));
                            init.setDesc(resolveMethod(init.getDesc(), remapping));
                        } else if (e.getOpcode() == Opcode.INSTANCEOF) {
                            InstanceofExpr inst = (InstanceofExpr) e;
                            String newType = resolveType(inst.getCheckType(), remapping);
                            if (newType != null) {
                                inst.setCheckType(Type.getType(newType));
                            }
                        } else if (e.getOpcode() == Opcode.NEW_ARRAY) {
                            NewArrayExpr na = (NewArrayExpr) e;
                            String newType = resolveType(na.getType(), remapping);
                            if (newType != null) {
                                na.setType(Type.getType(newType));
                            }
                        } else if (e.getOpcode() == Opcode.ALLOC_OBJ) {
                            AllocObjectExpr uninit = (AllocObjectExpr) e;
                            String newType = resolveType(uninit.getType(), remapping);
                            if (newType != null) {
                                uninit.setType(Type.getType(newType));
                            }
                        } else if (e.getOpcode() == Opcode.LOCAL_LOAD) {
                            VarExpr v = (VarExpr) e;
                            String newType = resolveType(v.getType(), remapping);
                            if (newType != null) {
                                v.setType(Type.getType(newType));
                            }
                        } else if (e.getOpcode() == Opcode.CONST_LOAD) {
                            ConstantExpr c = (ConstantExpr) e;
                            Object cst = c.getConstant();
                            if (cst instanceof Type) {
                                Type t = (Type) cst;
                                if (t.getSort() == Type.OBJECT) {
                                    String newType = resolveType(t, remapping);
                                    if (newType != null) {
                                        c.setConstant(Type.getType(newType));
                                    }
                                } else {
                                    throw new UnsupportedOperationException(String.format("Unsupported ctype %s (%d)", t, t.getSort()));
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    source.rebuildTable();
    return PassResult.with(pcxt, this).finished().make();
}
Also used : AnalysisContext(org.mapleir.context.AnalysisContext) FieldStoreStmt(org.mapleir.ir.code.stmt.FieldStoreStmt) Stmt(org.mapleir.ir.code.Stmt) AbstractCopyStmt(org.mapleir.ir.code.stmt.copy.AbstractCopyStmt) ReturnStmt(org.mapleir.ir.code.stmt.ReturnStmt) ApplicationClassSource(org.mapleir.app.service.ApplicationClassSource) MethodNode(org.mapleir.asm.MethodNode) AbstractCopyStmt(org.mapleir.ir.code.stmt.copy.AbstractCopyStmt) FieldStoreStmt(org.mapleir.ir.code.stmt.FieldStoreStmt) ClassNode(org.mapleir.asm.ClassNode) TryCatchBlockNode(org.objectweb.asm.tree.TryCatchBlockNode) FieldNode(org.mapleir.asm.FieldNode) BasicBlock(org.mapleir.ir.cfg.BasicBlock) InitialisedObjectExpr(org.mapleir.ir.code.expr.invoke.InitialisedObjectExpr) LocalVariableNode(org.objectweb.asm.tree.LocalVariableNode) Type(org.objectweb.asm.Type) InitialisedObjectExpr(org.mapleir.ir.code.expr.invoke.InitialisedObjectExpr) InvocationExpr(org.mapleir.ir.code.expr.invoke.InvocationExpr) Expr(org.mapleir.ir.code.Expr) ControlFlowGraph(org.mapleir.ir.cfg.ControlFlowGraph) ReturnStmt(org.mapleir.ir.code.stmt.ReturnStmt) InvocationExpr(org.mapleir.ir.code.expr.invoke.InvocationExpr)

Example 30 with ControlFlowGraph

use of org.mapleir.ir.cfg.ControlFlowGraph in project maple-ir by LLVM-but-worse.

the class ConstantParameterPass method accept.

@Override
public PassResult accept(PassContext pcxt) {
    AnalysisContext cxt = pcxt.getAnalysis();
    Map<MethodNode, Set<MethodNode>> chainMap = new HashMap<>();
    for (MethodNode mn : cxt.getIRCache().getActiveMethods()) {
        makeUpChain(cxt, mn, chainMap);
    }
    InvocationResolver resolver = cxt.getInvocationResolver();
    Map<MethodNode, List<Set<Object>>> rawConstantParameters = new HashMap<>();
    Map<MethodNode, boolean[]> chainedNonConstant = new HashMap<>();
    Map<MethodNode, boolean[]> specificNonConstant = new HashMap<>();
    IPAnalysisVisitor vis = new IPAnalysisVisitor() {

        @Override
        public void postVisitMethod(IPAnalysis analysis, MethodNode m) {
            int pCount = Type.getArgumentTypes(m.getDesc()).length;
            /* init map entries */
            if (!chainedNonConstant.containsKey(m)) {
                for (MethodNode assoc : chainMap.get(m)) {
                    boolean[] arr = new boolean[pCount];
                    chainedNonConstant.put(assoc, arr);
                }
                for (MethodNode assoc : chainMap.get(m)) {
                    boolean[] arr = new boolean[pCount];
                    specificNonConstant.put(assoc, arr);
                }
            }
            if (Modifier.isStatic(m.node.access)) {
                if (!rawConstantParameters.containsKey(m)) {
                    List<Set<Object>> l = new ArrayList<>(pCount);
                    rawConstantParameters.put(m, l);
                    for (int i = 0; i < pCount; i++) {
                        l.add(new HashSet<>());
                    }
                }
            } else {
                // TODO: cache
                for (MethodNode site : resolver.resolveVirtualCalls(m, true)) {
                    if (!rawConstantParameters.containsKey(site)) {
                        List<Set<Object>> l = new ArrayList<>(pCount);
                        rawConstantParameters.put(site, l);
                        for (int i = 0; i < pCount; i++) {
                            l.add(new HashSet<>());
                        }
                    }
                }
            }
        }

        @Override
        public void postProcessedInvocation(IPAnalysis analysis, MethodNode caller, MethodNode callee, Invocation call) {
            Expr[] params = call.getParameterExprs();
            for (int i = 0; i < params.length; i++) {
                Expr e = params[i];
                if (e.getOpcode() == Opcode.CONST_LOAD) {
                    if (Modifier.isStatic(callee.node.access)) {
                        rawConstantParameters.get(callee).get(i).add(((ConstantExpr) e).getConstant());
                    } else {
                        /* only chain callsites *can* have this input */
                        for (MethodNode site : resolver.resolveVirtualCalls(callee, true)) {
                            rawConstantParameters.get(site).get(i).add(((ConstantExpr) e).getConstant());
                        }
                    }
                } else {
                    /* whole branch tainted */
                    for (MethodNode associated : chainMap.get(callee)) {
                        chainedNonConstant.get(associated)[i] = true;
                    }
                    /* callsites tainted */
                    if (Modifier.isStatic(callee.node.access)) {
                        specificNonConstant.get(callee)[i] = true;
                    } else {
                        /* only chain callsites *can* have this input */
                        for (MethodNode site : resolver.resolveVirtualCalls(callee, true)) {
                            specificNonConstant.get(site)[i] = true;
                        }
                    }
                }
            }
        }
    };
    IPAnalysis constAnalysis = IPAnalysis.create(cxt, vis);
    // ApplicationClassSource app = cxt.getApplication();
    // ClassTree structures = app.getStructures();
    /* remove all calls to library methods since we can't
		 * handle them. */
    /*Iterator<Entry<MethodNode, List<Set<Object>>>> it = rawConstantParameters.entrySet().iterator();
		while(it.hasNext()) {
			Entry<MethodNode, List<Set<Object>>> en = it.next();
			
			MethodNode m = en.getKey();

			if(app.isLibraryClass(m.owner.getName())) {
				it.remove();
				continue;
			}
			
			// TODO: MUST BE CONVERTED TO ACCOUNT FOR DIRECT SUPERS, NOT ALL
			superFor: for(ClassNode cn : structures.getAllParents(m.owner)) {
				if(app.isLibraryClass(cn.getName())) {
					for(MethodNode m1 : cn.methods) {
						if(resolver.areMethodsCongruent(m1, m, Modifier.isStatic(m.node.access))) {
							it.remove();
							break superFor;
						}
					}
				}
			}
		}*/
    /* aggregate constant parameters indices with their chained
		 * methods such that the map contains only constant parameter
		 * indices that we can actually remove while keeping a valid chain.
		 * 
		 * We do this as we can have methods from different branches that
		 * are cousin-related but have different constant parameter values.
		 * In these cases we can still inline the constants (different constants)
		 * and change the descriptions, keeping the chain. */
    Map<MethodNode, boolean[]> filteredConstantParameters = new HashMap<>();
    for (Entry<MethodNode, List<Set<Object>>> en : rawConstantParameters.entrySet()) {
        MethodNode m = en.getKey();
        List<Set<Object>> objParams = en.getValue();
        boolean[] tainted = chainedNonConstant.get(m);
        if (filteredConstantParameters.containsKey(m)) {
            /* note: if this method is contained in the
				 * map all of it's cousin-reachable methods
				 * must also be and furthermore the dead map
				 * for the entire chain is the same array. 
				 * 
				 * we need to now merge the current dead map
				 * with the one specifically for this method.*/
            boolean[] thisDeadMap = makeDeadMap(objParams, tainted);
            boolean[] prevDeadMap = filteredConstantParameters.get(m);
            if (thisDeadMap.length != prevDeadMap.length) {
                throw new IllegalStateException(String.format("m: %s, chain:%s, %d:%d", m, chainMap.get(m), thisDeadMap.length, prevDeadMap.length));
            }
            /* each dead map contains true values for an
				 * index if that index is a constant parameter. */
            for (int i = 0; i < prevDeadMap.length; i++) {
                prevDeadMap[i] &= thisDeadMap[i];
            }
        } else {
            boolean[] deadParams = makeDeadMap(objParams, tainted);
            for (MethodNode chm : chainMap.get(m)) {
                filteredConstantParameters.put(chm, deadParams);
            }
        }
        ControlFlowGraph cfg = cxt.getIRCache().getFor(m);
        // boolean b = false;
        boolean[] specificTaint = specificNonConstant.get(m);
        for (int i = 0; i < objParams.size(); i++) {
            Set<Object> set = objParams.get(i);
            if (!specificTaint[i] && set.size() == 1) {
                inlineConstant(cfg, constAnalysis.getLocalIndex(m, i), set.iterator().next());
            }
        }
    }
    Map<MethodNode, String> remap = new HashMap<>();
    Set<MethodNode> toRemove = new HashSet<>();
    Set<Set<MethodNode>> mustRename = new HashSet<>();
    for (Entry<MethodNode, boolean[]> en : filteredConstantParameters.entrySet()) {
        MethodNode m = en.getKey();
        if (!remap.containsKey(m) && !toRemove.contains(m)) {
            boolean[] deadMap = en.getValue();
            boolean notSame = false;
            for (boolean b : deadMap) {
                notSame |= b;
            }
            if (!notSame) {
                /* eliminate all branches (same congruence class) */
                for (MethodNode n : chainMap.get(m)) {
                    toRemove.add(n);
                }
                continue;
            }
            Type[] params = Type.getArgumentTypes(m.getDesc());
            Type ret = Type.getReturnType(m.getDesc());
            String desc = buildDesc(params, ret, deadMap);
            Set<MethodNode> conflicts = new HashSet<>();
            for (MethodNode chm : chainMap.get(m)) {
                remap.put(chm, desc);
                if (Modifier.isStatic(m.node.access)) {
                    MethodNode mm = resolver.resolveStaticCall(chm.owner.getName(), chm.getName(), desc);
                    if (mm != null) {
                        conflicts.add(mm);
                    }
                } else {
                    if (chm.getName().equals("<init>")) {
                        conflicts.addAll(resolver.resolveVirtualCalls(chm.owner.getName(), "<init>", desc, false));
                    } else {
                        conflicts.addAll(resolver.getHierarchyMethodChain(m.owner, m.getName(), desc, true));
                    }
                }
            }
            if (conflicts.size() > 0) {
                Set<MethodNode> chain = chainMap.get(m);
                /* rename the smallest conflict set */
                // if(chain.size() < conflicts.size()) {
                // 
                // } else {
                // mustRename.add(conflicts);
                // }
                mustRename.add(chain);
            }
        }
    }
    remap.keySet().removeAll(toRemove);
    int k = RenamingUtil.numeric("aaaaa");
    Map<MethodNode, String> methodNameRemap = new HashMap<>();
    for (Set<MethodNode> set : mustRename) {
        // MethodNode first = set.iterator().next();
        // String newName = "rename_" + first.getName();
        String newName = RenamingUtil.createName(k++);
        System.out.printf(" renaming %s to %s%n", set, newName);
        System.out.println("   recom " + computeChain(cxt, set.iterator().next()));
        Set<MethodNode> s2 = new HashSet<>();
        for (MethodNode m : set) {
            s2.addAll(chainMap.get(m));
        }
        if (!s2.equals(set)) {
            System.err.println(set);
            System.err.println(s2);
            throw new IllegalStateException();
        }
        for (MethodNode m : set) {
            methodNameRemap.put(m, newName);
        }
    }
    if (mustRename.size() > 0) {
        MethodRenamerPass.rename(cxt, methodNameRemap, false);
    }
    Set<MethodNode> visitedMethods = new HashSet<>();
    Set<Expr> visitedExprs = new HashSet<>();
    int killedTotal = 0;
    for (; ; ) {
        int killedBeforePass = killedTotal;
        for (Entry<MethodNode, String> en : remap.entrySet()) {
            MethodNode key = en.getKey();
            String newDesc = en.getValue();
            if (!visitedMethods.contains(key)) {
                Set<MethodNode> chain = chainMap.get(key);
                /*for(MethodNode n : chain) {
						if(visitedMethods.contains(n)) {
							throw new IllegalStateException(String.format("Invalid transistivityr: %s in %s but not %s", n, chain, key));
						}
					}*/
                boolean[] dead = filteredConstantParameters.get(key);
                for (MethodNode n : chain) {
                    n.node.desc = newDesc;
                    /* boolean[] dead = filteredConstantParameters.get(n);
						boolean[] deadM = filteredConstantParameters.get(key);
						
						if(!Arrays.equals(dead, deadM)) {
							throw new IllegalStateException(String.format("neq: %s vs %s for %s and %s", Arrays.toString(dead), Arrays.toString(deadM), n, key));
						} */
                    demoteDeadParamters(constAnalysis, cxt.getIRCache().getFor(n), n, dead);
                    for (Invocation call : constAnalysis.getCallsTo(n)) {
                        /* since the callgrapher finds all
							 * the methods in a hierarchy and considers
							 * it as a single invocation, a certain
							 * invocation may be considered multiple times. */
                        if (visitedExprs.contains(call)) {
                            continue;
                        }
                        /* the invocationexpr method desc is changed implicitly
							 * when the new expression is created in patchCall() */
                        visitedExprs.add(call);
                        patchCall(newDesc, call, dead);
                        killedTotal += chain.size();
                    }
                }
                visitedMethods.addAll(chain);
            }
        }
        if (killedBeforePass == killedTotal) {
            break;
        }
    }
    System.out.printf("  removed %d constant parameters.%n", killedTotal);
    return PassResult.with(pcxt, this).finished(killedTotal).make();
}
Also used : HashSet(java.util.HashSet) Set(java.util.Set) Invocation(org.mapleir.ir.code.expr.invoke.Invocation) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) AnalysisContext(org.mapleir.context.AnalysisContext) MethodNode(org.mapleir.asm.MethodNode) ArrayList(java.util.ArrayList) List(java.util.List) HashSet(java.util.HashSet) IPAnalysisVisitor(org.mapleir.deob.interproc.IPAnalysisVisitor) Type(org.objectweb.asm.Type) ConstantExpr(org.mapleir.ir.code.expr.ConstantExpr) InitialisedObjectExpr(org.mapleir.ir.code.expr.invoke.InitialisedObjectExpr) InvocationExpr(org.mapleir.ir.code.expr.invoke.InvocationExpr) VarExpr(org.mapleir.ir.code.expr.VarExpr) Expr(org.mapleir.ir.code.Expr) ControlFlowGraph(org.mapleir.ir.cfg.ControlFlowGraph) InvocationResolver(org.mapleir.app.service.InvocationResolver) IPAnalysis(org.mapleir.deob.interproc.IPAnalysis)

Aggregations

ControlFlowGraph (org.mapleir.ir.cfg.ControlFlowGraph)30 MethodNode (org.mapleir.asm.MethodNode)17 BasicBlock (org.mapleir.ir.cfg.BasicBlock)14 Expr (org.mapleir.ir.code.Expr)14 ClassNode (org.mapleir.asm.ClassNode)13 Stmt (org.mapleir.ir.code.Stmt)13 AnalysisContext (org.mapleir.context.AnalysisContext)11 ApplicationClassSource (org.mapleir.app.service.ApplicationClassSource)9 InvocationResolver (org.mapleir.app.service.InvocationResolver)7 InvocationExpr (org.mapleir.ir.code.expr.invoke.InvocationExpr)7 FieldStoreStmt (org.mapleir.ir.code.stmt.FieldStoreStmt)7 MethodNode (org.objectweb.asm.tree.MethodNode)6 IRCache (org.mapleir.context.IRCache)5 ControlFlowGraphBuilder (org.mapleir.ir.cfg.builder.ControlFlowGraphBuilder)5 ConstantExpr (org.mapleir.ir.code.expr.ConstantExpr)5 FieldLoadExpr (org.mapleir.ir.code.expr.FieldLoadExpr)5 Type (org.objectweb.asm.Type)5 HashMap (java.util.HashMap)4 HashSet (java.util.HashSet)4 SimpleApplicationContext (org.mapleir.app.client.SimpleApplicationContext)4