0

I need to analyze various android apks, find methods that execute intents and then get the action name of the intent like "ACTION_VIEW" etc.

I was able to retrieve all relevant methods like startActivity(), startActivityForResult() and onCreate(). But I cannot get the action names or constants in the corresponding Locals (Intent reference). Is it somehow possible to load the Intent.java class into the Scene (does adding as basic class already do that?) and then cast the Local into an Intent object? Or can you recommend me a complete different approach using soot?

Below a listing of my current custom soot class:

Options.v().set_src_prec(Options.src_prec_apk);
Options.v().set_whole_program(true);
Options.v().set_output_format(Options.output_format_none);

Scene.v().addBasicClass("java.lang.Object");          
Scene.v().addBasicClass("android.content.Intent");

    PackManager.v().getPack("jtp").add(new Transform("jtp.myInstrumenter", new BodyTransformer() {

        @Override
        protected void internalTransform(Body b, String phaseName, Map options) {
            final PatchingChain<Unit> units = b.getUnits();

            //important to use snapshotIterator here
            for(Iterator<Unit> iter = units.snapshotIterator(); iter.hasNext();) {
                final Unit u = iter.next();
                u.apply(new AbstractStmtSwitch() {

                    // getting invoke statements
                    public void caseInvokeStmt(InvokeStmt stmt) {
                        InvokeExpr invokeExpr = stmt.getInvokeExpr();
                        // getting intent respective methods
                        if(invokeExpr.getMethod().getName().equals("onCreate") ||
                                invokeExpr.getMethod().getName().equals("startActivity") ||
                                invokeExpr.getMethod().getName().equals("startActivityForResult")) {

                            System.out.println(invokeExpr.getMethod().getSignature());

                            // get value 0, always an Intent in those methods
                            Value val = invokeExpr.getArg(0); // references Intent
                            if(val.getType() instanceof RefType) {
                                RefType rt = (RefType) val.getType();

                                // Cast to android.content.Intent here..
                                // Intent in = (Intent) val;

                                System.out.println(rt.getClassName());
                            }       
                        }   
                    }
                });
            }
        }
    }));

Outputs the following for some example apk:

<android.app.Activity: void startActivityForResult(android.content.Intent,int)>
android.content.Intent
<android.app.Activity: void startActivityForResult(android.content.Intent,int)>
android.content.Intent
<android.app.Activity: void startActivityForResult(android.content.Intent,int)>
android.content.Intent
<android.app.Activity: void onCreate(android.os.Bundle)>
android.os.Bundle
<android.content.Context: void startActivity(android.content.Intent)>
android.content.Intent

1 Answers1

0

You must consider that Soot analyses the target "statically". This means that the actual values passed as arguments are not (trivially) accessible. Your code prints the "type" of the argument (Class android.content.Intent). The reason is that the Java (Dalvik or ART) bytecode is typed. So this information is available statically. If you want to retrieve the actual values, as far as I know, you have two ways: switch to dynamic analysis (e.g. you might instrument the call and print its arguments during a test) or carry out a data flow analysis. The second approach my be very complex and poorly scalable. You might want to have a look at program slicing-based techniques or abstract interpretation frameworks.