/** * */ package de.rub.syssec.saaf.analysis.steps.obfuscation; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import de.rub.syssec.saaf.analysis.steps.AbstractStep; import de.rub.syssec.saaf.misc.config.Config; import de.rub.syssec.saaf.misc.config.ConfigKeys; import de.rub.syssec.saaf.model.analysis.AnalysisException; import de.rub.syssec.saaf.model.analysis.AnalysisInterface; import de.rub.syssec.saaf.model.application.ClassInterface; import de.rub.syssec.saaf.model.application.FieldInterface; import de.rub.syssec.saaf.model.application.MethodInterface; /** * Detects obfuscated classes based on median length of members. * * @author Tilman Bender <tilman.bender@rub.de> * */ public class LengthBasedDetectObfuscationStep extends AbstractStep { private static final int MAX_LENGTH = 11; private static final int MIN_LENGTH = 6; public static double median(ArrayList<Integer> allLengths) { Collections.sort(allLengths); int middle = allLengths.size() / 2; if (allLengths.size() % 2 == 1) { return allLengths.get(middle); } else { return (allLengths.get(middle - 1) + allLengths.get(middle)) / 2.0; } } public LengthBasedDetectObfuscationStep(Config cfg, boolean enabled) { this.logger = Logger.getLogger(getClass()); this.config = cfg; this.name = "Obfuscation Check"; this.description = "Detects obfuscation by checking the length of methods and field"; this.enabled = enabled; } /* * (non-Javadoc) * * @see * de.rub.syssec.saaf.analysis.steps.AbstractStep#doProcessing(de.rub.syssec * .saaf.model.analysis.AnalysisInterface) */ @Override protected boolean doProcessing(AnalysisInterface analysis) throws AnalysisException { for (ClassInterface smaliClass : analysis.getApp().getAllSmaliClasss( true)) { analyze(smaliClass); } return true; } private void analyze(ClassInterface smaliClass) { ArrayList<Integer> allLengths = new ArrayList<Integer>(); ArrayList<Integer> methodNameLengths = new ArrayList<Integer>(); ArrayList<Integer> fieldNameLengths = new ArrayList<Integer>(); //add the length of classname to the list of all name lengths allLengths.add(smaliClass.getClassName().length()); //iterate over the methods int length=0; for(MethodInterface method : smaliClass.getMethods()) { //get the length of the method name length=method.getName().length(); //add it to the list of method name lengths // methodNameLengths.add(length); //add it to the list of all name lengths allLengths.add(length); //if it is not inside the interval if(length<MIN_LENGTH || length>MAX_LENGTH) { //mark method as obfuscated method.setObfuscated(true); } } //iterate over the fields for(FieldInterface field : smaliClass.getAllFields()) { //get the length of the field name length = field.getFieldName().length(); //add it to the list of field name lengths //fieldNameLengths.add(length); //add it to the list of all name lengths allLengths.add(length); //if it is not inside the interval mark field as obfuscated if(length<MIN_LENGTH || length>MAX_LENGTH) { //mark method as obfuscated field.setObfuscated(true); } } double median = median(allLengths); if(median<MIN_LENGTH || median>MAX_LENGTH) { smaliClass.setObfuscated(true); } } }