All Downloads are FREE. Search and download functionalities are using the official Maven repository.

soot.jimple.infoflow.android.manifest.binary.AbstractBinaryAndroidComponent Maven / Gradle / Ivy

package soot.jimple.infoflow.android.manifest.binary;

import java.util.Map.Entry;

import pxb.android.axml.AxmlVisitor;
import soot.jimple.infoflow.android.axml.AXmlAttribute;
import soot.jimple.infoflow.android.axml.AXmlNode;
import soot.jimple.infoflow.android.manifest.BaseProcessManifest;
import soot.jimple.infoflow.android.manifest.IAndroidComponent;
import soot.jimple.infoflow.android.resources.ARSCFileParser;
import soot.jimple.infoflow.util.SystemClassHandler;

/**
 * Abstract base class for Android components loaded from a binary manifest file
 * 
 * @author Steven Arzt
 *
 */
public abstract class AbstractBinaryAndroidComponent implements IAndroidComponent {

	protected final AXmlNode node;
	protected final BaseProcessManifest manifest;
	protected boolean enabled;
	protected boolean exported;

	protected AbstractBinaryAndroidComponent(AXmlNode node, BaseProcessManifest manifest) {
		this.node = node;
		this.manifest = manifest;
		ARSCFileParser arscParser = manifest.getArscParser();

		AXmlAttribute attrEnabled = node.getAttribute("enabled");
		enabled = attrEnabled == null || attrEnabled.asBoolean(arscParser);

		loadIntentFilters();

		AXmlAttribute attrExported = node.getAttribute("exported");
		if (attrExported == null)
			exported = getExportedDefault();
		else
			exported = attrExported.asBoolean(arscParser);
	}

	/**
	 * Allows components with intent filters to load them
	 */
	protected void loadIntentFilters() {
		//
	}

	/**
	 * Gets whether the component is exported by default
	 * 
	 * @return True if the component is exported by default, false otherwise
	 */
	protected boolean getExportedDefault() {
		return false;
	}

	public AXmlNode getAXmlNode() {
		return node;
	}

	@Override
	public boolean isEnabled() {
		return enabled;
	}

	@Override
	public boolean isExported() {
		return exported;
	}

	@Override
	public String getNameString() {
		AXmlAttribute attr = node.getAttribute("name");
		if (attr != null)
			return manifest.expandClassName(attr.asString(manifest.getArscParser()));
		else {
			// This component does not have a name, so this might be
			// obfuscated malware. We apply a heuristic.
			for (Entry> a : node.getAttributes().entrySet()) {
				AXmlAttribute attrValue = a.getValue();
				if (attrValue != null) {
					String attrValueName = attrValue.getName();
					if ((attrValueName == null || attrValueName.isEmpty())
							&& attrValue.getType() == AxmlVisitor.TYPE_STRING) {
						String name = (String) attrValue.getValue();
						if (isValidComponentName(name)) {
							String expandedName = manifest.expandClassName(name);
							if (!SystemClassHandler.v().isClassInSystemPackage(expandedName))
								return expandedName;
						}
					}
				}
			}
		}
		return null;
	}

	/**
	 * Checks if the specified name is a valid Android component name
	 *
	 * @param name The Android component name to check
	 * @return True if the given name is a valid Android component name, otherwise
	 *         false
	 */
	private boolean isValidComponentName(String name) {
		if (name == null || name.isEmpty())
			return false;
		if (name.equals("true") || name.equals("false"))
			return false;
		if (Character.isDigit(name.charAt(0)))
			return false;

		if (name.startsWith("."))
			return true;

		// Be conservative
		return false;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy