private void addTemporalManifestChanges(ProcessManifest androidManifest) { File manifestFile = null; try{ //temporarily save the modified AndroidManifest manifestFile = File.createTempFile("AndroidManifest.xml", null); FileOutputStream fos = new FileOutputStream(manifestFile.getPath()); byte[] output = androidManifest.getOutput(); fos.write(output); fos.close(); ArrayList<File> files = new ArrayList<File>(); files.add(manifestFile); HashMap<String, String> paths = new HashMap<String, String>(); paths.put(manifestFile.getAbsolutePath(), "AndroidManifest.xml"); //add the modified AndroidManifest into the original APK androidManifest.getApk().addFilesToApk(files, paths); }catch(Exception ex) { LoggerHelper.logEvent(MyLevel.EXCEPTION_ANALYSIS, ex.getMessage()); ex.printStackTrace(); System.exit(-1); } finally { if (manifestFile != null && manifestFile.exists()) manifestFile.delete(); } }
@SuppressWarnings("unchecked") private static void addMaxPrioForSMSReceiver(ProcessManifest manifest) { for(AXmlNode receiver : manifest.getReceivers()) { for(AXmlNode receiverChild : receiver.getChildren()) { if(receiverChild.getTag().equals("intent-filter")) { //search for SMS receiver for(AXmlNode childChild : receiverChild.getChildren()) { if(childChild.getTag().equals("action")) { if(childChild.hasAttribute("name") && ((String)childChild.getAttribute("name").getValue()).equalsIgnoreCase("android.provider.Telephony.SMS_RECEIVED")){ //prepare the priority filter if(receiverChild.hasAttribute("priority")) ((AXmlAttribute<Integer>)receiverChild.getAttribute("priority")).setValue(Integer.MAX_VALUE); else { AXmlAttribute<Integer> attr = new AXmlAttribute<Integer>("priority", Integer.MAX_VALUE, ANDROID_NAMESPACE); receiverChild.addAttribute(attr); } } } } } } } }
public static void extractApkInfo(String apkPath) { GlobalRef.apkPath = apkPath; try { ProcessManifest manifest = new ProcessManifest(apkPath); GlobalRef.pkgName = manifest.getPackageName(); GlobalRef.apkVersionCode = manifest.getVersionCode(); GlobalRef.apkVersionName = manifest.getVersionName(); GlobalRef.apkMinSdkVersion = manifest.getMinSdkVersion(); GlobalRef.apkPermissions = manifest.getPermissions(); } catch (Exception e) { e.printStackTrace(); } }
@Override protected void internalTransform(String phaseName, Map<String, String> options) { try { ProcessManifest processMan = new ProcessManifest(apkFileLocation); Set<String> entrypoints = processMan.getEntryPointClasses(); SootMethod mainMethod = generateMain(entrypoints); System.out.println(mainMethod.retrieveActiveBody()); } catch (Exception ex) { ex.printStackTrace(); } }
public static SootMethod generateDummyMain(String apkFileLocation) { SootMethod mainMethod = null; try { ProcessManifest processMan = new ProcessManifest(apkFileLocation); Set<String> entrypoints = processMan.getEntryPointClasses(); DummyMainGenerator dmGenerator = new DummyMainGenerator(apkFileLocation); mainMethod = dmGenerator.generateMain(entrypoints); System.out.println(mainMethod.retrieveActiveBody()); } catch (Exception ex) { ex.printStackTrace(); } return mainMethod; }
public static void main(String[] args) { DB.setJdbcPath("res/jdbc.xml"); String apkPath = args[0]; try { ProcessManifest processMan = new ProcessManifest(apkPath); String pkgName = processMan.getPackageName(); buildLinks(pkgName); } catch (Exception e) { e.printStackTrace(); } }
/** * This is a kind of hack and includes much more instrumentation which is necessary; * But it is still sound ;-). * @param apkFileLocation: apk file path */ public static void initializePePInAllPossibleClasses(String apkFileLocation){ try { ProcessManifest manifest = new ProcessManifest(apkFileLocation); Set<String> entryClasses = manifest.getEntryPointClasses(); for(String entryClass : entryClasses){ SootClass sc = Scene.v().getSootClass(entryClass); List<SootClass> allSuperClasses = Scene.v().getActiveHierarchy().getSuperclassesOf(sc); for(SootClass subclass : allSuperClasses) if(subclass.getName().equals("android.content.Context")){ initializePeP(sc); break; } } } catch (IOException | XmlPullParserException ex) { System.err.println("Could not read Android manifest file: " + ex.getMessage()); throw new RuntimeException(ex); } }
private boolean isLaunchableAcitivity(SootClass sc, ProcessManifest manifest) { Set<AXmlNode> launchableActivities = manifest.getLaunchableActivities(); for(AXmlNode node : launchableActivities) { if(node.hasAttribute("name")) { String activityName = (String)node.getAttribute("name").getValue(); activityName = getFullyQualifiedName(manifest, activityName); if(activityName.equals(sc.getName())) return true; } } return false; }
public static void manipulateAndroidManifest(ProcessManifest androidManifest) { // process old manifest addHookinHelperAsApplicationIfNecessary(androidManifest); addInternetPermissionIfNecessary(androidManifest); addTracingService(androidManifest); addComponentCallerService(androidManifest); addMaxPrioForSMSReceiver(androidManifest); addPermissionIfNecessary("android.permission.READ_EXTERNAL_STORAGE", androidManifest); addPermissionIfNecessary("android.permission.WRITE_EXTERNAL_STORAGE", androidManifest); addPermissionIfNecessary("android.permission.WRITE_CONTACT", androidManifest); }
private static void addPermissionIfNecessary(String permission, ProcessManifest androidManifest) { Set<String> allPermissions = androidManifest.getPermissions(); for(String perm : allPermissions) { if(perm.equals(permission)) //do nothing in case the sdcard-permission already exists return; } androidManifest.addPermission(permission); }
private static void addComponentCallerService(ProcessManifest androidManifest) { AXmlNode componentCallerService = new AXmlNode("service", null, androidManifest.getApplication()); AXmlAttribute<String> nameAttribute = new AXmlAttribute<String>("name", UtilInstrumenter.COMPONENT_CALLER_SERVICE_HELPER, ANDROID_NAMESPACE); AXmlAttribute<String> exportedAttribute = new AXmlAttribute<String>("exported", "false", ANDROID_NAMESPACE); componentCallerService.addAttribute(nameAttribute); componentCallerService.addAttribute(exportedAttribute); androidManifest.addService(componentCallerService); }
private static void addHookinHelperAsApplicationIfNecessary(ProcessManifest androidManifest){ AXmlNode application = androidManifest.getApplication(); if(!application.hasAttribute("name")) { AXmlAttribute<String> nameAttribute = new AXmlAttribute<String>("name", UtilInstrumenter.HELPER_APPLICATION_FOR_HOOKING, ANDROID_NAMESPACE); application.addAttribute(nameAttribute); } }
private static void addInternetPermissionIfNecessary(ProcessManifest androidManifest) { String internetPerm = "android.permission.INTERNET"; Set<String> allPermissions = androidManifest.getPermissions(); for(String perm : allPermissions) { if(perm.equals(internetPerm)) //do nothing in case the internet-permission already exists return; } androidManifest.addPermission(internetPerm); }
private static void addTracingService(ProcessManifest androidManifest) { AXmlNode tracingService = new AXmlNode("service", null, androidManifest.getApplication()); AXmlAttribute<String> nameAttribute = new AXmlAttribute<String>("name", UtilInstrumenter.HELPER_SERVICE_FOR_PATH_TRACKING, ANDROID_NAMESPACE); AXmlAttribute<String> exportedAttribute = new AXmlAttribute<String>("exported", "false", ANDROID_NAMESPACE); tracingService.addAttribute(nameAttribute); tracingService.addAttribute(exportedAttribute); androidManifest.addService(tracingService); }
public SetupApplicationJIT(String apkFileLocation, String sootCP, ISourceSinkDefinitionProvider sourceSinkProvider) { this.apkFileLocation = apkFileLocation; this.sootCP = sootCP; try { // Load Android callbacks this.androidCallbacks = Activator.getDefault().getAndroidCallbacks(); // Process manifest ProcessManifest processMan = new ProcessManifest(apkFileLocation); this.appPackageName = processMan.getPackageName(); this.entrypoints = processMan.getEntryPointClasses(); // Parse the resource file ARSCFileParser resParser = new ARSCFileParser(); resParser.parse(apkFileLocation); this.resourcePackages = resParser.getPackages(); // LayoutFileParser LayoutFileParser lfp = new LayoutFileParser(this.appPackageName, resParser); lfp.parseLayoutFile(apkFileLocation, entrypoints); // Create the SourceSinkManager Set<SootMethodAndClass> callbacks = new HashSet<>(); for (Set<SootMethodAndClass> methods : this.callbackMethods.values()) callbacks.addAll(methods); sourceSinkManager = new AccessPathBasedSourceSinkManager(sourceSinkProvider.getSources(), sourceSinkProvider.getSinks(), callbacks, LayoutMatchingMode.MatchSensitiveOnly, lfp == null ? null : lfp.getUserControlsByID()); sourceSinkManager.setAppPackageName(this.appPackageName); sourceSinkManager.setResourcePackages(this.resourcePackages); sourceSinkManager.setEnableCallbackSources(true); } catch (IOException | XmlPullParserException e) { LOGGER.error("Error initializing " + apkFileLocation); } }
public static Set<String> getComponents(String apkFileLocation) { Set<String> entrypoints = null; try { ProcessManifest processMan = new ProcessManifest(apkFileLocation); entrypoints = processMan.getEntryPointClasses(); } catch (Exception ex) { ex.printStackTrace(); } return entrypoints; }
/** * Get the package name of the application * @param apkFileLocation * @return */ public static String getApplicationPackageName(String apkFileLocation) { String packageName = null; try { ProcessManifest pm = new ProcessManifest(apkFileLocation); AXmlHandler axmlh = pm.getAXml(); // Find main activity and remove main intent-filter List<AXmlNode> anodes = axmlh.getNodesWithTag("manifest"); for (AXmlNode an: anodes) { boolean hasMain = false; boolean hasLauncher = false; AXmlNode filter = null; AXmlAttribute aname = an.getAttribute("package"); String aval = (String)aname.getValue(); packageName = aval; System.out.println("package: "+ packageName); break; } } catch (IOException | XmlPullParserException ex) { System.err.println("Could not read Android manifest file: " + ex.getMessage()); throw new RuntimeException(ex); } return packageName; }
private void executeTransformers(ProcessManifest manifest) { // We first need to retrieve some information from the manifest Set<String> constructors = new HashSet<>(); for (String className : manifest.getEntryPointClasses()) constructors.add("<" + className + ": void <init>()>"); ConditionTracking conditionTracking = new ConditionTracking(); CodePositionTracking codePositionTracking = new CodePositionTracking(codePositionManager); DynamicCallGraphTracking dynamicCallGraphTracking = new DynamicCallGraphTracking(codePositionManager); PathExecutionTransformer pathExecutionTransformer = new PathExecutionTransformer(); GoalReachedTracking goalReachedTracking = new GoalReachedTracking(config.getAllTargetLocations()); TimingBombTransformer timingBombs = new TimingBombTransformer(); DummyMethodHookTransformer dummyMethods = new DummyMethodHookTransformer(); DynamicValueTransformer dynamicValues = new DynamicValueTransformer(true); ClassLoaderTransformer classLoaders = new ClassLoaderTransformer(); for (SootClass sc : Scene.v().getApplicationClasses()) for (SootMethod sm : sc.getMethods()) if (sm.isConcrete()) { Body body = sm.getActiveBody(); //todo PAPER-EVAL ONLY codePositionTracking.transform(body); if(!FrameworkOptions.evaluationOnly){ // conditionTracking.transform(body); // dynamicCallGraphTracking.transform(body); } // if (FrameworkOptions.recordPathExecution) // pathExecutionTransformer.transform(body); goalReachedTracking.transform(body); //todo PAPER-EVAL ONLY if(!FrameworkOptions.evaluationOnly){ timingBombs.transform(body); dummyMethods.transform(body); dynamicValues.transform(body); } classLoaders.transform(body); } //todo PAPER-EVAL ONLY if(!FrameworkOptions.evaluationOnly) new CrashReporterInjection(constructors).transform(); new GlobalInstanceTransformer().transform(); }
private void initializeHooking(ProcessManifest manifest) { String applicationName = manifest.getApplicationName(); //case 1 if(applicationName != null) { if(applicationName.startsWith(".")) { String packageName = manifest.getPackageName(); if(packageName == null) throw new RuntimeException("There is a problem with the package name"); applicationName = packageName + applicationName; } SootClass applicationSootClass = Scene.v().getSootClass(applicationName); if(applicationSootClass != null) { String attachMethodName = String.format("<%s: void attachBaseContext(android.content.Context)>", applicationName); SootMethod attachMethod = Scene.v().grabMethod(attachMethodName); //case 1 if(attachMethod != null) { Body body = attachMethod.getActiveBody(); Local contextParam = body.getParameterLocal(0); List<Unit> unitsToInstrument = new ArrayList<Unit>(); String hookingHelperApplicationClassAttachMethodName = String.format("<%s: void initializeHooking(android.content.Context)>", UtilInstrumenter.HOOKER_CLASS); SootMethod hookingHelperApplicationClassAttachMethod = Scene.v().getMethod(hookingHelperApplicationClassAttachMethodName); if(hookingHelperApplicationClassAttachMethod == null) throw new RuntimeException("this should not happen"); SootMethodRef ref = hookingHelperApplicationClassAttachMethod.makeRef(); InvokeExpr invExpr = Jimple.v().newStaticInvokeExpr(ref, contextParam); unitsToInstrument.add(Jimple.v().newInvokeStmt(invExpr)); Unit instrumentAfterUnit = null; for(Unit unit : body.getUnits()) { if(unit instanceof InvokeStmt) { InvokeStmt invStmt = (InvokeStmt)unit; if(invStmt.getInvokeExpr().getMethod().getSubSignature().equals("void attachBaseContext(android.content.Context)")) { instrumentAfterUnit = unit; break; } } } if(instrumentAfterUnit == null) throw new RuntimeException("this should not happen"); body.getUnits().insertAfter(unitsToInstrument, instrumentAfterUnit); } //case 2 else { attachMethodName = String.format("<%s: void attachBaseContext(android.content.Context)>", UtilInstrumenter.HELPER_APPLICATION_FOR_HOOKING); attachMethod = Scene.v().grabMethod(attachMethodName); if(attachMethod == null) throw new RuntimeException("this should not happen"); List<Type> params = new ArrayList<Type>(); SootClass contextClass = Scene.v().getSootClass("android.content.Context"); params.add(contextClass.getType()); SootMethod newAttachMethod = new SootMethod("attachBaseContext", params, VoidType.v()); newAttachMethod.setModifiers(soot.Modifier.PROTECTED); newAttachMethod.setActiveBody(attachMethod.getActiveBody()); applicationSootClass.addMethod(newAttachMethod); } //there is no need for our Application class Scene.v().getSootClass(UtilInstrumenter.HELPER_APPLICATION_FOR_HOOKING).setLibraryClass(); } else { throw new RuntimeException("There is a problem with the Application class!"); } } //case 3 else{ //there is no need for any instrumentation since the Application class is set to application-class. } }
private Set<FrameworkEvent> getFrameworkEvents(Unit targetLocation, BackwardsInfoflowCFG cfg) { FrameworkEventManager eventManager = FrameworkEventManager.getEventManager(); ProcessManifest manifest = UtilApk.getManifest(); Set<FrameworkEvent> targetAndroidEvents = eventManager.extractInitalEventsForReachingTarget(targetLocation, cfg, manifest); return targetAndroidEvents; }
public Set<FrameworkEvent> extractInitalEventsForReachingTarget(Unit targetLocation, BackwardsInfoflowCFG backwardsCFG, ProcessManifest manifest) { Set<Unit> headUnits = getAllInitalMethodCalls(targetLocation, backwardsCFG); Set<FrameworkEvent> androidEvents = getAndroidEventsFromManifest(backwardsCFG, headUnits, manifest); return androidEvents; }
public static void main(final String[] args) { apkPath = args[0]; androidJars =args[1]; System.out.println("[IccTA]" + apkPath + ", " + androidJars); parseConfig(); try { DB.setJdbcPath("res/jdbc.xml"); ProcessManifest processMan = new ProcessManifest(apkPath); Test.appPackageName = processMan.getPackageName(); System.out.println("[IccTA]" + "ICC Provider is " + iccProviderStr); if (iccProviderStr.equals("ic3")) { ICCLinker.buildLinks(Test.appPackageName); } if (apkPath.contains(APK_COMBINER)) { if (apkPath.contains("/")) { int startPos = apkPath.lastIndexOf('/'); String filename = apkPath.substring(startPos+1); filename = filename.replace(".apk", ""); Test.appPackageNames = filename.split(Test.APK_COMBINER); } } AndroidIPCManager ipcManager = new AndroidIPCManager("res/IPCMethods.txt", Test.appPackageName); if (Test.appPackageNames != null) { ipcManager = new AndroidIPCManager("res/IPCMethods.txt", Test.appPackageNames); } ipcManager.setIccProvider(iccProviderStr); InfoStatistic mostBeginning = new InfoStatistic("Beginning"); ipcManager.addJimpleUpdater(mostBeginning); InfoStatistic mostEnding = new InfoStatistic("Ending"); ipcManager.addPostJimpleUpdater(mostEnding); SharedPreferencesUpdater sharedPreferencesUpdater = new SharedPreferencesUpdater(); ipcManager.addJimpleUpdater(sharedPreferencesUpdater); //JimpleReduceStaticFieldsTransformer jrsf = new JimpleReduceStaticFieldsTransformer(); //ipcManager.addJimpleUpdater(jrsf); JimpleIndexNumberTransformer jinTransformer = new JimpleIndexNumberTransformer(); ipcManager.addJimpleUpdater(jinTransformer); ApplicationClassSet acs = new ApplicationClassSet(); ipcManager.addJimpleUpdater(acs); //ExtraMapping extraMapping = new ExtraMapping(ApplicationClassSet.applicationClasses); //ipcManager.addJimpleUpdater(extraMapping); ExtraExtractor extraExtractor = new ExtraExtractor(); ipcManager.addJimpleUpdater(extraExtractor); FlowDroidLauncher.setIPCManager(ipcManager); FlowDroidLauncher.main(args); } catch (Exception ex) { ex.printStackTrace(); } }
/** * Get the name of the main activity in the AndroidManifest.xml file * @param apkFileLocation * @return */ public static String getMainActivityName(String apkFileLocation) { String mainActivityName = null; try { ProcessManifest pm = new ProcessManifest(apkFileLocation); AXmlHandler axmlh = pm.getAXml(); // Find main activity and remove main intent-filter List<AXmlNode> anodes = axmlh.getNodesWithTag("activity"); for (AXmlNode an: anodes) { boolean hasMain = false; boolean hasLauncher = false; AXmlNode filter = null; AXmlAttribute aname = an.getAttribute("name"); String aval = (String)aname.getValue(); System.out.println("activity: "+ aval); for (AXmlNode ch : an.getChildren()) { System.out.println("children: "+ ch); } List<AXmlNode> fnodes = an.getChildrenWithTag("intent-filter"); for (AXmlNode fn: fnodes) { hasMain = false; hasLauncher = false; // check action List<AXmlNode> acnodes = fn.getChildrenWithTag("action"); for (AXmlNode acn: acnodes) { AXmlAttribute acname = acn.getAttribute("name"); String acval = (String)acname.getValue(); System.out.println("action: "+ acval); if (acval.equals("android.intent.action.MAIN")) { hasMain = true; } } // check category List<AXmlNode> catnodes = fn.getChildrenWithTag("category"); for (AXmlNode catn: catnodes) { AXmlAttribute catname = catn.getAttribute("name"); String catval = (String)catname.getValue(); System.out.println("category: "+ catval); if (catval.equals("android.intent.category.LAUNCHER")) { hasLauncher = true; filter = fn; } } if (hasLauncher && hasMain) { break; } } if (hasLauncher && hasMain) { // replace name with the activity waiting for the connection to the PDP System.out.println("main activity is: "+ aval); System.out.println("excluding filter: "+ filter); filter.exclude(); mainActivityName = aval; break; } } } catch (IOException | XmlPullParserException ex) { System.err.println("Could not read Android manifest file: " + ex.getMessage()); throw new RuntimeException(ex); } return mainActivityName; }